package HTML::Dojo::src;
1;
__DATA__
__CPAN_DIR__ src
__CPAN_FILE__ src/date.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.date");


/* Supplementary Date Functions
 *******************************/

dojo.date.setDayOfYear = function (dateObject, dayofyear) {
	dateObject.setMonth(0);
	dateObject.setDate(dayofyear);
	return dateObject;
}

dojo.date.getDayOfYear = function (dateObject) {
	var firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1);
	return Math.floor((dateObject.getTime() -
		firstDayOfYear.getTime()) / 86400000);
}




dojo.date.setWeekOfYear = function (dateObject, week, firstDay) {
	if (arguments.length == 1) { firstDay = 0; } // Sunday
	dojo.unimplemented("dojo.date.setWeekOfYear");
}

dojo.date.getWeekOfYear = function (dateObject, firstDay) {
	if (arguments.length == 1) { firstDay = 0; } // Sunday

	// work out the first day of the year corresponding to the week
	var firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1);
	var day = firstDayOfYear.getDay();
	firstDayOfYear.setDate(firstDayOfYear.getDate() -
			day + firstDay - (day > firstDay ? 7 : 0));

	return Math.floor((dateObject.getTime() -
		firstDayOfYear.getTime()) / 604800000);
}




dojo.date.setIsoWeekOfYear = function (dateObject, week, firstDay) {
	if (arguments.length == 1) { firstDay = 1; } // Monday
	dojo.unimplemented("dojo.date.setIsoWeekOfYear");
}

dojo.date.getIsoWeekOfYear = function (dateObject, firstDay) {
	if (arguments.length == 1) { firstDay = 1; } // Monday
	dojo.unimplemented("dojo.date.getIsoWeekOfYear");
}




/* ISO 8601 Functions
 *********************/

dojo.date.setIso8601 = function (dateObject, string){
	var comps = (string.indexOf("T") == -1) ? string.split(" ") : string.split("T");
	dojo.date.setIso8601Date(dateObject, comps[0]);
	if (comps.length == 2) { dojo.date.setIso8601Time(dateObject, comps[1]); }
	return dateObject;
}

dojo.date.fromIso8601 = function (string) {
	return dojo.date.setIso8601(new Date(0, 0), string);
}




dojo.date.setIso8601Date = function (dateObject, string) {
	var regexp = "^([0-9]{4})((-?([0-9]{2})(-?([0-9]{2}))?)|" +
			"(-?([0-9]{3}))|(-?W([0-9]{2})(-?([1-7]))?))?$";
	var d = string.match(new RegExp(regexp));
	if(!d) {
		dojo.debug("invalid date string: " + string);
		return false;
	}
	var year = d[1];
	var month = d[4];
	var date = d[6];
	var dayofyear = d[8];
	var week = d[10];
	var dayofweek = (d[12]) ? d[12] : 1;

	dateObject.setYear(year);
	
	if (dayofyear) { dojo.date.setDayOfYear(dateObject, Number(dayofyear)); }
	else if (week) {
		dateObject.setMonth(0);
		dateObject.setDate(1);
		var gd = dateObject.getDay();
		var day =  (gd) ? gd : 7;
		var offset = Number(dayofweek) + (7 * Number(week));
		
		if (day <= 4) { dateObject.setDate(offset + 1 - day); }
		else { dateObject.setDate(offset + 8 - day); }
	} else {
		if (month) { 
			dateObject.setDate(1);
			dateObject.setMonth(month - 1); 
		}
		if (date) { dateObject.setDate(date); }
	}
	
	return dateObject;
}

dojo.date.fromIso8601Date = function (string) {
	return dojo.date.setIso8601Date(new Date(0, 0), string);
}




dojo.date.setIso8601Time = function (dateObject, string) {
	// first strip timezone info from the end
	var timezone = "Z|(([-+])([0-9]{2})(:?([0-9]{2}))?)$";
	var d = string.match(new RegExp(timezone));

	var offset = 0; // local time if no tz info
	if (d) {
		if (d[0] != 'Z') {
			offset = (Number(d[3]) * 60) + Number(d[5]);
			offset *= ((d[2] == '-') ? 1 : -1);
		}
		offset -= dateObject.getTimezoneOffset();
		string = string.substr(0, string.length - d[0].length);
	}

	// then work out the time
	var regexp = "^([0-9]{2})(:?([0-9]{2})(:?([0-9]{2})(\.([0-9]+))?)?)?$";
	var d = string.match(new RegExp(regexp));
	if(!d) {
		dojo.debug("invalid time string: " + string);
		return false;
	}
	var hours = d[1];
	var mins = Number((d[3]) ? d[3] : 0);
	var secs = (d[5]) ? d[5] : 0;
	var ms = d[7] ? (Number("0." + d[7]) * 1000) : 0;

	dateObject.setHours(hours);
	dateObject.setMinutes(mins);
	dateObject.setSeconds(secs);
	dateObject.setMilliseconds(ms);
	
	return dateObject;
}

dojo.date.fromIso8601Time = function (string) {
	return dojo.date.setIso8601Time(new Date(0, 0), string);
}



/* Informational Functions
 **************************/

dojo.date.shortTimezones = ["IDLW", "BET", "HST", "MART", "AKST", "PST", "MST",
	"CST", "EST", "AST", "NFT", "BST", "FST", "AT", "GMT", "CET", "EET", "MSK",
	"IRT", "GST", "AFT", "AGTT", "IST", "NPT", "ALMT", "MMT", "JT", "AWST",
	"JST", "ACST", "AEST", "LHST", "VUT", "NFT", "NZT", "CHAST", "PHOT",
	"LINT"];
dojo.date.timezoneOffsets = [-720, -660, -600, -570, -540, -480, -420, -360,
	-300, -240, -210, -180, -120, -60, 0, 60, 120, 180, 210, 240, 270, 300,
	330, 345, 360, 390, 420, 480, 540, 570, 600, 630, 660, 690, 720, 765, 780,
	840];
/*
dojo.date.timezones = ["International Date Line West", "Bering Standard Time",
	"Hawaiian Standard Time", "Marquesas Time", "Alaska Standard Time",
	"Pacific Standard Time (USA)", "Mountain Standard Time",
	"Central Standard Time (USA)", "Eastern Standard Time (USA)",
	"Atlantic Standard Time", "Newfoundland Time", "Brazil Standard Time",
	"Fernando de Noronha Standard Time (Brazil)", "Azores Time",
	"Greenwich Mean Time", "Central Europe Time", "Eastern Europe Time",
	"Moscow Time", "Iran Standard Time", "Gulf Standard Time",
	"Afghanistan Time", "Aqtobe Time", "Indian Standard Time", "Nepal Time",
	"Almaty Time", "Myanmar Time", "Java Time",
	"Australian Western Standard Time", "Japan Standard Time",
	"Australian Central Standard Time", "Lord Hove Standard Time (Australia)",
	"Vanuata Time", "Norfolk Time (Australia)", "New Zealand Standard Time",
	"Chatham Standard Time (New Zealand)", "Phoenix Islands Time (Kribati)",
	"Line Islands Time (Kribati)"];
*/
dojo.date.months = ["January", "February", "March", "April", "May", "June",
	"July", "August", "September", "October", "November", "December"];
dojo.date.shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "June",
	"July", "Aug", "Sep", "Oct", "Nov", "Dec"];
dojo.date.days = ["Sunday", "Monday", "Tuesday", "Wednesday",
	"Thursday", "Friday", "Saturday"];
dojo.date.shortDays = ["Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat"];


dojo.date.getDaysInMonth = function (dateObject) {
	var month = dateObject.getMonth();
	var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
	if (month == 1 && dojo.date.isLeapYear(dateObject)) { return 29; }
	else { return days[month]; }
}

dojo.date.isLeapYear = function (dateObject) {
	/*
	 * Leap years are years with an additional day YYYY-02-29, where the year
	 * number is a multiple of four with the following exception: If a year
	 * is a multiple of 100, then it is only a leap year if it is also a
	 * multiple of 400. For example, 1900 was not a leap year, but 2000 is one.
	 */
	var year = dateObject.getFullYear();
	return (year%400 == 0) ? true : (year%100 == 0) ? false : (year%4 == 0) ? true : false;
}



dojo.date.getDayName = function (dateObject) {
	return dojo.date.days[dateObject.getDay()];
}

dojo.date.getDayShortName = function (dateObject) {
	return dojo.date.shortDays[dateObject.getDay()];
}




dojo.date.getMonthName = function (dateObject) {
	return dojo.date.months[dateObject.getMonth()];
}

dojo.date.getMonthShortName = function (dateObject) {
	return dojo.date.shortMonths[dateObject.getMonth()];
}




dojo.date.getTimezoneName = function (dateObject) {
	// need to negate timezones to get it right 
	// i.e UTC+1 is CET winter, but getTimezoneOffset returns -60
	var timezoneOffset = -(dateObject.getTimezoneOffset());
	
	for (var i = 0; i < dojo.date.timezoneOffsets.length; i++) {
		if (dojo.date.timezoneOffsets[i] == timezoneOffset) {
			return dojo.date.shortTimezones[i];
		}
	}
	
	// we don't know so return it formatted as "+HH:MM"
	function $ (s) { s = String(s); while (s.length < 2) { s = "0" + s; } return s; }
	return (timezoneOffset < 0 ? "-" : "+") + $(Math.floor(Math.abs(
		timezoneOffset)/60)) + ":" + $(Math.abs(timezoneOffset)%60);
}




dojo.date.getOrdinal = function (dateObject) {
	var date = dateObject.getDate();

	if (date%100 != 11 && date%10 == 1) { return "st"; }
	else if (date%100 != 12 && date%10 == 2) { return "nd"; }
	else if (date%100 != 13 && date%10 == 3) { return "rd"; }
	else { return "th"; }
}



/* Date Formatter Functions
 ***************************/

// POSIX strftime
// see <http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html>
dojo.date.format = dojo.date.strftime = function (dateObject, format) {

	// zero pad
	var padChar = null;
	function _ (s, n) {
		s = String(s);
		n = (n || 2) - s.length;
		while (n-- > 0) { s = (padChar == null ? "0" : padChar) + s; }
		return s;
	}
	
	function $ (property) {
		switch (property) {
			case "a": // abbreviated weekday name according to the current locale
				return dojo.date.getDayShortName(dateObject); break;

			case "A": // full weekday name according to the current locale
				return dojo.date.getDayName(dateObject); break;

			case "b":
			case "h": // abbreviated month name according to the current locale
				return dojo.date.getMonthShortName(dateObject); break;
				
			case "B": // full month name according to the current locale
				return dojo.date.getMonthName(dateObject); break;
				
			case "c": // preferred date and time representation for the current
				      // locale
				return dateObject.toLocaleString(); break;

			case "C": // century number (the year divided by 100 and truncated
				      // to an integer, range 00 to 99)
				return _(Math.floor(dateObject.getFullYear()/100)); break;
				
			case "d": // day of the month as a decimal number (range 01 to 31)
				return _(dateObject.getDate()); break;
				
			case "D": // same as %m/%d/%y
				return $("m") + "/" + $("d") + "/" + $("y"); break;
					
			case "e": // day of the month as a decimal number, a single digit is
				      // preceded by a space (range ' 1' to '31')
				if (padChar == null) { padChar = " "; }
				return _(dateObject.getDate(), 2); break;
			
			case "g": // like %G, but without the century.
				break;
			
			case "G": // The 4-digit year corresponding to the ISO week number
				      // (see %V).  This has the same format and value as %Y,
				      // except that if the ISO week number belongs to the
				      // previous or next year, that year is used instead.
				break;
			
			case "F": // same as %Y-%m-%d
				return $("Y") + "-" + $("m") + "-" + $("d"); break;
				
			case "H": // hour as a decimal number using a 24-hour clock (range
				      // 00 to 23)
				return _(dateObject.getHours()); break;
				
			case "I": // hour as a decimal number using a 12-hour clock (range
				      // 01 to 12)
				return _(dateObject.getHours() % 12 || 12); break;
				
			case "j": // day of the year as a decimal number (range 001 to 366)
				return _(dojo.date.getDayOfYear(dateObject), 3); break;
				
			case "m": // month as a decimal number (range 01 to 12)
				return _(dateObject.getMonth() + 1); break;
				
			case "M": // minute as a decimal numbe
				return _(dateObject.getMinutes()); break;
			
			case "n":
				return "\n"; break;

			case "p": // either `am' or `pm' according to the given time value,
				      // or the corresponding strings for the current locale
				return dateObject.getHours() < 12 ? "am" : "pm"; break;
				
			case "r": // time in a.m. and p.m. notation
				return $("I") + ":" + $("M") + ":" + $("S") + " " + $("p"); break;
				
			case "R": // time in 24 hour notation
				return $("H") + ":" + $("M"); break;
				
			case "S": // second as a decimal number
				return _(dateObject.getSeconds()); break;

			case "t":
				return "\t"; break;

			case "T": // current time, equal to %H:%M:%S
				return $("H") + ":" + $("M") + ":" + $("S"); break;
				
			case "u": // weekday as a decimal number [1,7], with 1 representing
				      // Monday
				return String(dateObject.getDay() || 7); break;
				
			case "U": // week number of the current year as a decimal number,
				      // starting with the first Sunday as the first day of the
				      // first week
				return _(dojo.date.getWeekOfYear(dateObject)); break;

			case "V": // week number of the year (Monday as the first day of the
				      // week) as a decimal number [01,53]. If the week containing
				      // 1 January has four or more days in the new year, then it 
				      // is considered week 1. Otherwise, it is the last week of 
				      // the previous year, and the next week is week 1.
				return _(dojo.date.getIsoWeekOfYear(dateObject)); break;
				
			case "W": // week number of the current year as a decimal number,
				      // starting with the first Monday as the first day of the
				      // first week
				return _(dojo.date.getWeekOfYear(dateObject, 1)); break;
				
			case "w": // day of the week as a decimal, Sunday being 0
				return String(dateObject.getDay()); break;

			case "x": // preferred date representation for the current locale
				      // without the time
				break;

			case "X": // preferred date representation for the current locale
				      // without the time
				break;

			case "y": // year as a decimal number without a century (range 00 to
				      // 99)
				return _(dateObject.getFullYear()%100); break;
				
			case "Y": // year as a decimal number including the century
				return String(dateObject.getFullYear()); break;
			
			case "z": // time zone or name or abbreviation
				var timezoneOffset = dateObject.getTimezoneOffset();
				return (timezoneOffset < 0 ? "-" : "+") + 
					_(Math.floor(Math.abs(timezoneOffset)/60)) + ":" +
					_(Math.abs(timezoneOffset)%60); break;
				
			case "Z": // time zone or name or abbreviation
				return dojo.date.getTimezoneName(dateObject); break;
			
			case "%":
				return "%"; break;
		}
	}

	// parse the formatting string and construct the resulting string
	var string = "";
	var i = 0, index = 0, switchCase;
	while ((index = format.indexOf("%", i)) != -1) {
		string += format.substring(i, index++);
		
		// inspect modifier flag
		switch (format.charAt(index++)) {
			case "_": // Pad a numeric result string with spaces.
				padChar = " "; break;
			case "-": // Do not pad a numeric result string.
				padChar = ""; break;
			case "0": // Pad a numeric result string with zeros.
				padChar = "0"; break;
			case "^": // Convert characters in result string to upper case.
				switchCase = "upper"; break;
			case "#": // Swap the case of the result string.
				switchCase = "swap"; break;
			default: // no modifer flag so decremenet the index
				padChar = null; index--; break;
		}

		// toggle case if a flag is set
		var property = $(format.charAt(index++));
		if (switchCase == "upper" ||
			(switchCase == "swap" && /[a-z]/.test(property))) {
			property = property.toUpperCase();
		} else if (switchCase == "swap" && !/[a-z]/.test(property)) {
			property = property.toLowerCase();
		}
		var swicthCase = null;
		
		string += property;
		i = index;
	}
	string += format.substring(i);
	
	return string;
}

/* compare and add
 ******************/
dojo.date.compareTypes={
	// 	summary
	//	bitmask for comparison operations.
	DATE:1, TIME:2 
};
dojo.date.compare=function(/* Date */ dateA, /* Date */ dateB, /* int */ options){
	//	summary
	//	Compare two date objects by date, time, or both.
	var dA=dateA;
	var dB=dateB||new Date();
	var now=new Date();
	var opt=options||(dojo.date.compareTypes.DATE|dojo.date.compareTypes.TIME);
	var d1=new Date(
		((opt&dojo.date.compareTypes.DATE)?(dA.getFullYear()):now.getFullYear()), 
		((opt&dojo.date.compareTypes.DATE)?(dA.getMonth()):now.getMonth()), 
		((opt&dojo.date.compareTypes.DATE)?(dA.getDate()):now.getDate()), 
		((opt&dojo.date.compareTypes.TIME)?(dA.getHours()):0), 
		((opt&dojo.date.compareTypes.TIME)?(dA.getMinutes()):0), 
		((opt&dojo.date.compareTypes.TIME)?(dA.getSeconds()):0)
	);
	var d2=new Date(
		((opt&dojo.date.compareTypes.DATE)?(dB.getFullYear()):now.getFullYear()), 
		((opt&dojo.date.compareTypes.DATE)?(dB.getMonth()):now.getMonth()), 
		((opt&dojo.date.compareTypes.DATE)?(dB.getDate()):now.getDate()), 
		((opt&dojo.date.compareTypes.TIME)?(dB.getHours()):0), 
		((opt&dojo.date.compareTypes.TIME)?(dB.getMinutes()):0), 
		((opt&dojo.date.compareTypes.TIME)?(dB.getSeconds()):0)
	);
	if(d1.valueOf()>d2.valueOf()){
		return 1;	//	int
	}
	if(d1.valueOf()<d2.valueOf()){
		return -1;	//	int
	}
	return 0;	//	int
}

dojo.date.dateParts={ 
	//	summary
	//	constants for use in dojo.date.add
	YEAR:0, MONTH:1, DAY:2, HOUR:3, MINUTE:4, SECOND:5, MILLISECOND:6 
};
dojo.date.add=function(/* Date */ d, /* dojo.date.dateParts */ unit, /* int */ amount){
	var n=(amount)?amount:1;
	var v;
	switch(unit){
		case dojo.date.dateParts.YEAR:{
			v=new Date(d.getFullYear()+n, d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
			break;
		}
		case dojo.date.dateParts.MONTH:{
			v=new Date(d.getFullYear(), d.getMonth()+n, d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
			break;
		}
		case dojo.date.dateParts.HOUR:{
			v=new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours()+n, d.getMinutes(), d.getSeconds(), d.getMilliseconds());
			break;
		}
		case dojo.date.dateParts.MINUTE:{
			v=new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes()+n, d.getSeconds(), d.getMilliseconds());
			break;
		}
		case dojo.date.dateParts.SECOND:{
			v=new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds()+n, d.getMilliseconds());
			break;
		}
		case dojo.date.dateParts.MILLISECOND:{
			v=new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()+n);
			break;
		}
		default:{
			v=new Date(d.getFullYear(), d.getMonth(), d.getDate()+n, d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
		}
	};
	return v;	//	Date
};

/* Deprecated
 *************/


dojo.date.toString = function(date, format){
	dojo.deprecated("dojo.date.toString",
		"use dojo.date.format instead", "0.4");

	if (format.indexOf("#d") > -1) {
		format = format.replace(/#dddd/g, dojo.date.getDayOfWeekName(date));
		format = format.replace(/#ddd/g, dojo.date.getShortDayOfWeekName(date));
		format = format.replace(/#dd/g, (date.getDate().toString().length==1?"0":"")+date.getDate());
		format = format.replace(/#d/g, date.getDate());
	}

	if (format.indexOf("#M") > -1) {
		format = format.replace(/#MMMM/g, dojo.date.getMonthName(date));
		format = format.replace(/#MMM/g, dojo.date.getShortMonthName(date));
		format = format.replace(/#MM/g, ((date.getMonth()+1).toString().length==1?"0":"")+(date.getMonth()+1));
		format = format.replace(/#M/g, date.getMonth() + 1);
	}

	if (format.indexOf("#y") > -1) {
		var fullYear = date.getFullYear().toString();
		format = format.replace(/#yyyy/g, fullYear);
		format = format.replace(/#yy/g, fullYear.substring(2));
		format = format.replace(/#y/g, fullYear.substring(3));
	}

	// Return if only date needed;
	if (format.indexOf("#") == -1) {
		return format;
	}
	
	if (format.indexOf("#h") > -1) {
		var hours = date.getHours();
		hours = (hours > 12 ? hours - 12 : (hours == 0) ? 12 : hours);
		format = format.replace(/#hh/g, (hours.toString().length==1?"0":"")+hours);
		format = format.replace(/#h/g, hours);
	}
	
	if (format.indexOf("#H") > -1) {
		format = format.replace(/#HH/g, (date.getHours().toString().length==1?"0":"")+date.getHours());
		format = format.replace(/#H/g, date.getHours());
	}
	
	if (format.indexOf("#m") > -1) {
		format = format.replace(/#mm/g, (date.getMinutes().toString().length==1?"0":"")+date.getMinutes());
		format = format.replace(/#m/g, date.getMinutes());
	}

	if (format.indexOf("#s") > -1) {
		format = format.replace(/#ss/g, (date.getSeconds().toString().length==1?"0":"")+date.getSeconds());
		format = format.replace(/#s/g, date.getSeconds());
	}
	
	if (format.indexOf("#T") > -1) {
		format = format.replace(/#TT/g, date.getHours() >= 12 ? "PM" : "AM");
		format = format.replace(/#T/g, date.getHours() >= 12 ? "P" : "A");
	}

	if (format.indexOf("#t") > -1) {
		format = format.replace(/#tt/g, date.getHours() >= 12 ? "pm" : "am");
		format = format.replace(/#t/g, date.getHours() >= 12 ? "p" : "a");
	}
					
	return format;
	
}


dojo.date.daysInMonth = function (month, year) {
	dojo.deprecated("daysInMonth(month, year)",
		"replaced by getDaysInMonth(dateObject)", "0.4");
	return dojo.date.getDaysInMonth(new Date(year, month, 1));
}

/**
 *
 * Returns a string of the date in the version "January 1, 2004"
 *
 * @param date The date object
 */
dojo.date.toLongDateString = function(date) {
	dojo.deprecated("dojo.date.toLongDateString",
		'use dojo.date.format(date, "%B %e, %Y") instead', "0.4");
	return dojo.date.format(date, "%B %e, %Y")
}

/**
 *
 * Returns a string of the date in the version "Jan 1, 2004"
 *
 * @param date The date object
 */
dojo.date.toShortDateString = function(date) {
	dojo.deprecated("dojo.date.toShortDateString",
		'use dojo.date.format(date, "%b %e, %Y") instead', "0.4");
	return dojo.date.format(date, "%b %e, %Y");
}

/**
 *
 * Returns military formatted time
 *
 * @param date the date object
 */
dojo.date.toMilitaryTimeString = function(date){
	dojo.deprecated("dojo.date.toMilitaryTimeString",
		'use dojo.date.format(date, "%T")', "0.4");
	return dojo.date.format(date, "%T");
}

/**
 *
 * Returns a string of the date relative to the current date.
 *
 * @param date The date object
 *
 * Example returns:
 * - "1 minute ago"
 * - "4 minutes ago"
 * - "Yesterday"
 * - "2 days ago"
 */
dojo.date.toRelativeString = function(date) {
	var now = new Date();
	var diff = (now - date) / 1000;
	var end = " ago";
	var future = false;
	if(diff < 0) {
		future = true;
		end = " from now";
		diff = -diff;
	}

	if(diff < 60) {
		diff = Math.round(diff);
		return diff + " second" + (diff == 1 ? "" : "s") + end;
	} else if(diff < 3600) {
		diff = Math.round(diff/60);
		return diff + " minute" + (diff == 1 ? "" : "s") + end;
	} else if(diff < 3600*24 && date.getDay() == now.getDay()) {
		diff = Math.round(diff/3600);
		return diff + " hour" + (diff == 1 ? "" : "s") + end;
	} else if(diff < 3600*24*7) {
		diff = Math.round(diff/(3600*24));
		if(diff == 1) {
			return future ? "Tomorrow" : "Yesterday";
		} else {
			return diff + " days" + end;
		}
	} else {
		return dojo.date.toShortDateString(date);
	}
}

/**
 * Retrieves the day of the week the Date is set to.
 *
 * @return The day of the week
 */
dojo.date.getDayOfWeekName = function (date) {
	dojo.deprecated("dojo.date.getDayOfWeekName",
		"use dojo.date.getDayName instead", "0.4");
	return dojo.date.days[date.getDay()];
}

/**
 * Retrieves the short day of the week name the Date is set to.
 *
 * @return The short day of the week name
 */
dojo.date.getShortDayOfWeekName = function (date) {
	dojo.deprecated("dojo.date.getShortDayOfWeekName",
		"use dojo.date.getDayShortName instead", "0.4");
	return dojo.date.shortDays[date.getDay()];
}

/**
 * Retrieves the short month name the Date is set to.
 *
 * @return The short month name
 */
dojo.date.getShortMonthName = function (date) {
	dojo.deprecated("dojo.date.getShortMonthName",
		"use dojo.date.getMonthShortName instead", "0.4");
	return dojo.date.shortMonths[date.getMonth()];
}


/**
 * Convert a Date to a SQL string, optionally ignoring the HH:MM:SS portion of the Date
 */
dojo.date.toSql = function(date, noTime) {
	return dojo.date.format(date, "%F" + !noTime ? " %T" : "");
}

/**
 * Convert a SQL date string to a JavaScript Date object
 */
dojo.date.fromSql = function(sqlDate) {
	var parts = sqlDate.split(/[\- :]/g);
	while(parts.length < 6) {
		parts.push(0);
	}
	return new Date(parts[0], (parseInt(parts[1],10)-1), parts[2], parts[3], parts[4], parts[5]);
}


__CPAN_FILE__ src/Deferred.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.Deferred");
dojo.require("dojo.lang.func");

dojo.Deferred = function(/* optional */ canceller){
	/*
	NOTE: this namespace and documentation are imported wholesale 
		from MochiKit

	Encapsulates a sequence of callbacks in response to a value that
	may not yet be available.  This is modeled after the Deferred class
	from Twisted <http://twistedmatrix.com>.

	Why do we want this?  JavaScript has no threads, and even if it did,
	threads are hard.  Deferreds are a way of abstracting non-blocking
	events, such as the final response to an XMLHttpRequest.

	The sequence of callbacks is internally represented as a list
	of 2-tuples containing the callback/errback pair.  For example,
	the following call sequence::

		var d = new Deferred();
		d.addCallback(myCallback);
		d.addErrback(myErrback);
		d.addBoth(myBoth);
		d.addCallbacks(myCallback, myErrback);

	is translated into a Deferred with the following internal
	representation::

		[
			[myCallback, null],
			[null, myErrback],
			[myBoth, myBoth],
			[myCallback, myErrback]
		]

	The Deferred also keeps track of its current status (fired).
	Its status may be one of three things:

		-1: no value yet (initial condition)
		0: success
		1: error

	A Deferred will be in the error state if one of the following
	three conditions are met:

		1. The result given to callback or errback is "instanceof" Error
		2. The previous callback or errback raised an exception while
		   executing
		3. The previous callback or errback returned a value "instanceof"
			Error

	Otherwise, the Deferred will be in the success state.  The state of
	the Deferred determines the next element in the callback sequence to
	run.

	When a callback or errback occurs with the example deferred chain,
	something equivalent to the following will happen (imagine that
	exceptions are caught and returned)::

		// d.callback(result) or d.errback(result)
		if(!(result instanceof Error)){
			result = myCallback(result);
		}
		if(result instanceof Error){
			result = myErrback(result);
		}
		result = myBoth(result);
		if(result instanceof Error){
			result = myErrback(result);
		}else{
			result = myCallback(result);
		}

	The result is then stored away in case another step is added to the
	callback sequence.	Since the Deferred already has a value available,
	any new callbacks added will be called immediately.

	There are two other "advanced" details about this implementation that
	are useful:

	Callbacks are allowed to return Deferred instances themselves, so you
	can build complicated sequences of events with ease.

	The creator of the Deferred may specify a canceller.  The canceller
	is a function that will be called if Deferred.cancel is called before
	the Deferred fires.	 You can use this to implement clean aborting of
	an XMLHttpRequest, etc.	 Note that cancel will fire the deferred with
	a CancelledError (unless your canceller returns another kind of
	error), so the errbacks should be prepared to handle that error for
	cancellable Deferreds.

	*/
	
	this.chain = [];
	this.id = this._nextId();
	this.fired = -1;
	this.paused = 0;
	this.results = [null, null];
	this.canceller = canceller;
	this.silentlyCancelled = false;
};

dojo.lang.extend(dojo.Deferred, {
	getFunctionFromArgs: function(){
		var a = arguments;
		if((a[0])&&(!a[1])){
			if(dojo.lang.isFunction(a[0])){
				return a[0];
			}else if(dojo.lang.isString(a[0])){
				return dj_global[a[0]];
			}
		}else if((a[0])&&(a[1])){
			return dojo.lang.hitch(a[0], a[1]);
		}
		return null;
	},

	repr: function(){
		var state;
		if(this.fired == -1){
			state = 'unfired';
		}else if(this.fired == 0){
			state = 'success';
		} else {
			state = 'error';
		}
		return 'Deferred(' + this.id + ', ' + state + ')';
	},

	toString: dojo.lang.forward("repr"),

	_nextId: (function(){
		var n = 1;
		return function(){ return n++; };
	})(),

	cancel: function(){
		/***
		Cancels a Deferred that has not yet received a value, or is
		waiting on another Deferred as its value.

		If a canceller is defined, the canceller is called. If the
		canceller did not return an error, or there was no canceller,
		then the errback chain is started with CancelledError.
		***/
		if(this.fired == -1){
			if (this.canceller){
				this.canceller(this);
			}else{
				this.silentlyCancelled = true;
			}
			if(this.fired == -1){
				this.errback(new Error(this.repr()));
			}
		}else if(	(this.fired == 0)&&
					(this.results[0] instanceof dojo.Deferred)){
			this.results[0].cancel();
		}
	},
			

	_pause: function(){
		// Used internally to signal that it's waiting on another Deferred
		this.paused++;
	},

	_unpause: function(){
		// Used internally to signal that it's no longer waiting on
		// another Deferred.
		this.paused--;
		if ((this.paused == 0) && (this.fired >= 0)) {
			this._fire();
		}
	},

	_continue: function(res){
		// Used internally when a dependent deferred fires.
		this._resback(res);
		this._unpause();
	},

	_resback: function(res){
		// The primitive that means either callback or errback
		this.fired = ((res instanceof Error) ? 1 : 0);
		this.results[this.fired] = res;
		this._fire();
	},

	_check: function(){
		if(this.fired != -1){
			if(!this.silentlyCancelled){
				dojo.raise("already called!");
			}
			this.silentlyCancelled = false;
			return;
		}
	},

	callback: function(res){
		/*
		Begin the callback sequence with a non-error value.
		
		callback or errback should only be called once on a given
		Deferred.
		*/
		this._check();
		this._resback(res);
	},

	errback: function(res){
		// Begin the callback sequence with an error result.
		this._check();
		if(!(res instanceof Error)){
			res = new Error(res);
		}
		this._resback(res);
	},

	addBoth: function(cb, cbfn){
		/*
		Add the same function as both a callback and an errback as the
		next element on the callback sequence.	This is useful for code
		that you want to guarantee to run, e.g. a finalizer.
		*/
		var enclosed = this.getFunctionFromArgs(cb, cbfn);
		if(arguments.length > 2){
			enclosed = dojo.lang.curryArguments(null, enclosed, arguments, 2);
		}
		return this.addCallbacks(enclosed, enclosed);
	},

	addCallback: function(cb, cbfn){
		// Add a single callback to the end of the callback sequence.
		var enclosed = this.getFunctionFromArgs(cb, cbfn);
		if(arguments.length > 2){
			enclosed = dojo.lang.curryArguments(null, enclosed, arguments, 2);
		}
		return this.addCallbacks(enclosed, null);
	},

	addErrback: function(cb, cbfn){
		// Add a single callback to the end of the callback sequence.
		var enclosed = this.getFunctionFromArgs(cb, cbfn);
		if(arguments.length > 2){
			enclosed = dojo.lang.curryArguments(null, enclosed, arguments, 2);
		}
		return this.addCallbacks(null, enclosed);
		return this.addCallbacks(null, cbfn);
	},

	addCallbacks: function (cb, eb) {
		// Add separate callback and errback to the end of the callback
		// sequence.
		this.chain.push([cb, eb])
		if (this.fired >= 0) {
			this._fire();
		}
		return this;
	},

	_fire: function(){
		// Used internally to exhaust the callback sequence when a result
		// is available.
		var chain = this.chain;
		var fired = this.fired;
		var res = this.results[fired];
		var self = this;
		var cb = null;
		while (chain.length > 0 && this.paused == 0) {
			// Array
			var pair = chain.shift();
			var f = pair[fired];
			if (f == null) {
				continue;
			}
			try {
				res = f(res);
				fired = ((res instanceof Error) ? 1 : 0);
				if(res instanceof dojo.Deferred) {
					cb = function(res){
						self._continue(res);
					}
					this._pause();
				}
			}catch(err){
				fired = 1;
				res = err;
			}
		}
		this.fired = fired;
		this.results[fired] = res;
		if((cb)&&(this.paused)){
			// this is for "tail recursion" in case the dependent
			// deferred is already fired
			res.addBoth(cb);
		}
	}
});

__CPAN_FILE__ src/animation.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.animation");
dojo.require("dojo.animation.Animation");

__CPAN_FILE__ src/behavior.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.behavior");
dojo.require("dojo.event.*");

dojo.require("dojo.experimental");
dojo.experimental("dojo.behavior");

dojo.behavior = new function(){
	function arrIn(obj, name){
		if(!obj[name]){ obj[name] = []; }
		return obj[name];
	}

	function forIn(obj, scope, func){
		var tmpObj = {};
		for(var x in obj){
			if(typeof tmpObj[x] == "undefined"){
				if(!func){
					scope(obj[x], x);
				}else{
					func.call(scope, obj[x], x);
				}
			}
		}
	}

	// FIXME: need a better test so we don't exclude nightly Safari's!
	this.behaviors = {};
	this.add = function(behaviorObj){
		/*	behavior objects are specified in the following format:
		 *
		 *	{ 
		 *	 	"#id": {
		 *			"found": function(element){
		 *				// ...
		 *			},
		 *
		 *			"onblah": {targetObj: foo, targetFunc: "bar"},
		 *
		 *			"onblarg": "/foo/bar/baz/blarg",
		 *
		 *			"onevent": function(evt){
		 *			},
		 *
		 *			"onotherevent: function(evt){
		 *				// ...
		 *			}
		 *		},
		 *
		 *		"#id2": {
		 *			// ...
		 *		},
		 *
		 *		"#id3": function(element){
		 *			// ...
		 *		},
		 *
		 *		// publish the match on a topic
		 *		"#id4": "/found/topic/name",
		 *
		 *		// match all direct descendants
		 *		"#id4 > *": function(element){
		 *			// ...
		 *		},
		 *
		 *		// match the first child node that's an element
		 *		"#id4 > @firstElement": { ... },
		 *
		 *		// match the last child node that's an element
		 *		"#id4 > @lastElement":  { ... },
		 *
		 *		// all elements of type tagname
		 *		"tagname": {
		 *			// ...
		 *		},
		 *
		 *		// maps to roughly:
		 *		//	dojo.lang.forEach(body.getElementsByTagName("tagname1"), function(node){
		 *		//		dojo.lang.forEach(node.getElementsByTagName("tagname2"), function(node2){
		 *		//			dojo.lang.forEach(node2.getElementsByTagName("tagname3", function(node3){
		 *		//				// apply rules
		 *		//			});
		 *		//		});
		 *		//	});
		 *		"tagname1 tagname2 tagname3": {
		 *			// ...
		 *		},
		 *
		 *		".classname": {
		 *			// ...
		 *		},
		 *
		 *		"tagname.classname": {
		 *			// ...
		 *		},
		 *	}
		 *
		 *	The "found" method is a generalized handler that's called as soon
		 *	as the node matches the selector. Rules for values that follow also
		 *	apply to the "found" key.
		 *	
		 *	The "on*" handlers are attached with dojo.event.connect(). If the
		 *	value is not a function but is rather an object, it's assumed to be
		 *	the "other half" of a dojo.event.kwConnect() argument object. It
		 *	may contain any/all properties of such a connection modifier save
		 *	for the sourceObj and sourceFunc properties which are filled in by
		 *	the system automatically. If a string is instead encountered, the
		 *	node publishes the specified event on the topic contained in the
		 *	string value.
		 *
		 *	If the value corresponding to the ID key is a function and not a
		 *	list, it's treated as though it was the value of "found".
		 *
		 */

		var tmpObj = {};
		forIn(behaviorObj, this, function(behavior, name){
			var tBehavior = arrIn(this.behaviors, name);
			if((dojo.lang.isString(behavior))||(dojo.lang.isFunction(behavior))){
				behavior = { found: behavior };
			}
			forIn(behavior, function(rule, ruleName){
				arrIn(tBehavior, ruleName).push(rule);
			});
		});
	}

	this.apply = function(){
		dojo.profile.start("dojo.behavior.apply");
		var r = dojo.render.html;
		// note, we apply one way for fast queries and one way for slow
		// iteration. So be it.
		var safariGoodEnough = (!r.safari);
		if(r.safari){
			// Anything over release #420 should work the fast way
			var uas = r.UA.split("AppleWebKit/")[1];
			if(parseInt(uas.match(/[0-9.]{3,}/)) >= 420){
				safariGoodEnough = true;
			}
		}
		if((dj_undef("behaviorFastParse", djConfig) ? (safariGoodEnough) : djConfig["behaviorFastParse"])){
			this.applyFast();
		}else{
			this.applySlow();
		}
		dojo.profile.end("dojo.behavior.apply");
	}

	this.matchCache = {};

	this.elementsById = function(id, handleRemoved){
		var removed = [];
		var added = [];
		arrIn(this.matchCache, id);
		if(handleRemoved){
			var nodes = this.matchCache[id];
			for(var x=0; x<nodes.length; x++){
				if(nodes[x].id != ""){
					removed.push(nodes[x]);
					nodes.splice(x, 1);
					x--;
				}
			}
		}
		var tElem = dojo.byId(id);
		while(tElem){
			if(!tElem["idcached"]){
				added.push(tElem);
			}
			tElem.id = "";
			tElem = dojo.byId(id);
		}
		this.matchCache[id] = this.matchCache[id].concat(added);
		dojo.lang.forEach(this.matchCache[id], function(node){
			node.id = id;
			node.idcached = true;
		});
		return { "removed": removed, "added": added, "match": this.matchCache[id] };
	}

	this.applyToNode = function(node, action, ruleSetName){
		if(typeof action == "string"){
			dojo.event.topic.registerPublisher(action, node, ruleSetName);
		}else if(typeof action == "function"){
			if(ruleSetName == "found"){
				action(node);
			}else{
				dojo.event.connect(node, ruleSetName, action);
			}
		}else{
			action.srcObj = node;
			action.srcFunc = ruleSetName;
			dojo.event.kwConnect(action);
		}
	}

	this.applyFast = function(){
		dojo.profile.start("dojo.behavior.applyFast");
		// fast DOM queries...wheeee!
		forIn(this.behaviors, function(tBehavior, id){
			var elems = dojo.behavior.elementsById(id);
			dojo.lang.forEach(elems.added, 
				function(elem){
					forIn(tBehavior, function(ruleSet, ruleSetName){
						if(dojo.lang.isArray(ruleSet)){
							dojo.lang.forEach(ruleSet, function(action){
								dojo.behavior.applyToNode(elem, action, ruleSetName);
							});
						}
					});
				}
			);
		});
		dojo.profile.end("dojo.behavior.applyFast");
	}
	
	this.applySlow = function(){
		// iterate. Ugg.
		dojo.profile.start("dojo.behavior.applySlow");
		var all = document.getElementsByTagName("*");
		var allLen = all.length;
		for(var x=0; x<allLen; x++){
			var elem = all[x];
			if((elem.id)&&(!elem["behaviorAdded"])&&(this.behaviors[elem.id])){
				elem["behaviorAdded"] = true;
				forIn(this.behaviors[elem.id], function(ruleSet, ruleSetName){
					if(dojo.lang.isArray(ruleSet)){
						dojo.lang.forEach(ruleSet, function(action){
							dojo.behavior.applyToNode(elem, action, ruleSetName);
						});
					}
				});
			}
		}
		dojo.profile.end("dojo.behavior.applySlow");
	}
}

dojo.addOnLoad(dojo.behavior, "apply");

__CPAN_FILE__ src/hostenv_adobesvg.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/*
 * Adobe SVG Viewer host environment
 */
if(typeof window == 'undefined'){
	dojo.raise("attempt to use adobe svg hostenv when no window object");
}

with(dojo.render){
	name = navigator.appName;
	ver = parseFloat(navigator.appVersion, 10);
	switch(navigator.platform){
		case "MacOS":
			os.osx =  true;
			break;
		case "Linux":
			os.linux =  true;
			break;
		case "Windows":
			os.win =  true;
			break;
		default:
			os.linux = true;
			break;
	};
	svg.capable = true;
	svg.support.builtin = true;
	svg.adobe = true;
};

// browserEval("alert(window.location);");

dojo.hostenv.println = function(s){
	try{
    // FIXME: this may not work with adobe's viewer, as we may first need a 
		// reference to the svgDocument
		// FIXME: need a way to determine where to position the text for this
    var ti = document.createElement("text");
    ti.setAttribute("x","50");
		var yPos = 25 + 15*document.getElementsByTagName("text").length;
    ti.setAttribute("y",yPos);
		var tn = document.createTextNode(s);
		ti.appendChild(tn);
		document.documentElement.appendChild(ti);
	}catch(e){

	}
}

dojo.debug = function() {
	if (!djConfig.isDebug) { return; }
	var args = arguments;
	if(typeof dojo.hostenv.println != 'function'){
		dojo.raise("attempt to call dojo.debug when there is no dojo.hostenv println implementation (yet?)");
	}
	var isJUM = dj_global["jum"];
	var s = isJUM ? "": "DEBUG: ";
	for(var i=0;i<args.length;++i){ s += args[i]; }
	if(isJUM){ // this seems to be the only way to get JUM to "play nice"
		jum.debug(s);
	}else{
		dojo.hostenv.println(s);
	}
}

dojo.hostenv.startPackage("dojo.hostenv");

dojo.hostenv.name_ = 'adobesvg';

dojo.hostenv.anonCtr = 0;
dojo.hostenv.anon = {};

dojo.hostenv.nameAnonFunc = function(anonFuncPtr, namespaceObj){
	var ret = "_"+this.anonCtr++;
	var nso = (namespaceObj || this.anon);
	while(typeof nso[ret] != "undefined"){
		ret = "_"+this.anonCtr++;
	}
	nso[ret] = anonFuncPtr;
	return ret;
}

dojo.hostenv.modulesLoadedFired = false;
dojo.hostenv.modulesLoadedListeners = [];
dojo.hostenv.getTextStack = [];
dojo.hostenv.loadUriStack = [];
dojo.hostenv.loadedUris = [];


dojo.hostenv.modulesLoaded = function(){
	if(this.modulesLoadedFired){ return; }
	if((this.loadUriStack.length==0)&&(this.getTextStack.length==0)){
		if(this.inFlightCount > 0){ 
			dojo.debug("couldn't initialize, there are files still in flight");
			return;
		}
		this.modulesLoadedFired = true;
		var mll = this.modulesLoadedListeners;
		for(var x=0; x<mll.length; x++){
			mll[x]();
		}
	}
}

dojo.hostenv.getNewAnonFunc = function(){
	var ret = "_"+this.anonCtr++;
	while(typeof this.anon[ret] != "undefined"){
		ret = "_"+this.anonCtr++;
	}
	// this.anon[ret] = function(){};
	eval("dojo.nostenv.anon."+ret+" = function(){};");
	return [ret, this.anon[ret]];
}

dojo.hostenv.displayStack = function(){
	var oa = [];
	var stack = this.loadUriStack;
	for(var x=0; x<stack.length; x++){
		oa.unshift([stack[x][0], (typeof stack[x][2])]);
	}
	dojo.debug("<pre>"+oa.join("\n")+"</pre>");
}

dojo.hostenv.unwindUriStack = function(){
	var stack = this.loadUriStack;
	for(var x in dojo.hostenv.loadedUris){
		for(var y=stack.length-1; y>=0; y--){
			if(stack[y][0]==x){
				stack.splice(y, 1);
			}
		}
	}
	var next = stack.pop();
	if((!next)&&(stack.length==0)){ 
		return;
	}
	for(var x=0; x<stack.length; x++){
		if((stack[x][0]==next[0])&&(stack[x][2])){
			next[2] == stack[x][2]
		}
	}
	var last = next;
	while(dojo.hostenv.loadedUris[next[0]]){
		last = next;
		next = stack.pop();
	}
	while(typeof next[2] == "string"){ // unwind as far as we can
		try{
			// dojo.debug("<pre><![CDATA["+next[2]+"]]></pre>");
			dj_eval(next[2]);
			next[1](true);
		}catch(e){
			dojo.debug("we got an error when loading "+next[0]);
			dojo.debug("error: "+e);
			// for(var x in e){ alert(x+" "+e[x]); }
		}
		dojo.hostenv.loadedUris[next[0]] = true;
		dojo.hostenv.loadedUris.push(next[0]);
		last = next;
		next = stack.pop();
		if((!next)&&(stack.length==0)){ break; }
		while(dojo.hostenv.loadedUris[next[0]]){
			last = next;
			next = stack.pop();
		}
	}
	if(next){
		stack.push(next);
		dojo.debug("### CHOKED ON: "+next[0]);
	}
}

/**
 * Reads the contents of the URI, and evaluates the contents.
 * Returns true if it succeeded. Returns false if the URI reading failed. Throws if the evaluation throws.
 * The result of the eval is not available to the caller.
 */
dojo.hostenv.loadUri = function(uri, cb){
	if(dojo.hostenv.loadedUris[uri]){
		return;
	}
	var stack = this.loadUriStack;
	stack.push([uri, cb, null]);
	var tcb = function(contents){
		// gratuitous hack for Adobe SVG 3, what a fucking POS
		if(contents.content){
			contents = contents.content;
		}

		// stack management
		var next = stack.pop();
		if((!next)&&(stack.length==0)){ 
			dojo.hostenv.modulesLoaded();
			return;
		}
		if(typeof contents == "string"){
			stack.push(next);
			for(var x=0; x<stack.length; x++){
				if(stack[x][0]==uri){
					stack[x][2] = contents;
				}
			}
			next = stack.pop();
		}
		if(dojo.hostenv.loadedUris[next[0]]){ 
			// dojo.debug("WE ALREADY HAD: "+next[0]);
			dojo.hostenv.unwindUriStack();
			return;
		}
		// push back onto stack
		stack.push(next);
		if(next[0]!=uri){
			//  and then unwind as far as we can
			if(typeof next[2] == "string"){
				dojo.hostenv.unwindUriStack();
			}

		}else{
			if(!contents){ 
				next[1](false);
			}else{
				var deps = dojo.hostenv.getDepsForEval(next[2]);
				if(deps.length>0){
					eval(deps.join(";"));
				}else{
					dojo.hostenv.unwindUriStack();
				}
			}
		}
	}
	this.getText(uri, tcb, true);
}

/**
 * Reads the contents of the URI, and evaluates the contents.
 * Returns true if it succeeded. Returns false if the URI reading failed. Throws if the evaluation throws.
 * The result of the eval is not available to the caller.
 */
dojo.hostenv.loadUri = function(uri, cb){
	if(dojo.hostenv.loadedUris[uri]){
		return;
	}
	var stack = this.loadUriStack;
	stack.push([uri, cb, null]);
	var tcb = function(contents){
		// gratuitous hack for Adobe SVG 3, what a fucking POS
		if(contents.content){
			contents = contents.content;
		}

		// stack management
		var next = stack.pop();
		if((!next)&&(stack.length==0)){ 
			dojo.hostenv.modulesLoaded();
			return;
		}
		if(typeof contents == "string"){
			stack.push(next);
			for(var x=0; x<stack.length; x++){
				if(stack[x][0]==uri){
					stack[x][2] = contents;
				}
			}
			next = stack.pop();
		}
		if(dojo.hostenv.loadedUris[next[0]]){ 
			// dojo.debug("WE ALREADY HAD: "+next[0]);
			dojo.hostenv.unwindUriStack();
			return;
		}
		// push back onto stack
		stack.push(next);
		if(next[0]!=uri){
			//  and then unwind as far as we can
			if(typeof next[2] == "string"){
				dojo.hostenv.unwindUriStack();
			}

		}else{
			if(!contents){ 
				next[1](false);
			}else{
				var deps = dojo.hostenv.getDepsForEval(next[2]);
				if(deps.length>0){
					eval(deps.join(";"));
				}else{
					dojo.hostenv.unwindUriStack();
				}
			}
		}
	}
	this.getText(uri, tcb, true);
}

/**
* loadModule("A.B") first checks to see if symbol A.B is defined. 
* If it is, it is simply returned (nothing to do).
* If it is not defined, it will look for "A/B.js" in the script root directory, followed
* by "A.js".
* It throws if it cannot find a file to load, or if the symbol A.B is not defined after loading.
* It returns the object A.B.
*
* This does nothing about importing symbols into the current package.
* It is presumed that the caller will take care of that. For example, to import
* all symbols:
*
*    with (dojo.hostenv.loadModule("A.B")) {
*       ...
*    }
*
* And to import just the leaf symbol:
*
*    var B = dojo.hostenv.loadModule("A.B");
*    ...
*
* dj_load is an alias for dojo.hostenv.loadModule
*/
dojo.hostenv.loadModule = function(modulename, exact_only, omit_module_check){
	// alert("dojo.hostenv.loadModule('"+modulename+"');");
	var module = this.findModule(modulename, 0);
	if(module){
		return module;
	}

	// dojo.debug("dojo.hostenv.loadModule('"+modulename+"');");

	// protect against infinite recursion from mutual dependencies
	if (typeof this.loading_modules_[modulename] !== 'undefined'){
		// NOTE: this should never throw an exception!! "recursive" includes
		// are normal in the course of app and module building, so blow out of
		// it gracefully, but log it in debug mode

		// dojo.raise("recursive attempt to load module '" + modulename + "'");
		dojo.debug("recursive attempt to load module '" + modulename + "'");
	}else{
		this.addedToLoadingCount.push(modulename);
	}
	this.loading_modules_[modulename] = 1;


	// convert periods to slashes
	var relpath = modulename.replace(/\./g, '/') + '.js';

	var syms = modulename.split(".");
	var nsyms = modulename.split(".");
	if(syms[0]=="dojo"){ // FIXME: need a smarter way to do this!
		syms[0] = "src"; 
	}
	var last = syms.pop();
	syms.push(last);
	// figure out if we're looking for a full package, if so, we want to do
	// things slightly diffrently
	var _this = this;
	var pfn = this.pkgFileName;
	if(last=="*"){
		modulename = (nsyms.slice(0, -1)).join('.');

		var module = this.findModule(modulename, 0);
		// dojo.debug("found: "+modulename+"="+module);
		if(module){
			_this.removedFromLoadingCount.push(modulename);
			return module;
		}

		var nextTry = function(lastStatus){
			if(lastStatus){ 
				module = _this.findModule(modulename, false); // pass in false so we can give better error
				if((!module)&&(syms[syms.length-1]!=pfn)){
					dojo.raise("Module symbol '" + modulename + "' is not defined after loading '" + relpath + "'"); 
				}
				if(module){
					_this.removedFromLoadingCount.push(modulename);
					dojo.hostenv.modulesLoaded();
					return;
				}
			}
			syms.pop();
			syms.push(pfn);
			// dojo.debug("syms: "+syms);
			relpath = syms.join("/") + '.js';
			if(relpath.charAt(0)=="/"){
				relpath = relpath.slice(1);
			}
			// dojo.debug("relpath: "+relpath);
			_this.loadPath(relpath, ((!omit_module_check) ? modulename : null), nextTry);
		}

		nextTry();
	}else{
		relpath = syms.join("/") + '.js';
		modulename = nsyms.join('.');

		var nextTry = function(lastStatus){
			// dojo.debug("lastStatus: "+lastStatus);
			if(lastStatus){ 
				// dojo.debug("inital relpath: "+relpath);
				module = _this.findModule(modulename, false); // pass in false so we can give better error
				// if(!module){
				if((!module)&&(syms[syms.length-1]!=pfn)){
					dojo.raise("Module symbol '" + modulename + "' is not defined after loading '" + relpath + "'"); 
				}
				if(module){
					_this.removedFromLoadingCount.push(modulename);
					dojo.hostenv.modulesLoaded();
					return;
				}
			}
			var setPKG = (syms[syms.length-1]==pfn) ? false : true;
			syms.pop();
			if(setPKG){
				syms.push(pfn);
			}
			relpath = syms.join("/") + '.js';
			if(relpath.charAt(0)=="/"){
				relpath = relpath.slice(1);
			}
			// dojo.debug("relpath: "+relpath);
			_this.loadPath(relpath, ((!omit_module_check) ? modulename : null), nextTry);
		}

		this.loadPath(relpath, ((!omit_module_check) ? modulename : null), nextTry);
	}
	return;
}

/**
 * Read the contents of the specified uri and return those contents.
 *
 * FIXME: Make sure this is consistent with other implementations of getText
 * @param uri A relative or absolute uri. If absolute, it still must be in the same "domain" as we are.
 * @param async_cb If not specified, returns false as synchronous is not
 * supported. If specified, load asynchronously, and use async_cb as the handler which receives the result of the request.
 * @param fail_ok Default false. If fail_ok and !async_cb and loading fails, return null instead of throwing.
 */ 
dojo.hostenv.async_cb = null;

dojo.hostenv.unWindGetTextStack = function(){
	if(dojo.hostenv.inFlightCount>0){
		setTimeout("dojo.hostenv.unWindGetTextStack()", 100);
		return;
	}
	// we serialize because this goddamned environment is too fucked up
	// to know how to do anything else
	dojo.hostenv.inFlightCount++;
	var next = dojo.hostenv.getTextStack.pop();
	if((!next)&&(dojo.hostenv.getTextStack.length==0)){ 
		dojo.hostenv.inFlightCount--;
		dojo.hostenv.async_cb = function(){};
		return;
	}
	dojo.hostenv.async_cb = next[1];
	// http = window.getURL(uri, dojo.hostenv.anon[cbn]);
	window.getURL(next[0], function(result){ 
		dojo.hostenv.inFlightCount--;
		dojo.hostenv.async_cb(result.content);
		dojo.hostenv.unWindGetTextStack();
	});
}

dojo.hostenv.getText = function(uri, async_cb, fail_ok){
	// dojo.debug("Calling getText()");
	try{
		if(async_cb){
			dojo.hostenv.getTextStack.push([uri, async_cb, fail_ok]);
			dojo.hostenv.unWindGetTextStack();
		}else{
			return dojo.raise("No synchronous XMLHTTP implementation available, for uri " + uri);
		}
	}catch(e){
		return dojo.raise("No XMLHTTP implementation available, for uri " + uri);
	}
}


/**
 * Makes an async post to the specified uri.
 *
 * FIXME: Not sure that we need this, but adding for completeness.
 * More details about the implementation of this are available at 
 * http://wiki.svg.org/index.php/PostUrl
 * @param uri A relative or absolute uri. If absolute, it still must be in the same "domain" as we are.
 * @param async_cb If not specified, returns false as synchronous is not
 * supported. If specified, load asynchronously, and use async_cb as the progress handler which takes the xmlhttp object as its argument. If async_cb, this function returns null.
 * @param text Data to post
 * @param fail_ok Default false. If fail_ok and !async_cb and loading fails, return null instead of throwing.
 * @param mime_type optional MIME type of the posted data (such as "text/plain")
 * @param encoding optional encoding for data. null, 'gzip' and 'deflate' are possible values. If browser does not support binary post this parameter is ignored.
 */ 
dojo.hostenv.postText = function(uri, async_cb, text, fail_ok, mime_type, encoding){
	var http = null;
	
	var async_callback = function(httpResponse){
		if (!httpResponse.success) {
			dojo.raise("Request for uri '" + uri + "' resulted in " + httpResponse.status);
		}
		
		if(!httpResponse.content) {
			if (!fail_ok) dojo.raise("Request for uri '" + uri + "' resulted in no content");
			return null;
		}
		// FIXME: wtf, I'm losing a reference to async_cb
		async_cb(httpResponse.content);
	}
	
	try {
		if(async_cb) {
			http = window.postURL(uri, text, async_callback, mimeType, encoding);
		} else {
		return dojo.raise("No synchronous XMLHTTP post implementation available, for uri " + uri);
		}
	} catch(e) {
		return dojo.raise("No XMLHTTP post implementation available, for uri " + uri);
	}
}

/*
 * It turns out that if we check *right now*, as this script file is being loaded,
 * then the last script element in the window DOM is ourselves.
 * That is because any subsequent script elements haven't shown up in the document
 * object yet.
 */
function dj_last_script_src() {
	var scripts = window.document.getElementsByTagName('script');
	if(scripts.length < 1){ 
		dojo.raise("No script elements in window.document, so can't figure out my script src"); 
	}
	var li = scripts.length-1;
	var xlinkNS = "http://www.w3.org/1999/xlink";
	var src = null;
	var script = null;
	while(!src){
		script = scripts.item(li);
		src = script.getAttributeNS(xlinkNS,"href");
		li--;
		if(li<0){ break; }
		// break;
	}
	if(!src){
		dojo.raise("Last script element (out of " + scripts.length + ") has no src");
	}
	return src;
}

if(!dojo.hostenv["library_script_uri_"]){
	dojo.hostenv.library_script_uri_ = dj_last_script_src();
}

// dojo.hostenv.loadUri = function(uri){
	/* FIXME: adding a script element doesn't seem to be synchronous, and so
	 * checking for namespace or object existance after loadUri using this
	 * method will error out. Need to figure out some other way of handling
	 * this!
	 */
	/*
	var se = document.createElement("script");
	se.src = uri;
	var head = document.getElementsByTagName("head")[0];
	head.appendChild(se);
	// document.write("<script type='text/javascript' src='"+uri+"' />");
	return 1;
}
*/

__CPAN_FILE__ src/debug.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/**
 * Produce a line of debug output. 
 * Does nothing unless djConfig.isDebug is true.
 * varargs, joined with ''.
 * Caller should not supply a trailing "\n".
 */
dojo.debug = function(){
	if (!djConfig.isDebug) { return; }
	var args = arguments;
	if(dj_undef("println", dojo.hostenv)){
		dojo.raise("dojo.debug not available (yet?)");
	}
	var isJUM = dj_global["jum"] && !dj_global["jum"].isBrowser;
	var s = [(isJUM ? "": "DEBUG: ")];
	for(var i=0;i<args.length;++i){
		if(!false && args[i] && args[i] instanceof Error){
			var msg = "[" + args[i].name + ": " + dojo.errorToString(args[i]) +
				(args[i].fileName ? ", file: " + args[i].fileName : "") +
				(args[i].lineNumber ? ", line: " + args[i].lineNumber : "") + "]";
		} else {
			try {
				var msg = String(args[i]);
			} catch(e) {
				if(dojo.render.html.ie) {
					var msg = "[ActiveXObject]";
				} else {
					var msg = "[unknown]";
				}
			}
		}
		s.push(msg);
	}
	if(isJUM){ // this seems to be the only way to get JUM to "play nice"
		jum.debug(s.join(" "));
	}else{
		dojo.hostenv.println(s.join(" "));
	}
}

/**
 * this is really hacky for now - just 
 * display the properties of the object
**/

dojo.debugShallow = function(obj){
	if (!djConfig.isDebug) { return; }
	dojo.debug('------------------------------------------------------------');
	dojo.debug('Object: '+obj);
	var props = [];
	for(var prop in obj){
		try {
			props.push(prop + ': ' + obj[prop]);
		} catch(E) {
			props.push(prop + ': ERROR - ' + E.message);
		}
	}
	props.sort();
	for(var i = 0; i < props.length; i++) {
		dojo.debug(props[i]);
	}
	dojo.debug('------------------------------------------------------------');
}

dojo.debugDeep = function(obj){
	if (!djConfig.isDebug) { return; }
	if (!dojo.uri || !dojo.uri.dojoUri){ return dojo.debug("You'll need to load dojo.uri.* for deep debugging - sorry!"); }
	if (!window.open){ return dojo.debug('Deep debugging is only supported in host environments with window.open'); }
	var win = window.open(dojo.uri.dojoUri("src/debug/deep.html"), '_blank', 'width=600, height=400, resizable=yes, scrollbars=yes, status=yes');
	win.debugVar = obj;
}

__CPAN_FILE__ src/hostenv_spidermonkey.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/*
 * SpiderMonkey host environment
 */

dojo.hostenv.name_ = 'spidermonkey';

dojo.hostenv.println = print;
dojo.hostenv.exit = function(exitcode){ 
	quit(exitcode); 
}

// version() returns 0, sigh. and build() returns nothing but just prints.
dojo.hostenv.getVersion = function(){ return version(); }

// make jsc shut up (so we can use jsc for sanity checking) 
/*@cc_on
@if (@_jscript_version >= 7)
var line2pc; var print; var load; var quit;
@end
@*/

if(typeof line2pc == 'undefined'){
	dojo.raise("attempt to use SpiderMonkey host environment when no 'line2pc' global");
}

/*
 * This is a hack that determines the current script file by parsing a generated
 * stack trace (relying on the non-standard "stack" member variable of the
 * SpiderMonkey Error object).
 * If param depth is passed in, it'll return the script file which is that far down
 * the stack, but that does require that you know how deep your stack is when you are
 * calling.
 */
function dj_spidermonkey_current_file(depth){
    var s = '';
    try{
		throw Error("whatever");
	}catch(e){
		s = e.stack;
	}
    // lines are like: bu_getCurrentScriptURI_spidermonkey("ScriptLoader.js")@burst/Runtime.js:101
    var matches = s.match(/[^@]*\.js/gi);
    if(!matches){ 
		dojo.raise("could not parse stack string: '" + s + "'");
	}
    var fname = (typeof depth != 'undefined' && depth) ? matches[depth + 1] : matches[matches.length - 1];
    if(!fname){ 
		dojo.raise("could not find file name in stack string '" + s + "'");
	}
    //print("SpiderMonkeyRuntime got fname '" + fname + "' from stack string '" + s + "'");
    return fname;
}

// call this now because later we may not be on the top of the stack
if(!dojo.hostenv.library_script_uri_){ 
	dojo.hostenv.library_script_uri_ = dj_spidermonkey_current_file(0); 
}

dojo.hostenv.loadUri = function(uri){
	// spidermonkey load() evaluates the contents into the global scope (which
	// is what we want).
	// TODO: sigh, load() does not return a useful value. 
	// Perhaps it is returning the value of the last thing evaluated?
	var ok = load(uri);
	// dojo.debug("spidermonkey load(", uri, ") returned ", ok);
	return 1;
}



__CPAN_FILE__ src/bootstrap2.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

//Semicolon is for when this file is integrated with a custom build on one line
//with some other file's contents. Sometimes that makes things not get defined
//properly, particularly with the using the closure below to do all the work.
;(function(){
	//Don't do this work if dojo.js has already done it.
	if(typeof dj_usingBootstrap != "undefined"){
		return;
	}

	var isRhino = false;
	var isSpidermonkey = false;
	var isDashboard = false;
	if((typeof this["load"] == "function")&&((typeof this["Packages"] == "function")||(typeof this["Packages"] == "object"))){
		isRhino = true;
	}else if(typeof this["load"] == "function"){
		isSpidermonkey  = true;
	}else if(window.widget){
		isDashboard = true;
	}

	var tmps = [];
	if((this["djConfig"])&&((djConfig["isDebug"])||(djConfig["debugAtAllCosts"]))){
		tmps.push("debug.js");
	}

	if((this["djConfig"])&&(djConfig["debugAtAllCosts"])&&(!isRhino)&&(!isDashboard)){
		tmps.push("browser_debug.js");
	}

	//Support compatibility packages. Right now this only allows setting one
	//compatibility package. Might need to revisit later down the line to support
	//more than one.
	if((this["djConfig"])&&(djConfig["compat"])){
		tmps.push("compat/" + djConfig["compat"] + ".js");
	}

	var loaderRoot = djConfig["baseScriptUri"];
	if((this["djConfig"])&&(djConfig["baseLoaderUri"])){
		loaderRoot = djConfig["baseLoaderUri"];
	}

	for(var x=0; x < tmps.length; x++){
		var spath = loaderRoot+"src/"+tmps[x];
		if(isRhino||isSpidermonkey){
			load(spath);
		} else {
			try {
				document.write("<scr"+"ipt type='text/javascript' src='"+spath+"'></scr"+"ipt>");
			} catch (e) {
				var script = document.createElement("script");
				script.src = spath;
				document.getElementsByTagName("head")[0].appendChild(script);
			}
		}
	}
})();

// Localization routines

/**
 * The locale to look for string bundles if none are defined for your locale.  Translations for all strings
 * should be provided in this locale.
 */
//TODO: this really belongs in translation metadata, not in code
dojo.fallback_locale = 'en';

/**
 * Returns canonical form of locale, as used by Dojo.  All variants are case-insensitive and are separated by '-'
 * as specified in RFC 3066
 */
dojo.normalizeLocale = function(locale) {
	return locale ? locale.toLowerCase() : dojo.locale;
};

/**
 * requireLocalization() is for loading translated bundles provided within a package in the namespace.
 * Contents are typically strings, but may be any name/value pair, represented in JSON format.
 * A bundle is structured in a program as follows:
 *
 * <package>/
 *  nls/
 *   de/
 *    mybundle.js
 *   de-at/
 *    mybundle.js
 *   en/
 *    mybundle.js
 *   en-us/
 *    mybundle.js
 *   en-gb/
 *    mybundle.js
 *   es/
 *    mybundle.js
 *  ...etc
 *
 * where package is part of the namespace as used by dojo.require().  Each directory is named for a
 * locale as specified by RFC 3066, (http://www.ietf.org/rfc/rfc3066.txt), normalized in lowercase.
 *
 * For a given locale, string bundles will be loaded for that locale and all general locales above it, as well
 * as a system-specified fallback.  For example, "de_at" will also load "de" and "en".  Lookups will traverse
 * the locales in this order.  A build step can preload the bundles to avoid data redundancy and extra network hits.
 *
 * @param modulename package in which the bundle is found
 * @param bundlename bundle name, typically the filename without the '.js' suffix
 * @param locale the locale to load (optional)  By default, the browser's user locale as defined
 *	in dojo.locale
 */
dojo.requireLocalization = function(modulename, bundlename, locale /*optional*/){

	dojo.debug("EXPERIMENTAL: dojo.requireLocalization"); //dojo.experimental

	var syms = dojo.hostenv.getModuleSymbols(modulename);
	var modpath = syms.concat("nls").join("/");

	locale = dojo.normalizeLocale(locale);

	var elements = locale.split('-');
	var searchlist = [];
	for(var i = elements.length; i > 0; i--){
		searchlist.push(elements.slice(0, i).join('-'));
	}
	if(searchlist[searchlist.length-1] != dojo.fallback_locale){
		searchlist.push(dojo.fallback_locale);
	}

	var bundlepackage = [modulename, "_nls", bundlename].join(".");
	var bundle = dojo.hostenv.startPackage(bundlepackage);
	dojo.hostenv.loaded_modules_[bundlepackage] = bundle;
	
	var inherit = false;
	for(var i = searchlist.length - 1; i >= 0; i--){
		var loc = searchlist[i];
		var pkg = [bundlepackage, loc].join(".");
		var loaded = false;
		if(!dojo.hostenv.findModule(pkg)){
			// Mark loaded whether it's found or not, so that further load attempts will not be made
			dojo.hostenv.loaded_modules_[pkg] = null;

			var filespec = [modpath, loc, bundlename].join("/") + '.js';
			loaded = dojo.hostenv.loadPath(filespec, null, function(hash) {
 				bundle[loc] = hash;
 				if(inherit){
					// Use mixins approach to copy string references from inherit bundle, but skip overrides.
					for(var x in inherit){
						if(!bundle[loc][x]){
							bundle[loc][x] = inherit[x];
						}
					}
 				}
/*
				// Use prototype to point to other bundle, then copy in result from loadPath
				bundle[loc] = new function(){};
				if(inherit){ bundle[loc].prototype = inherit; }
				for(var i in hash){ bundle[loc][i] = hash[i]; }
*/
			});
		}else{
			loaded = true;
		}
		if(loaded && bundle[loc]){
			inherit = bundle[loc];
		}
	}
};

__CPAN_FILE__ src/loader.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/*
 * loader.js - runs before the hostenv_*.js file. Contains all of the package loading methods.
 */

//A semi-colon is at the start of the line because after doing a build, this function definition
//get compressed onto the same line as the last line in bootstrap1.js. That list line is just a
//curly bracket, and the browser complains about that syntax. The semicolon fixes it. Putting it
//here instead of at the end of bootstrap1.js, since it is more of an issue for this file, (using
//the closure), and bootstrap1.js could change in the future.
;(function(){
	//Additional properties for dojo.hostenv
	var _addHostEnv = {
		pkgFileName: "__package__",
	
		// for recursion protection
		loading_modules_: {},
		loaded_modules_: {},
		addedToLoadingCount: [],
		removedFromLoadingCount: [],
	
		inFlightCount: 0,
	
		// FIXME: it should be possible to pull module prefixes in from djConfig
		modulePrefixes_: {
			dojo: {name: "dojo", value: "src"}
		},
	
	
		setModulePrefix: function(module, prefix){
			this.modulePrefixes_[module] = {name: module, value: prefix};
		},
	
		getModulePrefix: function(module){
			var mp = this.modulePrefixes_;
			if((mp[module])&&(mp[module]["name"])){
				return mp[module].value;
			}
			return module;
		},

		getTextStack: [],
		loadUriStack: [],
		loadedUris: [],
	
		//WARNING: This variable is referenced by packages outside of bootstrap: FloatingPane.js and undo/browser.js
		post_load_: false,
		
		//Egad! Lots of test files push on this directly instead of using dojo.addOnLoad.
		modulesLoadedListeners: [],
		unloadListeners: [],
		loadNotifying: false
	};
	
	//Add all of these properties to dojo.hostenv
	for(var param in _addHostEnv){
		dojo.hostenv[param] = _addHostEnv[param];
	}
})();

/**
 * Loads and interprets the script located at relpath, which is relative to the
 * script root directory.  If the script is found but its interpretation causes
 * a runtime exception, that exception is not caught by us, so the caller will
 * see it.  We return a true value if and only if the script is found.
 *
 * For now, we do not have an implementation of a true search path.  We
 * consider only the single base script uri, as returned by getBaseScriptUri().
 *
 * @param relpath A relative path to a script (no leading '/', and typically
 * ending in '.js').
 * @param module A module whose existance to check for after loading a path.
 * Can be used to determine success or failure of the load.
 * @param cb a function to pass the result of evaluating the script (optional)
 */
dojo.hostenv.loadPath = function(relpath, module /*optional*/, cb /*optional*/){
	var uri;
	if((relpath.charAt(0) == '/')||(relpath.match(/^\w+:/))){
		// dojo.raise("relpath '" + relpath + "'; must be relative");
		uri = relpath;
	}else{
		uri = this.getBaseScriptUri() + relpath;
	}
	if(djConfig.cacheBust && dojo.render.html.capable){
		uri += "?" + String(djConfig.cacheBust).replace(/\W+/g,"");
	}
	try{
		return ((!module) ? this.loadUri(uri, cb) : this.loadUriAndCheck(uri, module, cb));
	}catch(e){
		dojo.debug(e);
		return false;
	}
}

/**
 * Reads the contents of the URI, and evaluates the contents.
 * Returns true if it succeeded. Returns false if the URI reading failed.
 * Throws if the evaluation throws.
 * The result of the eval is not available to the caller TODO: now it is; was this a deliberate restriction?
 *
 * @param uri a uri which points at the script to be loaded
 * @param cb a function to process the result of evaluating the script as an expression (optional)
 */
dojo.hostenv.loadUri = function(uri, cb /*optional*/){
	if(this.loadedUris[uri]){
		return 1;
	}
	var contents = this.getText(uri, null, true);
	if(contents == null){ return 0; }
	this.loadedUris[uri] = true;
	if(cb){ contents = '('+contents+')'; }
	var value = dj_eval(contents);
	if(cb){
		cb(value);
	}
	return 1;
}

// FIXME: probably need to add logging to this method
dojo.hostenv.loadUriAndCheck = function(uri, module, cb){
	var ok = true;
	try{
		ok = this.loadUri(uri, cb);
	}catch(e){
		dojo.debug("failed loading ", uri, " with error: ", e);
	}
	return ((ok)&&(this.findModule(module, false))) ? true : false;
}

dojo.loaded = function(){ }
dojo.unloaded = function(){ }

dojo.hostenv.loaded = function(){
	this.loadNotifying = true;
	this.post_load_ = true;
	var mll = this.modulesLoadedListeners;
	for(var x=0; x<mll.length; x++){
		mll[x]();
	}

	//Clear listeners so new ones can be added
	//For other xdomain package loads after the initial load.
	this.modulesLoadedListeners = [];
	this.loadNotifying = false;

	dojo.loaded();
}

dojo.hostenv.unloaded = function(){
	var mll = this.unloadListeners;
	while(mll.length){
		(mll.pop())();
	}
	dojo.unloaded();
}

/*
Call styles:
	dojo.addOnLoad(functionPointer)
	dojo.addOnLoad(object, "functionName")
*/
dojo.addOnLoad = function(obj, fcnName) {
	var dh = dojo.hostenv;
	if(arguments.length == 1) {
		dh.modulesLoadedListeners.push(obj);
	} else if(arguments.length > 1) {
		dh.modulesLoadedListeners.push(function() {
			obj[fcnName]();
		});
	}

	//Added for xdomain loading. dojo.addOnLoad is used to
	//indicate callbacks after doing some dojo.require() statements.
	//In the xdomain case, if all the requires are loaded (after initial
	//page load), then immediately call any listeners.
	if(dh.post_load_ && dh.inFlightCount == 0 && !dh.loadNotifying){
		dh.callLoaded();
	}
}

dojo.addOnUnload = function(obj, fcnName){
	var dh = dojo.hostenv;
	if(arguments.length == 1){
		dh.unloadListeners.push(obj);
	} else if(arguments.length > 1) {
		dh.unloadListeners.push(function() {
			obj[fcnName]();
		});
	}
}

dojo.hostenv.modulesLoaded = function(){
	if(this.post_load_){ return; }
	if((this.loadUriStack.length==0)&&(this.getTextStack.length==0)){
		if(this.inFlightCount > 0){ 
			dojo.debug("files still in flight!");
			return;
		}
		dojo.hostenv.callLoaded();
	}
}

dojo.hostenv.callLoaded = function(){
	if(typeof setTimeout == "object"){
		setTimeout("dojo.hostenv.loaded();", 0);
	}else{
		dojo.hostenv.loaded();
	}
}

dojo.hostenv.getModuleSymbols = function(modulename) {
	var syms = modulename.split(".");
	for(var i = syms.length - 1; i > 0; i--){
		var parentModule = syms.slice(0, i).join(".");
		var parentModulePath = this.getModulePrefix(parentModule);
		if(parentModulePath != parentModule){
			syms.splice(0, i, parentModulePath);
			break;
		}
	}
	return syms;
}

/**
* loadModule("A.B") first checks to see if symbol A.B is defined. 
* If it is, it is simply returned (nothing to do).
*
* If it is not defined, it will look for "A/B.js" in the script root directory,
* followed by "A.js".
*
* It throws if it cannot find a file to load, or if the symbol A.B is not
* defined after loading.
*
* It returns the object A.B.
*
* This does nothing about importing symbols into the current package.
* It is presumed that the caller will take care of that. For example, to import
* all symbols:
*
*    with (dojo.hostenv.loadModule("A.B")) {
*       ...
*    }
*
* And to import just the leaf symbol:
*
*    var B = dojo.hostenv.loadModule("A.B");
*    ...
*
* dj_load is an alias for dojo.hostenv.loadModule
*/
dojo.hostenv._global_omit_module_check = false;
dojo.hostenv.loadModule = function(modulename, exact_only, omit_module_check){
	if(!modulename){ return; }
	omit_module_check = this._global_omit_module_check || omit_module_check;
	var module = this.findModule(modulename, false);
	if(module){
		return module;
	}

	// protect against infinite recursion from mutual dependencies
	if(dj_undef(modulename, this.loading_modules_)){
		this.addedToLoadingCount.push(modulename);
	}
	this.loading_modules_[modulename] = 1;

	// convert periods to slashes
	var relpath = modulename.replace(/\./g, '/') + '.js';

	var syms = this.getModuleSymbols(modulename);
	var startedRelative = ((syms[0].charAt(0) != '/')&&(!syms[0].match(/^\w+:/)));
	var last = syms[syms.length - 1];
	// figure out if we're looking for a full package, if so, we want to do
	// things slightly diffrently
	var nsyms = modulename.split(".");
	if(last=="*"){
		modulename = (nsyms.slice(0, -1)).join('.');

		while(syms.length){
			syms.pop();
			syms.push(this.pkgFileName);
			relpath = syms.join("/") + '.js';
			if(startedRelative && (relpath.charAt(0)=="/")){
				relpath = relpath.slice(1);
			}
			ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null));
			if(ok){ break; }
			syms.pop();
		}
	}else{
		relpath = syms.join("/") + '.js';
		modulename = nsyms.join('.');
		var ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null));
		if((!ok)&&(!exact_only)){
			syms.pop();
			while(syms.length){
				relpath = syms.join('/') + '.js';
				ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null));
				if(ok){ break; }
				syms.pop();
				relpath = syms.join('/') + '/'+this.pkgFileName+'.js';
				if(startedRelative && (relpath.charAt(0)=="/")){
					relpath = relpath.slice(1);
				}
				ok = this.loadPath(relpath, ((!omit_module_check) ? modulename : null));
				if(ok){ break; }
			}
		}

		if((!ok)&&(!omit_module_check)){
			dojo.raise("Could not load '" + modulename + "'; last tried '" + relpath + "'");
		}
	}

	// check that the symbol was defined
	//Don't bother if we're doing xdomain (asynchronous) loading.
	if(!omit_module_check && !this["isXDomain"]){
		// pass in false so we can give better error
		module = this.findModule(modulename, false);
		if(!module){
			dojo.raise("symbol '" + modulename + "' is not defined after loading '" + relpath + "'"); 
		}
	}

	return module;
}

/**
* startPackage("A.B") follows the path, and at each level creates a new empty
* object or uses what already exists. It returns the result.
*/
dojo.hostenv.startPackage = function(packname){
	var modref = dojo.evalObjPath((packname.split(".").slice(0, -1)).join('.'));
	this.loaded_modules_[(new String(packname)).toLowerCase()] = modref;

	var syms = packname.split(/\./);
	if(syms[syms.length-1]=="*"){
		syms.pop();
	}
	return dojo.evalObjPath(syms.join("."), true);
}

/**
 * findModule("A.B") returns the object A.B if it exists, otherwise null.
 * @param modulename A string like 'A.B'.
 * @param must_exist Optional, defualt false. throw instead of returning null
 * if the module does not currently exist.
 */
dojo.hostenv.findModule = function(modulename, must_exist){
	// check cache
	/*
	if(!dj_undef(modulename, this.modules_)){
		return this.modules_[modulename];
	}
	*/

	var lmn = (new String(modulename)).toLowerCase();

	if(this.loaded_modules_[lmn]){
		return this.loaded_modules_[lmn];
	}

	// see if symbol is defined anyway
	var module = dojo.evalObjPath(modulename);
	if((modulename)&&(typeof module != 'undefined')&&(module)){
		this.loaded_modules_[lmn] = module;
		return module;
	}

	if(must_exist){
		dojo.raise("no loaded module named '" + modulename + "'");
	}
	return null;
}

//Start of old bootstrap2:

/*
 * This method taks a "map" of arrays which one can use to optionally load dojo
 * modules. The map is indexed by the possible dojo.hostenv.name_ values, with
 * two additional values: "default" and "common". The items in the "default"
 * array will be loaded if none of the other items have been choosen based on
 * the hostenv.name_ item. The items in the "common" array will _always_ be
 * loaded, regardless of which list is chosen.  Here's how it's normally
 * called:
 *
 *	dojo.kwCompoundRequire({
 *		browser: [
 *			["foo.bar.baz", true, true], // an example that passes multiple args to loadModule()
 *			"foo.sample.*",
 *			"foo.test,
 *		],
 *		default: [ "foo.sample.*" ],
 *		common: [ "really.important.module.*" ]
 *	});
 */
dojo.kwCompoundRequire = function(modMap){
	var common = modMap["common"]||[];
	var result = (modMap[dojo.hostenv.name_]) ? common.concat(modMap[dojo.hostenv.name_]||[]) : common.concat(modMap["default"]||[]);

	for(var x=0; x<result.length; x++){
		var curr = result[x];
		if(curr.constructor == Array){
			dojo.hostenv.loadModule.apply(dojo.hostenv, curr);
		}else{
			dojo.hostenv.loadModule(curr);
		}
	}
}

dojo.require = function(){
	dojo.hostenv.loadModule.apply(dojo.hostenv, arguments);
}

dojo.requireIf = function(){
	if((arguments[0] === true)||(arguments[0]=="common")||(arguments[0] && dojo.render[arguments[0]].capable)){
		var args = [];
		for (var i = 1; i < arguments.length; i++) { args.push(arguments[i]); }
		dojo.require.apply(dojo, args);
	}
}

dojo.requireAfterIf = dojo.requireIf;

dojo.provide = function(){
	return dojo.hostenv.startPackage.apply(dojo.hostenv, arguments);
}

dojo.setModulePrefix = function(module, prefix){
	return dojo.hostenv.setModulePrefix(module, prefix);
}

// determine if an object supports a given method
// useful for longer api chains where you have to test each object in the chain
dojo.exists = function(obj, name){
	var p = name.split(".");
	for(var i = 0; i < p.length; i++){
	if(!(obj[p[i]])) return false;
		obj = obj[p[i]];
	}
	return true;
}

__CPAN_FILE__ src/storage.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/** 
		FIXME: Write better docs.

		@author Alex Russel, alex@dojotoolkit.org
		@author Brad Neuberg, bkn3@columbia.edu 
*/
dojo.provide("dojo.storage");
dojo.provide("dojo.storage.StorageProvider");

dojo.require("dojo.lang.*");
dojo.require("dojo.event.*");


/** The base class for all storage providers. */

/** 
	 The constructor for a storage provider. You should avoid initialization
	 in the constructor; instead, define initialization in your initialize()
	 method. 
*/
dojo.storage = function(){
}

dojo.lang.extend(dojo.storage, {
	/** A put() call to a storage provider was succesful. */
	SUCCESS: "success",
	
	/** A put() call to a storage provider failed. */
	FAILED: "failed",
	
	/** A put() call to a storage provider is pending user approval. */
	PENDING: "pending",
	
	/** 
	  Returned by getMaximumSize() if this storage provider can not determine
	  the maximum amount of data it can support. 
	*/
	SIZE_NOT_AVAILABLE: "Size not available",
	
	/**
	  Returned by getMaximumSize() if this storage provider has no theoretical
	  limit on the amount of data it can store. 
	*/
	SIZE_NO_LIMIT: "No size limit",
	
	/** 
	  The namespace for all storage operations. This is useful if
	  several applications want access to the storage system from the same
	  domain but want different storage silos. 
	*/
	namespace: "dojoStorage",
	
	/**  
	  If a function is assigned to this property, then 
	  when the settings provider's UI is closed this
	  function is called. Useful, for example, if the
	  user has just cleared out all storage for this
	  provider using the settings UI, and you want to 
	  update your UI.
	*/
	onHideSettingsUI: null,

	/** 
	  Allows this storage provider to initialize itself. This is called
	  after the page has finished loading, so you can not do document.writes(). 
	*/
	initialize: function(){
	 dojo.unimplemented("dojo.storage.initialize");
	},
	
	/** 
	  Returns whether this storage provider is 
	  available on this platform. 
	
	  @returns True or false if this storage 
	  provider is supported.
	*/
	isAvailable: function(){
		dojo.unimplemented("dojo.storage.isAvailable");
	},
	
	/**
	  Puts a key and value into this storage system.

	  @param key A string key to use when retrieving 
	         this value in the future.
	  @param value A value to store; this can be 
	         any JavaScript type.
	  @param resultsHandler A callback function 
	         that will receive three arguments.
	         The first argument is one of three 
	         values: dojo.storage.SUCCESS,
	         dojo.storage.FAILED, or 
	         dojo.storage.PENDING; these values 
	         determine how the put request went. 
	         In some storage systems users can deny
	         a storage request, resulting in a 
	         dojo.storage.FAILED, while in 
	         other storage systems a storage 
	         request must wait for user approval,
	         resulting in a dojo.storage.PENDING 
	         status until the request
	         is either approved or denied, 
	         resulting in another call back
	         with dojo.storage.SUCCESS. 
  
	  The second argument in the call back is the key name
	  that was being stored.
	  
	  The third argument in the call back is an 
	  optional message that details possible error 
	  messages that might have occurred during
	  the storage process.

	  Example:
	    var resultsHandler = function(status, key, message){
	      alert("status="+status+", key="+key+", message="+message);
	    };
	    dojo.storage.put("test", "hello world", 
	                     resultsHandler);	
	*/
	put: function(key, value, resultsHandler){ 
    dojo.unimplemented("dojo.storage.put");
  },

	/**
	  Gets the value with the given key. Returns null
	  if this key is not in the storage system.
	
	  @param key A string key to get the value of.
	  @returns Returns any JavaScript object type; 
	  null if the key is not
	  present. 
	*/
	get: function(key){
    dojo.unimplemented("dojo.storage.get");
  },

	/**
	  Determines whether the storage has the given 
	  key. 
	
	    @returns Whether this key is 
	             present or not. 
	*/
	hasKey: function(key){
		if (this.get(key) != null)
			return true;
		else
			return false;
	},

	/**
	  Enumerates all of the available keys in 
	  this storage system.
	
	  @returns Array of string keys in this 
	           storage system.
	*/
	getKeys: function(){
    dojo.unimplemented("dojo.storage.getKeys");
  },

	/**
	  Completely clears this storage system of all 
	  of it's values and keys. 
	*/
	clear: function(){
    dojo.unimplemented("dojo.storage.clear");
  },
  
  /** Removes the given key from the storage system. */
  remove: function(key){
  	dojo.unimplemented("dojo.storage.remove");
  },

	/**
	  Returns whether this storage provider's 
	  values are persisted when this platform 
	  is shutdown. 
	
	  @returns True or false whether this 
	  storage is permanent. 
	*/
	isPermanent: function(){
		dojo.unimplemented("dojo.storage.isPermanent");
	},

	/**
	  The maximum storage allowed by this provider.
	
	  @returns Returns the maximum storage size 
	           supported by this provider, in 
	           thousands of bytes (i.e., if it 
	           returns 60 then this means that 60K 
	           of storage is supported).
	    
	           If this provider can not determine 
	           it's maximum size, then 
	           dojo.storage.SIZE_NOT_AVAILABLE is 
	           returned; if there is no theoretical
	           limit on the amount of storage 
	           this provider can return, then
	           dojo.storage.SIZE_NO_LIMIT is 
	           returned
	*/
	getMaximumSize: function(){
    dojo.unimplemented("dojo.storage.getMaximumSize");
  },

	/**
	  Determines whether this provider has a 
	  settings UI.
	
	  @returns True or false if this provider has 
	           the ability to show a
	           a settings UI to change it's 
	           values, change the amount of storage
	           available, etc. 
	*/
	hasSettingsUI: function(){
		return false;
	},

	/**
	  If this provider has a settings UI, it is 
	  shown. 
	*/
	showSettingsUI: function(){
	 dojo.unimplemented("dojo.storage.showSettingsUI");
	},

	/**
	  If this provider has a settings UI, hides
	  it.
	*/
	hideSettingsUI: function(){
	 dojo.unimplemented("dojo.storage.hideSettingsUI");
	},
	
	/** 
	  The provider name as a string, such as 
	  "dojo.storage.FlashStorageProvider". 
	*/
	getType: function(){
		dojo.unimplemented("dojo.storage.getType");
	},
	
	/**
	  Subclasses can call this to ensure that the key given is valid in a
	  consistent way across different storage providers. We use the lowest
	  common denominator for key values allowed: only letters, numbers, and
	  underscores are allowed. No spaces. 
	*/
	isValidKey: function(keyName){
		if (keyName == null || typeof keyName == "undefined")
			return false;
			
		return /^[0-9A-Za-z_]*$/.test(keyName);
  }
});




/**
	Initializes the storage systems and figures out the best available 
	storage options on this platform.
*/
dojo.storage.manager = new function(){
	this.currentProvider = null;
	this.available = false;
	this.initialized = false;
	this.providers = new Array();
	
	// TODO: Provide a way for applications to override the default namespace
	this.namespace = "dojo.storage";
	
	/** Initializes the storage system. */
	this.initialize = function(){
		// autodetect the best storage provider we can provide on this platform
		this.autodetect();
	}
	
	/**
	  Registers the existence of a new storage provider; used by subclasses
	  to inform the manager of their existence. 
	
	  @param name The full class name of this provider, such as 
	  "dojo.storage.browser.Flash6StorageProvider".
	  @param instance An instance of this provider, which we will use to
	  call isAvailable() on. 
	*/
	this.register = function(name, instance) {
		this.providers[this.providers.length] = instance;
		this.providers[name] = instance;
	}
	
	/**
	  Instructs the storageManager to use 
	  the given storage class for all storage requests.
	    
	  Example:
	    
	  dojo.storage.setProvider(
	         dojo.storage.browser.IEStorageProvider)
	*/
	this.setProvider = function(storageClass){
	
	}
	
	/** 
	  Autodetects the best possible persistent
	  storage provider available on this platform. 
	*/
	this.autodetect = function(){
		if(this.initialized == true) // already finished
			return;
			
		// go through each provider, seeing if it can be used
		var providerToUse = null;
		for(var i = 0; i < this.providers.length; i++) {
			providerToUse = this.providers[i];
			if(providerToUse.isAvailable()){
				break;
			}
		}	
		
		if(providerToUse == null){ // no provider available
			this.initialized = true;
			this.available = false;
			this.currentProvider = null;
			dojo.raise("No storage provider found for this platform");
		}
			
		// create this provider and copy over it's properties
		this.currentProvider = providerToUse;
	  	for(var i in providerToUse){
	  		dojo.storage[i] = providerToUse[i];
		}
		dojo.storage.manager = this;
		
		// have the provider initialize itself
		dojo.storage.initialize();
		
		this.initialized = true;
		this.available = true;
	}
	
	/** Returns whether any storage options are available. */
	this.isAvailable = function(){
		return this.available;
	}
	
	/** 
	 	Returns whether the storage system is initialized and
	 	ready to be used. 
	*/
	this.isInitialized = function(){
		// FIXME: This should _really_ not be in here, but it fixes a bug
		if(dojo.flash.ready == false){
			return false;
		}else{
			return this.initialized;
		}
	}

	/**
	  Determines if this platform supports
	  the given storage provider.
	
	  Example:
			
	  dojo.storage.manager.supportsProvider(
	    "dojo.storage.browser.InternetExplorerStorageProvider");
	*/
	this.supportsProvider = function(storageClass){
		// construct this class dynamically
		try{
			// dynamically call the given providers class level isAvailable()
			// method
			var provider = eval("new " + storageClass + "()");
			var results = provider.isAvailable();
			if(results == null || typeof results == "undefined")
				return false;
			return results;
		}catch (exception){
			dojo.debug("exception="+exception);
			return false;
		}
	}

	/** Gets the current provider. */
	this.getProvider = function(){
		return this.currentProvider;
	}
	
	/** 
	  The storage provider should call this method when it is loaded and
	  ready to be used. Clients who will use the provider will connect
	  to this method to know when they can use the storage system:
	
	  dojo.connect(dojo.storage.manager, "loaded", someInstance, 
	               someInstance.someMethod);
	*/
	this.loaded = function(){
	}
}

__CPAN_FILE__ src/style.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.style");
dojo.require("dojo.graphics.color");
dojo.require("dojo.uri.Uri");
dojo.require("dojo.lang.common");

(function(){
	var h = dojo.render.html;
	var ds = dojo.style;
	var db = document["body"]||document["documentElement"];

	ds.boxSizing = {
		MARGIN_BOX: "margin-box",
		BORDER_BOX: "border-box",
		PADDING_BOX: "padding-box",
		CONTENT_BOX: "content-box"
	};
	var bs = ds.boxSizing;
	
	ds.getBoxSizing = function(node){
		if((h.ie)||(h.opera)){ 
			var cm = document["compatMode"];
			if((cm == "BackCompat")||(cm == "QuirksMode")){ 
				return bs.BORDER_BOX; 
			}else{
				return bs.CONTENT_BOX; 
			}
		}else{
			if(arguments.length == 0){ node = document.documentElement; }
			var sizing = ds.getStyle(node, "-moz-box-sizing");
			if(!sizing){ sizing = ds.getStyle(node, "box-sizing"); }
			return (sizing ? sizing : bs.CONTENT_BOX);
		}
	}

	/*

	The following several function use the dimensions shown below

		+-------------------------+
		|  margin                 |
		| +---------------------+ |
		| |  border             | |
		| | +-----------------+ | |
		| | |  padding        | | |
		| | | +-------------+ | | |
		| | | |   content   | | | |
		| | | +-------------+ | | |
		| | +-|-------------|-+ | |
		| +-|-|-------------|-|-+ |
		+-|-|-|-------------|-|-|-+
		| | | |             | | | |
		| | | |<- content ->| | | |
		| |<------ inner ------>| |
		|<-------- outer -------->|
		+-------------------------+

		* content-box

		|m|b|p|             |p|b|m|
		| |<------ offset ----->| |
		| | |<---- client --->| | |
		| | | |<-- width -->| | | |

		* border-box

		|m|b|p|             |p|b|m|
		| |<------ offset ----->| |
		| | |<---- client --->| | |
		| |<------ width ------>| |
	*/

	/*
		Notes:

		General:
			- Uncomputable values are returned as NaN.
			- setOuterWidth/Height return *false* if the outer size could not
			  be computed, otherwise *true*.
			- (sjmiles) knows no way to find the calculated values for auto-margins. 
			- All returned values are floating point in 'px' units. If a
			  non-zero computed style value is not specified in 'px', NaN is
			  returned.

		FF:
			- styles specified as '0' (unitless 0) show computed as '0pt'.

		IE:
			- clientWidth/Height are unreliable (0 unless the object has 'layout').
			- margins must be specified in px, or 0 (in any unit) for any
			  sizing function to work. Otherwise margins detect as 'auto'.
			- padding can be empty or, if specified, must be in px, or 0 (in
			  any unit) for any sizing function to work.

		Safari:
			- Safari defaults padding values to 'auto'.

		See the unit tests for examples of (un)computable values in a given browser.

	*/

	// FIXME: these work for some elements (e.g. DIV) but not others (e.g. TABLE, TEXTAREA)

	ds.isBorderBox = function(node){
		return (ds.getBoxSizing(node) == bs.BORDER_BOX);
	}

	ds.getUnitValue = function(node, cssSelector, autoIsZero){
		var s = ds.getComputedStyle(node, cssSelector);
		if((!s)||((s == 'auto')&&(autoIsZero))){ return { value: 0, units: 'px' }; }
		if(dojo.lang.isUndefined(s)){return ds.getUnitValue.bad;}
		// FIXME: is regex inefficient vs. parseInt or some manual test? 
		var match = s.match(/(\-?[\d.]+)([a-z%]*)/i);
		if (!match){return ds.getUnitValue.bad;}
		return { value: Number(match[1]), units: match[2].toLowerCase() };
	}
	// FIXME: 'bad' value should be 0?
	ds.getUnitValue.bad = { value: NaN, units: '' };
	
	ds.getPixelValue = function(node, cssSelector, autoIsZero){
		var result = ds.getUnitValue(node, cssSelector, autoIsZero);
		// FIXME: there is serious debate as to whether or not this is the right solution
		if(isNaN(result.value)){ return 0; }
		// FIXME: code exists for converting other units to px (see Dean Edward's IE7) 
		// but there are cross-browser complexities
		if((result.value)&&(result.units != 'px')){ return NaN; }
		return result.value;
	}
	
	// FIXME: deprecated
	ds.getNumericStyle = function() {
		dojo.deprecated('dojo.(style|html).getNumericStyle', 'in favor of dojo.(style|html).getPixelValue', '0.4');
		return ds.getPixelValue.apply(this, arguments); 
	}

	ds.setPositivePixelValue = function(node, selector, value){
		if(isNaN(value)){return false;}
		node.style[selector] = Math.max(0, value) + 'px'; 
		return true;
	}
	
	ds._sumPixelValues = function(node, selectors, autoIsZero){
		var total = 0;
		for(var x=0; x<selectors.length; x++){
			total += ds.getPixelValue(node, selectors[x], autoIsZero);
		}
		return total;
	}

	ds.isPositionAbsolute = function(node){
		return (ds.getComputedStyle(node, 'position') == 'absolute');
	}

	ds.getBorderExtent = function(node, side){
		return (ds.getStyle(node, 'border-' + side + '-style') == 'none' ? 0 : ds.getPixelValue(node, 'border-' + side + '-width'));
	}

	ds.getMarginWidth = function(node){
		return ds._sumPixelValues(node, ["margin-left", "margin-right"], ds.isPositionAbsolute(node));
	}

	ds.getBorderWidth = function(node){
		return ds.getBorderExtent(node, 'left') + ds.getBorderExtent(node, 'right');
	}

	ds.getPaddingWidth = function(node){
		return ds._sumPixelValues(node, ["padding-left", "padding-right"], true);
	}

	ds.getPadBorderWidth = function(node) {
		return ds.getPaddingWidth(node) + ds.getBorderWidth(node);
	}
	
	ds.getContentBoxWidth = function(node){
		node = dojo.byId(node);
		return node.offsetWidth - ds.getPadBorderWidth(node);
	}

	ds.getBorderBoxWidth = function(node){
		node = dojo.byId(node);
		return node.offsetWidth;
	}

	ds.getMarginBoxWidth = function(node){
		return ds.getInnerWidth(node) + ds.getMarginWidth(node);
	}

	ds.setContentBoxWidth = function(node, pxWidth){
		node = dojo.byId(node);
		if (ds.isBorderBox(node)){
			pxWidth += ds.getPadBorderWidth(node);
		}
		return ds.setPositivePixelValue(node, "width", pxWidth);
	}

	ds.setMarginBoxWidth = function(node, pxWidth){
		node = dojo.byId(node);
		if (!ds.isBorderBox(node)){
			pxWidth -= ds.getPadBorderWidth(node);
		}
		pxWidth -= ds.getMarginWidth(node);
		return ds.setPositivePixelValue(node, "width", pxWidth);
	}

	// FIXME: deprecate and remove
	ds.getContentWidth = ds.getContentBoxWidth;
	ds.getInnerWidth = ds.getBorderBoxWidth;
	ds.getOuterWidth = ds.getMarginBoxWidth;
	ds.setContentWidth = ds.setContentBoxWidth;
	ds.setOuterWidth = ds.setMarginBoxWidth;

	ds.getMarginHeight = function(node){
		return ds._sumPixelValues(node, ["margin-top", "margin-bottom"], ds.isPositionAbsolute(node));
	}

	ds.getBorderHeight = function(node){
		return ds.getBorderExtent(node, 'top') + ds.getBorderExtent(node, 'bottom');
	}

	ds.getPaddingHeight = function(node){
		return ds._sumPixelValues(node, ["padding-top", "padding-bottom"], true);
	}

	ds.getPadBorderHeight = function(node) {
		return ds.getPaddingHeight(node) + ds.getBorderHeight(node);
	}
	
	ds.getContentBoxHeight = function(node){
		node = dojo.byId(node);
		return node.offsetHeight - ds.getPadBorderHeight(node);
	}

	ds.getBorderBoxHeight = function(node){
		node = dojo.byId(node);
		return node.offsetHeight; // FIXME: does this work?
	}

	ds.getMarginBoxHeight = function(node){
		return ds.getInnerHeight(node) + ds.getMarginHeight(node);
	}

	ds.setContentBoxHeight = function(node, pxHeight){
		node = dojo.byId(node);
		if (ds.isBorderBox(node)){
			pxHeight += ds.getPadBorderHeight(node);
		}
		return ds.setPositivePixelValue(node, "height", pxHeight);
	}

	ds.setMarginBoxHeight = function(node, pxHeight){
		node = dojo.byId(node);
		if (!ds.isBorderBox(node)){
			pxHeight -= ds.getPadBorderHeight(node);
		}
		pxHeight -= ds.getMarginHeight(node);
		return ds.setPositivePixelValue(node, "height", pxHeight);
	}

	// FIXME: deprecate and remove
	ds.getContentHeight = ds.getContentBoxHeight;
	ds.getInnerHeight = ds.getBorderBoxHeight;
	ds.getOuterHeight = ds.getMarginBoxHeight;
	ds.setContentHeight = ds.setContentBoxHeight;
	ds.setOuterHeight = ds.setMarginBoxHeight;

	/**
	 * dojo.style.getAbsolutePosition(xyz, true) returns xyz's position relative to the document.
	 * Itells you where you would position a node
	 * inside document.body such that it was on top of xyz.  Most people set the flag to true when calling
	 * getAbsolutePosition().
	 *
	 * dojo.style.getAbsolutePosition(xyz, false) returns xyz's position relative to the viewport.
	 * It returns the position that would be returned
	 * by event.clientX/Y if the mouse were directly over the top/left of this node.
	 */
	ds.getAbsolutePosition = ds.abs = function(node, includeScroll){
		node = dojo.byId(node);
		var ret = [];
		ret.x = ret.y = 0;
		var st = dojo.html.getScrollTop();
		var sl = dojo.html.getScrollLeft();

		if(h.ie){
			with(node.getBoundingClientRect()){
				ret.x = left-2;
				ret.y = top-2;
			}
		}else if(document.getBoxObjectFor){
			// mozilla
			var bo = document.getBoxObjectFor(node);
			ret.x = bo.x - ds.sumAncestorProperties(node, "scrollLeft");
			ret.y = bo.y - ds.sumAncestorProperties(node, "scrollTop");
		}else{
			if(node["offsetParent"]){
				var endNode;		
				// in Safari, if the node is an absolutely positioned child of
				// the body and the body has a margin the offset of the child
				// and the body contain the body's margins, so we need to end
				// at the body
				if(	(h.safari)&&
					(node.style.getPropertyValue("position") == "absolute")&&
					(node.parentNode == db)){
					endNode = db;
				}else{
					endNode = db.parentNode;
				}

				if(node.parentNode != db){
					var nd = node;
					if(window.opera){ nd = db; }
					ret.x -= ds.sumAncestorProperties(nd, "scrollLeft");
					ret.y -= ds.sumAncestorProperties(nd, "scrollTop");
				}
				do{
					var n = node["offsetLeft"];
					ret.x += isNaN(n) ? 0 : n;
					var m = node["offsetTop"];
					ret.y += isNaN(m) ? 0 : m;
					node = node.offsetParent;
				}while((node != endNode)&&(node != null));
			}else if(node["x"]&&node["y"]){
				ret.x += isNaN(node.x) ? 0 : node.x;
				ret.y += isNaN(node.y) ? 0 : node.y;
			}
		}

		// account for document scrolling!
		if(includeScroll){
			ret.y += st;
			ret.x += sl;
		}

		ret[0] = ret.x;
		ret[1] = ret.y;
		return ret;
	}

	ds.sumAncestorProperties = function(node, prop){
		node = dojo.byId(node);
		if(!node){ return 0; } // FIXME: throw an error?
		
		var retVal = 0;
		while(node){
			var val = node[prop];
			if(val){
				retVal += val - 0;
				if(node==document.body){ break; }// opera and khtml #body & #html has the same values, we only need one value
			}
			node = node.parentNode;
		}
		return retVal;
	}

	ds.getTotalOffset = function(node, type, includeScroll){
		return ds.abs(node, includeScroll)[(type == "top") ? "y" : "x"];
	}

	ds.getAbsoluteX = ds.totalOffsetLeft = function(node, includeScroll){
		return ds.getTotalOffset(node, "left", includeScroll);
	}

	ds.getAbsoluteY = ds.totalOffsetTop = function(node, includeScroll){
		return ds.getTotalOffset(node, "top", includeScroll);
	}

	ds.styleSheet = null;

	// FIXME: this is a really basic stub for adding and removing cssRules, but
	// it assumes that you know the index of the cssRule that you want to add 
	// or remove, making it less than useful.  So we need something that can 
	// search for the selector that you you want to remove.
	ds.insertCssRule = function(selector, declaration, index) {
		if (!ds.styleSheet) {
			if (document.createStyleSheet) { // IE
				ds.styleSheet = document.createStyleSheet();
			} else if (document.styleSheets[0]) { // rest
				// FIXME: should create a new style sheet here
				// fall back on an exsiting style sheet
				ds.styleSheet = document.styleSheets[0];
			} else { return null; } // fail
		}

		if (arguments.length < 3) { // index may == 0
			if (ds.styleSheet.cssRules) { // W3
				index = ds.styleSheet.cssRules.length;
			} else if (ds.styleSheet.rules) { // IE
				index = ds.styleSheet.rules.length;
			} else { return null; } // fail
		}

		if (ds.styleSheet.insertRule) { // W3
			var rule = selector + " { " + declaration + " }";
			return ds.styleSheet.insertRule(rule, index);
		} else if (ds.styleSheet.addRule) { // IE
			return ds.styleSheet.addRule(selector, declaration, index);
		} else { return null; } // fail
	}

	ds.removeCssRule = function(index){
		if(!ds.styleSheet){
			dojo.debug("no stylesheet defined for removing rules");
			return false;
		}
		if(h.ie){
			if(!index){
				index = ds.styleSheet.rules.length;
				ds.styleSheet.removeRule(index);
			}
		}else if(document.styleSheets[0]){
			if(!index){
				index = ds.styleSheet.cssRules.length;
			}
			ds.styleSheet.deleteRule(index);
		}
		return true;
	}

	// calls css by XmlHTTP and inserts it into DOM as <style [widgetType="widgetType"]> *downloaded cssText*</style>
	ds.insertCssFile = function(URI, doc, checkDuplicates){
		if(!URI){ return; }
		if(!doc){ doc = document; }
		var cssStr = dojo.hostenv.getText(URI);
		cssStr = ds.fixPathsInCssText(cssStr, URI);

		if(checkDuplicates){
			var styles = doc.getElementsByTagName("style");
			var cssText = "";
			for(var i = 0; i<styles.length; i++){
				cssText = (styles[i].styleSheet && styles[i].styleSheet.cssText) ? styles[i].styleSheet.cssText : styles[i].innerHTML;
				if(cssStr == cssText){ return; }
			}
		}

		var style = ds.insertCssText(cssStr);
		// insert custom attribute ex dbgHref="../foo.css" usefull when debugging in DOM inspectors, no?
		if(style && djConfig.isDebug){
			style.setAttribute("dbgHref", URI);
		}
		return style
	}

	// DomNode Style  = insertCssText(String ".dojoMenu {color: green;}"[, DomDoc document, dojo.uri.Uri Url ])
	ds.insertCssText = function(cssStr, doc, URI){
		if(!cssStr){ return; }
		if(!doc){ doc = document; }
		if(URI){// fix paths in cssStr
			cssStr = ds.fixPathsInCssText(cssStr, URI);
		}
		var style = doc.createElement("style");
		style.setAttribute("type", "text/css");
		// IE is b0rken enough to require that we add the element to the doc
		// before changing it's properties
		var head = doc.getElementsByTagName("head")[0];
		if(!head){ // must have a head tag 
			dojo.debug("No head tag in document, aborting styles");
			return;
		}else{
			head.appendChild(style);
		}
		if(style.styleSheet){// IE
			style.styleSheet.cssText = cssStr;
		}else{ // w3c
			var cssText = doc.createTextNode(cssStr);
			style.appendChild(cssText);
		}
		return style;
	}

	// String cssText = fixPathsInCssText(String cssStr, dojo.uri.Uri URI)
	// usage: cssText comes from dojoroot/src/widget/templates/HtmlFoobar.css
	// 	it has .dojoFoo { background-image: url(images/bar.png);} 
	//	then uri should point to dojoroot/src/widget/templates/
	ds.fixPathsInCssText = function(cssStr, URI){
		if(!cssStr || !URI){ return; }
		var pos = 0; var str = ""; var url = "";
		while(pos!=-1){
			pos = 0;url = "";
			pos = cssStr.indexOf("url(", pos);
			if(pos<0){ break; }
			str += cssStr.slice(0,pos+4);
			cssStr = cssStr.substring(pos+4, cssStr.length);
			url += cssStr.match(/^[\t\s\w()\/.\\'"-:#=&?]*\)/)[0]; // url string
			cssStr = cssStr.substring(url.length-1, cssStr.length); // remove url from css string til next loop
			url = url.replace(/^[\s\t]*(['"]?)([\w()\/.\\'"-:#=&?]*)\1[\s\t]*?\)/,"$2"); // clean string
			if(url.search(/(file|https?|ftps?):\/\//)==-1){
				url = (new dojo.uri.Uri(URI,url).toString());
			}
			str += url;
		};
		return str+cssStr;
	}

	ds.getBackgroundColor = function(node) {
		node = dojo.byId(node);
		var color;
		do{
			color = ds.getStyle(node, "background-color");
			// Safari doesn't say "transparent"
			if(color.toLowerCase() == "rgba(0, 0, 0, 0)") { color = "transparent"; }
			if(node == document.getElementsByTagName("body")[0]) { node = null; break; }
			node = node.parentNode;
		}while(node && dojo.lang.inArray(color, ["transparent", ""]));
		if(color == "transparent"){
			color = [255, 255, 255, 0];
		}else{
			color = dojo.graphics.color.extractRGB(color);
		}
		return color;
	}

	ds.getComputedStyle = function(node, cssSelector, inValue){
		node = dojo.byId(node);
		// cssSelector may actually be in camel case, so force selector version
		var cssSelector = ds.toSelectorCase(cssSelector);
		var property = ds.toCamelCase(cssSelector);
		if(!node || !node.style){
			return inValue;
		}else if(document.defaultView){ // W3, gecko, KHTML
			try{			
				var cs = document.defaultView.getComputedStyle(node, "");
				if (cs){ 
					return cs.getPropertyValue(cssSelector);
				} 
			}catch(e){ // reports are that Safari can throw an exception above
				if (node.style.getPropertyValue){ // W3
					return node.style.getPropertyValue(cssSelector);
				}else return inValue;
			}
		}else if(node.currentStyle){ // IE
			return node.currentStyle[property];
		}if(node.style.getPropertyValue){ // W3
			return node.style.getPropertyValue(cssSelector);
		}else{
			return inValue;
		}
	}

	/** 
	 * Retrieve a property value from a node's style object.
	 */
	ds.getStyleProperty = function(node, cssSelector){
		node = dojo.byId(node);
		// FIXME: should we use node.style.getPropertyValue over style[property]?
		// style[property] works in all (modern) browsers, getPropertyValue is W3 but not supported in IE
		// FIXME: what about runtimeStyle?
		return (node && node.style ? node.style[ds.toCamelCase(cssSelector)] : undefined);
	}

	/** 
	 * Retrieve a property value from a node's style object.
	 */
	ds.getStyle = function(node, cssSelector){
		var value = ds.getStyleProperty(node, cssSelector);
		return (value ? value : ds.getComputedStyle(node, cssSelector));
	}

	ds.setStyle = function(node, cssSelector, value){
		node = dojo.byId(node);
		if(node && node.style){
			var camelCased = ds.toCamelCase(cssSelector);
			node.style[camelCased] = value;
		}
	}

	ds.toCamelCase = function(selector) {
		var arr = selector.split('-'), cc = arr[0];
		for(var i = 1; i < arr.length; i++) {
			cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
		}
		return cc;		
	}

	ds.toSelectorCase = function(selector) {
		return selector.replace(/([A-Z])/g, "-$1" ).toLowerCase() ;
	}

	/* float between 0.0 (transparent) and 1.0 (opaque) */
	ds.setOpacity = function setOpacity(node, opacity, dontFixOpacity) {
		node = dojo.byId(node);
		if(!dontFixOpacity){
			if( opacity >= 1.0){
				if(h.ie){
					ds.clearOpacity(node);
					return;
				}else{
					opacity = 0.999999;
				}
			}else if( opacity < 0.0){ opacity = 0; }
		}
		if(h.ie){
			if(node.nodeName.toLowerCase() == "tr"){
				// FIXME: is this too naive? will we get more than we want?
				var tds = node.getElementsByTagName("td");
				for(var x=0; x<tds.length; x++){
					tds[x].style.filter = "Alpha(Opacity="+opacity*100+")";
				}
			}
			node.style.filter = "Alpha(Opacity="+opacity*100+")";
		}else if(h.moz){
			node.style.opacity = opacity; // ffox 1.0 directly supports "opacity"
			node.style.MozOpacity = opacity;
		}else if(h.safari){
			node.style.opacity = opacity; // 1.3 directly supports "opacity"
			node.style.KhtmlOpacity = opacity;
		}else{
			node.style.opacity = opacity;
		}
	}
		
	ds.getOpacity = function getOpacity (node){
		node = dojo.byId(node);
		if(h.ie){
			var opac = (node.filters && node.filters.alpha &&
				typeof node.filters.alpha.opacity == "number"
				? node.filters.alpha.opacity : 100) / 100;
		}else{
			var opac = node.style.opacity || node.style.MozOpacity ||
				node.style.KhtmlOpacity || 1;
		}
		return opac >= 0.999999 ? 1.0 : Number(opac);
	}

	ds.clearOpacity = function clearOpacity(node){
		node = dojo.byId(node);
		var ns = node.style;
		if(h.ie){
			try {
				if( node.filters && node.filters.alpha ){
					ns.filter = ""; // FIXME: may get rid of other filter effects
				}
			} catch(e) {
				/*
				 * IE7 gives error if node.filters not set;
				 * don't know why or how to workaround (other than this)
				 */
			}
		}else if(h.moz){
			ns.opacity = 1;
			ns.MozOpacity = 1;
		}else if(h.safari){
			ns.opacity = 1;
			ns.KhtmlOpacity = 1;
		}else{
			ns.opacity = 1;
		}
	}

	/** 
	* Set the given style attributes for the node. 
	* Patch submitted by Wolfram Kriesing, 22/03/2006.
	*
	* Ie. dojo.style.setStyleAttributes(myNode, "position:absolute; left:10px; top:10px;") 
	* This just makes it easier to set a style directly without the need to  
	* override it completely (as node.setAttribute() would). 
	* If there is a dojo-method for an attribute, like for "opacity" there 
	* is setOpacity, the dojo method is called instead. 
	* For example: dojo.style.setStyleAttributes(myNode, "opacity: .4"); 
	*  
	* Additionally all the dojo.style.set* methods can also be used. 
	* Ie. when attributes contains "outer-height: 10;" it will call dojo.style.setOuterHeight("10"); 
	* 
	* @param object The node to set the style attributes for. 
	* @param string Ie. "position:absolute; left:10px; top:10px;" 
	*/ 
	ds.setStyleAttributes = function(node, attributes) { 
		var methodMap={ 
			"opacity":dojo.style.setOpacity,
			"content-height":dojo.style.setContentHeight,
			"content-width":dojo.style.setContentWidth,
			"outer-height":dojo.style.setOuterHeight,
			"outer-width":dojo.style.setOuterWidth 
		} 

		var splittedAttribs=attributes.replace(/(;)?\s*$/, "").split(";"); 
		for(var i=0; i<splittedAttribs.length; i++){ 
			var nameValue=splittedAttribs[i].split(":"); 
			var name=nameValue[0].replace(/\s*$/, "").replace(/^\s*/, "").toLowerCase();
			var value=nameValue[1].replace(/\s*$/, "").replace(/^\s*/, "");
			if(dojo.lang.has(methodMap,name)) { 
				methodMap[name](node,value); 
			} else { 
				node.style[dojo.style.toCamelCase(name)]=value; 
			} 
		} 
	} 

	ds._toggle = function(node, tester, setter){
		node = dojo.byId(node);
		setter(node, !tester(node));
		return tester(node);
	}

	// show/hide are library constructs

	// show() 
	// if the node.style.display == 'none' then 
	// set style.display to '' or the value cached by hide()
	ds.show = function(node){
		node = dojo.byId(node);
		if(ds.getStyleProperty(node, 'display')=='none'){
			ds.setStyle(node, 'display', (node.dojoDisplayCache||''));
			node.dojoDisplayCache = undefined;	// cannot use delete on a node in IE6
		}
	}

	// if the node.style.display == 'none' then 
	// set style.display to '' or the value cached by hide()
	ds.hide = function(node){
		node = dojo.byId(node);
		if(typeof node["dojoDisplayCache"] == "undefined"){ // it could == '', so we cannot say !node.dojoDisplayCount
			var d = ds.getStyleProperty(node, 'display')
			if(d!='none'){
				node.dojoDisplayCache = d;
			}
		}
		ds.setStyle(node, 'display', 'none');
	}

	// setShowing() calls show() if showing is true, hide() otherwise
	ds.setShowing = function(node, showing){
		ds[(showing ? 'show' : 'hide')](node);
	}

	// isShowing() is true if the node.style.display is not 'none'
	// FIXME: returns true if node is bad, isHidden would be easier to make correct
	ds.isShowing = function(node){
		return (ds.getStyleProperty(node, 'display') != 'none');
	}

	// Call setShowing() on node with the complement of isShowing(), then return the new value of isShowing()
	ds.toggleShowing = function(node){
		return ds._toggle(node, ds.isShowing, ds.setShowing);
	}

	// display is a CSS concept

	// Simple mapping of tag names to display values
	// FIXME: simplistic 
	ds.displayMap = { tr: '', td: '', th: '', img: 'inline', span: 'inline', input: 'inline', button: 'inline' };

	// Suggest a value for the display property that will show 'node' based on it's tag
	ds.suggestDisplayByTagName = function(node)
	{
		node = dojo.byId(node);
		if(node && node.tagName){
			var tag = node.tagName.toLowerCase();
			return (tag in ds.displayMap ? ds.displayMap[tag] : 'block');
		}
	}

	// setDisplay() sets the value of style.display to value of 'display' parameter if it is a string.
	// Otherwise, if 'display' is false, set style.display to 'none'.
	// Finally, set 'display' to a suggested display value based on the node's tag
	ds.setDisplay = function(node, display){
		ds.setStyle(node, 'display', (dojo.lang.isString(display) ? display : (display ? ds.suggestDisplayByTagName(node) : 'none')));
	}

	// isDisplayed() is true if the the computed display style for node is not 'none'
	// FIXME: returns true if node is bad, isNotDisplayed would be easier to make correct
	ds.isDisplayed = function(node){
		return (ds.getComputedStyle(node, 'display') != 'none');
	}

	// Call setDisplay() on node with the complement of isDisplayed(), then
	// return the new value of isDisplayed()
	ds.toggleDisplay = function(node){
		return ds._toggle(node, ds.isDisplayed, ds.setDisplay);
	}

	// visibility is a CSS concept

	// setVisibility() sets the value of style.visibility to value of
	// 'visibility' parameter if it is a string.
	// Otherwise, if 'visibility' is false, set style.visibility to 'hidden'.
	// Finally, set style.visibility to 'visible'.
	ds.setVisibility = function(node, visibility){
		ds.setStyle(node, 'visibility', (dojo.lang.isString(visibility) ? visibility : (visibility ? 'visible' : 'hidden')));
	}

	// isVisible() is true if the the computed visibility style for node is not 'hidden'
	// FIXME: returns true if node is bad, isInvisible would be easier to make correct
	ds.isVisible = function(node){
		return (ds.getComputedStyle(node, 'visibility') != 'hidden');
	}

	// Call setVisibility() on node with the complement of isVisible(), then
	// return the new value of isVisible()
	ds.toggleVisibility = function(node){
		return ds._toggle(node, ds.isVisible, ds.setVisibility);
	}

	// in: coordinate array [x,y,w,h] or dom node
	// return: coordinate array
	ds.toCoordinateArray = function(coords, includeScroll) {
		if(dojo.lang.isArray(coords)){
			// coords is already an array (of format [x,y,w,h]), just return it
			while ( coords.length < 4 ) { coords.push(0); }
			while ( coords.length > 4 ) { coords.pop(); }
			var ret = coords;
		} else {
			// coords is an dom object (or dom object id); return it's coordinates
			var node = dojo.byId(coords);
			var pos = ds.getAbsolutePosition(node, includeScroll);
			var ret = [
				pos.x,
				pos.y,
				ds.getBorderBoxWidth(node),
				ds.getBorderBoxHeight(node)
			];
		}
		ret.x = ret[0];
		ret.y = ret[1];
		ret.w = ret[2];
		ret.h = ret[3];
		return ret;
	};
})();

__CPAN_FILE__ src/data.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data");

// currently a stub for dojo.data

dojo.data = {};

__CPAN_FILE__ src/svg.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.svg");
dojo.require("dojo.lang");
dojo.require("dojo.dom");

dojo.lang.mixin(dojo.svg, dojo.dom);

dojo.svg.graphics=dojo.svg.g=new function(/* DomDocument */ d){
	//	summary
	//	Singleton to encapsulate SVG rendering functions.
	this.suspend=function(){
		//	summary
		//	Suspend the rendering engine
		try { d.documentElement.suspendRedraw(0); } catch(e){ }
	};
	this.resume=function(){
		//	summary
		//	Resume the rendering engine
		try { d.documentElement.unsuspendRedraw(0); } catch(e){ }
	};
	this.force=function(){
		//	summary
		//	Force the render engine to redraw
		try { d.documentElement.forceRedraw(); } catch(e){ }
	};
}(document);

dojo.svg.animations=dojo.svg.anim=new function(/* DOMDocument */ d){
	//	summary
	//	Singleton to encapsulate SVG animation functionality.
	this.arePaused=function(){
		//	summary
		//	check to see if all animations are paused
		try {
			return d.documentElement.animationsPaused();	//	bool
		} catch(e){
			return false;	//	bool
		}
	} ;
	this.pause=function(){
		//	summary
		//	pause all animations
		try { d.documentElement.pauseAnimations(); } catch(e){ }
	};
	this.resume=function(){
		//	summary
		//	resume all animations
		try { d.documentElement.unpauseAnimations(); } catch(e){ }
	};
}(document);

//	fixme: these functions should be mixed in from dojo.style, but dojo.style is HTML-centric and needs to change.
dojo.svg.toCamelCase=function(/* string */ selector){
	//	summary
	//	converts a CSS-style selector to a camelCased one
	var arr=selector.split('-'), cc=arr[0];
	for(var i=1; i < arr.length; i++) {
		cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
	}
	return cc;	// string
};
dojo.svg.toSelectorCase=function(/* string */ selector) {
	//	summary
	//	converts a camelCased selector to a CSS style one
	return selector.replace(/([A-Z])/g, "-$1" ).toLowerCase();	//	string
};
dojo.svg.getStyle=function(/* SVGElement */ node, /* string */ cssSelector){
	//	summary
	//	get the computed style of selector for node.
	return document.defaultView.getComputedStyle(node, cssSelector);	//	object
};
dojo.svg.getNumericStyle=function(/* SVGElement */ node, /* string */ cssSelector){
	//	summary
	//	return the numeric version of the computed style of selector on node.
	return parseFloat(dojo.svg.getStyle(node, cssSelector));
};

//	fixme: there are different ways of doing the following, need to take into account
dojo.svg.getOpacity=function(/* SVGElement */node){
	//	summary
	//	Return the opacity of the passed element
	return Math.min(1.0, dojo.svg.getNumericStyle(node, "fill-opacity"));	//	float
};
dojo.svg.setOpacity=function(/* SVGElement */ node, /* float */ opacity){
	//	summary
	//	set the opacity of node using attributes.
	node.setAttributeNS(this.xmlns.svg, "fill-opacity", opacity);
	node.setAttributeNS(this.xmlns.svg, "stroke-opacity", opacity);
};
dojo.svg.clearOpacity=function(/* SVGElement */ node){
	//	summary
	//	Set any attributes setting opacity to opaque (1.0)
	node.setAttributeNS(this.xmlns.svg, "fill-opacity", "1.0");
	node.setAttributeNS(this.xmlns.svg, "stroke-opacity", "1.0");
};

/**
 *	Coordinates and dimensions.
 */

// TODO ////////////////////////////////////////////////////////// TODO
dojo.svg.getCoords=function(/* SVGElement */ node){
	if (node.getBBox) {
		var box=node.getBBox();
		return { x: box.x, y: box.y };
	}
	return null;
};
dojo.svg.setCoords=function(node, coords){
	var p=dojo.svg.getCoords();
	if (!p) return;
	var dx=p.x - coords.x;
	var dy=p.y - coords.y;
	dojo.svg.translate(node, dx, dy);
};
dojo.svg.getDimensions=function(node){
	if (node.getBBox){
		var box=node.getBBox();
		return { width: box.width, height : box.height };
	}
	return null;
};
dojo.svg.setDimensions=function(node, dim){
	//	will only support shape-based and container elements; path-based elements are ignored.
	if (node.width){
		node.width.baseVal.value=dim.width;
		node.height.baseVal.value=dim.height;
	}
	else if (node.r){
		node.r.baseVal.value=Math.min(dim.width, dim.height)/2;
	}
	else if (node.rx){
		node.rx.baseVal.value=dim.width/2;
		node.ry.baseVal.value=dim.height/2;
	}
};

/**
 *	Transformations.
 */
dojo.svg.translate=function(node, dx, dy){
	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
		var t=node.ownerSVGElement.createSVGTransform();
		t.setTranslate(dx, dy);
		node.transform.baseVal.appendItem(t);
	}
};
dojo.svg.scale=function(node, scaleX, scaleY){
	if (!scaleY) var scaleY=scaleX;
	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
		var t=node.ownerSVGElement.createSVGTransform();
		t.setScale(scaleX, scaleY);
		node.transform.baseVal.appendItem(t);
	}
};
dojo.svg.rotate=function(node, ang, cx, cy){
	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
		var t=node.ownerSVGElement.createSVGTransform();
		if (!cx) t.setMatrix(t.matrix.rotate(ang));
		else t.setRotate(ang, cx, cy);
		node.transform.baseVal.appendItem(t);
	}
};
dojo.svg.skew=function(node, ang, axis){
	var dir=axis || "x";
	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
		var t=node.ownerSVGElement.createSVGTransform();
		if (dir != "x") t.setSkewY(ang);
		else t.setSkewX(ang);
		node.transform.baseVal.appendItem(t);
	}
};
dojo.svg.flip=function(node, axis){
	var dir=axis || "x";
	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
		var t=node.ownerSVGElement.createSVGTransform();
		t.setMatrix((dir != "x") ? t.matrix.flipY() : t.matrix.flipX());
		node.transform.baseVal.appendItem(t);
	}
};
dojo.svg.invert=function(node){
	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
		var t=node.ownerSVGElement.createSVGTransform();
		t.setMatrix(t.matrix.inverse());
		node.transform.baseVal.appendItem(t);
	}
};
dojo.svg.applyMatrix=function(node, a, b, c, d, e, f){
	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
		var m;
		if (b){
			var m=node.ownerSVGElement.createSVGMatrix();
			m.a=a;
			m.b=b;
			m.c=c;
			m.d=d;
			m.e=e;
			m.f=f;
		} else m=a;
		var t=node.ownerSVGElement.createSVGTransform();
		t.setMatrix(m);
		node.transform.baseVal.appendItem(t);
	}
};

/**
 *	Grouping and z-index operations.
 */
dojo.svg.group=function(nodes){
	//	expect an array of nodes, attaches the group to the parent of the first node.
	var p=nodes.item(0).parentNode;
	var g=document.createElementNS(this.xmlns.svg, "g");
	for (var i=0; i < nodes.length; i++) g.appendChild(nodes.item(i));
	p.appendChild(g);
	return g;
};
dojo.svg.ungroup=function(g){
	//	puts the children of the group on the same level as group was.
	var p=g.parentNode;
	while (g.childNodes.length > 0) p.appendChild(g.childNodes.item(0));
	p.removeChild(g);
};
//	if the node is part of a group, return the group, else return null.
dojo.svg.getGroup=function(node){
	//	if the node is part of a group, return the group, else return null.
	var a=this.getAncestors(node);
	for (var i=0; i < a.length; i++){
		if (a[i].nodeType == this.ELEMENT_NODE && a[i].nodeName.toLowerCase() == "g")
			return a[i];
	}
	return null;
};
dojo.svg.bringToFront=function(node){
	var n=this.getGroup(node) || node;
	n.ownerSVGElement.appendChild(n);
};
dojo.svg.sendToBack=function(node){
	var n=this.getGroup(node) || node;
	n.ownerSVGElement.insertBefore(n, n.ownerSVGElement.firstChild);
};

//	TODO: possibly push node up a level in the DOM if it's at the beginning or end of the childNodes list.
dojo.svg.bringForward=function(node){
	var n=this.getGroup(node) || node;
	if (this.getLastChildElement(n.parentNode) != n){
		this.insertAfter(n, this.getNextSiblingElement(n), true);
	}
};
dojo.svg.sendBackward=function(node){
	var n=this.getGroup(node) || node;
	if (this.getFirstChildElement(n.parentNode) != n){
		this.insertBefore(n, this.getPreviousSiblingElement(n), true);
	}
};
// END TODO ////////////////////////////////////////////////////// TODO

dojo.svg.createNodesFromText=function(/* string */ txt, /* bool? */ wrap){
	//	summary
	//	Create a list of nodes from text
	var docFrag=(new DOMParser()).parseFromString(txt, "text/xml").normalize();
	if(wrap){ 
		return [docFrag.firstChild.cloneNode(true)];	//	array
	}
	var nodes=[];
	for(var x=0; x<docFrag.childNodes.length; x++){
		nodes.push(docFrag.childNodes.item(x).cloneNode(true));
	}
	return nodes;	// array
}
// vim:ts=4:noet:tw=0:

__CPAN_FILE__ src/validate.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.validate");
dojo.require("dojo.validate.common");

__CPAN_FILE__ src/crypto.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.crypto");

//	enumerations for use in crypto code. Note that 0 == default, for the most part.
dojo.crypto.cipherModes={ ECB:0, CBC:1, PCBC:2, CFB:3, OFB:4, CTR:5 };
dojo.crypto.outputTypes={ Base64:0,Hex:1,String:2,Raw:3 };

__CPAN_FILE__ src/regexp.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.regexp");
dojo.provide("dojo.regexp.us");

// *** Regular Expression Generators ***

/**
  Builds a RE that matches a top-level domain.

  @param flags  An object.
    flags.allowCC  Include 2 letter country code domains.  Default is true.
    flags.allowGeneric  Include the generic domains.  Default is true.
    flags.allowInfra  Include infrastructure domains.  Default is true.

  @return  A string for a regular expression for a top-level domain.
*/
dojo.regexp.tld = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.allowCC != "boolean") { flags.allowCC = true; }
	if (typeof flags.allowInfra != "boolean") { flags.allowInfra = true; }
	if (typeof flags.allowGeneric != "boolean") { flags.allowGeneric = true; }

	// Infrastructure top-level domain - only one at present
	var infraRE = "arpa";

	// Generic top-level domains RE.
	var genericRE = 
		"aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|xxx|jobs|mobi|post";
	
	// Country Code top-level domains RE
	var ccRE = 
		"ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|" +
		"bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|" +
		"ec|ee|eg|er|es|et|fi|fj|fk|fm|fo|fr|ga|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|" +
		"hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kr|kw|ky|kz|la|" +
		"lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|" +
		"mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|" +
		"ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sk|sl|sm|sn|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|" +
		"to|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw";

	// Build top-level domain RE
	var a = [];
	if (flags.allowInfra) { a.push(infraRE); }
	if (flags.allowGeneric) { a.push(genericRE); }
	if (flags.allowCC) { a.push(ccRE); }

	var tldRE = "";
	if (a.length > 0) {
		tldRE = "(" + a.join("|") + ")";
	}

	return tldRE;
}

/**
  Builds a RE that matches an IP Address.
  Supports 5 formats for IPv4: dotted decimal, dotted hex, dotted octal, decimal and hexadecimal.
  Supports 2 formats for Ipv6.

  @param flags  An object.  All flags are boolean with default = true.
    flags.allowDottedDecimal  Example, 207.142.131.235.  No zero padding.
    flags.allowDottedHex  Example, 0x18.0x11.0x9b.0x28.  Case insensitive.  Zero padding allowed.
    flags.allowDottedOctal  Example, 0030.0021.0233.0050.  Zero padding allowed.
    flags.allowDecimal  Example, 3482223595.  A decimal number between 0-4294967295.
    flags.allowHex  Example, 0xCF8E83EB.  Hexadecimal number between 0x0-0xFFFFFFFF.
      Case insensitive.  Zero padding allowed.
    flags.allowIPv6   IPv6 address written as eight groups of four hexadecimal digits.
    flags.allowHybrid   IPv6 address written as six groups of four hexadecimal digits
      followed by the usual 4 dotted decimal digit notation of IPv4. x:x:x:x:x:x:d.d.d.d

  @return  A string for a regular expression for an IP address.
*/
dojo.regexp.ipAddress = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.allowDottedDecimal != "boolean") { flags.allowDottedDecimal = true; }
	if (typeof flags.allowDottedHex != "boolean") { flags.allowDottedHex = true; }
	if (typeof flags.allowDottedOctal != "boolean") { flags.allowDottedOctal = true; }
	if (typeof flags.allowDecimal != "boolean") { flags.allowDecimal = true; }
	if (typeof flags.allowHex != "boolean") { flags.allowHex = true; }
	if (typeof flags.allowIPv6 != "boolean") { flags.allowIPv6 = true; }
	if (typeof flags.allowHybrid != "boolean") { flags.allowHybrid = true; }

	// decimal-dotted IP address RE.
	var dottedDecimalRE = 
		// Each number is between 0-255.  Zero padding is not allowed.
		"((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])";

	// dotted hex IP address RE.  Each number is between 0x0-0xff.  Zero padding is allowed, e.g. 0x00.
	var dottedHexRE = "(0[xX]0*[\\da-fA-F]?[\\da-fA-F]\\.){3}0[xX]0*[\\da-fA-F]?[\\da-fA-F]";

	// dotted octal IP address RE.  Each number is between 0000-0377.  
	// Zero padding is allowed, but each number must have at least 4 characters.
	var dottedOctalRE = "(0+[0-3][0-7][0-7]\\.){3}0+[0-3][0-7][0-7]";

	// decimal IP address RE.  A decimal number between 0-4294967295.  
	var decimalRE =  "(0|[1-9]\\d{0,8}|[1-3]\\d{9}|4[01]\\d{8}|42[0-8]\\d{7}|429[0-3]\\d{6}|" +
		"4294[0-8]\\d{5}|42949[0-5]\\d{4}|429496[0-6]\\d{3}|4294967[01]\\d{2}|42949672[0-8]\\d|429496729[0-5])";

	// hexadecimal IP address RE. 
	// A hexadecimal number between 0x0-0xFFFFFFFF. Case insensitive.  Zero padding is allowed.
	var hexRE = "0[xX]0*[\\da-fA-F]{1,8}";

	// IPv6 address RE. 
	// The format is written as eight groups of four hexadecimal digits, x:x:x:x:x:x:x:x,
	// where x is between 0000-ffff. Zero padding is optional. Case insensitive. 
	var ipv6RE = "([\\da-fA-F]{1,4}\\:){7}[\\da-fA-F]{1,4}";

	// IPv6/IPv4 Hybrid address RE. 
	// The format is written as six groups of four hexadecimal digits, 
	// followed by the 4 dotted decimal IPv4 format. x:x:x:x:x:x:d.d.d.d
	var hybridRE = "([\\da-fA-F]{1,4}\\:){6}" + 
		"((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])";

	// Build IP Address RE
	var a = [];
	if (flags.allowDottedDecimal) { a.push(dottedDecimalRE); }
	if (flags.allowDottedHex) { a.push(dottedHexRE); }
	if (flags.allowDottedOctal) { a.push(dottedOctalRE); }
	if (flags.allowDecimal) { a.push(decimalRE); }
	if (flags.allowHex) { a.push(hexRE); }
	if (flags.allowIPv6) { a.push(ipv6RE); }
	if (flags.allowHybrid) { a.push(hybridRE); }

	var ipAddressRE = "";
	if (a.length > 0) {
		ipAddressRE = "(" + a.join("|") + ")";
	}

	return ipAddressRE;
}

/**
  Builds a RE that matches a host.
	A host is a domain name or an IP address, possibly followed by a port number.

  @param flags  An object.
    flags.allowIP  Allow an IP address for hostname.  Default is true.
    flags.allowLocal  Allow the host to be "localhost".  Default is false.
    flags.allowPort  Allow a port number to be present.  Default is true.
    flags in regexp.ipAddress can be applied.
    flags in regexp.tld can be applied.

  @return  A string for a regular expression for a host.
*/
dojo.regexp.host = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.allowIP != "boolean") { flags.allowIP = true; }
	if (typeof flags.allowLocal != "boolean") { flags.allowLocal = false; }
	if (typeof flags.allowPort != "boolean") { flags.allowPort = true; }

	// Domain names can not end with a dash.
	var domainNameRE = "([0-9a-zA-Z]([-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?\\.)+" + dojo.regexp.tld(flags);

	// port number RE
	var portRE = ( flags.allowPort ) ? "(\\:" + dojo.regexp.integer({signed: false}) + ")?" : "";

	// build host RE
	var hostNameRE = domainNameRE;
	if (flags.allowIP) { hostNameRE += "|" +  dojo.regexp.ipAddress(flags); }
	if (flags.allowLocal) { hostNameRE += "|localhost"; }

	return "(" + hostNameRE + ")" + portRE;
}

/**
  Builds a regular expression that matches a URL.

  @param flags  An object.
    flags.scheme  Can be true, false, or [true, false]. 
      This means: required, not allowed, or match either one.
    flags in regexp.host can be applied.
    flags in regexp.ipAddress can be applied.
    flags in regexp.tld can be applied.

  @return  A string for a regular expression for a URL.
*/
dojo.regexp.url = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.scheme == "undefined") { flags.scheme = [true, false]; }

	// Scheme RE
	var protocalRE = dojo.regexp.buildGroupRE(flags.scheme,
		function(q) { if (q) { return "(https?|ftps?)\\://"; }  return ""; }
	);

	// Path and query and anchor RE
	var pathRE = "(/([^?#\\s/]+/)*)?([^?#\\s/]+(\\?[^?#\\s/]*)?(#[A-Za-z][\\w.:-]*)?)?";

	return (protocalRE + dojo.regexp.host(flags) + pathRE);
}

/**
  Builds a regular expression that matches an email address.

  @param flags  An object.
    flags.allowCruft  Allow address like <mailto:foo@yahoo.com>.  Default is false.
    flags in regexp.host can be applied.
    flags in regexp.ipAddress can be applied.
    flags in regexp.tld can be applied.

  @return  A string for a regular expression for an email address.
*/
dojo.regexp.emailAddress = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.allowCruft != "boolean") { flags.allowCruft = false; }
	flags.allowPort = false; // invalid in email addresses

	// user name RE - apostrophes are valid if there's not 2 in a row
	var usernameRE = "([\\da-z]+[-._+&'])*[\\da-z]+";

	// build emailAddress RE
	var emailAddressRE = usernameRE + "@" + dojo.regexp.host(flags);

	// Allow email addresses with cruft
	if ( flags.allowCruft ) {
		emailAddressRE = "<?(mailto\\:)?" + emailAddressRE + ">?";
	}

	return emailAddressRE;
}

/**
  Builds a regular expression that matches a list of email addresses.

  @param flags  An object.
    flags.listSeparator  The character used to separate email addresses.  Default is ";", ",", "\n" or " ".
    flags in regexp.emailAddress can be applied.
    flags in regexp.host can be applied.
    flags in regexp.ipAddress can be applied.
    flags in regexp.tld can be applied.

  @return  A string for a regular expression for an email address list.
*/
dojo.regexp.emailAddressList = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.listSeparator != "string") { flags.listSeparator = "\\s;,"; }

	// build a RE for an Email Address List
	var emailAddressRE = dojo.regexp.emailAddress(flags);
	var emailAddressListRE = "(" + emailAddressRE + "\\s*[" + flags.listSeparator + "]\\s*)*" + 
		emailAddressRE + "\\s*[" + flags.listSeparator + "]?\\s*";

	return emailAddressListRE;
}

/**
  Builds a regular expression that matches an integer.

  @param flags  An object.
    flags.signed  The leading plus-or-minus sign.  Can be true, false, or [true, false].
      Default is [true, false], (i.e. will match if it is signed or unsigned).
    flags.separator  The character used as the thousands separator.  Default is no separator.
      For more than one symbol use an array, e.g. [",", ""], makes ',' optional.

  @return  A string for a regular expression for an integer.
*/
dojo.regexp.integer = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.signed == "undefined") { flags.signed = [true, false]; }
	if (typeof flags.separator == "undefined") { flags.separator = ""; }

	// build sign RE
	var signRE = dojo.regexp.buildGroupRE(flags.signed,
		function(q) { if (q) { return "[-+]"; }  return ""; }
	);

	// number RE
	var numberRE = dojo.regexp.buildGroupRE(flags.separator,
		function(sep) { 
			if ( sep == "" ) { 
				return "(0|[1-9]\\d*)"; 
			}
			return "(0|[1-9]\\d{0,2}([" + sep + "]\\d{3})*)"; 
		}
	);
	var numberRE;

	// integer RE
	return (signRE + numberRE);
}

/**
  Builds a regular expression to match a real number in exponential notation.

  @param flags  An object.
    flags.places  The integer number of decimal places.
      If not given, the decimal part is optional and the number of places is unlimited.
    flags.decimal  A string for the character used as the decimal point.  Default is ".".
    flags.exponent  Express in exponential notation.  Can be true, false, or [true, false].
      Default is [true, false], (i.e. will match if the exponential part is present are not).
    flags.eSigned  The leading plus-or-minus sign on the exponent.  Can be true, false, 
      or [true, false].  Default is [true, false], (i.e. will match if it is signed or unsigned).
    flags in regexp.integer can be applied.

  @return  A string for a regular expression for a real number.
*/
dojo.regexp.realNumber = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.places != "number") { flags.places = Infinity; }
	if (typeof flags.decimal != "string") { flags.decimal = "."; }
	if (typeof flags.exponent == "undefined") { flags.exponent = [true, false]; }
	if (typeof flags.eSigned == "undefined") { flags.eSigned = [true, false]; }

	// integer RE
	var integerRE = dojo.regexp.integer(flags);

	// decimal RE
	var decimalRE = "";
	if ( flags.places == Infinity) { 
		decimalRE = "(\\" + flags.decimal + "\\d+)?"; 
	}
	else if ( flags.places > 0) { 
		decimalRE = "\\" + flags.decimal + "\\d{" + flags.places + "}"; 
	}

	// exponent RE
	var exponentRE = dojo.regexp.buildGroupRE(flags.exponent,
		function(q) { 
			if (q) { return "([eE]" + dojo.regexp.integer({signed: flags.eSigned}) + ")"; }
			return ""; 
		}
	);

	// real number RE
	return (integerRE + decimalRE + exponentRE);
}

/**
  Builds a regular expression to match a monetary value.

  @param flags  An object.
    flags.signed  The leading plus-or-minus sign.  Can be true, false, or [true, false].
      Default is [true, false], (i.e. will match if it is signed or unsigned).
    flags.symbol  A currency symbol such as Yen "ï¿½", Pound "ï¿½", or the Euro sign "ï¿½".  
      Default is "$".  For more than one symbol use an array, e.g. ["$", ""], makes $ optional.
    flags.placement  The symbol can come "before" the number or "after".  Default is "before".
    flags.separator  The character used as the thousands separator. The default is ",".
    flags.cents  The two decimal places for cents.  Can be true, false, or [true, false].
      Default is [true, false], (i.e. will match if cents are present are not).
    flags.decimal  A string for the character used as the decimal point.  Default is ".".

  @return  A string for a regular expression for a monetary value.
*/
dojo.regexp.currency = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.signed == "undefined") { flags.signed = [true, false]; }
	if (typeof flags.symbol == "undefined") { flags.symbol = "$"; }
	if (typeof flags.placement != "string") { flags.placement = "before"; }
	if (typeof flags.separator != "string") { flags.separator = ","; }
	if (typeof flags.cents == "undefined") { flags.cents = [true, false]; }
	if (typeof flags.decimal != "string") { flags.decimal = "."; }

	// build sign RE
	var signRE = dojo.regexp.buildGroupRE(flags.signed,
		function(q) { if (q) { return "[-+]"; }  return ""; }
	);

	// build symbol RE
	var symbolRE = dojo.regexp.buildGroupRE(flags.symbol,
		function(symbol) { 
			// escape all special characters
			return "\\s?" + symbol.replace( /([.$?*!=:|\\\/^])/g, "\\$1") + "\\s?";
		}
	);

	// number RE
	var numberRE = dojo.regexp.integer( {signed: false, separator: flags.separator} );

	// build cents RE
	var centsRE = dojo.regexp.buildGroupRE(flags.cents,
		function(q) { if (q) { return "(\\" + flags.decimal + "\\d\\d)"; }  return ""; }
	);

	// build currency RE
	var currencyRE;
	if (flags.placement == "before") {
		currencyRE = signRE + symbolRE + numberRE + centsRE;
	}
	else {
		currencyRE = signRE + numberRE + centsRE + symbolRE;
	}

	return currencyRE;
}

/**
  A regular expression to match US state and territory abbreviations.

  @param flags  An object.
    flags.allowTerritories  Allow Guam, Puerto Rico, etc.  Default is true.
    flags.allowMilitary  Allow military 'states', e.g. Armed Forces Europe (AE).  Default is true.

  @return  A string for a regular expression for a US state.
*/
dojo.regexp.us.state = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.allowTerritories != "boolean") { flags.allowTerritories = true; }
	if (typeof flags.allowMilitary != "boolean") { flags.allowMilitary = true; }

	// state RE
	var statesRE = 
		"AL|AK|AZ|AR|CA|CO|CT|DE|DC|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|" + 
		"NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY";

	// territories RE
	var territoriesRE = "AS|FM|GU|MH|MP|PW|PR|VI";

	// military states RE
	var militaryRE = "AA|AE|AP";

	// Build states and territories RE
	if (flags.allowTerritories) { statesRE += "|" + territoriesRE; }
	if (flags.allowMilitary) { statesRE += "|" + militaryRE; }

	return "(" + statesRE + ")";
}

/**
  Builds a regular expression to match any International format for time.
  The RE can match one format or one of multiple formats.

  Format
  h        12 hour, no zero padding.
  hh       12 hour, has leading zero.
  H        24 hour, no zero padding.
  HH       24 hour, has leading zero.
  m        minutes, no zero padding.
  mm       minutes, has leading zero.
  s        seconds, no zero padding.
  ss       seconds, has leading zero.
  t        am or pm, case insensitive.
  All other characters must appear literally in the expression.

  Example
    "h:m:s t"  ->   2:5:33 PM
    "HH:mm:ss" ->  14:05:33

  @param flags  An object.
    flags.format  A string or an array of strings.  Default is "h:mm:ss t".
    flags.amSymbol  The symbol used for AM.  Default is "AM".
    flags.pmSymbol  The symbol used for PM.  Default is "PM".

  @return  A string for a regular expression for a time value.
*/
dojo.regexp.time = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.format == "undefined") { flags.format = "h:mm:ss t"; }
	if (typeof flags.amSymbol != "string") { flags.amSymbol = "AM"; }
	if (typeof flags.pmSymbol != "string") { flags.pmSymbol = "PM"; }

	// Converts a time format to a RE
	var timeRE = function(format) {
		// escape all special characters
		format = format.replace( /([.$?*!=:|{}\(\)\[\]\\\/^])/g, "\\$1");
		var amRE = flags.amSymbol.replace( /([.$?*!=:|{}\(\)\[\]\\\/^])/g, "\\$1");
		var pmRE = flags.pmSymbol.replace( /([.$?*!=:|{}\(\)\[\]\\\/^])/g, "\\$1");

		// replace tokens with Regular Expressions
		format = format.replace("hh", "(0[1-9]|1[0-2])");
		format = format.replace("h", "([1-9]|1[0-2])");
		format = format.replace("HH", "([01][0-9]|2[0-3])");
		format = format.replace("H", "([0-9]|1[0-9]|2[0-3])");
		format = format.replace("mm", "([0-5][0-9])");
		format = format.replace("m", "([1-5][0-9]|[0-9])");
		format = format.replace("ss", "([0-5][0-9])");
		format = format.replace("s", "([1-5][0-9]|[0-9])");
		format = format.replace("t", "\\s?(" + amRE + "|" + pmRE + ")\\s?" );

		return format;
	};

	// build RE for multiple time formats
	return dojo.regexp.buildGroupRE(flags.format, timeRE);
}

/**
  Builds a regular expression to match any sort of number based format.
  Use it for phone numbers, social security numbers, zip-codes, etc.
  The RE can match one format or one of multiple formats.

  Format
    #        Stands for a digit, 0-9.
    ?        Stands for an optional digit, 0-9 or nothing.
    All other characters must appear literally in the expression.

  Example   
    "(###) ###-####"       ->   (510) 542-9742
    "(###) ###-#### x#???" ->   (510) 542-9742 x153
    "###-##-####"          ->   506-82-1089       i.e. social security number
    "#####-####"           ->   98225-1649        i.e. zip code

  @param flags  An object.
    flags.format  A string or an Array of strings for multiple formats.
  @return  A string for a regular expression for the number format(s).
*/
dojo.regexp.numberFormat = function(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.format == "undefined") { flags.format = "###-###-####"; }

	// Converts a number format to RE.
	var digitRE = function(format) {
		// escape all special characters, except '?'
		format = format.replace( /([.$*!=:|{}\(\)\[\]\\\/^])/g, "\\$1");

		// Now replace '?' with Regular Expression
		format = format.replace(/\?/g, "\\d?");

		// replace # with Regular Expression
		format = format.replace(/#/g, "\\d");

		return format;
	};

	// build RE for multiple number formats
	return dojo.regexp.buildGroupRE(flags.format, digitRE);
}


/**
  This is basically a utility function used by some of the RE generators.
  Builds a regular expression that groups subexpressions.
  The subexpressions are constructed by the function, re, in the second parameter.
  re builds one subexpression for each elem in the array a, in the first parameter.

  @param a  A single value or an array of values.
  @param re  A function.  Takes one parameter and converts it to a regular expression. 
  @return  A string for a regular expression that groups all the subexpressions.
*/
dojo.regexp.buildGroupRE = function(a, re) {

	// case 1: a is a single value.
	if ( !( a instanceof Array ) ) { 
		return re(a);
	}

	// case 2: a is an array
	var b = [];
	for (var i = 0; i < a.length; i++) {
		// convert each elem to a RE
		b.push(re(a[i]));
	}

	 // join the REs as alternatives in a RE group.
	return "(" + b.join("|") + ")";
}

__CPAN_FILE__ src/hostenv_rhino.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/*
* Rhino host environment
*/

// make jsc shut up (so we can use jsc for sanity checking) 
/*@cc_on
@if (@_jscript_version >= 7)
var loadClass; var print; var load; var quit; var version; var Packages; var java;
@end
@*/

// TODO: not sure what we gain from the next line, anyone?
//if (typeof loadClass == 'undefined') { dojo.raise("attempt to use Rhino host environment when no 'loadClass' global"); }

dojo.render.name = dojo.hostenv.name_ = 'rhino';
dojo.hostenv.getVersion = function() {return version()};

// see comments in spidermonkey loadUri
dojo.hostenv.loadUri = function(uri, cb){
	dojo.debug("uri: "+uri);
	try{
		// FIXME: what about remote URIs?
		var found = true;
		if(!(new java.io.File(uri)).exists()){
			try{
				// try it as a file first, URL second
				(new java.io.URL(uri)).openStream();
			}catch(e){
				found = false;
			}
		}
		if(!found){
			dojo.debug(uri+" does not exist");
			if(cb){ cb(0); }
			return 0;
		}
		var ok = load(uri);
		// dojo.debug(typeof ok);
		dojo.debug("rhino load('", uri, "') returned. Ok: ", ok);
		if(cb){ cb(1); }
		return 1;
	}catch(e){
		dojo.debug("rhino load('", uri, "') failed");
		if(cb){ cb(0); }
		return 0;
	}
}

dojo.hostenv.println = print;
dojo.hostenv.exit = function(exitcode){ 
	quit(exitcode);
}

// Hack to determine current script...
//
// These initial attempts failed:
//   1. get an EcmaError and look at e.getSourceName(): try {eval ("static in return")} catch(e) { ...
//   Won't work because NativeGlobal.java only does a put of "name" and "message", not a wrapped reflecting object.
//   Even if the EcmaError object had the sourceName set.
//  
//   2. var e = Packages.org.mozilla.javascript.Context.getCurrentContext().reportError('');
//   Won't work because it goes directly to the errorReporter, not the return value.
//   We want context.interpreterSourceFile and context.interpreterLine, which are used in static Context.getSourcePositionFromStack
//   (set by Interpreter.java at interpretation time, if in interpreter mode).
//
//   3. var e = Packages.org.mozilla.javascript.Context.getCurrentContext().reportRuntimeError('');
//   This returns an object, but e.message still does not have source info.
//   In compiler mode, perhaps not set; in interpreter mode, perhaps not used by errorReporter?
//
// What we found works is to do basically the same hack as is done in getSourcePositionFromStack,
// making a new java.lang.Exception() and then calling printStackTrace on a string stream.
// We have to parse the string for the .js files (different from the java files).
// This only works however in compiled mode (-opt 0 or higher).
// In interpreter mode, entire stack is java.
// When compiled, printStackTrace is like:
// java.lang.Exception
//	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
//	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
//	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
//	at java.lang.reflect.Constructor.newInstance(Constructor.java:274)
//	at org.mozilla.javascript.NativeJavaClass.constructSpecific(NativeJavaClass.java:228)
//	at org.mozilla.javascript.NativeJavaClass.construct(NativeJavaClass.java:185)
//	at org.mozilla.javascript.ScriptRuntime.newObject(ScriptRuntime.java:1269)
//	at org.mozilla.javascript.gen.c2.call(/Users/mda/Sites/burstproject/testrhino.js:27)
//    ...
//	at org.mozilla.javascript.tools.shell.Main.main(Main.java:76)
//
// Note may get different answers based on:
//    Context.setOptimizationLevel(-1)
//    Context.setGeneratingDebug(true)
//    Context.setGeneratingSource(true) 
//
// Some somewhat helpful posts:
//    http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=9v9n0g%246gr1%40ripley.netscape.com
//    http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=3BAA2DC4.6010702%40atg.com
//
// Note that Rhino1.5R5 added source name information in some exceptions.
// But this seems not to help in command-line Rhino, because Context.java has an error reporter
// so no EvaluationException is thrown.

// do it by using java java.lang.Exception
function dj_rhino_current_script_via_java(depth) {
    var optLevel = Packages.org.mozilla.javascript.Context.getCurrentContext().getOptimizationLevel();  
    if (optLevel == -1) dojo.unimplemented("getCurrentScriptURI (determine current script path for rhino when interpreter mode)", '');
    var caw = new java.io.CharArrayWriter();
    var pw = new java.io.PrintWriter(caw);
    var exc = new java.lang.Exception();
    var s = caw.toString();
    // we have to exclude the ones with or without line numbers because they put double entries in:
    //   at org.mozilla.javascript.gen.c3._c4(/Users/mda/Sites/burstproject/burst/Runtime.js:56)
    //   at org.mozilla.javascript.gen.c3.call(/Users/mda/Sites/burstproject/burst/Runtime.js)
    var matches = s.match(/[^\(]*\.js\)/gi);
    if(!matches){
		throw Error("cannot parse printStackTrace output: " + s);
	}

    // matches[0] is entire string, matches[1] is this function, matches[2] is caller, ...
    var fname = ((typeof depth != 'undefined')&&(depth)) ? matches[depth + 1] : matches[matches.length - 1];
    var fname = matches[3];
	if(!fname){ fname = matches[1]; }
    // print("got fname '" + fname + "' from stack string '" + s + "'");
    if (!fname) throw Error("could not find js file in printStackTrace output: " + s);
    //print("Rhino getCurrentScriptURI returning '" + fname + "' from: " + s); 
    return fname;
}

// UNUSED: leverage new support in native exception for getSourceName
/*
function dj_rhino_current_script_via_eval_exception() {
    var exc;
    // 'ReferenceError: "undefinedsymbol" is not defined.'
    try {eval ("undefinedsymbol()") } catch(e) {exc = e;}
    // 'Error: whatever'
    // try{throw Error("whatever");} catch(e) {exc = e;}
    // 'SyntaxError: identifier is a reserved word'
    // try {eval ("static in return")} catch(e) { exc = e; }
    print("got exception: '" + exc + "'");
    print("exc.stack=" + (typeof exc.stack));
    var sn = exc.getSourceName();
    print("SourceName=" + sn);
    return sn;
} 
*/

// reading a file from disk in Java is a humiliating experience by any measure.
// Lets avoid that and just get the freaking text
function readText(uri){
	// NOTE: we intentionally avoid handling exceptions, since the caller will
	// want to know
	var jf = new java.io.File(uri);
	var sb = new java.lang.StringBuffer();
	var input = new java.io.BufferedReader(new java.io.FileReader(jf));
	var line = "";
	while((line = input.readLine()) != null){
		sb.append(line);
		sb.append(java.lang.System.getProperty("line.separator"));
	}
	return sb.toString();
}

// call this now because later we may not be on the top of the stack
if(!djConfig.libraryScriptUri.length){
	try{
		djConfig.libraryScriptUri = dj_rhino_current_script_via_java(1);
	}catch(e){
		// otherwise just fake it
		if(djConfig["isDebug"]){
			print("\n");
			print("we have no idea where Dojo is located from.");
			print("Please try loading rhino in a non-interpreted mode or set a");
			print("\n	djConfig.libraryScriptUri\n");
			print("Setting the dojo path to './'");
			print("This is probably wrong!");
			print("\n");
			print("Dojo will try to load anyway");
		}
		djConfig.libraryScriptUri = "./";
	}
}


__CPAN_FILE__ src/lang.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lang");
dojo.provide("dojo.lang.Lang");

dojo.require("dojo.lang.common");

__CPAN_FILE__ src/bootstrap1.js
/**
* @file bootstrap1.js
*
* summary: First file that is loaded that 'bootstraps' the entire dojo library suite.
* note:  Must run before hostenv_*.js file.
*
* @author  Copyright 2004 Mark D. Anderson (mda@discerning.com)
* TODOC: should the copyright be changed to Dojo Foundation?
* @license Licensed under the Academic Free License 2.1 http://www.opensource.org/licenses/afl-2.1.php
*
* $Id: bootstrap1.js 4342 2006-06-11 23:03:30Z alex $
*/

// TODOC: HOW TO DOC THE BELOW?
// @global: djConfig
// summary:  
//		Application code can set the global 'djConfig' prior to loading
//		the library to override certain global settings for how dojo works.  
// description:  The variables that can be set are as follows:
//			- isDebug: false
//			- allowQueryConfig: false
//			- baseScriptUri: ""
//			- baseRelativePath: ""
//			- libraryScriptUri: ""
//			- iePreventClobber: false
//			- ieClobberMinimal: true
//			- preventBackButtonFix: true
//			- searchIds: []
//			- parseWidgets: true
// TODOC: HOW TO DOC THESE VARIABLES?
// TODOC: IS THIS A COMPLETE LIST?
// note:
//		'djConfig' does not exist under 'dojo.*' so that it can be set before the 
//		'dojo' variable exists.  
// note:
//		Setting any of these variables *after* the library has loaded does nothing at all. 
// TODOC: is this still true?  Release notes for 0.3 indicated they could be set after load.
//



//TODOC:  HOW TO DOC THIS?
// @global: dj_global
// summary: 
//		an alias for the top-level global object in the host environment
//		(e.g., the window object in a browser).
// description:  
//		Refer to 'dj_global' rather than referring to window to ensure your
//		code runs correctly in contexts other than web browsers (eg: Rhino on a server).
var dj_global = this;



function dj_undef(/*String*/ name, /*Object?*/ object){
	//summary: Returns true if 'name' is defined on 'object' (or globally if 'object' is null).
	//description: Note that 'defined' and 'exists' are not the same concept.
	if(object==null){ object = dj_global; }
	// exception if object is not an Object
	return (typeof object[name] == "undefined");	// Boolean
}


// make sure djConfig is defined
if(dj_undef("djConfig")){ 
	var djConfig = {}; 
}


//TODOC:  HOW TO DOC THIS?
// dojo is the root variable of (almost all) our public symbols -- make sure it is defined.
if(dj_undef("dojo")){ 
	var dojo = {}; 
}

//TODOC:  HOW TO DOC THIS?
dojo.version = {
	// summary: version number of this instance of dojo.
	major: 0, minor: 3, patch: 1, flag: "",
	revision: Number("$Rev: 4342 $".match(/[0-9]+/)[0]),
	toString: function(){
		with(dojo.version){
			return major + "." + minor + "." + patch + flag + " (" + revision + ")";	// String
		}
	}
}

dojo.evalProp = function(/*String*/ name, /*Object*/ object, /*Boolean?*/ create){
	// summary: Returns 'object[name]'.  If not defined and 'create' is true, will return a new Object.
	// description: 
	//		Returns null if 'object[name]' is not defined and 'create' is not true.
	// 		Note: 'defined' and 'exists' are not the same concept.	
	return (object && !dj_undef(name, object) ? object[name] : (create ? (object[name]={}) : undefined));	// mixed
}


dojo.parseObjPath = function(/*String*/ path, /*Object?*/ context, /*Boolean?*/ create){
	// summary: Parse string path to an object, and return corresponding object reference and property name.
	// description: 
	//		Returns an object with two properties, 'obj' and 'prop'.  
	//		'obj[prop]' is the reference indicated by 'path'.
	// path: Path to an object, in the form "A.B.C".
	// context: Object to use as root of path.  Defaults to 'dj_global'.
	// create: If true, Objects will be created at any point along the 'path' that is undefined.
	var object = (context != null ? context : dj_global);
	var names = path.split('.');
	var prop = names.pop();
	for (var i=0,l=names.length;i<l && object;i++){
		object = dojo.evalProp(names[i], object, create);
	}
	return {obj: object, prop: prop};	// Object: {obj: Object, prop: String}
}


dojo.evalObjPath = function(/*String*/ path, /*Boolean?*/ create){
	// summary: Return the value of object at 'path' in the global scope, without using 'eval()'.
	// path: Path to an object, in the form "A.B.C".
	// create: If true, Objects will be created at any point along the 'path' that is undefined.
	if(typeof path != "string"){ 
		return dj_global; 
	}
	// fast path for no periods
	if(path.indexOf('.') == -1){
		return dojo.evalProp(path, dj_global, create);		// mixed
	}

	//MOW: old 'with' syntax was confusing and would throw an error if parseObjPath returned null.
	var ref = dojo.parseObjPath(path, dj_global, create);
	if(ref){
		return dojo.evalProp(ref.prop, ref.obj, create);	// mixed
	}
	return null;
}

// ****************************************************************
// global public utils
// TODOC: DO WE WANT TO NOTE THAT THESE ARE GLOBAL PUBLIC UTILS?
// ****************************************************************

dojo.errorToString = function(/*Error*/ exception){
	// summary: Return an exception's 'message', 'description' or text.

	// TODO: overriding Error.prototype.toString won't accomplish this?
 	// 		... since natively generated Error objects do not always reflect such things?
	if(!dj_undef("message", exception)){
		return exception.message;		// String
	}else if(!dj_undef("description", exception)){
		return exception.description;	// String
	}else{
		return exception;				// Error
	}
}


dojo.raise = function(/*String*/ message, /*Error?*/ exception){
	// summary: Throw an error message, appending text of 'exception' if provided.
	// note: Also prints a message to the user using 'dojo.hostenv.println'.
	if(exception){
		message = message + ": "+dojo.errorToString(exception);
	}

	// print the message to the user if hostenv.println is defined
	try {	dojo.hostenv.println("FATAL: "+message); } catch (e) {}

	throw Error(message);
}

//Stub functions so things don't break.
//TODOC:  HOW TO DOC THESE?
dojo.debug = function(){}
dojo.debugShallow = function(obj){}
dojo.profile = { start: function(){}, end: function(){}, stop: function(){}, dump: function(){} };


function dj_eval(/*String*/ scriptFragment){ 
	// summary: Perform an evaluation in the global scope.  Use this rather than calling 'eval()' directly.
	// description: Placed in a separate function to minimize size of trapped evaluation context.
	// note:
	//	 - JSC eval() takes an optional second argument which can be 'unsafe'.
	//	 - Mozilla/SpiderMonkey eval() takes an optional second argument which is the
	//  	 scope object for new symbols.
	return dj_global.eval ? dj_global.eval(scriptFragment) : eval(scriptFragment); 	// mixed
}



dojo.unimplemented = function(/*String*/ funcname, /*String?*/ extra){
	// summary: Throw an exception because some function is not implemented.
	// extra: Text to append to the exception message.
	var message = "'" + funcname + "' not implemented";
	if (extra != null) { message += " " + extra; }
	dojo.raise(message);
}


dojo.deprecated = function(/*String*/ behaviour, /*String?*/ extra, /*String?*/ removal){
	// summary: Log a debug message to indicate that a behavior has been deprecated.
	// extra: Text to append to the message.
	// removal: Text to indicate when in the future the behavior will be removed.
	var message = "DEPRECATED: " + behaviour;
	if(extra){ message += " " + extra; }
	if(removal){ message += " -- will be removed in version: " + removal; }
	dojo.debug(message);
}



dojo.inherits = function(/*Function*/ subclass, /*Function*/ superclass){
	// summary: Set up inheritance between two classes.
	if(typeof superclass != 'function'){ 
		dojo.raise("dojo.inherits: superclass argument ["+superclass+"] must be a function (subclass: [" + subclass + "']");
	}
	subclass.prototype = new superclass();
	subclass.prototype.constructor = subclass;
	subclass.superclass = superclass.prototype;
	// DEPRICATED: super is a reserved word, use 'superclass'
	subclass['super'] = superclass.prototype;
}

dojo.render = (function(){
	//TODOC: HOW TO DOC THIS?
	// summary: Details rendering support, OS and browser of the current environment.
	// TODOC: is this something many folks will interact with?  If so, we should doc the structure created...
	function vscaffold(prefs, names){
		var tmp = {
			capable: false,
			support: {
				builtin: false,
				plugin: false
			},
			prefixes: prefs
		};
		for(var prop in names){
			tmp[prop] = false;
		}
		return tmp;
	}

	return {
		name: "",
		ver: dojo.version,
		os: { win: false, linux: false, osx: false },
		html: vscaffold(["html"], ["ie", "opera", "khtml", "safari", "moz"]),
		svg: vscaffold(["svg"], ["corel", "adobe", "batik"]),
		vml: vscaffold(["vml"], ["ie"]),
		swf: vscaffold(["Swf", "Flash", "Mm"], ["mm"]),
		swt: vscaffold(["Swt"], ["ibm"])
	};
})();

// ****************************************************************
// dojo.hostenv methods that must be defined in hostenv_*.js
// ****************************************************************

/**
 * The interface definining the interaction with the EcmaScript host environment.
*/

/*
 * None of these methods should ever be called directly by library users.
 * Instead public methods such as loadModule should be called instead.
 */
dojo.hostenv = (function(){
	// TODOC:  HOW TO DOC THIS?
	// summary: Provides encapsulation of behavior that changes across different 'host environments' 
	//			(different browsers, server via Rhino, etc).
	// description: None of these methods should ever be called directly by library users.
	//				Use public methods such as 'loadModule' instead.
	
	// default configuration options
	var config = {
		isDebug: false,
		allowQueryConfig: false,
		baseScriptUri: "",
		baseRelativePath: "",
		libraryScriptUri: "",
		iePreventClobber: false,
		ieClobberMinimal: true,
		preventBackButtonFix: true,
		searchIds: [],
		parseWidgets: true
	};

	if (typeof djConfig == "undefined") { djConfig = config; }
	else {
		for (var option in config) {
			if (typeof djConfig[option] == "undefined") {
				djConfig[option] = config[option];
			}
		}
	}

	return {
		name_: '(unset)',
		version_: '(unset)',


		getName: function(){ 
			// sumary: Return the name of the host environment.
			return this.name_; 	// String
		},


		getVersion: function(){ 
			// summary: Return the version of the hostenv.
			return this.version_; // String
		},

		getText: function(/*String*/ uri){
			// summary:	Read the plain/text contents at the specified 'uri'.
			// description: 
			//			If 'getText()' is not implemented, then it is necessary to override 
			//			'loadUri()' with an implementation that doesn't rely on it.

			dojo.unimplemented('getText', "uri=" + uri);
		}
	};
})();


dojo.hostenv.getBaseScriptUri = function(){
	// summary: Return the base script uri that other scripts are found relative to.
	// TODOC: HUH?  This comment means nothing to me.  What other scripts? Is this the path to other dojo libraries?
	//		MAYBE:  Return the base uri to scripts in the dojo library.	 ???
	// return: Empty string or a path ending in '/'.
	if(djConfig.baseScriptUri.length){ 
		return djConfig.baseScriptUri;
	}

	// MOW: Why not:
	//			uri = djConfig.libraryScriptUri || djConfig.baseRelativePath
	//		??? Why 'new String(...)'
	var uri = new String(djConfig.libraryScriptUri||djConfig.baseRelativePath);
	if (!uri) { dojo.raise("Nothing returned by getLibraryScriptUri(): " + uri); }

	// MOW: uri seems to not be actually used.  Seems to be hard-coding to djConfig.baseRelativePath... ???
	var lastslash = uri.lastIndexOf('/');		// MOW ???
	djConfig.baseScriptUri = djConfig.baseRelativePath;
	return djConfig.baseScriptUri;	// String
}

__CPAN_FILE__ src/html.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.html");

dojo.require("dojo.lang.func");
dojo.require("dojo.dom");
dojo.require("dojo.style");
dojo.require("dojo.string");

dojo.lang.mixin(dojo.html, dojo.dom);
dojo.lang.mixin(dojo.html, dojo.style);

// FIXME: we are going to assume that we can throw any and every rendering
// engine into the IE 5.x box model. In Mozilla, we do this w/ CSS.
// Need to investigate for KHTML and Opera

dojo.html.clearSelection = function(){
	try{
		if(window["getSelection"]){ 
			if(dojo.render.html.safari){
				// pulled from WebCore/ecma/kjs_window.cpp, line 2536
				window.getSelection().collapse();
			}else{
				window.getSelection().removeAllRanges();
			}
		}else if(document.selection){
			if(document.selection.empty){
				document.selection.empty();
			}else if(document.selection.clear){
				document.selection.clear();
			}
		}
		return true;
	}catch(e){
		dojo.debug(e);
		return false;
	}
}

dojo.html.disableSelection = function(element){
	element = dojo.byId(element)||document.body;
	var h = dojo.render.html;
	
	if(h.mozilla){
		element.style.MozUserSelect = "none";
	}else if(h.safari){
		element.style.KhtmlUserSelect = "none"; 
	}else if(h.ie){
		element.unselectable = "on";
	}else{
		return false;
	}
	return true;
}

dojo.html.enableSelection = function(element){
	element = dojo.byId(element)||document.body;
	
	var h = dojo.render.html;
	if(h.mozilla){ 
		element.style.MozUserSelect = ""; 
	}else if(h.safari){
		element.style.KhtmlUserSelect = "";
	}else if(h.ie){
		element.unselectable = "off";
	}else{
		return false;
	}
	return true;
}

dojo.html.selectElement = function(element){
	element = dojo.byId(element);
	if(document.selection && document.body.createTextRange){ // IE
		var range = document.body.createTextRange();
		range.moveToElementText(element);
		range.select();
	}else if(window["getSelection"]){
		var selection = window.getSelection();
		// FIXME: does this work on Safari?
		if(selection["selectAllChildren"]){ // Mozilla
			selection.selectAllChildren(element);
		}
	}
}

dojo.html.selectInputText = function(element){
	element = dojo.byId(element);
	if(document.selection && document.body.createTextRange){ // IE
		var range = element.createTextRange();
		range.moveStart("character", 0);
		range.moveEnd("character", element.value.length);
		range.select();
	}else if(window["getSelection"]){
		var selection = window.getSelection();
		// FIXME: does this work on Safari?
		element.setSelectionRange(0, element.value.length);
	}
	element.focus();
}


dojo.html.isSelectionCollapsed = function(){
	if(document["selection"]){ // IE
		return document.selection.createRange().text == "";
	}else if(window["getSelection"]){
		var selection = window.getSelection();
		if(dojo.lang.isString(selection)){ // Safari
			return selection == "";
		}else{ // Mozilla/W3
			return selection.isCollapsed;
		}
	}
}

dojo.html.getEventTarget = function(evt){
	if(!evt) { evt = window.event || {} };
	var t = (evt.srcElement ? evt.srcElement : (evt.target ? evt.target : null));
	while((t)&&(t.nodeType!=1)){ t = t.parentNode; }
	return t;
}

dojo.html.getDocumentWidth = function(){
	dojo.deprecated("dojo.html.getDocument*", "replaced by dojo.html.getViewport*", "0.4");
	return dojo.html.getViewportWidth();
}

dojo.html.getDocumentHeight = function(){
	dojo.deprecated("dojo.html.getDocument*", "replaced by dojo.html.getViewport*", "0.4");
	return dojo.html.getViewportHeight();
}

dojo.html.getDocumentSize = function(){
	dojo.deprecated("dojo.html.getDocument*", "replaced of dojo.html.getViewport*", "0.4");
	return dojo.html.getViewportSize();
}

dojo.html.getViewportWidth = function(){
	var w = 0;

	if(window.innerWidth){
		w = window.innerWidth;
	}

	if(dojo.exists(document, "documentElement.clientWidth")){
		// IE6 Strict
		var w2 = document.documentElement.clientWidth;
		// this lets us account for scrollbars
		if(!w || w2 && w2 < w) {
			w = w2;
		}
		return w;
	}

	if(document.body){
		// IE
		return document.body.clientWidth;
	}

	return 0;
}

dojo.html.getViewportHeight = function(){
	if (window.innerHeight){
		return window.innerHeight;
	}

	if (dojo.exists(document, "documentElement.clientHeight")){
		// IE6 Strict
		return document.documentElement.clientHeight;
	}

	if (document.body){
		// IE
		return document.body.clientHeight;
	}

	return 0;
}

dojo.html.getViewportSize = function(){
	var ret = [dojo.html.getViewportWidth(), dojo.html.getViewportHeight()];
	ret.w = ret[0];
	ret.h = ret[1];
	return ret;
}

dojo.html.getScrollTop = function(){
	return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
}

dojo.html.getScrollLeft = function(){
	return window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
}

dojo.html.getScrollOffset = function(){
	var off = [dojo.html.getScrollLeft(), dojo.html.getScrollTop()];
	off.x = off[0];
	off.y = off[1];
	return off;
}

dojo.html.getParentOfType = function(node, type){
	dojo.deprecated("dojo.html.getParentOfType", "replaced by dojo.html.getParentByType*", "0.4");
	return dojo.html.getParentByType(node, type);
}

dojo.html.getParentByType = function(node, type) {
	var parent = dojo.byId(node);
	type = type.toLowerCase();
	while((parent)&&(parent.nodeName.toLowerCase()!=type)){
		if(parent==(document["body"]||document["documentElement"])){
			return null;
		}
		parent = parent.parentNode;
	}
	return parent;
}

// RAR: this function comes from nwidgets and is more-or-less unmodified.
// We should probably look ant Burst and f(m)'s equivalents
dojo.html.getAttribute = function(node, attr){
	node = dojo.byId(node);
	// FIXME: need to add support for attr-specific accessors
	if((!node)||(!node.getAttribute)){
		// if(attr !== 'nwType'){
		//	alert("getAttr of '" + attr + "' with bad node"); 
		// }
		return null;
	}
	var ta = typeof attr == 'string' ? attr : new String(attr);

	// first try the approach most likely to succeed
	var v = node.getAttribute(ta.toUpperCase());
	if((v)&&(typeof v == 'string')&&(v!="")){ return v; }

	// try returning the attributes value, if we couldn't get it as a string
	if(v && v.value){ return v.value; }

	// this should work on Opera 7, but it's a little on the crashy side
	if((node.getAttributeNode)&&(node.getAttributeNode(ta))){
		return (node.getAttributeNode(ta)).value;
	}else if(node.getAttribute(ta)){
		return node.getAttribute(ta);
	}else if(node.getAttribute(ta.toLowerCase())){
		return node.getAttribute(ta.toLowerCase());
	}
	return null;
}
	
/**
 *	Determines whether or not the specified node carries a value for the
 *	attribute in question.
 */
dojo.html.hasAttribute = function(node, attr){
	node = dojo.byId(node);
	return dojo.html.getAttribute(node, attr) ? true : false;
}
	
/**
 * Returns the string value of the list of CSS classes currently assigned
 * directly to the node in question. Returns an empty string if no class attribute
 * is found;
 */
dojo.html.getClass = function(node){
	node = dojo.byId(node);
	if(!node){ return ""; }
	var cs = "";
	if(node.className){
		cs = node.className;
	}else if(dojo.html.hasAttribute(node, "class")){
		cs = dojo.html.getAttribute(node, "class");
	}
	return dojo.string.trim(cs);
}

/**
 * Returns an array of CSS classes currently assigned
 * directly to the node in question. Returns an empty array if no classes
 * are found;
 */
dojo.html.getClasses = function(node) {
	var c = dojo.html.getClass(node);
	return (c == "") ? [] : c.split(/\s+/g);
}

/**
 * Returns whether or not the specified classname is a portion of the
 * class list currently applied to the node. Does not cover cascaded
 * styles, only classes directly applied to the node.
 */
dojo.html.hasClass = function(node, classname){
	return dojo.lang.inArray(dojo.html.getClasses(node), classname);
}

/**
 * Adds the specified class to the beginning of the class list on the
 * passed node. This gives the specified class the highest precidence
 * when style cascading is calculated for the node. Returns true or
 * false; indicating success or failure of the operation, respectively.
 */
dojo.html.prependClass = function(node, classStr){
	classStr += " " + dojo.html.getClass(node);
	return dojo.html.setClass(node, classStr);
}

/**
 * Adds the specified class to the end of the class list on the
 *	passed &node;. Returns &true; or &false; indicating success or failure.
 */
dojo.html.addClass = function(node, classStr){
	if (dojo.html.hasClass(node, classStr)) {
	  return false;
	}
	classStr = dojo.string.trim(dojo.html.getClass(node) + " " + classStr);
	return dojo.html.setClass(node, classStr);
}

/**
 *	Clobbers the existing list of classes for the node, replacing it with
 *	the list given in the 2nd argument. Returns true or false
 *	indicating success or failure.
 */
dojo.html.setClass = function(node, classStr){
	node = dojo.byId(node);
	var cs = new String(classStr);
	try{
		if(typeof node.className == "string"){
			node.className = cs;
		}else if(node.setAttribute){
			node.setAttribute("class", classStr);
			node.className = cs;
		}else{
			return false;
		}
	}catch(e){
		dojo.debug("dojo.html.setClass() failed", e);
	}
	return true;
}

/**
 * Removes the className from the node;. Returns
 * true or false indicating success or failure.
 */ 
dojo.html.removeClass = function(node, classStr, allowPartialMatches){
	var classStr = dojo.string.trim(new String(classStr));

	try{
		var cs = dojo.html.getClasses(node);
		var nca	= [];
		if(allowPartialMatches){
			for(var i = 0; i<cs.length; i++){
				if(cs[i].indexOf(classStr) == -1){ 
					nca.push(cs[i]);
				}
			}
		}else{
			for(var i=0; i<cs.length; i++){
				if(cs[i] != classStr){ 
					nca.push(cs[i]);
				}
			}
		}
		dojo.html.setClass(node, nca.join(" "));
	}catch(e){
		dojo.debug("dojo.html.removeClass() failed", e);
	}

	return true;
}

/**
 * Replaces 'oldClass' and adds 'newClass' to node
 */
dojo.html.replaceClass = function(node, newClass, oldClass) {
	dojo.html.removeClass(node, oldClass);
	dojo.html.addClass(node, newClass);
}

// Enum type for getElementsByClass classMatchType arg:
dojo.html.classMatchType = {
	ContainsAll : 0, // all of the classes are part of the node's class (default)
	ContainsAny : 1, // any of the classes are part of the node's class
	IsOnly : 2 // only all of the classes are part of the node's class
}


/**
 * Returns an array of nodes for the given classStr, children of a
 * parent, and optionally of a certain nodeType
 */
dojo.html.getElementsByClass = function(classStr, parent, nodeType, classMatchType, useNonXpath){
	parent = dojo.byId(parent) || document;
	var classes = classStr.split(/\s+/g);
	var nodes = [];
	if( classMatchType != 1 && classMatchType != 2 ) classMatchType = 0; // make it enum
	var reClass = new RegExp("(\\s|^)((" + classes.join(")|(") + "))(\\s|$)");
	var candidateNodes = [];
	
	if(!useNonXpath && document.evaluate) { // supports dom 3 xpath
		var xpath = "//" + (nodeType || "*") + "[contains(";
		if(classMatchType != dojo.html.classMatchType.ContainsAny){
			xpath += "concat(' ',@class,' '), ' " +
			classes.join(" ') and contains(concat(' ',@class,' '), ' ") +
			" ')]";
		}else{
			xpath += "concat(' ',@class,' '), ' " +
			classes.join(" ')) or contains(concat(' ',@class,' '), ' ") +
			" ')]";
		}
		var xpathResult = document.evaluate(xpath, parent, null, XPathResult.ANY_TYPE, null);
		var result = xpathResult.iterateNext();
		while(result){
			try{
				candidateNodes.push(result);
				result = xpathResult.iterateNext();
			}catch(e){ break; }
		}
		return candidateNodes;
	}else{
		if(!nodeType){
			nodeType = "*";
		}
		candidateNodes = parent.getElementsByTagName(nodeType);

		var node, i = 0;
		outer:
		while(node = candidateNodes[i++]){
			var nodeClasses = dojo.html.getClasses(node);
			if(nodeClasses.length == 0){ continue outer; }
			var matches = 0;
	
			for(var j = 0; j < nodeClasses.length; j++){
				if(reClass.test(nodeClasses[j])){
					if(classMatchType == dojo.html.classMatchType.ContainsAny){
						nodes.push(node);
						continue outer;
					}else{
						matches++;
					}
				}else{
					if(classMatchType == dojo.html.classMatchType.IsOnly){
						continue outer;
					}
				}
			}
	
			if(matches == classes.length){
				if(	(classMatchType == dojo.html.classMatchType.IsOnly)&&
					(matches == nodeClasses.length)){
					nodes.push(node);
				}else if(classMatchType == dojo.html.classMatchType.ContainsAll){
					nodes.push(node);
				}
			}
		}
		return nodes;
	}
}

dojo.html.getElementsByClassName = dojo.html.getElementsByClass;

/**
 * Returns the mouse position relative to the document (not the viewport).
 * For example, if you have a document that is 10000px tall,
 * but your browser window is only 100px tall,
 * if you scroll to the bottom of the document and call this function it
 * will return {x: 0, y: 10000}
 */
dojo.html.getCursorPosition = function(e){
	e = e || window.event;
	var cursor = {x:0, y:0};
	if(e.pageX || e.pageY){
		cursor.x = e.pageX;
		cursor.y = e.pageY;
	}else{
		var de = document.documentElement;
		var db = document.body;
		cursor.x = e.clientX + ((de||db)["scrollLeft"]) - ((de||db)["clientLeft"]);
		cursor.y = e.clientY + ((de||db)["scrollTop"]) - ((de||db)["clientTop"]);
	}
	return cursor;
}

dojo.html.overElement = function(element, e){
	element = dojo.byId(element);
	var mouse = dojo.html.getCursorPosition(e);

	with(dojo.html){
		var top = getAbsoluteY(element, true);
		var bottom = top + getInnerHeight(element);
		var left = getAbsoluteX(element, true);
		var right = left + getInnerWidth(element);
	}
	
	return (mouse.x >= left && mouse.x <= right &&
		mouse.y >= top && mouse.y <= bottom);
}

dojo.html.setActiveStyleSheet = function(title){
	var i = 0, a, els = document.getElementsByTagName("link");
	while (a = els[i++]) {
		if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")){
			a.disabled = true;
			if (a.getAttribute("title") == title) { a.disabled = false; }
		}
	}
}

dojo.html.getActiveStyleSheet = function(){
	var i = 0, a, els = document.getElementsByTagName("link");
	while (a = els[i++]) {
		if (a.getAttribute("rel").indexOf("style") != -1 &&
			a.getAttribute("title") && !a.disabled) { return a.getAttribute("title"); }
	}
	return null;
}

dojo.html.getPreferredStyleSheet = function(){
	var i = 0, a, els = document.getElementsByTagName("link");
	while (a = els[i++]) {
		if(a.getAttribute("rel").indexOf("style") != -1
			&& a.getAttribute("rel").indexOf("alt") == -1
			&& a.getAttribute("title")) { return a.getAttribute("title"); }
	}
	return null;
}

dojo.html.body = function(){
	// Note: document.body is not defined for a strict xhtml document
	return document.body || document.getElementsByTagName("body")[0];
}

/**
 * Like dojo.dom.isTag, except case-insensitive
**/
dojo.html.isTag = function(node /* ... */) {
	node = dojo.byId(node);
	if(node && node.tagName) {
		var arr = dojo.lang.map(dojo.lang.toArray(arguments, 1),
			function(a) { return String(a).toLowerCase(); });
		return arr[ dojo.lang.find(node.tagName.toLowerCase(), arr) ] || "";
	}
	return "";
}

dojo.html.copyStyle = function(target, source){
	// work around for opera which doesn't have cssText, and for IE which fails on setAttribute 
	if(dojo.lang.isUndefined(source.style.cssText)){ 
		target.setAttribute("style", source.getAttribute("style")); 
	}else{
		target.style.cssText = source.style.cssText; 
	}
	dojo.html.addClass(target, dojo.html.getClass(source));
}

dojo.html._callExtrasDeprecated = function(inFunc, args) {
	var module = "dojo.html.extras";
	dojo.deprecated("dojo.html." + inFunc, "moved to " + module, "0.4");
	dojo["require"](module); // weird syntax to fool list-profile-deps (build)
	return dojo.html[inFunc].apply(dojo.html, args);
}

dojo.html.createNodesFromText = function() {
	return dojo.html._callExtrasDeprecated('createNodesFromText', arguments);
}

dojo.html.gravity = function() {
	return dojo.html._callExtrasDeprecated('gravity', arguments);
}

dojo.html.placeOnScreen = function() {
	return dojo.html._callExtrasDeprecated('placeOnScreen', arguments);
}

dojo.html.placeOnScreenPoint = function() {
	return dojo.html._callExtrasDeprecated('placeOnScreenPoint', arguments);
}

dojo.html.renderedTextContent = function() {
	return dojo.html._callExtrasDeprecated('renderedTextContent', arguments);
}

dojo.html.BackgroundIframe = function() {
	return dojo.html._callExtrasDeprecated('BackgroundIframe', arguments);
}

__CPAN_FILE__ src/hostenv_jsc.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/*
 * JScript .NET jsc
 *
 */

dojo.hostenv.name_ = 'jsc';

// Sanity check this is the right hostenv.
// See the Rotor source code jscript/engine/globalobject.cs for what globals
// are available.
if((typeof ScriptEngineMajorVersion != 'function')||(ScriptEngineMajorVersion() < 7)){
	dojo.raise("attempt to use JScript .NET host environment with inappropriate ScriptEngine"); 
}

// for more than you wanted to know about why this import is required even if
// we fully qualify all symbols, see
// http://groups.google.com/groups?th=f050c7aeefdcbde2&rnum=12
import System;

dojo.hostenv.getText = function(uri){
	if(!System.IO.File.Exists(uri)){
		// dojo.raise("No such file '" + uri + "'");
		return 0;
	}
	var reader = new System.IO.StreamReader(uri);
	var contents : String = reader.ReadToEnd();
	return contents;
}

dojo.hostenv.loadUri = function(uri){
	var contents = this.getText(uri);
	if(!contents){
		dojo.raise("got no back contents from uri '" + uri + "': " + contents);
	}
	// TODO: in JScript .NET, eval will not affect the symbol table of the current code?
	var value = dj_eval(contents);
	dojo.debug("jsc eval of contents returned: ", value);
	return 1;

	// for an example doing runtime code compilation, see:
	// http://groups.google.com/groups?selm=eQ1aeciCBHA.1644%40tkmsftngp05&rnum=6
	// Microsoft.JScript or System.CodeDom.Compiler ?
	// var engine = new Microsoft.JScript.Vsa.VsaEngine()
	// what about loading a js file vs. a dll?
	// GetObject("script:" . uri);
}

/* The System.Environment object is useful:
    print ("CommandLine='" + System.Environment.CommandLine + "' " +
	   "program name='" + System.Environment.GetCommandLineArgs()[0] + "' " +
	   "CurrentDirectory='" + System.Environment.CurrentDirectory + "' " +
	   "StackTrace='" + System.Environment.StackTrace + "'");
*/

// same as System.Console.WriteLine
// sigh; Rotor treats symbol "print" at parse time without actually putting it
// in the builtin symbol table.
// Note that the print symbol is not available if jsc is run with the "/print-"
// option.
dojo.hostenv.println = function(s){
	print(s); // = print
}

dojo.hostenv.getLibraryScriptUri = function(){
	return System.Environment.GetCommandLineArgs()[0];
}

__CPAN_FILE__ src/doc.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.doc");
dojo.require("dojo.io.*");
dojo.require("dojo.event.topic");
dojo.require("dojo.rpc.JotService");
dojo.require("dojo.dom");

/*
 * TODO:
 *
 * Package summary needs to compensate for "is"
 * Handle host environments
 * Deal with dojo.widget weirdness
 * Parse parameters
 * Limit function parameters to only the valid ones (Involves packing parameters onto meta during rewriting)
 * Package display page
 *
 */

dojo.doc._count = 0;
dojo.doc._keys = {};
dojo.doc._myKeys = [];
dojo.doc._callbacks = {function_names: []};
dojo.doc._cache = {}; // Saves the JSON objects in cache
dojo.doc._rpc = new dojo.rpc.JotService;
dojo.doc._rpc.serviceUrl = "http://dojotoolkit.org/~pottedmeat/jsonrpc.php";

dojo.lang.mixin(dojo.doc, {
	functionNames: function(/*mixed*/ selectKey, /*Function*/ callback){
		// summary: Returns an ordered list of package and function names.
		dojo.debug("functionNames()");
		if(!selectKey){
			selectKey = ++dojo.doc._count;
		}
		dojo.doc._buildCache({
			type: "function_names",
			callbacks: [dojo.doc._functionNames, callback],
			selectKey: selectKey
		});
	},

	_functionNames: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
		dojo.debug("_functionNames()");
		var searchData = [];
		for(var key in data){
			// Add the package if it doesn't exist in its children
			if(!dojo.lang.inArray(data[key], key)){
				searchData.push([key, key]);
			}
			// Add the functions
			for(var pkg_key in data[key]){
				searchData.push([data[key][pkg_key], data[key][pkg_key]]);
			}
		}

		searchData = searchData.sort(dojo.doc._sort);

		if(evt.callbacks && evt.callbacks.length){
			var callback = evt.callbacks.shift();
			callback.call(null, type, searchData, evt);
		}
	},

	getMeta: function(/*mixed*/ selectKey, /*Function*/ callback, /*Function*/ name, /*String?*/ id){
		// summary: Gets information about a function in regards to its meta data
		dojo.debug("getMeta(" + name + ")");
		if(!selectKey){
			selectKey = ++dojo.doc._count;
		}
		dojo.doc._buildCache({
			type: "meta",
			callbacks: [callback],
			name: name,
			id: id,
			selectKey: selectKey
		});
	},

	_getMeta: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
		dojo.debug("_getMeta(" + evt.name + ") has package: " + evt.pkg + " with: " + type);
		if("load" == type && evt.pkg){
			evt.type = "meta";
			dojo.doc._buildCache(evt);
		}else{
			if(evt.callbacks && evt.callbacks.length){
				var callback = evt.callbacks.shift();
				callback.call(null, "error", {}, evt);
			}
		}
	},

	getSrc: function(/*mixed*/ selectKey, /*Function*/ callback, /*String*/ name, /*String?*/ id){
		// summary: Gets src file (created by the doc parser)
		dojo.debug("getSrc()");
		if(!selectKey){
			selectKey = ++dojo.doc._count;
		}	
		dojo.doc._buildCache({
			type: "src",
			callbacks: [callback],
			name: name,
			id: id,
			selectKey: selectKey
		});
	},

	_getSrc: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
		dojo.debug("_getSrc()");
		if(evt.pkg){	
			evt.type = "src";
			dojo.doc._buildCache(evt);
		}else{
			if(evt.callbacks && evt.callbacks.length){
				var callback =  evt.callbacks.shift();
				callback.call(null, "error", {}, evt);
			}
		}
	},

	getDoc: function(/*mixed*/ selectKey, /*Function*/ callback, /*String*/ name, /*String?*/ id){
		// summary: Gets external documentation stored on jot
		dojo.debug("getDoc()");
		if(!selectKey){
			selectKey = ++dojo.doc._count;
		}
		var input = {
			type: "doc",
			callbacks: [callback],
			name: name,
			id: id,
			selectKey: selectKey
		}
		dojo.doc.functionPackage(dojo.doc._getDoc, input);
	},

	_getDoc: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
		dojo.debug("_getDoc(" + evt.pkg + "/" + evt.name + ")");
	
		dojo.doc._keys[evt.selectKey] = {count: 0};

		var search = {};
		search.forFormName = "DocFnForm";
		search.limit = 1;

		if(!evt.id){
			search.filter = "it/DocFnForm/require = '" + evt.pkg + "' and it/DocFnForm/name = '" + evt.name + "' and not(it/DocFnForm/id)";
		}else{
			search.filter = "it/DocFnForm/require = '" + evt.pkg + "' and it/DocFnForm/name = '" + evt.name + "' and it/DocFnForm/id = '" + evt.id + "'";
		}
		dojo.debug(dojo.json.serialize(search));
	
		dojo.doc._rpc.callRemote("search", search).addCallbacks(function(data){ evt.type = "fn"; dojo.doc._gotDoc("load", data.list[0], evt); }, function(data){ evt.type = "fn"; dojo.doc._gotDoc("error", {}, evt); });
	
		search.forFormName = "DocParamForm";

		if(!evt.id){
			search.filter = "it/DocParamForm/fns = '" + evt.pkg + "=>" + evt.name + "'";
		}else{
			search.filter = "it/DocParamForm/fns = '" + evt.pkg + "=>" + evt.name + "=>" + evt.id + "'";
		}
		delete search.limit;

		dojo.doc._rpc.callRemote("search", search).addCallbacks(function(data){ evt.type = "param"; dojo.doc._gotDoc("load", data.list, evt); }, function(data){ evt.type = "param"; dojo.doc._gotDoc("error", {}, evt); });
	},

	_gotDoc: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
		dojo.debug("_gotDoc(" + evt.type + ") for " + evt.selectKey);
		dojo.doc._keys[evt.selectKey][evt.type] = data;
		if(++dojo.doc._keys[evt.selectKey].count == 2){
			dojo.debug("_gotDoc() finished");
			var keys = dojo.doc._keys[evt.selectKey];
			var description = '';
			if(!keys.fn){
				keys.fn = {}
			}
			if(keys.fn["main/text"]){
				description = dojo.dom.createDocumentFromText(keys.fn["main/text"]).childNodes[0].innerHTML;
				if(!description){
					description = keys.fn["main/text"];
				}			
			}
			data = {
				description: description,
				returns: keys.fn["DocFnForm/returns"],
				id: keys.fn["DocFnForm/id"],
				parameters: {},
				variables: []
			}
			for(var i = 0, param; param = keys["param"][i]; i++){
				data.parameters[param["DocParamForm/name"]] = {
					description: param["DocParamForm/desc"]
				};
			}

			delete dojo.doc._keys[evt.selectKey];
		
			if(evt.callbacks && evt.callbacks.length){
				var callback = evt.callbacks.shift();
				callback.call(null, "load", data, evt);
			}
		}
	},

	getPkgMeta: function(/*mixed*/ selectKey, /*Function*/ callback, /*String*/ name){
		dojo.debug("getPkgMeta(" + name + ")");
		if(!selectKey){
			selectKey = ++dojo.doc._count;
		}
		dojo.doc._buildCache({
			type: "pkgmeta",
			callbacks: [callback],
			name: name,
			selectKey: selectKey
		});
	},

	_getPkgMeta: function(/*Object*/ input){
		dojo.debug("_getPkgMeta(" + input.name + ")");
		input.type = "pkgmeta";
		dojo.doc._buildCache(input);
	},

	_onDocSearch: function(/*Object*/ input){
		dojo.debug("_onDocSearch(" + input.name + ")");
		if(!input.name){
			return;
		}
		if(!input.selectKey){
			input.selectKey = ++dojo.doc._count;
		}
		input.callbacks = [dojo.doc._onDocSearchFn];
		input.name = input.name.toLowerCase();
		input.type = "function_names";

		dojo.doc._buildCache(input);
	},

	_onDocSearchFn: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
		dojo.debug("_onDocSearchFn(" + evt.name + ")");
		var packages = [];
		var size = 0;
		pkgLoop:
		for(var pkg in data){
			for(var i = 0, fn; fn = data[pkg][i]; i++){
				if(fn.toLowerCase().indexOf(evt.name) != -1){
					// Build a list of all packages that need to be loaded and their loaded state.
					++size;
					packages.push(pkg);
					continue pkgLoop;
				}
			}
		}
		dojo.doc._keys[evt.selectKey] = {};
		dojo.doc._keys[evt.selectKey].pkgs = packages;
		dojo.doc._keys[evt.selectKey].pkg = evt.name; // Remember what we were searching for
		dojo.doc._keys[evt.selectKey].loaded = 0;
		for(var i = 0, pkg; pkg = packages[i]; i++){
			setTimeout("dojo.doc.getPkgMeta(\"" + evt.selectKey + "\", dojo.doc._onDocResults, \"" + pkg + "\");", i*10);
		}
	},

	_onDocResults: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
		dojo.debug("_onDocResults(" + evt.name + "/" + dojo.doc._keys[evt.selectKey].pkg + ") " + type);
		++dojo.doc._keys[evt.selectKey].loaded;

		if(dojo.doc._keys[evt.selectKey].loaded == dojo.doc._keys[evt.selectKey].pkgs.length){
			var info = dojo.doc._keys[evt.selectKey];
			var pkgs = info.pkgs;
			var name = info.pkg;
			delete dojo.doc._keys[evt.selectKey];
			var results = {selectKey: evt.selectKey, docResults: []};
			data = dojo.doc._cache;

			for(var i = 0, pkg; pkg = pkgs[i]; i++){
				if(!data[pkg]){
					continue;
				}
				for(var fn in data[pkg]["meta"]){
					if(fn.toLowerCase().indexOf(name) == -1){
						continue;
					}
					if(fn != "requires"){
						for(var pId in data[pkg]["meta"][fn]){
							var result = {
								pkg: pkg,
								name: fn,
								summary: ""
							}
							if(data[pkg]["meta"][fn][pId].summary){
								result.summary = data[pkg]["meta"][fn][pId].summary;
							}
							results.docResults.push(result);
						}
					}
				}
			}

			dojo.debug("Publishing docResults");
			dojo.doc._printResults(results);
		}
	},
	
	_printResults: function(results){
		dojo.debug("_printResults(): called");
		// summary: Call this function to send the /doc/results topic
	},

	_onDocSelectFunction: function(/*Object*/ input){
		// summary: Get doc, meta, and src
		var name = input.name;
		var selectKey = selectKey;
		dojo.debug("_onDocSelectFunction(" + name + ")");
		if(!name){
			return false;
		}
		if(!selectKey){
			selectKey = ++dojo.doc._count;
		}

		dojo.doc._keys[selectKey] = {size: 0};
		dojo.doc._myKeys[++dojo.doc._count] = {selectKey: selectKey, type: "meta"}
		dojo.doc.getMeta(dojo.doc._count, dojo.doc._onDocSelectResults, name);
		dojo.doc._myKeys[++dojo.doc._count] = {selectKey: selectKey, type: "src"}
		dojo.doc.getSrc(dojo.doc._count, dojo.doc._onDocSelectResults, name);
		dojo.doc._myKeys[++dojo.doc._count] = {selectKey: selectKey, type: "doc"}
		dojo.doc.getDoc(dojo.doc._count, dojo.doc._onDocSelectResults, name);
	},

	_onDocSelectResults: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
		dojo.debug("dojo.doc._onDocSelectResults(" + evt.type + ", " + evt.name + ")");
		var myKey = dojo.doc._myKeys[evt.selectKey];
		dojo.doc._keys[myKey.selectKey][myKey.type] = data;
		dojo.doc._keys[myKey.selectKey].size;
		if(++dojo.doc._keys[myKey.selectKey].size == 3){
			var key = dojo.lang.mixin(evt, dojo.doc._keys[myKey.selectKey]);
			delete key.size;
			dojo.debug("Publishing docFunctionDetail");
			dojo.doc._printFunctionDetail(key);
			delete dojo.doc._keys[myKey.selectKey];
			delete dojo.doc._myKeys[evt.selectKey];
		}
	},
	
	_printFunctionDetail: function(results) {
		// summary: Call this function to send the /doc/functionDetail topic event
	},

	_buildCache: function(/*Object*/ input){
		var type = input.type;
		var pkg = input.pkg;
		var callbacks = input.callbacks;
		var id = input.id;
		if(!id){
			id = "_";
		}
		var name = input.name;
	
		dojo.debug("_buildCache() type: " + type);
		if(type == "function_names"){
			if(!dojo.doc._cache["function_names"]){
				dojo.debug("_buildCache() new cache");
				if(callbacks && callbacks.length){
					dojo.doc._callbacks.function_names.push([input, callbacks.shift()]);
				}
				dojo.doc._cache["function_names"] = {loading: true};
				dojo.io.bind({
					url: "json/function_names",
					mimetype: "text/json",
					error: function(type, data, evt){
						dojo.debug("Unable to load function names");
						for(var i = 0, callback; callback = dojo.doc._callbacks.function_names[i]; i++){
							callback[1].call(null, "error", {}, callback[0]);
						}
					},
					load: function(type, data, evt){
						dojo.doc._cache['function_names'] = data;
						for(var i = 0, callback; callback = dojo.doc._callbacks.function_names[i]; i++){
							callback[1].call(null, "load", data, callback[0]);
						}
					}
				});
			}else if(dojo.doc._cache["function_names"].loading){
				dojo.debug("_buildCache() loading cache");
				if(callbacks && callbacks.length){
					dojo.doc._callbacks.function_names.push([input, callbacks.shift()]);
				}
			}else{
				dojo.debug("_buildCache() from cache");
				if(callbacks && callbacks.length){
					var callback = callbacks.shift();
					callback.call(null, "load", dojo.doc._cache["function_names"], input);
				}
			}
		}else if(type == "meta" || type == "src"){
			if(!pkg){
				if(type == "meta"){
					dojo.doc.functionPackage(dojo.doc._getMeta, input);
				}else{
					dojo.doc.functionPackage(dojo.doc._getSrc, input);
				}
			}else{
				try{
					var cached = dojo.doc._cache[pkg][name][id][type];
				}catch(e){}

				if(cached){
					if(callbacks && callbacks.length){
						var callback = callbacks.shift();
						callback.call(null, "load", cached, input);
						return;
					}
				}

				dojo.debug("Finding " + type + " for: " + pkg + ", function: " + name + ", id: " + id);

				var mimetype = "text/json";
				if(type == "src"){
					mimetype = "text/plain"
				}

				var url = "json/" + pkg + "/" + name + "/" + id + "/" + type;

				dojo.io.bind({
					url: url,
					input: input,
					mimetype: mimetype,
					error: function(type, data, evt, args){
						var input = args.input;
						var pkg = input.pkg;
						var type = input.type;
						var callbacks = input.callbacks;
						var id = input.id;
						var name = input.name;

						if(callbacks && callbacks.length){
							if(!data){
								data = {};
							}
							if(!dojo.doc._cache[pkg]){
								dojo.doc._cache[pkg] = {};
							}
							if(!dojo.doc._cache[pkg][name]){
								dojo.doc._cache[pkg][name] = {};
							}
							if(type == "meta"){
								data.sig = dojo.doc._cache[pkg][name][id].sig;
								data.params = dojo.doc._cache[pkg][name][id].params;
							}
							var callback = callbacks.shift();
							callback.call(null, "error", data, args.input);
						}
					},
					load: function(type, data, evt, args){
						var input = args.input;
						var pkg = input.pkg;
						var type = input.type;
						var id = input.id;
						var name = input.name;
						var cache = dojo.doc._cache;
						dojo.debug("_buildCache() loaded " + type);

						if(!data){
							data = {};
						}
						if(!cache[pkg]){
							dojo.doc._cache[pkg] = {};
						}
						if(!cache[pkg][name]){
							dojo.doc._cache[pkg][name] = {};
						}
						if(!cache[pkg][name][id]){
							dojo.doc._cache[pkg][name][id] = {};
						}
						if(!cache[pkg][name][id].meta){
							dojo.doc._cache[pkg][name][id].meta = {};
						}
						dojo.doc._cache[pkg][name][id][type] = data;
						if(callbacks && callbacks.length){
							var callback = callbacks.shift();
							callback.call(null, "load", data, args.input);
						}
					}
				});
			}
		}else if(type == "pkgmeta"){
			try{
				var cached = dojo.doc._cache[name]["meta"];
			}catch(e){}

			if(cached){
				if(callbacks && callbacks.length){
					var callback = callbacks.shift();
					callback.call(null, "load", cached, input);
					return;
				}
			}

			dojo.debug("Finding package meta for: " + name);

			dojo.io.bind({
				url: "json/" + name + "/meta",
				input: input,
				mimetype: "text/json",
				error: function(type, data, evt, args){
					var callbacks = args.input.callbacks;
					if(callbacks && callbacks.length){
						var callback = callbacks.shift();
						callback.call(null, "error", {}, args.input);
					}
				},
				load: function(type, data, evt, args){
					var pkg = args.input.name;
					var cache = dojo.doc._cache;

					dojo.debug("_buildCache() loaded for: " + pkg);
					if(!cache[pkg]){
						dojo.doc._cache[pkg] = {};
					}
				
					if(!cache[pkg]["meta"]){
						dojo.doc._cache[pkg]["meta"] = {};
					}
				
					var methods = data.methods;
					if(methods){
						for(var method in methods){
							if (method == "is") {
								continue;
							}
							for(var pId in methods[method]){
								if(!cache[pkg]["meta"][method]){
									dojo.doc._cache[pkg]["meta"][method] = {};
								}
								if(!cache[pkg]["meta"][method][pId]){
									dojo.doc._cache[pkg]["meta"][method][pId] = {};
								}
								dojo.doc._cache[pkg]["meta"][method][pId].summary = methods[method][pId];
							}
						}
					}

					dojo.doc._cache[pkg]["meta"].methods = methods;
					var requires = data.requires;
					if(requires){
						dojo.doc._cache[pkg]["meta"].requires = requires;
					}
					if(callbacks && callbacks.length){
						var callback = callbacks.shift();
						callback.call(null, "load", methods, input);
					}
				}
			});
		}
	},

	selectFunction: function(/*String*/ name, /*String?*/ id){
		// summary: The combined information
	},

	savePackage: function(/*String*/ name, /*String*/ description){
		dojo.doc._rpc.callRemote(
			"saveForm",
			{
				form: "DocPkgForm",
				path: "/WikiHome/DojoDotDoc/id",
				pname1: "main/text",
				pvalue1: "Test"
			}
		).addCallbacks(dojo.doc._results, dojo.doc._results);
	},

	functionPackage: function(/*Function*/ callback, /*Object*/ input){
		dojo.debug("functionPackage() name: " + input.name + " for type: " + input.type);
		input.type = "function_names";
		input.callbacks.unshift(callback);
		input.callbacks.unshift(dojo.doc._functionPackage);
		dojo.doc._buildCache(input);
	},

	_functionPackage: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
		dojo.debug("_functionPackage() name: " + evt.name + " for: " + evt.type + " with: " + type);
		evt.pkg = '';

		var data = dojo.doc._cache['function_names'];
		for(var key in data){
			if(dojo.lang.inArray(data[key], evt.name)){
				evt.pkg = key;
				break;
			}
		}

		if(evt.callbacks && evt.callbacks.length){
			var callback = evt.callbacks.shift();
			callback.call(null, type, data[key], evt);
		}
	},

	_sort: function(a, b){
		if(a[0] < b[0]){
			return -1;
		}
		if(a[0] > b[0]){
			return 1;
		}
	  return 0;
	}
});

dojo.event.topic.subscribe("/doc/search", dojo.doc, "_onDocSearch");
dojo.event.topic.subscribe("/doc/selectFunction", dojo.doc, "_onDocSelectFunction");

dojo.event.topic.registerPublisher("/doc/results", dojo.doc, "_printResults");
dojo.event.topic.registerPublisher("/doc/functionDetail", dojo.doc, "_printFunctionDetail");
__CPAN_FILE__ src/browser_debug.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.hostenv.loadedUris.push("../src/bootstrap1.js");
dojo.hostenv.loadedUris.push("../src/loader.js");
dojo.hostenv.loadedUris.push("../src/hostenv_browser.js");
dojo.hostenv.loadedUris.push("../src/bootstrap2.js");

function removeComments(contents){
	contents = new String((!contents) ? "" : contents);
	// clobber all comments
	contents = contents.replace( /^(.*?)\/\/(.*)$/mg , "$1");
	contents = contents.replace( /(\n)/mg , "__DOJONEWLINE");
	contents = contents.replace( /\/\*(.*?)\*\//g , "");
	return contents.replace( /__DOJONEWLINE/mg , "\n");
}

dojo.hostenv.getRequiresAndProvides = function(contents){
	// FIXME: should probably memoize this!
	if(!contents){ return []; }
	

	// check to see if we need to load anything else first. Ugg.
	var deps = [];
	var tmp;
	RegExp.lastIndex = 0;
	var testExp = /dojo.(hostenv.loadModule|hosetnv.require|require|requireIf|kwCompoundRequire|hostenv.conditionalLoadModule|hostenv.startPackage|provide)\([\w\W]*?\)/mg;
	while((tmp = testExp.exec(contents)) != null){
		deps.push(tmp[0]);
	}
	return deps;
}

dojo.hostenv.getDelayRequiresAndProvides = function(contents){
	// FIXME: should probably memoize this!
	if(!contents){ return []; }

	// check to see if we need to load anything else first. Ugg.
	var deps = [];
	var tmp;
	RegExp.lastIndex = 0;
	var testExp = /dojo.(requireAfterIf)\([\w\W]*?\)/mg;
	while((tmp = testExp.exec(contents)) != null){
		deps.push(tmp[0]);
	}
	return deps;
}

/*
dojo.getNonExistantDescendants = function(objpath){
	var ret = [];
	// fast path for no periods
	if(typeof objpath != "string"){ return dj_global; }
	if(objpath.indexOf('.') == -1){
		if(dj_undef(objpath, dj_global)){
			ret.push[objpath];
		}
		return ret;
	}

	var syms = objpath.split(/\./);
	var obj = dj_global;
	for(var i=0;i<syms.length;++i){
		if(dj_undef(syms[i], obj)){
			for(var j=i; j<syms.length; j++){
				ret.push(syms.slice(0, j+1).join("."));
			}
			break;
		}
	}
	return ret;
}
*/

dojo.clobberLastObject = function(objpath){
	if(objpath.indexOf('.') == -1){
		if(!dj_undef(objpath, dj_global)){
			delete dj_global[objpath];
		}
		return true;
	}

	var syms = objpath.split(/\./);
	var base = dojo.evalObjPath(syms.slice(0, -1).join("."), false);
	var child = syms[syms.length-1];
	if(!dj_undef(child, base)){
		// alert(objpath);
		delete base[child];
		return true;
	}
	return false;
}

var removals = [];

function zip(arr){
	var ret = [];
	var seen = {};
	for(var x=0; x<arr.length; x++){
		if(!seen[arr[x]]){
			ret.push(arr[x]);
			seen[arr[x]] = true;
		}
	}
	return ret;
}

// over-write dj_eval to prevent actual loading of subsequent files
var old_dj_eval = dj_eval;
dj_eval = function(){ return true; }
dojo.hostenv.oldLoadUri = dojo.hostenv.loadUri;
dojo.hostenv.loadUri = function(uri){
	if(dojo.hostenv.loadedUris[uri]){
		return true; // fixes endless recursion opera trac 471
	}
	try{
		var text = this.getText(uri, null, true);
		var requires = dojo.hostenv.getRequiresAndProvides(text);
		eval(requires.join(";"));
		dojo.hostenv.loadedUris.push(uri);
		dojo.hostenv.loadedUris[uri] = true;
		var delayRequires = dojo.hostenv.getDelayRequiresAndProvides(text);
		eval(delayRequires.join(";"));
	}catch(e){ 
		alert(e);
	}
	return true;
}

dojo.hostenv.writeIncludes = function(){
	for(var x=removals.length-1; x>=0; x--){
		dojo.clobberLastObject(removals[x]);
	}
	var depList = [];
	var seen = {};
	for(var x=0; x<dojo.hostenv.loadedUris.length; x++){
		var curi = dojo.hostenv.loadedUris[x];
		// dojo.debug(curi);
		if(!seen[curi]){
			seen[curi] = true;
			depList.push(curi);
		}
	}

	dojo.hostenv._global_omit_module_check = true;
	for(var x=4; x<depList.length; x++){
		document.write("<script type='text/javascript' src='"+depList[x]+"'></script>");
	}
	document.write("<script type='text/javascript'>dojo.hostenv._global_omit_module_check = false;</script>");

	// turn off debugAtAllCosts, so that dojo.require() calls inside of ContentPane hrefs
	// work correctly
	dj_eval = old_dj_eval;
	dojo.hostenv.loadUri = dojo.hostenv.oldLoadUri;
}

__CPAN_FILE__ src/json.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.json");
dojo.require("dojo.lang.func");
dojo.require("dojo.string.extras");
dojo.require("dojo.AdapterRegistry");

dojo.json = {
	jsonRegistry: new dojo.AdapterRegistry(),

	register: function(name, check, wrap, /*optional*/ override){
		/***

			Register a JSON serialization function.	 JSON serialization 
			functions should take one argument and return an object
			suitable for JSON serialization:

			- string
			- number
			- boolean
			- undefined
			- object
				- null
				- Array-like (length property that is a number)
				- Objects with a "json" method will have this method called
				- Any other object will be used as {key:value, ...} pairs
			
			If override is given, it is used as the highest priority
			JSON serialization, otherwise it will be used as the lowest.
		***/

		dojo.json.jsonRegistry.register(name, check, wrap, override);
	},

	evalJson: function(/* jsonString */ json){
		// FIXME: should this accept mozilla's optional second arg?
		try {
			return eval("(" + json + ")");
		}catch(e){
			dojo.debug(e);
			return json;
		}
	},

	evalJSON: function (json) {
		dojo.deprecated("dojo.json.evalJSON", "use dojo.json.evalJson", "0.4");
		return this.evalJson(json);
	},

	serialize: function(o){
		/***
			Create a JSON serialization of an object, note that this doesn't
			check for infinite recursion, so don't do that!
		***/

		var objtype = typeof(o);
		if(objtype == "undefined"){
			return "undefined";
		}else if((objtype == "number")||(objtype == "boolean")){
			return o + "";
		}else if(o === null){
			return "null";
		}
		if (objtype == "string") { return dojo.string.escapeString(o); }
		// recurse
		var me = arguments.callee;
		// short-circuit for objects that support "json" serialization
		// if they return "self" then just pass-through...
		var newObj;
		if(typeof(o.__json__) == "function"){
			newObj = o.__json__();
			if(o !== newObj){
				return me(newObj);
			}
		}
		if(typeof(o.json) == "function"){
			newObj = o.json();
			if (o !== newObj) {
				return me(newObj);
			}
		}
		// array
		if(objtype != "function" && typeof(o.length) == "number"){
			var res = [];
			for(var i = 0; i < o.length; i++){
				var val = me(o[i]);
				if(typeof(val) != "string"){
					val = "undefined";
				}
				res.push(val);
			}
			return "[" + res.join(",") + "]";
		}
		// look in the registry
		try {
			window.o = o;
			newObj = dojo.json.jsonRegistry.match(o);
			return me(newObj);
		}catch(e){
			// dojo.debug(e);
		}
		// it's a function with no adapter, bad
		if(objtype == "function"){
			return null;
		}
		// generic object code path
		res = [];
		for (var k in o){
			var useKey;
			if (typeof(k) == "number"){
				useKey = '"' + k + '"';
			}else if (typeof(k) == "string"){
				useKey = dojo.string.escapeString(k);
			}else{
				// skip non-string or number keys
				continue;
			}
			val = me(o[k]);
			if(typeof(val) != "string"){
				// skip non-serializable values
				continue;
			}
			res.push(useKey + ":" + val);
		}
		return "{" + res.join(",") + "}";
	}
};

__CPAN_FILE__ src/string.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.string");
dojo.require("dojo.string.common");

__CPAN_FILE__ src/io.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.io.IO");
dojo.require("dojo.string");
dojo.require("dojo.lang.extras");

/******************************************************************************
 *	Notes about dojo.io design:
 *	
 *	The dojo.io.* package has the unenviable task of making a lot of different
 *	types of I/O feel natural, despite a universal lack of good (or even
 *	reasonable!) I/O capability in the host environment. So lets pin this down
 *	a little bit further.
 *
 *	Rhino:
 *		perhaps the best situation anywhere. Access to Java classes allows you
 *		to do anything one might want in terms of I/O, both synchronously and
 *		async. Can open TCP sockets and perform low-latency client/server
 *		interactions. HTTP transport is available through Java HTTP client and
 *		server classes. Wish it were always this easy.
 *
 *	xpcshell:
 *		XPCOM for I/O. A cluster-fuck to be sure.
 *
 *	spidermonkey:
 *		S.O.L.
 *
 *	Browsers:
 *		Browsers generally do not provide any useable filesystem access. We are
 *		therefore limited to HTTP for moving information to and from Dojo
 *		instances living in a browser.
 *
 *		XMLHTTP:
 *			Sync or async, allows reading of arbitrary text files (including
 *			JS, which can then be eval()'d), writing requires server
 *			cooperation and is limited to HTTP mechanisms (POST and GET).
 *
 *		<iframe> hacks:
 *			iframe document hacks allow browsers to communicate asynchronously
 *			with a server via HTTP POST and GET operations. With significant
 *			effort and server cooperation, low-latency data transit between
 *			client and server can be acheived via iframe mechanisms (repubsub).
 *
 *		SVG:
 *			Adobe's SVG viewer implements helpful primitives for XML-based
 *			requests, but receipt of arbitrary text data seems unlikely w/o
 *			<![CDATA[]]> sections.
 *
 *
 *	A discussion between Dylan, Mark, Tom, and Alex helped to lay down a lot
 *	the IO API interface. A transcript of it can be found at:
 *		http://dojotoolkit.org/viewcvs/viewcvs.py/documents/irc/irc_io_api_log.txt?rev=307&view=auto
 *	
 *	Also referenced in the design of the API was the DOM 3 L&S spec:
 *		http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/load-save.html
 ******************************************************************************/

// a map of the available transport options. Transports should add themselves
// by calling add(name)
dojo.io.transports = [];
dojo.io.hdlrFuncNames = [ "load", "error", "timeout" ]; // we're omitting a progress() event for now

dojo.io.Request = function(url, mimetype, transport, changeUrl){
	if((arguments.length == 1)&&(arguments[0].constructor == Object)){
		this.fromKwArgs(arguments[0]);
	}else{
		this.url = url;
		if(mimetype){ this.mimetype = mimetype; }
		if(transport){ this.transport = transport; }
		if(arguments.length >= 4){ this.changeUrl = changeUrl; }
	}
}

dojo.lang.extend(dojo.io.Request, {

	/** The URL to hit */
	url: "",
	
	/** The mime type used to interrpret the response body */
	mimetype: "text/plain",
	
	/** The HTTP method to use */
	method: "GET",
	
	/** An Object containing key-value pairs to be included with the request */
	content: undefined, // Object
	
	/** The transport medium to use */
	transport: undefined, // String
	
	/** If defined the URL of the page is physically changed */
	changeUrl: undefined, // String
	
	/** A form node to use in the request */
	formNode: undefined, // HTMLFormElement
	
	/** Whether the request should be made synchronously */
	sync: false,
	
	bindSuccess: false,

	/** Cache/look for the request in the cache before attempting to request?
	 *  NOTE: this isn't a browser cache, this is internal and would only cache in-page
	 */
	useCache: false,

	/** Prevent the browser from caching this by adding a query string argument to the URL */
	preventCache: false,
	
	// events stuff
	load: function(type, data, evt){ },
	error: function(type, error){ },
	timeout: function(type){ },
	handle: function(){ },

	//FIXME: change BrowserIO.js to use timeouts? IframeIO?
	// The number of seconds to wait until firing a timeout callback.
	// If it is zero, that means, don't do a timeout check.
	timeoutSeconds: 0,
	
	// the abort method needs to be filled in by the transport that accepts the
	// bind() request
	abort: function(){ },
	
	// backButton: function(){ },
	// forwardButton: function(){ },

	fromKwArgs: function(kwArgs){
		// normalize args
		if(kwArgs["url"]){ kwArgs.url = kwArgs.url.toString(); }
		if(kwArgs["formNode"]) { kwArgs.formNode = dojo.byId(kwArgs.formNode); }
		if(!kwArgs["method"] && kwArgs["formNode"] && kwArgs["formNode"].method) {
			kwArgs.method = kwArgs["formNode"].method;
		}
		
		// backwards compatibility
		if(!kwArgs["handle"] && kwArgs["handler"]){ kwArgs.handle = kwArgs.handler; }
		if(!kwArgs["load"] && kwArgs["loaded"]){ kwArgs.load = kwArgs.loaded; }
		if(!kwArgs["changeUrl"] && kwArgs["changeURL"]) { kwArgs.changeUrl = kwArgs.changeURL; }

		// encoding fun!
		kwArgs.encoding = dojo.lang.firstValued(kwArgs["encoding"], djConfig["bindEncoding"], "");

		kwArgs.sendTransport = dojo.lang.firstValued(kwArgs["sendTransport"], djConfig["ioSendTransport"], false);

		var isFunction = dojo.lang.isFunction;
		for(var x=0; x<dojo.io.hdlrFuncNames.length; x++){
			var fn = dojo.io.hdlrFuncNames[x];
			if(isFunction(kwArgs[fn])){ continue; }
			if(isFunction(kwArgs["handle"])){
				kwArgs[fn] = kwArgs.handle;
			}
			// handler is aliased above, shouldn't need this check
			/* else if(dojo.lang.isObject(kwArgs.handler)){
				if(isFunction(kwArgs.handler[fn])){
					kwArgs[fn] = kwArgs.handler[fn]||kwArgs.handler["handle"]||function(){};
				}
			}*/
		}
		dojo.lang.mixin(this, kwArgs);
	}

});

dojo.io.Error = function(msg, type, num){
	this.message = msg;
	this.type =  type || "unknown"; // must be one of "io", "parse", "unknown"
	this.number = num || 0; // per-substrate error number, not normalized
}

dojo.io.transports.addTransport = function(name){
	this.push(name);
	// FIXME: do we need to handle things that aren't direct children of the
	// dojo.io namespace? (say, dojo.io.foo.fooTransport?)
	this[name] = dojo.io[name];
}

// binding interface, the various implementations register their capabilities
// and the bind() method dispatches
dojo.io.bind = function(request){
	// if the request asks for a particular implementation, use it
	if(!(request instanceof dojo.io.Request)){
		try{
			request = new dojo.io.Request(request);
		}catch(e){ dojo.debug(e); }
	}
	var tsName = "";
	if(request["transport"]){
		tsName = request["transport"];
		// FIXME: it would be good to call the error handler, although we'd
		// need to use setTimeout or similar to accomplish this and we can't
		// garuntee that this facility is available.
		if(!this[tsName]){ return request; }
	}else{
		// otherwise we do our best to auto-detect what available transports
		// will handle 
		for(var x=0; x<dojo.io.transports.length; x++){
			var tmp = dojo.io.transports[x];
			if((this[tmp])&&(this[tmp].canHandle(request))){
				tsName = tmp;
			}
		}
		if(tsName == ""){ return request; }
	}
	this[tsName].bind(request);
	request.bindSuccess = true;
	return request;
}

dojo.io.queueBind = function(request){
	if(!(request instanceof dojo.io.Request)){
		try{
			request = new dojo.io.Request(request);
		}catch(e){ dojo.debug(e); }
	}

	// make sure we get called if/when we get a response
	var oldLoad = request.load;
	request.load = function(){
		dojo.io._queueBindInFlight = false;
		var ret = oldLoad.apply(this, arguments);
		dojo.io._dispatchNextQueueBind();
		return ret;
	}

	var oldErr = request.error;
	request.error = function(){
		dojo.io._queueBindInFlight = false;
		var ret = oldErr.apply(this, arguments);
		dojo.io._dispatchNextQueueBind();
		return ret;
	}

	dojo.io._bindQueue.push(request);
	dojo.io._dispatchNextQueueBind();
	return request;
}

dojo.io._dispatchNextQueueBind = function(){
	if(!dojo.io._queueBindInFlight){
		dojo.io._queueBindInFlight = true;
		if(dojo.io._bindQueue.length > 0){
			dojo.io.bind(dojo.io._bindQueue.shift());
		}else{
			dojo.io._queueBindInFlight = false;
		}
	}
}
dojo.io._bindQueue = [];
dojo.io._queueBindInFlight = false;

dojo.io.argsFromMap = function(map, encoding, last){
	var enc = /utf/i.test(encoding||"") ? encodeURIComponent : dojo.string.encodeAscii;
	var mapped = [];
	var control = new Object();
	for(var name in map){
		var domap = function(elt){
			var val = enc(name)+"="+enc(elt);
			mapped[(last == name) ? "push" : "unshift"](val);
		}
		if(!control[name]){
			var value = map[name];
			// FIXME: should be isArrayLike?
			if (dojo.lang.isArray(value)){
				dojo.lang.forEach(value, domap);
			}else{
				domap(value);
			}
		}
	}
	return mapped.join("&");
}

dojo.io.setIFrameSrc = function(iframe, src, replace){
	try{
		var r = dojo.render.html;
		// dojo.debug(iframe);
		if(!replace){
			if(r.safari){
				iframe.location = src;
			}else{
				frames[iframe.name].location = src;
			}
		}else{
			// Fun with DOM 0 incompatibilities!
			var idoc;
			if(r.ie){
				idoc = iframe.contentWindow.document;
			}else if(r.safari){
				idoc = iframe.document;
			}else{ //  if(r.moz){
				idoc = iframe.contentWindow;
			}

			//For Safari (at least 2.0.3) and Opera, if the iframe
			//has just been created but it doesn't have content
			//yet, then iframe.document may be null. In that case,
			//use iframe.location and return.
			if(!idoc){
				iframe.location = src;
				return;
			}else{
				idoc.location.replace(src);
			}
		}
	}catch(e){ 
		dojo.debug(e); 
		dojo.debug("setIFrameSrc: "+e); 
	}
}

/*
dojo.io.sampleTranport = new function(){
	this.canHandle = function(kwArgs){
		// canHandle just tells dojo.io.bind() if this is a good transport to
		// use for the particular type of request.
		if(	
			(
				(kwArgs["mimetype"] == "text/plain") ||
				(kwArgs["mimetype"] == "text/html") ||
				(kwArgs["mimetype"] == "text/javascript")
			)&&(
				(kwArgs["method"] == "get") ||
				( (kwArgs["method"] == "post") && (!kwArgs["formNode"]) )
			)
		){
			return true;
		}

		return false;
	}

	this.bind = function(kwArgs){
		var hdlrObj = {};

		// set up a handler object
		for(var x=0; x<dojo.io.hdlrFuncNames.length; x++){
			var fn = dojo.io.hdlrFuncNames[x];
			if(typeof kwArgs.handler == "object"){
				if(typeof kwArgs.handler[fn] == "function"){
					hdlrObj[fn] = kwArgs.handler[fn]||kwArgs.handler["handle"];
				}
			}else if(typeof kwArgs[fn] == "function"){
				hdlrObj[fn] = kwArgs[fn];
			}else{
				hdlrObj[fn] = kwArgs["handle"]||function(){};
			}
		}

		// build a handler function that calls back to the handler obj
		var hdlrFunc = function(evt){
			if(evt.type == "onload"){
				hdlrObj.load("load", evt.data, evt);
			}else if(evt.type == "onerr"){
				var errObj = new dojo.io.Error("sampleTransport Error: "+evt.msg);
				hdlrObj.error("error", errObj);
			}
		}

		// the sample transport would attach the hdlrFunc() when sending the
		// request down the pipe at this point
		var tgtURL = kwArgs.url+"?"+dojo.io.argsFromMap(kwArgs.content);
		// sampleTransport.sendRequest(tgtURL, hdlrFunc);
	}

	dojo.io.transports.addTransport("sampleTranport");
}
*/

__CPAN_FILE__ src/experimental.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.experimental");

/**
 * Convenience for informing of experimental code.
 */
dojo.experimental = function(packageName, extra){
	var mess = "EXPERIMENTAL: " + packageName;
	mess += " -- Not yet ready for use.  APIs subject to change without notice.";
	if(extra){ mess += " " + extra; }
	dojo.debug(mess);
}

__CPAN_FILE__ src/hostenv_dashboard.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.render.name = dojo.hostenv.name_ = "dashboard";

dojo.hostenv.println = function(/*String*/ message){
	// summary: Prints a message to the OS X console
	return alert(message); // null
}

dojo.hostenv.getXmlhttpObject = function(/*Object*/ kwArgs){
	// summary: Returns the appropriate transfer object for the call type
	if(widget.system && kwArgs){
		if((kwArgs.contentType && kwArgs.contentType.indexOf("text/") != 0) || (kwArgs.headers && kwArgs.headers["content-type"] && kwArgs.headers["content-type"].indexOf("text/") != 0)){
			var curl = new dojo.hostenv.CurlRequest;
			curl._save = true;
			return curl;
		}else if(kwArgs.method && kwArgs.method.toUpperCase() == "HEAD"){
			return new dojo.hostenv.CurlRequest;
		}else if(kwArgs.headers && kwArgs.header.referer){
			return new dojo.hostenv.CurlRequest; 
		}
	}
	return new XMLHttpRequest; // XMLHttpRequest
}

dojo.hostenv.CurlRequest = function(){
	// summary: Emulates the XMLHttpRequest Object
	this.onreadystatechange = null;
	this.readyState = 0;
	this.responseText = "";
	this.responseXML = null;
	this.status = 0;
	this.statusText = "";
	this._method = "";
	this._url = "";
	this._async = true;
	this._referrer = "";
	this._headers = [];
	this._save = false;
	this._responseHeader = "";
	this._responseHeaders = {};
	this._fileName = "";
	this._username = "";
	this._password = "";
}

dojo.hostenv.CurlRequest.prototype.open = function(/*String*/ method, /*URL*/ url, /*Boolean?*/ async, /*String?*/ username, /*String?*/ password){
	this._method = method;
	this._url = url;
	if(async){
		this._async = async;
	}
	if(username){
		this._username = username;
	}
	if(password){
		this._password = password;
	}
}

dojo.hostenv.CurlRequest.prototype.setRequestHeader = function(/*String*/ label, /*String*/ value){
	switch(label){
		case "Referer":
			this._referrer = value;
			break;
		case "content-type":
			break;
		default:
			this._headers.push(label + "=" + value);
			break;
	}
}

dojo.hostenv.CurlRequest.prototype.getAllResponseHeaders = function(){
	return this._responseHeader; // String
}

dojo.hostenv.CurlRequest.prototype.getResponseHeader = function(/*String*/ headerLabel){
	return this._responseHeaders[headerLabel]; // String
}

// -sS = Show only errors in errorString
// -i = Display headers with return
// -e = Referrer URI
// -H = Headers
// -d = data to be sent (forces POST)
// -G = forces GET
// -o = Writes to file (in the cache directory)
// -I = Only load headers
// -u = user:password
dojo.hostenv.CurlRequest.prototype.send = function(/*String*/ content){
	this.readyState = 1;
	if(this.onreadystatechange){
		this.onreadystatechange.call(this);
	}
	var query = {sS: ""};
	if(this._referrer){
		query.e = this._referrer;
	}
	if(this._headers.length){
		query.H = this._headers.join("&");
	}
	if(this._username){
		if(this._password){
			query.u = this._username + ":" + this._password;
		}else{
			query.u = this._username;
		}
	}
	if(content){
		query.d = this.content;
		if(this._method != "POST"){
			query.G = "";
		}
	}
	if(this._method == "HEAD"){
		query.I = "";
	}else{
		if(this._save){
			query.I = ""; // Get the headers in the initial query
		}else{
			query.i = "";
		}
	}

	var system = widget.system(dojo.hostenv.CurlRequest._formatCall(query, this._url), null);
	this.readyState = 2;
	if(this.onreadystatechange){
		this.onreadystatechange.call(this);
	}
	if(system.errorString){
		this.responseText = system.errorString;
		this.status = 0;
	}else{
		if(this._save){
			this._responseHeader = system.outputString;
		}else{
			var split = system.outputString.replace(/\r/g, "").split("\n\n", 2);
			this._responseHeader = split[0];
			this.responseText = split[1];
		}
		split = this._responseHeader.split("\n");
		this.statusText = split.shift();
		this.status = this.statusText.split(" ")[1];
		for(var i = 0, header; header = split[i]; i++){
			var header_split = header.split(": ", 2);
			this._responseHeaders[header_split[0]] = header_split[1];
		}
		if(this._save){
			widget.system("/bin/mkdir cache", null);
			// First, make a file name
			this._fileName = this._url.split("/").pop().replace(/\W/g, "");
			// Then, get its extension
			this._fileName += "." + this._responseHeaders["Content-Type"].replace(/[\r\n]/g, "").split("/").pop()
			delete query.I;
			query.o = "cache/" + this._fileName; // Tell it where to be saved.
			system = widget.system(dojo.hostenv.CurlRequest._formatCall(query, this._url), null);
			if(!system.errorString){
				this.responseText = "cache/" + this._fileName;
			}
		}else if(this._method == "HEAD"){
			this.responseText = this._responseHeader;
		}
	}

	this.readyState = 4;
	if(this.onreadystatechange){
		this.onreadystatechange.call(this);
	}
}

dojo.hostenv.CurlRequest._formatCall = function(query, url){
	var call = ["/usr/bin/curl"];
	for(var key in query){
		if(query[key] != ""){
			call.push("-" + key + " '" + query[key].replace(/'/g, "\'") + "'");
		}else{
			call.push("-" + key);
		}
	}
	call.push("'" + url.replace(/'/g, "\'") + "'");
	return call.join(" ");
}

dojo.hostenv.exit = function(){
	if(widget.system){
		widget.system("/bin/rm -rf cache/*", null);
	}
}

__CPAN_FILE__ src/loader_xd.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

//Cross-domain package loader.

//FIXME: How will xd loading work with debugAtAllCosts? Any bad interactions?
//FIXME: widgets won't work fully (HTML/CSS) and also because of the requireIf() thing.

dojo.hostenv.resetXd = function(){
	//This flag indicates where or not we have crossed into xdomain territory. Once any package says
	//it is cross domain, then the rest of the packages have to be treated as xdomain because we need
	//to evaluate packages in order. If there is a xdomain package followed by a xhr package, we can't load
	//the xhr package until the one before it finishes loading. The text of the xhr package will be converted
	//to match the format for a xd package and put in the xd load queue.
	//You can force all packages to be treated as xd by setting the djConfig.forceXDomain.
	this.isXDomain = djConfig.forceXDomain || false;

	this.xdTimer = 0;
	this.xdInFlight = {};
	this.xdOrderedReqs = [];
	this.xdDepMap = {};
	this.xdContents = [];
}

//Call reset immediately to set the state.
dojo.hostenv.resetXd();

dojo.hostenv.createXdPackage = function(contents){
	//Find dependencies.
	var deps = [];
    var depRegExp = /dojo.(require|requireIf|requireAll|provide|requireAfterIf|requireAfter|kwCompoundRequire|conditionalRequire|hostenv\.conditionalLoadModule|.hostenv\.loadModule|hostenv\.moduleLoaded)\(([\w\W]*?)\)/mg;
    var match;
	while((match = depRegExp.exec(contents)) != null){
		deps.push("\"" + match[1] + "\", " + match[2]);
	}

	//Create package object and the call to packageLoaded.
	var output = [];
	output.push("dojo.hostenv.packageLoaded({\n");

	//Add dependencies
	if(deps.length > 0){
		output.push("depends: [");
		for(var i = 0; i < deps.length; i++){
			if(i > 0){
				output.push(",\n");
			}
			output.push("[" + deps[i] + "]");
		}
		output.push("],");
	}

	//Add the contents of the file inside a function.
	//Pass in dojo as an argument to the function to help with
	//allowing multiple versions of dojo in a page.
	output.push("\ndefinePackage: function(dojo){");
	output.push(contents);
	output.push("\n}});");
	
	return output.join("");
}

dojo.hostenv.loadPath = function(relpath, module /*optional*/, cb /*optional*/){
	//Only do getBaseScriptUri if path does not start with a URL with a protocol.
	//If there is a colon before the first / then, we have a URL with a protocol.
	var colonIndex = relpath.indexOf(":");
	var slashIndex = relpath.indexOf("/");
	var uri;
	var currentIsXDomain = false;
	if(colonIndex > 0 && colonIndex < slashIndex){
		uri = relpath;
		this.isXDomain = currentIsXDomain = true;
	}else{
		uri = this.getBaseScriptUri() + relpath;

		//Is ithe base script URI-based URL a cross domain URL?
		colonIndex = uri.indexOf(":");
		slashIndex = uri.indexOf("/");
		if(colonIndex > 0 && colonIndex < slashIndex && (!location.host || uri.indexOf("http://" + location.host) != 0)){
			this.isXDomain = currentIsXDomain = true;
		}
	}

	if(djConfig.cacheBust && dojo.render.html.capable) { uri += "?" + String(djConfig.cacheBust).replace(/\W+/g,""); }
	try{
		return ((!module || this.isXDomain) ? this.loadUri(uri, cb, currentIsXDomain, module) : this.loadUriAndCheck(uri, module, cb));
	}catch(e){
		dojo.debug(e);
		return false;
	}
}

//Overriding loadUri for now. Wanted to override getText(), but it is used by
//the widget code in too many, synchronous ways right now. This means the xd stuff
//is not suitable for widgets yet.
dojo.hostenv.loadUri = function(uri, cb, currentIsXDomain, module){
	if(this.loadedUris[uri]){
		return 1;
	}

	//Add the module (package) to the list of modules.
	if(this.isXDomain){
		//Curious: is this array going to get whacked with multiple access since scripts
		//load asynchronously and may be accessing the array at the same time?
		//JS is single-threaded supposedly, so it should be ok. And we don't need
		//a precise ordering.
		this.xdOrderedReqs.push(module);

		//Add to waiting packages.
		//If this is a __package__.js file, then this must be
		//a package.* request (since xdomain can only work with the first
		//path in a package search list. However, .* module names are not
		//passed to this function, so do an adjustment here.
		if(uri.indexOf("__package__") != -1){
			module += ".*";
		}

		this.xdInFlight[module] = true;

		//Increment inFlightCount
		//This will stop the modulesLoaded from firing all the way.
		this.inFlightCount++;
				
		//Start timer
		if(!this.xdTimer){
			this.xdTimer = setInterval("dojo.hostenv.watchInFlightXDomain();", 100);
		}
		this.xdStartTime = (new Date()).getTime();
	}

	if (currentIsXDomain){
		//Fix name to be a .xd.fileextension name.
		var lastIndex = uri.lastIndexOf('.');
		if(lastIndex <= 0){
			lastIndex = uri.length - 1;
		}

		var xdUri = uri.substring(0, lastIndex) + ".xd";
		if(lastIndex != uri.length - 1){
			xdUri += uri.substring(lastIndex, uri.length);
		}

		//Add to script src
		var element = document.createElement("script");
		element.type = "text/javascript";
		element.src = xdUri;
		if(!this.headElement){
			this.headElement = document.getElementsByTagName("head")[0];
		}
		this.headElement.appendChild(element);
	}else{
		var contents = this.getText(uri, null, true);
		if(contents == null){ return 0; }
		
		if(this.isXDomain){
			var pkg = this.createXdPackage(contents);
			dj_eval(pkg);
		}else{
			if(cb){ contents = '('+contents+')'; }
			var value = dj_eval(contents);
			if(cb){
				cb(value);
			}
		}
	}

	//These steps are done in the non-xd loader version of this function.
	//Maintain these steps to fit in with the existing system.
	this.loadedUris[uri] = true;
	return 1;
}

dojo.hostenv.packageLoaded = function(pkg){
	var deps = pkg.depends;
	var requireList = null;
	var requireAfterList = null;
	var provideList = [];
	if(deps && deps.length > 0){
		var dep = null;
		var insertHint = 0;
		var attachedPackage = false;
		for(var i = 0; i < deps.length; i++){
			dep = deps[i];

			//Look for specific dependency indicators.
			if (dep[0] == "provide" || dep[0] == "hostenv.moduleLoaded"){
				provideList.push(dep[1]);
			}else{
				if(!requireList){
					requireList = [];
				}
				if(!requireAfterList){
					requireAfterList = [];
				}

				var unpackedDeps = this.unpackXdDependency(dep);
				if(unpackedDeps.requires){
					requireList = requireList.concat(unpackedDeps.requires);
				}
				if(unpackedDeps.requiresAfter){
					requireAfterList = requireAfterList.concat(unpackedDeps.requiresAfter);
				}
			}

			//Call the dependency indicator to allow for the normal dojo setup.
			//Only allow for one dot reference, for the hostenv.* type calls.
			var depType = dep[0];
			var objPath = depType.split(".");
			if(objPath.length == 2){
				dojo[objPath[0]][objPath[1]].apply(dojo[objPath[0]], dep.slice(1));
			}else{
				dojo[depType].apply(dojo, dep.slice(1));
			}
		}

		//Save off the package contents for definition later.
		var contentIndex = this.xdContents.push({content: pkg.definePackage, isDefined: false}) - 1;

		//Add provide/requires to dependency map.
		for(var i = 0; i < provideList.length; i++){
			this.xdDepMap[provideList[i]] = { requires: requireList, requiresAfter: requireAfterList, contentIndex: contentIndex };
		}

		//Now update the inflight status for any provided packages in this loaded package.
		//Do this at the very end (in a *separate* for loop) to avoid shutting down the 
		//inflight timer check too soon.
		for(var i = 0; i < provideList.length; i++){
			this.xdInFlight[provideList[i]] = false;
		}
	}
}

//This is a bit brittle: it has to know about the dojo methods that deal with dependencies
//It would be ideal to intercept the actual methods and do something fancy at that point,
//but I have concern about knowing which provide to match to the dependency in that case,
//since scripts can load whenever they want, and trigger new calls to dojo.hostenv.packageLoaded().
dojo.hostenv.unpackXdDependency = function(dep){
	//Extract the dependency(ies).
	var newDeps = null;
	var newAfterDeps = null;
	switch(dep[0]){
		case "requireIf":
		case "requireAfterIf":
		case "conditionalRequire":
			//First arg (dep[1]) is the test. Depedency is dep[2].
			if((dep[1] === true)||(dep[1]=="common")||(dep[1] && dojo.render[dep[1]].capable)){
				newDeps = [{name: dep[2], content: null}];
			}
			break;
		case "requireAll":
			//the arguments are an array, each element a call to require.
			//Get rid of first item, which is "requireAll".
			dep.shift();
			newDeps = dep;
			dojo.hostenv.flattenRequireArray(newDeps);
			break;
		case "kwCompoundRequire":
		case "hostenv.conditionalLoadModule":
			var modMap = dep[1];
			var common = modMap["common"]||[];
			var newDeps = (modMap[dojo.hostenv.name_]) ? common.concat(modMap[dojo.hostenv.name_]||[]) : common.concat(modMap["default"]||[]);	
			dojo.hostenv.flattenRequireArray(newDeps);
			break;
		case "require":
		case "requireAfter":
		case "hostenv.loadModule":
			//Just worry about dep[1]
			newDeps = [{name: dep[1], content: null}];
			break;
	}

	//The requireAfterIf or requireAfter needs to be evaluated after the current package is evaluated.
	if(dep[0] == "requireAfterIf"){
		newAfterDeps = newDeps;
		newDeps = null;
	}
	return {requires: newDeps, requiresAfter: newAfterDeps};
}

//Walks the requires and evaluates package contents in
//the right order.
dojo.hostenv.xdWalkReqs = function(){
	var reqChain = null;
	var req;
	for(var i = 0; i < this.xdOrderedReqs.length; i++){
		req = this.xdOrderedReqs[i];
		if(this.xdDepMap[req]){
			reqChain = [req];
			reqChain[req] = true; //Allow for fast lookup of the req in the array
			this.xdEvalReqs(reqChain);
		}
	}
}

//Trace down any requires.
dojo.hostenv.xdTraceReqs = function(reqs, reqChain){
	if(reqs && reqs.length > 0){
		var nextReq;
		for(var i = 0; i < reqs.length; i++){
			nextReq = reqs[i].name;
			if(nextReq && !reqChain[nextReq]){
				//New req depedency. Follow it down.
				reqChain.push(nextReq);
				reqChain[nextReq] = true;
				this.xdEvalReqs(reqChain);
			}
		}
	}
}

//Do a depth first, breadth second search and eval or reqs.
dojo.hostenv.xdEvalReqs = function(reqChain){
	if(reqChain.length > 0){
		var req = reqChain[reqChain.length - 1];
		var pkg = this.xdDepMap[req];
		if(pkg){
			//Trace down any requires for this package.
			this.xdTraceReqs(pkg.requires, reqChain);

			//Evaluate the package.
			var contents = this.xdContents[pkg.contentIndex];
			if(!contents.isDefined){
				//Evaluate the package to bring it into being.
				//Pass dojo in so that later, to support multiple versions of dojo
				//in a page, we can pass which version of dojo to use.
				contents.content(dojo);
				contents.isDefined = true;
			}
			this.xdDepMap[req] = null;

			//Trace down any requireAfters for this package..
			this.xdTraceReqs(pkg.requiresAfter, reqChain);
		}

		//Done with that require. Remove it and go to the next one.
		reqChain.pop();
		this.xdEvalReqs(reqChain);
	}
}

dojo.hostenv.clearXdInterval = function(){
	clearInterval(this.xdTimer);
	this.xdTimer = 0;
}

dojo.hostenv.watchInFlightXDomain = function(){
	//Make sure we haven't waited timed out.
	var waitInterval = (djConfig.xdWaitSeconds || 30) * 1000;

	if(this.xdStartTime + waitInterval < (new Date()).getTime()){
		this.clearXdInterval();
		var noLoads = "";
		for(var param in this.xdInFlight){
			if(this.xdInFlight[param]){
				noLoads += param + " ";
			}
		}
		dojo.raise("Could not load cross-domain packages: " + noLoads);
	}

	//If any are true, then still waiting.
	//Come back later.	
	for(var param in this.xdInFlight){
		if(this.xdInFlight[param]){
			return;
		}
	}

	//All done loading. Clean up and notify that we are loaded.
	this.clearXdInterval();

	this.xdWalkReqs();

	//Evaluate any packages that were not evaled before.
	//This normally shouldn't happen with proper dojo.provide and dojo.require
	//usage, but providing it just in case. Note that these may not be executed
	//in the original order that the developer intended.
	//Pass dojo in so that later, to support multiple versions of dojo
	//in a page, we can pass which version of dojo to use.
	for(var i = 0; i < this.xdContents.length; i++){
		var current = this.xdContents[i];
		if(current.content && !current.isDefined){
			current.content(dojo);
		}
	}

	//Clean up for the next round of xd loading.
	this.resetXd();

	//Clear inflight count so we will finally do finish work.
	this.inFlightCount = 0; 
	this.callLoaded();
}

dojo.hostenv.flattenRequireArray = function(target){
	//Each result could be an array of 3 elements  (the 3 arguments to dojo.require).
	//We only need the first one.
	if(target){
		for(var i = 0; i < target.length; i++){
			if(target[i] instanceof Array){
				target[i] = {name: target[i][0], content: null};
			}else{
				target[i] = {name: target[i], content: null};
			}
		}
	}
}

__CPAN_FILE__ src/dom.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.dom");
dojo.require("dojo.lang.array");

dojo.dom.ELEMENT_NODE                  = 1;
dojo.dom.ATTRIBUTE_NODE                = 2;
dojo.dom.TEXT_NODE                     = 3;
dojo.dom.CDATA_SECTION_NODE            = 4;
dojo.dom.ENTITY_REFERENCE_NODE         = 5;
dojo.dom.ENTITY_NODE                   = 6;
dojo.dom.PROCESSING_INSTRUCTION_NODE   = 7;
dojo.dom.COMMENT_NODE                  = 8;
dojo.dom.DOCUMENT_NODE                 = 9;
dojo.dom.DOCUMENT_TYPE_NODE            = 10;
dojo.dom.DOCUMENT_FRAGMENT_NODE        = 11;
dojo.dom.NOTATION_NODE                 = 12;
	
dojo.dom.dojoml = "http://www.dojotoolkit.org/2004/dojoml";

/**
 *	comprehensive list of XML namespaces
**/
dojo.dom.xmlns = {
	svg : "http://www.w3.org/2000/svg",
	smil : "http://www.w3.org/2001/SMIL20/",
	mml : "http://www.w3.org/1998/Math/MathML",
	cml : "http://www.xml-cml.org",
	xlink : "http://www.w3.org/1999/xlink",
	xhtml : "http://www.w3.org/1999/xhtml",
	xul : "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
	xbl : "http://www.mozilla.org/xbl",
	fo : "http://www.w3.org/1999/XSL/Format",
	xsl : "http://www.w3.org/1999/XSL/Transform",
	xslt : "http://www.w3.org/1999/XSL/Transform",
	xi : "http://www.w3.org/2001/XInclude",
	xforms : "http://www.w3.org/2002/01/xforms",
	saxon : "http://icl.com/saxon",
	xalan : "http://xml.apache.org/xslt",
	xsd : "http://www.w3.org/2001/XMLSchema",
	dt: "http://www.w3.org/2001/XMLSchema-datatypes",
	xsi : "http://www.w3.org/2001/XMLSchema-instance",
	rdf : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
	rdfs : "http://www.w3.org/2000/01/rdf-schema#",
	dc : "http://purl.org/dc/elements/1.1/",
	dcq: "http://purl.org/dc/qualifiers/1.0",
	"soap-env" : "http://schemas.xmlsoap.org/soap/envelope/",
	wsdl : "http://schemas.xmlsoap.org/wsdl/",
	AdobeExtensions : "http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
};

dojo.dom.isNode = function(wh){
	if(typeof Element == "object") {
		try {
			return wh instanceof Element;
		} catch(E) {}
	} else {
		// best-guess
		return wh && !isNaN(wh.nodeType);
	}
}

dojo.dom.getTagName = function(node){
	dojo.deprecated("dojo.dom.getTagName", "use node.tagName instead", "0.4");

	var tagName = node.tagName;
	if(tagName.substr(0,5).toLowerCase()!="dojo:"){
		
		if(tagName.substr(0,4).toLowerCase()=="dojo"){
			// FIXME: this assuumes tag names are always lower case
			return "dojo:" + tagName.substring(4).toLowerCase();
		}

		// allow lower-casing
		var djt = node.getAttribute("dojoType")||node.getAttribute("dojotype");
		if(djt){
			return "dojo:"+djt.toLowerCase();
		}
		
		if((node.getAttributeNS)&&(node.getAttributeNS(this.dojoml,"type"))){
			return "dojo:" + node.getAttributeNS(this.dojoml,"type").toLowerCase();
		}
		try{
			// FIXME: IE really really doesn't like this, so we squelch
			// errors for it
			djt = node.getAttribute("dojo:type");
		}catch(e){ /* FIXME: log? */ }
		if(djt){
			return "dojo:"+djt.toLowerCase();
		}

		if((!dj_global["djConfig"])||(!djConfig["ignoreClassNames"])){
			// FIXME: should we make this optionally enabled via djConfig?
			var classes = node.className||node.getAttribute("class");
			// FIXME: following line, without check for existence of classes.indexOf
			// breaks firefox 1.5's svg widgets
			if((classes)&&(classes.indexOf)&&(classes.indexOf("dojo-") != -1)){
				var aclasses = classes.split(" ");
				for(var x=0; x<aclasses.length; x++){
					if((aclasses[x].length>5)&&(aclasses[x].indexOf("dojo-")>=0)){
						return "dojo:"+aclasses[x].substr(5).toLowerCase();
					}
				}
			}
		}

	}
	return tagName.toLowerCase();
}

dojo.dom.getUniqueId = function(){
	do {
		var id = "dj_unique_" + (++arguments.callee._idIncrement);
	}while(document.getElementById(id));
	return id;
}
dojo.dom.getUniqueId._idIncrement = 0;

dojo.dom.firstElement = dojo.dom.getFirstChildElement = function(parentNode, tagName){
	var node = parentNode.firstChild;
	while(node && node.nodeType != dojo.dom.ELEMENT_NODE){
		node = node.nextSibling;
	}
	if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
		node = dojo.dom.nextElement(node, tagName);
	}
	return node;
}

dojo.dom.lastElement = dojo.dom.getLastChildElement = function(parentNode, tagName){
	var node = parentNode.lastChild;
	while(node && node.nodeType != dojo.dom.ELEMENT_NODE) {
		node = node.previousSibling;
	}
	if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
		node = dojo.dom.prevElement(node, tagName);
	}
	return node;
}

dojo.dom.nextElement = dojo.dom.getNextSiblingElement = function(node, tagName){
	if(!node) { return null; }
	do {
		node = node.nextSibling;
	} while(node && node.nodeType != dojo.dom.ELEMENT_NODE);

	if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
		return dojo.dom.nextElement(node, tagName);
	}
	return node;
}

dojo.dom.prevElement = dojo.dom.getPreviousSiblingElement = function(node, tagName){
	if(!node) { return null; }
	if(tagName) { tagName = tagName.toLowerCase(); }
	do {
		node = node.previousSibling;
	} while(node && node.nodeType != dojo.dom.ELEMENT_NODE);

	if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
		return dojo.dom.prevElement(node, tagName);
	}
	return node;
}

// TODO: hmph
/*this.forEachChildTag = function(node, unaryFunc) {
	var child = this.getFirstChildTag(node);
	while(child) {
		if(unaryFunc(child) == "break") { break; }
		child = this.getNextSiblingTag(child);
	}
}*/

dojo.dom.moveChildren = function(srcNode, destNode, trim){
	var count = 0;
	if(trim) {
		while(srcNode.hasChildNodes() &&
			srcNode.firstChild.nodeType == dojo.dom.TEXT_NODE) {
			srcNode.removeChild(srcNode.firstChild);
		}
		while(srcNode.hasChildNodes() &&
			srcNode.lastChild.nodeType == dojo.dom.TEXT_NODE) {
			srcNode.removeChild(srcNode.lastChild);
		}
	}
	while(srcNode.hasChildNodes()){
		destNode.appendChild(srcNode.firstChild);
		count++;
	}
	return count;
}

dojo.dom.copyChildren = function(srcNode, destNode, trim){
	var clonedNode = srcNode.cloneNode(true);
	return this.moveChildren(clonedNode, destNode, trim);
}

dojo.dom.removeChildren = function(node){
	var count = node.childNodes.length;
	while(node.hasChildNodes()){ node.removeChild(node.firstChild); }
	return count;
}

dojo.dom.replaceChildren = function(node, newChild){
	// FIXME: what if newChild is an array-like object?
	dojo.dom.removeChildren(node);
	node.appendChild(newChild);
}

dojo.dom.removeNode = function(node){
	if(node && node.parentNode){
		// return a ref to the removed child
		return node.parentNode.removeChild(node);
	}
}

dojo.dom.getAncestors = function(node, filterFunction, returnFirstHit) {
	var ancestors = [];
	var isFunction = dojo.lang.isFunction(filterFunction);
	while(node) {
		if (!isFunction || filterFunction(node)) {
			ancestors.push(node);
		}
		if (returnFirstHit && ancestors.length > 0) { return ancestors[0]; }
		
		node = node.parentNode;
	}
	if (returnFirstHit) { return null; }
	return ancestors;
}

dojo.dom.getAncestorsByTag = function(node, tag, returnFirstHit) {
	tag = tag.toLowerCase();
	return dojo.dom.getAncestors(node, function(el){
		return ((el.tagName)&&(el.tagName.toLowerCase() == tag));
	}, returnFirstHit);
}

dojo.dom.getFirstAncestorByTag = function(node, tag) {
	return dojo.dom.getAncestorsByTag(node, tag, true);
}

dojo.dom.isDescendantOf = function(node, ancestor, guaranteeDescendant){
	// guaranteeDescendant allows us to be a "true" isDescendantOf function
	if(guaranteeDescendant && node) { node = node.parentNode; }
	while(node) {
		if(node == ancestor){ return true; }
		node = node.parentNode;
	}
	return false;
}

dojo.dom.innerXML = function(node){
	if(node.innerXML){
		return node.innerXML;
	}else if (node.xml){
		return node.xml;
	}else if(typeof XMLSerializer != "undefined"){
		return (new XMLSerializer()).serializeToString(node);
	}
}

dojo.dom.createDocument = function(){
	var doc = null;

	if(!dj_undef("ActiveXObject")){
		var prefixes = [ "MSXML2", "Microsoft", "MSXML", "MSXML3" ];
		for(var i = 0; i<prefixes.length; i++){
			try{
				doc = new ActiveXObject(prefixes[i]+".XMLDOM");
			}catch(e){ /* squelch */ };

			if(doc){ break; }
		}
	}else if((document.implementation)&&
		(document.implementation.createDocument)){
		doc = document.implementation.createDocument("", "", null);
	}
	
	return doc;
}

dojo.dom.createDocumentFromText = function(str, mimetype){
	if(!mimetype){ mimetype = "text/xml"; }
	if(!dj_undef("DOMParser")){
		var parser = new DOMParser();
		return parser.parseFromString(str, mimetype);
	}else if(!dj_undef("ActiveXObject")){
		var domDoc = dojo.dom.createDocument();
		if(domDoc){
			domDoc.async = false;
			domDoc.loadXML(str);
			return domDoc;
		}else{
			dojo.debug("toXml didn't work?");
		}
	/*
	}else if((dojo.render.html.capable)&&(dojo.render.html.safari)){
		// FIXME: this doesn't appear to work!
		// from: http://web-graphics.com/mtarchive/001606.php
		// var xml = '<?xml version="1.0"?>'+str;
		var mtype = "text/xml";
		var xml = '<?xml version="1.0"?>'+str;
		var url = "data:"+mtype+";charset=utf-8,"+encodeURIComponent(xml);
		var req = new XMLHttpRequest();
		req.open("GET", url, false);
		req.overrideMimeType(mtype);
		req.send(null);
		return req.responseXML;
	*/
	}else if(document.createElement){
		// FIXME: this may change all tags to uppercase!
		var tmp = document.createElement("xml");
		tmp.innerHTML = str;
		if(document.implementation && document.implementation.createDocument) {
			var xmlDoc = document.implementation.createDocument("foo", "", null);
			for(var i = 0; i < tmp.childNodes.length; i++) {
				xmlDoc.importNode(tmp.childNodes.item(i), true);
			}
			return xmlDoc;
		}
		// FIXME: probably not a good idea to have to return an HTML fragment
		// FIXME: the tmp.doc.firstChild is as tested from IE, so it may not
		// work that way across the board
		return ((tmp.document)&&
			(tmp.document.firstChild ?  tmp.document.firstChild : tmp));
	}
	return null;
}

dojo.dom.prependChild = function(node, parent) {
	if(parent.firstChild) {
		parent.insertBefore(node, parent.firstChild);
	} else {
		parent.appendChild(node);
	}
	return true;
}

dojo.dom.insertBefore = function(node, ref, force){
	if (force != true &&
		(node === ref || node.nextSibling === ref)){ return false; }
	var parent = ref.parentNode;
	parent.insertBefore(node, ref);
	return true;
}

dojo.dom.insertAfter = function(node, ref, force){
	var pn = ref.parentNode;
	if(ref == pn.lastChild){
		if((force != true)&&(node === ref)){
			return false;
		}
		pn.appendChild(node);
	}else{
		return this.insertBefore(node, ref.nextSibling, force);
	}
	return true;
}

dojo.dom.insertAtPosition = function(node, ref, position){
	if((!node)||(!ref)||(!position)){ return false; }
	switch(position.toLowerCase()){
		case "before":
			return dojo.dom.insertBefore(node, ref);
		case "after":
			return dojo.dom.insertAfter(node, ref);
		case "first":
			if(ref.firstChild){
				return dojo.dom.insertBefore(node, ref.firstChild);
			}else{
				ref.appendChild(node);
				return true;
			}
			break;
		default: // aka: last
			ref.appendChild(node);
			return true;
	}
}

dojo.dom.insertAtIndex = function(node, containingNode, insertionIndex){
	var siblingNodes = containingNode.childNodes;

	// if there aren't any kids yet, just add it to the beginning

	if (!siblingNodes.length){
		containingNode.appendChild(node);
		return true;
	}

	// otherwise we need to walk the childNodes
	// and find our spot

	var after = null;

	for(var i=0; i<siblingNodes.length; i++){

		var sibling_index = siblingNodes.item(i)["getAttribute"] ? parseInt(siblingNodes.item(i).getAttribute("dojoinsertionindex")) : -1;

		if (sibling_index < insertionIndex){
			after = siblingNodes.item(i);
		}
	}

	if (after){
		// add it after the node in {after}

		return dojo.dom.insertAfter(node, after);
	}else{
		// add it to the start

		return dojo.dom.insertBefore(node, siblingNodes.item(0));
	}
}
	
/**
 * implementation of the DOM Level 3 attribute.
 * 
 * @param node The node to scan for text
 * @param text Optional, set the text to this value.
 */
dojo.dom.textContent = function(node, text){
	if (text) {
		dojo.dom.replaceChildren(node, document.createTextNode(text));
		return text;
	} else {
		var _result = "";
		if (node == null) { return _result; }
		for (var i = 0; i < node.childNodes.length; i++) {
			switch (node.childNodes[i].nodeType) {
				case 1: // ELEMENT_NODE
				case 5: // ENTITY_REFERENCE_NODE
					_result += dojo.dom.textContent(node.childNodes[i]);
					break;
				case 3: // TEXT_NODE
				case 2: // ATTRIBUTE_NODE
				case 4: // CDATA_SECTION_NODE
					_result += node.childNodes[i].nodeValue;
					break;
				default:
					break;
			}
		}
		return _result;
	}
}

dojo.dom.collectionToArray = function(collection){
	dojo.deprecated("dojo.dom.collectionToArray", "use dojo.lang.toArray instead", "0.4");
	return dojo.lang.toArray(collection);
}

dojo.dom.hasParent = function (node) {
	return node && node.parentNode && dojo.dom.isNode(node.parentNode);
}

/**
 * Determines if node has any of the provided tag names and
 * returns the tag name that matches, empty string otherwise.
 *
 * Examples:
 *
 * myFooNode = <foo />
 * isTag(myFooNode, "foo"); // returns "foo"
 * isTag(myFooNode, "bar"); // returns ""
 * isTag(myFooNode, "FOO"); // returns ""
 * isTag(myFooNode, "hey", "foo", "bar"); // returns "foo"
**/
dojo.dom.isTag = function(node /* ... */) {
	if(node && node.tagName) {
		var arr = dojo.lang.toArray(arguments, 1);
		return arr[ dojo.lang.find(node.tagName, arr) ] || "";
	}
	return "";
}

__CPAN_FILE__ src/hostenv_wsh.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/*
 * WSH
 */

dojo.hostenv.name_ = 'wsh';

// make jsc shut up (so can sanity check)
/*@cc_on
@if (@_jscript_version >= 7)
var WScript;
@end
@*/

// make sure we are in right environment
if(typeof WScript == 'undefined'){
	dojo.raise("attempt to use WSH host environment when no WScript global");
}

dojo.hostenv.println = WScript.Echo;

dojo.hostenv.getCurrentScriptUri = function(){
	return WScript.ScriptFullName();
}

dojo.hostenv.getText = function(fpath){
	var fso = new ActiveXObject("Scripting.FileSystemObject");
	var istream = fso.OpenTextFile(fpath, 1); // iomode==1 means read only
	if(!istream){
		return null;
	}
	var contents = istream.ReadAll();
	istream.Close();
	return contents;
}

dojo.hostenv.exit = function(exitcode){ WScript.Quit(exitcode); }

__CPAN_FILE__ src/AdapterRegistry.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.AdapterRegistry");
dojo.require("dojo.lang.func");

dojo.AdapterRegistry = function(){
    /***
        A registry to facilitate adaptation.

        Pairs is an array of [name, check, wrap] triples
        
        All check/wrap functions in this registry should be of the same arity.
    ***/
    this.pairs = [];
}

dojo.lang.extend(dojo.AdapterRegistry, {
    register: function (name, check, wrap, /* optional */ override){
        /***
			The check function should return true if the given arguments are
			appropriate for the wrap function.

			If override is given and true, the check function will be given
			highest priority.  Otherwise, it will be the lowest priority
			adapter.
        ***/

        if (override) {
            this.pairs.unshift([name, check, wrap]);
        } else {
            this.pairs.push([name, check, wrap]);
        }
    },

    match: function (/* ... */) {
        /***
			Find an adapter for the given arguments.

			If no suitable adapter is found, throws NotFound.
        ***/
        for(var i = 0; i < this.pairs.length; i++){
            var pair = this.pairs[i];
            if(pair[1].apply(this, arguments)){
                return pair[2].apply(this, arguments);
            }
        }
		throw new Error("No match found");
        // dojo.raise("No match found");
    },

    unregister: function (name) {
        /***
			Remove a named adapter from the registry
        ***/
        for(var i = 0; i < this.pairs.length; i++){
            var pair = this.pairs[i];
            if(pair[0] == name){
                this.pairs.splice(i, 1);
                return true;
            }
        }
        return false;
    }
});

__CPAN_FILE__ src/hostenv_svg.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

//	hostenv_svg
if(typeof window == 'undefined'){
	dojo.raise("attempt to use adobe svg hostenv when no window object");
}
dojo.debug = function(){ 
	if (!djConfig.isDebug) { return; }
	var args = arguments;
	var isJUM = dj_global["jum"];
	var s = isJUM ? "": "DEBUG: ";
	for (var i = 0; i < args.length; ++i){ s += args[i]; }
	if (isJUM){ // this seems to be the only way to get JUM to "play nice"
		jum.debug(s);
	} else{ 
		dojo.hostenv.println(s);
	}
};

//	set up dojo.render.
dojo.render.name = navigator.appName;
dojo.render.ver = parseFloat(navigator.appVersion, 10);
switch(navigator.platform){
	case "MacOS":
		dojo.render.os.osx =  true;
		break;
	case "Linux":
		dojo.render.os.linux =  true;
		break;
	case "Windows":
		dojo.render.os.win =  true;
		break;
	default:
		dojo.render.os.linux = true;
		break;
};
dojo.render.svg.capable = true;
dojo.render.svg.support.builtin = true;
//	FIXME the following two is a big-ass hack for now.
dojo.render.svg.moz = ((navigator.userAgent.indexOf("Gecko") >= 0) && (!((navigator.appVersion.indexOf("Konqueror") >= 0) || (navigator.appVersion.indexOf("Safari") >= 0))));
dojo.render.svg.adobe = (window.parseXML != null);

//	agent-specific implementations.

//	from old hostenv_adobesvg.
dojo.hostenv.startPackage("dojo.hostenv");
dojo.hostenv.println = function(s){ 
	try {
		var ti = document.createElement("text");
		ti.setAttribute("x","50");
		ti.setAttribute("y", (25 + 15 * document.getElementsByTagName("text").length));
		ti.appendChild(document.createTextNode(s));
		document.documentElement.appendChild(ti);
	} catch(e){ }
};
dojo.hostenv.name_ = "svg";

//	expected/defined by bootstrap1.js
dojo.hostenv.setModulePrefix = function(module, prefix){ };
dojo.hostenv.getModulePrefix = function(module){ };
dojo.hostenv.getTextStack = [];
dojo.hostenv.loadUriStack = [];
dojo.hostenv.loadedUris = [];
dojo.hostenv.modules_ = {};
dojo.hostenv.modulesLoadedFired = false;
dojo.hostenv.modulesLoadedListeners = [];
dojo.hostenv.getText = function(uri, cb, data){ 
	if (!cb) var cb = function(result){ window.alert(result); };
	if (!data) {
		window.getUrl(uri, cb);
	} else {
		window.postUrl(uri, data, cb);
	}
};
dojo.hostenv.getLibaryScriptUri = function(){ };

dojo.hostenv.loadUri = function(uri){ };
dojo.hostenv.loadUriAndCheck = function(uri, module){ };

//	aliased in loader.js, don't ignore
//	we are going to kill loadModule for the first round of SVG stuff, and include shit manually.
dojo.hostenv.loadModule = function(moduleName){
	//	just like startPackage, but this time we're just checking to make sure it exists already.
	var a = moduleName.split(".");
	var currentObj = window;
	var s = [];
	for (var i = 0; i < a.length; i++){
		if (a[i] == "*") continue;
		s.push(a[i]);
		if (!currentObj[a[i]]){
			dojo.raise("dojo.require('" + moduleName + "'): module does not exist.");
		} else currentObj = currentObj[a[i]];
	}
	return; 
};
dojo.hostenv.startPackage = function(moduleName){
	var a = moduleName.split(".");
	var currentObj = window;
	var s = [];
	for (var i = 0; i < a.length; i++){
		if (a[i] == "*") continue;
		s.push(a[i]);
		if (!currentObj[a[i]]) currentObj[a[i]] = {};
		currentObj = currentObj[a[i]];
	}
	return; 
};

//	wrapper objects for ASVG
if (window.parseXML){
	window.XMLSerialzer = function(){
		//	based on WebFX RichTextControl getXHTML() function.
		function nodeToString(n, a) {
			function fixText(s) { return String(s).replace(/\&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;"); }
			function fixAttribute(s) { return fixText(s).replace(/\"/g, "&quot;"); }
			switch (n.nodeType) {
				case 1:	{	//	ELEMENT
					var name = n.nodeName;
					a.push("<" + name);
					for (var i = 0; i < n.attributes.length; i++) {
						if (n.attributes.item(i).specified) {
							a.push(" " + n.attributes.item(i).nodeName.toLowerCase() + "=\"" + fixAttribute(n.attributes.item(i).nodeValue) + "\"");
						}
					}
					if (n.canHaveChildren || n.hasChildNodes()) {
						a.push(">");
						for (var i = 0; i < n.childNodes.length; i++) nodeToString(n.childNodes.item(i), a);
						a.push("</" + name + ">\n");
					} else a.push(" />\n");
					break;
				}
				case 3: {	//	TEXT
					a.push(fixText(n.nodeValue));
					break;
				}
				case 4: {	//	CDATA
					a.push("<![CDA" + "TA[\n" + n.nodeValue + "\n]" + "]>");
					break;
				}
				case 7:{	//	PROCESSING INSTRUCTION
					a.push(n.nodeValue);
					if (/(^<\?xml)|(^<\!DOCTYPE)/.test(n.nodeValue)) a.push("\n");
					break;
				}
				case 8:{	//	COMMENT
					a.push("<!-- " + n.nodeValue + " -->\n");
					break;
				}
				case 9:		//	DOCUMENT
				case 11:{	//	DOCUMENT FRAGMENT
					for (var i = 0; i < n.childNodes.length; i++) nodeToString(n.childNodes.item(i), a);
					break;
				}
				default:{
					a.push("<!--\nNot Supported:\n\n" + "nodeType: " + n.nodeType + "\nnodeName: " + n.nodeName + "\n-->");
				}
			}
		}
		this.serializeToString = function(node){
			var a = [];
			nodeToString(node, a);
			return a.join("");
		};
	};

	window.DOMParser = function(){
		//	mimetype is basically ignored
		this.parseFromString = function(s){
			return parseXML(s, window.document);
		}
	};

	window.XMLHttpRequest = function(){
		//	we ignore the setting and getting of content-type.
		var uri = null;
		var method = "POST";
		var isAsync = true;	
		var cb = function(d){
			this.responseText = d.content;
			try {
				this.responseXML = parseXML(this.responseText, window.document);
			} catch(e){}
			this.status = "200";
			this.statusText = "OK";
			if (!d.success) {
				this.status = "500";
				this.statusText = "Internal Server Error";
			}
			this.onload();
			this.onreadystatechange();
		};
		this.onload = function(){};
		this.readyState = 4;
		this.onreadystatechange = function(){};
		this.status = 0;
		this.statusText = "";
		this.responseBody = null;
		this.responseStream = null;
		this.responseXML = null;
		this.responseText = null;
		this.abort = function(){ return; };
		this.getAllResponseHeaders = function(){ return []; };
		this.getResponseHeader = function(n){ return null; };
		this.setRequestHeader = function(nm, val){ };
		this.open = function(meth, url, async){ 
			method = meth;
			uri = url;
		};
		this.send = function(data){
			var d = data || null;
			if (method == "GET") getURL(uri, cb);
			else postURL(uri, data, cb);
		};
	};
}

__CPAN_FILE__ src/math.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.math");

dojo.math.degToRad = function (x) { return (x*Math.PI) / 180; }
dojo.math.radToDeg = function (x) { return (x*180) / Math.PI; }

dojo.math.factorial = function (n) {
	if(n<1){ return 0; }
	var retVal = 1;
	for(var i=1;i<=n;i++){ retVal *= i; }
	return retVal;
}

//The number of ways of obtaining an ordered subset of k elements from a set of n elements
dojo.math.permutations = function (n,k) {
	if(n==0 || k==0) return 1;
	return (dojo.math.factorial(n) / dojo.math.factorial(n-k));
}

//The number of ways of picking n unordered outcomes from r possibilities
dojo.math.combinations = function (n,r) {
	if(n==0 || r==0) return 1;
	return (dojo.math.factorial(n) / (dojo.math.factorial(n-r) * dojo.math.factorial(r)));
}

dojo.math.bernstein = function (t,n,i) {
	return (dojo.math.combinations(n,i) * Math.pow(t,i) * Math.pow(1-t,n-i));
}

/**
 * Returns random numbers with a Gaussian distribution, with the mean set at
 * 0 and the variance set at 1.
 *
 * @return A random number from a Gaussian distribution
 */
dojo.math.gaussianRandom = function () {
	var k = 2;
	do {
		var i = 2 * Math.random() - 1;
		var j = 2 * Math.random() - 1;
		k = i * i + j * j;
	} while (k >= 1);
	k = Math.sqrt((-2 * Math.log(k)) / k);
	return i * k;
}

/**
 * Calculates the mean of an Array of numbers.
 *
 * @return The mean of the numbers in the Array
 */
dojo.math.mean = function () {
	var array = dojo.lang.isArray(arguments[0]) ? arguments[0] : arguments;
	var mean = 0;
	for (var i = 0; i < array.length; i++) { mean += array[i]; }
	return mean / array.length;
}

/**
 * Extends Math.round by adding a second argument specifying the number of
 * decimal places to round to.
 *
 * @param number The number to round
 * @param places The number of decimal places to round to
 * @return The rounded number
 */
// TODO: add support for significant figures
dojo.math.round = function (number, places) {
	if (!places) { var shift = 1; }
	else { var shift = Math.pow(10, places); }
	return Math.round(number * shift) / shift;
}

/**
 * Calculates the standard deviation of an Array of numbers
 *
 * @return The standard deviation of the numbers
 */
dojo.math.sd = function () {
	var array = dojo.lang.isArray(arguments[0]) ? arguments[0] : arguments;
	return Math.sqrt(dojo.math.variance(array));
}

/**
 * Calculates the variance of an Array of numbers
 *
 * @return The variance of the numbers
 */
dojo.math.variance = function () {
	var array = dojo.lang.isArray(arguments[0]) ? arguments[0] : arguments;
	var mean = 0, squares = 0;
	for (var i = 0; i < array.length; i++) {
		mean += array[i];
		squares += Math.pow(array[i], 2);
	}
	return (squares / array.length)
		- Math.pow(mean / array.length, 2);
}

/**
 * Like range() in python
**/
dojo.math.range = function(a, b, step) {
    if(arguments.length < 2) {
        b = a;
        a = 0;
    }
    if(arguments.length < 3) {
        step = 1;
    }

    var range = [];
    if(step > 0) {
        for(var i = a; i < b; i += step) {
            range.push(i);
        }
    } else if(step < 0) {
        for(var i = a; i > b; i += step) {
            range.push(i);
        }
    } else {
        throw new Error("dojo.math.range: step must be non-zero");
    }
    return range;
}

__CPAN_FILE__ src/event.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.event");

dojo.require("dojo.lang.array");
dojo.require("dojo.lang.extras");
dojo.require("dojo.lang.func");

dojo.event = new function(){
	this.canTimeout = dojo.lang.isFunction(dj_global["setTimeout"])||dojo.lang.isAlien(dj_global["setTimeout"]);

	// FIXME: where should we put this method (not here!)?
	function interpolateArgs(args, searchForNames){
		var dl = dojo.lang;
		var ao = {
			srcObj: dj_global,
			srcFunc: null,
			adviceObj: dj_global,
			adviceFunc: null,
			aroundObj: null,
			aroundFunc: null,
			adviceType: (args.length>2) ? args[0] : "after",
			precedence: "last",
			once: false,
			delay: null,
			rate: 0,
			adviceMsg: false
		};

		switch(args.length){
			case 0: return;
			case 1: return;
			case 2:
				ao.srcFunc = args[0];
				ao.adviceFunc = args[1];
				break;
			case 3:
				if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isString(args[2]))){
					ao.adviceType = "after";
					ao.srcObj = args[0];
					ao.srcFunc = args[1];
					ao.adviceFunc = args[2];
				}else if((dl.isString(args[1]))&&(dl.isString(args[2]))){
					ao.srcFunc = args[1];
					ao.adviceFunc = args[2];
				}else if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isFunction(args[2]))){
					ao.adviceType = "after";
					ao.srcObj = args[0];
					ao.srcFunc = args[1];
					var tmpName  = dl.nameAnonFunc(args[2], ao.adviceObj, searchForNames);
					ao.adviceFunc = tmpName;
				}else if((dl.isFunction(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))){
					ao.adviceType = "after";
					ao.srcObj = dj_global;
					var tmpName  = dl.nameAnonFunc(args[0], ao.srcObj, searchForNames);
					ao.srcFunc = tmpName;
					ao.adviceObj = args[1];
					ao.adviceFunc = args[2];
				}
				break;
			case 4:
				if((dl.isObject(args[0]))&&(dl.isObject(args[2]))){
					// we can assume that we've got an old-style "connect" from
					// the sigslot school of event attachment. We therefore
					// assume after-advice.
					ao.adviceType = "after";
					ao.srcObj = args[0];
					ao.srcFunc = args[1];
					ao.adviceObj = args[2];
					ao.adviceFunc = args[3];
				}else if((dl.isString(args[0]))&&(dl.isString(args[1]))&&(dl.isObject(args[2]))){
					ao.adviceType = args[0];
					ao.srcObj = dj_global;
					ao.srcFunc = args[1];
					ao.adviceObj = args[2];
					ao.adviceFunc = args[3];
				}else if((dl.isString(args[0]))&&(dl.isFunction(args[1]))&&(dl.isObject(args[2]))){
					ao.adviceType = args[0];
					ao.srcObj = dj_global;
					var tmpName  = dl.nameAnonFunc(args[1], dj_global, searchForNames);
					ao.srcFunc = tmpName;
					ao.adviceObj = args[2];
					ao.adviceFunc = args[3];
				}else if((dl.isString(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))&&(dl.isFunction(args[3]))){
					ao.srcObj = args[1];
					ao.srcFunc = args[2];
					var tmpName  = dl.nameAnonFunc(args[3], dj_global, searchForNames);
					ao.adviceObj = dj_global;
					ao.adviceFunc = tmpName;
				}else if(dl.isObject(args[1])){
					ao.srcObj = args[1];
					ao.srcFunc = args[2];
					ao.adviceObj = dj_global;
					ao.adviceFunc = args[3];
				}else if(dl.isObject(args[2])){
					ao.srcObj = dj_global;
					ao.srcFunc = args[1];
					ao.adviceObj = args[2];
					ao.adviceFunc = args[3];
				}else{
					ao.srcObj = ao.adviceObj = ao.aroundObj = dj_global;
					ao.srcFunc = args[1];
					ao.adviceFunc = args[2];
					ao.aroundFunc = args[3];
				}
				break;
			case 6:
				ao.srcObj = args[1];
				ao.srcFunc = args[2];
				ao.adviceObj = args[3]
				ao.adviceFunc = args[4];
				ao.aroundFunc = args[5];
				ao.aroundObj = dj_global;
				break;
			default:
				ao.srcObj = args[1];
				ao.srcFunc = args[2];
				ao.adviceObj = args[3]
				ao.adviceFunc = args[4];
				ao.aroundObj = args[5];
				ao.aroundFunc = args[6];
				ao.once = args[7];
				ao.delay = args[8];
				ao.rate = args[9];
				ao.adviceMsg = args[10];
				break;
		}

		if(dl.isFunction(ao.aroundFunc)){
			var tmpName  = dl.nameAnonFunc(ao.aroundFunc, ao.aroundObj, searchForNames);
			ao.aroundFunc = tmpName;
		}

		if(dl.isFunction(ao.srcFunc)){
			ao.srcFunc = dl.getNameInObj(ao.srcObj, ao.srcFunc);
		}

		if(dl.isFunction(ao.adviceFunc)){
			ao.adviceFunc = dl.getNameInObj(ao.adviceObj, ao.adviceFunc);
		}

		if((ao.aroundObj)&&(dl.isFunction(ao.aroundFunc))){
			ao.aroundFunc = dl.getNameInObj(ao.aroundObj, ao.aroundFunc);
		}

		if(!ao.srcObj){
			dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc);
		}
		if(!ao.adviceObj){
			dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc);
		}
		return ao;
	}

	this.connect = function(){
		if(arguments.length == 1){
			var ao = arguments[0];
		}else{
			var ao = interpolateArgs(arguments, true);
		}

		if(dojo.lang.isArray(ao.srcObj) && ao.srcObj!=""){
			var tmpAO = {};
			for(var x in ao){
				tmpAO[x] = ao[x];
			}
			var mjps = [];
			dojo.lang.forEach(ao.srcObj, function(src){
				if((dojo.render.html.capable)&&(dojo.lang.isString(src))){
					src = dojo.byId(src);
					// dojo.debug(src);
				}
				tmpAO.srcObj = src;
				// dojo.debug(tmpAO.srcObj, tmpAO.srcFunc);
				// dojo.debug(tmpAO.adviceObj, tmpAO.adviceFunc);
				mjps.push(dojo.event.connect.call(dojo.event, tmpAO));
			});
			return mjps;
		}

		// FIXME: just doing a "getForMethod()" seems to be enough to put this into infinite recursion!!
		var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
		if(ao.adviceFunc){
			var mjp2 = dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj, ao.adviceFunc);
		}

		mjp.kwAddAdvice(ao);

		return mjp;	// advanced users might want to fsck w/ the join point
					// manually
	}

	this.log = function(a1, a2){
		var kwArgs;
		if((arguments.length == 1)&&(typeof a1 == "object")){
			kwArgs = a1;
		}else{
			kwArgs = {
				srcObj: a1,
				srcFunc: a2
			};
		}
		kwArgs.adviceFunc = function(){
			var argsStr = [];
			for(var x=0; x<arguments.length; x++){
				argsStr.push(arguments[x]);
			}
			dojo.debug("("+kwArgs.srcObj+")."+kwArgs.srcFunc, ":", argsStr.join(", "));
		}
		this.kwConnect(kwArgs);
	}

	this.connectBefore = function(){
		var args = ["before"];
		for(var i = 0; i < arguments.length; i++) { args.push(arguments[i]); }
		return this.connect.apply(this, args);
	}

	this.connectAround = function(){
		var args = ["around"];
		for(var i = 0; i < arguments.length; i++) { args.push(arguments[i]); }
		return this.connect.apply(this, args);
	}

	this.connectOnce = function(){
		var ao = interpolateArgs(arguments, true);
		ao.once = true;
		return this.connect(ao);
	}

	this._kwConnectImpl = function(kwArgs, disconnect){
		var fn = (disconnect) ? "disconnect" : "connect";
		if(typeof kwArgs["srcFunc"] == "function"){
			kwArgs.srcObj = kwArgs["srcObj"]||dj_global;
			var tmpName  = dojo.lang.nameAnonFunc(kwArgs.srcFunc, kwArgs.srcObj, true);
			kwArgs.srcFunc = tmpName;
		}
		if(typeof kwArgs["adviceFunc"] == "function"){
			kwArgs.adviceObj = kwArgs["adviceObj"]||dj_global;
			var tmpName  = dojo.lang.nameAnonFunc(kwArgs.adviceFunc, kwArgs.adviceObj, true);
			kwArgs.adviceFunc = tmpName;
		}
		return dojo.event[fn](	(kwArgs["type"]||kwArgs["adviceType"]||"after"),
									kwArgs["srcObj"]||dj_global,
									kwArgs["srcFunc"],
									kwArgs["adviceObj"]||kwArgs["targetObj"]||dj_global,
									kwArgs["adviceFunc"]||kwArgs["targetFunc"],
									kwArgs["aroundObj"],
									kwArgs["aroundFunc"],
									kwArgs["once"],
									kwArgs["delay"],
									kwArgs["rate"],
									kwArgs["adviceMsg"]||false );
	}

	this.kwConnect = function(kwArgs){
		return this._kwConnectImpl(kwArgs, false);

	}

	this.disconnect = function(){
		var ao = interpolateArgs(arguments, true);
		if(!ao.adviceFunc){ return; } // nothing to disconnect
		var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
		return mjp.removeAdvice(ao.adviceObj, ao.adviceFunc, ao.adviceType, ao.once);
	}

	this.kwDisconnect = function(kwArgs){
		return this._kwConnectImpl(kwArgs, true);
	}
}

// exactly one of these is created whenever a method with a joint point is run,
// if there is at least one 'around' advice.
dojo.event.MethodInvocation = function(join_point, obj, args) {
	this.jp_ = join_point;
	this.object = obj;
	this.args = [];
	for(var x=0; x<args.length; x++){
		this.args[x] = args[x];
	}
	// the index of the 'around' that is currently being executed.
	this.around_index = -1;
}

dojo.event.MethodInvocation.prototype.proceed = function() {
	this.around_index++;
	if(this.around_index >= this.jp_.around.length){
		return this.jp_.object[this.jp_.methodname].apply(this.jp_.object, this.args);
		// return this.jp_.run_before_after(this.object, this.args);
	}else{
		var ti = this.jp_.around[this.around_index];
		var mobj = ti[0]||dj_global;
		var meth = ti[1];
		return mobj[meth].call(mobj, this);
	}
} 


dojo.event.MethodJoinPoint = function(obj, methname){
	this.object = obj||dj_global;
	this.methodname = methname;
	this.methodfunc = this.object[methname];
	this.before = [];
	this.after = [];
	this.around = [];
}

dojo.event.MethodJoinPoint.getForMethod = function(obj, methname) {
	// if(!(methname in obj)){
	if(!obj){ obj = dj_global; }
	if(!obj[methname]){
		// supply a do-nothing method implementation
		obj[methname] = function(){};
		if(!obj[methname]){
			// e.g. cannot add to inbuilt objects in IE6
			dojo.raise("Cannot set do-nothing method on that object "+methname);
		}
	}else if((!dojo.lang.isFunction(obj[methname]))&&(!dojo.lang.isAlien(obj[methname]))){
		return null; // FIXME: should we throw an exception here instead?
	}
	// we hide our joinpoint instance in obj[methname + '$joinpoint']
	var jpname = methname + "$joinpoint";
	var jpfuncname = methname + "$joinpoint$method";
	var joinpoint = obj[jpname];
	if(!joinpoint){
		var isNode = false;
		if(dojo.event["browser"]){
			if( (obj["attachEvent"])||
				(obj["nodeType"])||
				(obj["addEventListener"]) ){
				isNode = true;
				dojo.event.browser.addClobberNodeAttrs(obj, [jpname, jpfuncname, methname]);
			}
		}
		var origArity = obj[methname].length;
		obj[jpfuncname] = obj[methname];
		// joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, methname);
		joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, jpfuncname);
		obj[methname] = function(){ 
			var args = [];

			if((isNode)&&(!arguments.length)){
				var evt = null;
				try{
					if(obj.ownerDocument){
						evt = obj.ownerDocument.parentWindow.event;
					}else if(obj.documentElement){
						evt = obj.documentElement.ownerDocument.parentWindow.event;
					}else{
						evt = window.event;
					}
				}catch(e){
					evt = window.event;
				}

				if(evt){
					args.push(dojo.event.browser.fixEvent(evt, this));
				}
			}else{
				for(var x=0; x<arguments.length; x++){
					if((x==0)&&(isNode)&&(dojo.event.browser.isEvent(arguments[x]))){
						args.push(dojo.event.browser.fixEvent(arguments[x], this));
					}else{
						args.push(arguments[x]);
					}
				}
			}
			// return joinpoint.run.apply(joinpoint, arguments); 
			return joinpoint.run.apply(joinpoint, args); 
		}
		obj[methname].__preJoinArity = origArity;
	}
	return joinpoint;
}

dojo.lang.extend(dojo.event.MethodJoinPoint, {
	unintercept: function(){
		this.object[this.methodname] = this.methodfunc;
		this.before = [];
		this.after = [];
		this.around = [];
	},

	disconnect: dojo.lang.forward("unintercept"),

	run: function() {
		var obj = this.object||dj_global;
		var args = arguments;

		// optimization. We only compute once the array version of the arguments
		// pseudo-arr in order to prevent building it each time advice is unrolled.
		var aargs = [];
		for(var x=0; x<args.length; x++){
			aargs[x] = args[x];
		}

		var unrollAdvice  = function(marr){ 
			if(!marr){
				dojo.debug("Null argument to unrollAdvice()");
				return;
			}
		  
			var callObj = marr[0]||dj_global;
			var callFunc = marr[1];
			
			if(!callObj[callFunc]){
				dojo.raise("function \"" + callFunc + "\" does not exist on \"" + callObj + "\"");
			}
			
			var aroundObj = marr[2]||dj_global;
			var aroundFunc = marr[3];
			var msg = marr[6];
			var undef;

			var to = {
				args: [],
				jp_: this,
				object: obj,
				proceed: function(){
					return callObj[callFunc].apply(callObj, to.args);
				}
			};
			to.args = aargs;

			var delay = parseInt(marr[4]);
			var hasDelay = ((!isNaN(delay))&&(marr[4]!==null)&&(typeof marr[4] != "undefined"));
			if(marr[5]){
				var rate = parseInt(marr[5]);
				var cur = new Date();
				var timerSet = false;
				if((marr["last"])&&((cur-marr.last)<=rate)){
					if(dojo.event.canTimeout){
						if(marr["delayTimer"]){
							clearTimeout(marr.delayTimer);
						}
						var tod = parseInt(rate*2); // is rate*2 naive?
						var mcpy = dojo.lang.shallowCopy(marr);
						marr.delayTimer = setTimeout(function(){
							// FIXME: on IE at least, event objects from the
							// browser can go out of scope. How (or should?) we
							// deal with it?
							mcpy[5] = 0;
							unrollAdvice(mcpy);
						}, tod);
					}
					return;
				}else{
					marr.last = cur;
				}
			}

			// FIXME: need to enforce rates for a connection here!

			if(aroundFunc){
				// NOTE: around advice can't delay since we might otherwise depend
				// on execution order!
				aroundObj[aroundFunc].call(aroundObj, to);
			}else{
				// var tmjp = dojo.event.MethodJoinPoint.getForMethod(obj, methname);
				if((hasDelay)&&((dojo.render.html)||(dojo.render.svg))){  // FIXME: the render checks are grotty!
					dj_global["setTimeout"](function(){
						if(msg){
							callObj[callFunc].call(callObj, to); 
						}else{
							callObj[callFunc].apply(callObj, args); 
						}
					}, delay);
				}else{ // many environments can't support delay!
					if(msg){
						callObj[callFunc].call(callObj, to); 
					}else{
						callObj[callFunc].apply(callObj, args); 
					}
				}
			}
		}

		if(this.before.length>0){
			dojo.lang.forEach(this.before, unrollAdvice);
		}

		var result;
		if(this.around.length>0){
			var mi = new dojo.event.MethodInvocation(this, obj, args);
			result = mi.proceed();
		}else if(this.methodfunc){
			result = this.object[this.methodname].apply(this.object, args);
		}

		if(this.after.length>0){
			dojo.lang.forEach(this.after, unrollAdvice);
		}

		return (this.methodfunc) ? result : null;
	},

	getArr: function(kind){
		var arr = this.after;
		// FIXME: we should be able to do this through props or Array.in()
		if((typeof kind == "string")&&(kind.indexOf("before")!=-1)){
			arr = this.before;
		}else if(kind=="around"){
			arr = this.around;
		}
		return arr;
	},

	kwAddAdvice: function(args){
		this.addAdvice(	args["adviceObj"], args["adviceFunc"], 
						args["aroundObj"], args["aroundFunc"], 
						args["adviceType"], args["precedence"], 
						args["once"], args["delay"], args["rate"], 
						args["adviceMsg"]);
	},

	addAdvice: function(	thisAdviceObj, thisAdvice, 
							thisAroundObj, thisAround, 
							advice_kind, precedence, 
							once, delay, rate, asMessage){
		var arr = this.getArr(advice_kind);
		if(!arr){
			dojo.raise("bad this: " + this);
		}

		var ao = [thisAdviceObj, thisAdvice, thisAroundObj, thisAround, delay, rate, asMessage];
		
		if(once){
			if(this.hasAdvice(thisAdviceObj, thisAdvice, advice_kind, arr) >= 0){
				return;
			}
		}

		if(precedence == "first"){
			arr.unshift(ao);
		}else{
			arr.push(ao);
		}
	},

	hasAdvice: function(thisAdviceObj, thisAdvice, advice_kind, arr){
		if(!arr){ arr = this.getArr(advice_kind); }
		var ind = -1;
		for(var x=0; x<arr.length; x++){
			var aao = (typeof thisAdvice == "object") ? (new String(thisAdvice)).toString() : thisAdvice;
			var a1o = (typeof arr[x][1] == "object") ? (new String(arr[x][1])).toString() : arr[x][1];
			if((arr[x][0] == thisAdviceObj)&&(a1o == aao)){
				ind = x;
			}
		}
		return ind;
	},

	removeAdvice: function(thisAdviceObj, thisAdvice, advice_kind, once){
		var arr = this.getArr(advice_kind);
		var ind = this.hasAdvice(thisAdviceObj, thisAdvice, advice_kind, arr);
		if(ind == -1){
			return false;
		}
		while(ind != -1){
			arr.splice(ind, 1);
			if(once){ break; }
			ind = this.hasAdvice(thisAdviceObj, thisAdvice, advice_kind, arr);
		}
		return true;
	}
});

__CPAN_FILE__ src/hostenv_browser.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

if(typeof window == 'undefined'){
	dojo.raise("no window object");
}

// attempt to figure out the path to dojo if it isn't set in the config
(function() {
	// before we get any further with the config options, try to pick them out
	// of the URL. Most of this code is from NW
	if(djConfig.allowQueryConfig){
		var baseUrl = document.location.toString(); // FIXME: use location.query instead?
		var params = baseUrl.split("?", 2);
		if(params.length > 1){
			var paramStr = params[1];
			var pairs = paramStr.split("&");
			for(var x in pairs){
				var sp = pairs[x].split("=");
				// FIXME: is this eval dangerous?
				if((sp[0].length > 9)&&(sp[0].substr(0, 9) == "djConfig.")){
					var opt = sp[0].substr(9);
					try{
						djConfig[opt]=eval(sp[1]);
					}catch(e){
						djConfig[opt]=sp[1];
					}
				}
			}
		}
	}

	if(((djConfig["baseScriptUri"] == "")||(djConfig["baseRelativePath"] == "")) &&(document && document.getElementsByTagName)){
		var scripts = document.getElementsByTagName("script");
		var rePkg = /(__package__|dojo|bootstrap1)\.js([\?\.]|$)/i;
		for(var i = 0; i < scripts.length; i++) {
			var src = scripts[i].getAttribute("src");
			if(!src) { continue; }
			var m = src.match(rePkg);
			if(m) {
				var root = src.substring(0, m.index);
				if(src.indexOf("bootstrap1") > -1) { root += "../"; }
				if(!this["djConfig"]) { djConfig = {}; }
				if(djConfig["baseScriptUri"] == "") { djConfig["baseScriptUri"] = root; }
				if(djConfig["baseRelativePath"] == "") { djConfig["baseRelativePath"] = root; }
				break;
			}
		}
	}

	// fill in the rendering support information in dojo.render.*
	var dr = dojo.render;
	var drh = dojo.render.html;
	var drs = dojo.render.svg;
	var dua = drh.UA = navigator.userAgent;
	var dav = drh.AV = navigator.appVersion;
	var t = true;
	var f = false;
	drh.capable = t;
	drh.support.builtin = t;

	dr.ver = parseFloat(drh.AV);
	dr.os.mac = dav.indexOf("Macintosh") >= 0;
	dr.os.win = dav.indexOf("Windows") >= 0;
	// could also be Solaris or something, but it's the same browser
	dr.os.linux = dav.indexOf("X11") >= 0;

	drh.opera = dua.indexOf("Opera") >= 0;
	drh.khtml = (dav.indexOf("Konqueror") >= 0)||(dav.indexOf("Safari") >= 0);
	drh.safari = dav.indexOf("Safari") >= 0;
	var geckoPos = dua.indexOf("Gecko");
	drh.mozilla = drh.moz = (geckoPos >= 0)&&(!drh.khtml);
	if (drh.mozilla) {
		// gecko version is YYYYMMDD
		drh.geckoVersion = dua.substring(geckoPos + 6, geckoPos + 14);
	}
	drh.ie = (document.all)&&(!drh.opera);
	drh.ie50 = drh.ie && dav.indexOf("MSIE 5.0")>=0;
	drh.ie55 = drh.ie && dav.indexOf("MSIE 5.5")>=0;
	drh.ie60 = drh.ie && dav.indexOf("MSIE 6.0")>=0;
	drh.ie70 = drh.ie && dav.indexOf("MSIE 7.0")>=0;

	// TODO: is the HTML LANG attribute relevant?
	dojo.locale = (drh.ie ? navigator.userLanguage : navigator.language).toLowerCase();

	dr.vml.capable=drh.ie;
	drs.capable = f;
	drs.support.plugin = f;
	drs.support.builtin = f;
	if (document.implementation
		&& document.implementation.hasFeature
		&& document.implementation.hasFeature("org.w3c.dom.svg", "1.0")
	){
		drs.capable = t;
		drs.support.builtin = t;
		drs.support.plugin = f;
	}
})();

dojo.hostenv.startPackage("dojo.hostenv");

dojo.render.name = dojo.hostenv.name_ = 'browser';
dojo.hostenv.searchIds = [];

// These are in order of decreasing likelihood; this will change in time.
dojo.hostenv._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];

dojo.hostenv.getXmlhttpObject = function(){
    var http = null;
	var last_e = null;
	try{ http = new XMLHttpRequest(); }catch(e){}
    if(!http){
		for(var i=0; i<3; ++i){
			var progid = dojo.hostenv._XMLHTTP_PROGIDS[i];
			try{
				http = new ActiveXObject(progid);
			}catch(e){
				last_e = e;
			}

			if(http){
				dojo.hostenv._XMLHTTP_PROGIDS = [progid];  // so faster next time
				break;
			}
		}

		/*if(http && !http.toString) {
			http.toString = function() { "[object XMLHttpRequest]"; }
		}*/
	}

	if(!http){
		return dojo.raise("XMLHTTP not available", last_e);
	}

	return http;
}

/**
 * Read the contents of the specified uri and return those contents.
 *
 * @param uri A relative or absolute uri. If absolute, it still must be in the
 * same "domain" as we are.
 *
 * @param async_cb If not specified, load synchronously. If specified, load
 * asynchronously, and use async_cb as the progress handler which takes the
 * xmlhttp object as its argument. If async_cb, this function returns null.
 *
 * @param fail_ok Default false. If fail_ok and !async_cb and loading fails,
 * return null instead of throwing.
 */
dojo.hostenv.getText = function(uri, async_cb, fail_ok){

	var http = this.getXmlhttpObject();

	if(async_cb){
		http.onreadystatechange = function(){
			if(4==http.readyState){
				if((!http["status"])||((200 <= http.status)&&(300 > http.status))){
					// dojo.debug("LOADED URI: "+uri);
					async_cb(http.responseText);
				}
			}
		}
	}

	http.open('GET', uri, async_cb ? true : false);
	try{
		http.send(null);
		if(async_cb){
			return null;
		}
		if((http["status"])&&((200 > http.status)||(300 <= http.status))){
			throw Error("Unable to load "+uri+" status:"+ http.status);
		}
	}catch(e){
		if((fail_ok)&&(!async_cb)){
			return null;
		}else{
			throw e;
		}
	}

	return http.responseText;
}

/*
 * It turns out that if we check *right now*, as this script file is being loaded,
 * then the last script element in the window DOM is ourselves.
 * That is because any subsequent script elements haven't shown up in the document
 * object yet.
 */
 /*
function dj_last_script_src() {
    var scripts = window.document.getElementsByTagName('script');
    if(scripts.length < 1){
		dojo.raise("No script elements in window.document, so can't figure out my script src");
	}
    var script = scripts[scripts.length - 1];
    var src = script.src;
    if(!src){
		dojo.raise("Last script element (out of " + scripts.length + ") has no src");
	}
    return src;
}

if(!dojo.hostenv["library_script_uri_"]){
	dojo.hostenv.library_script_uri_ = dj_last_script_src();
}
*/

dojo.hostenv.defaultDebugContainerId = 'dojoDebug';
dojo.hostenv._println_buffer = [];
dojo.hostenv._println_safe = false;
dojo.hostenv.println = function (line){
	if(!dojo.hostenv._println_safe){
		dojo.hostenv._println_buffer.push(line);
	}else{
		try {
			var console = document.getElementById(djConfig.debugContainerId ?
				djConfig.debugContainerId : dojo.hostenv.defaultDebugContainerId);
			if(!console) { console = document.getElementsByTagName("body")[0] || document.body; }

			var div = document.createElement("div");
			div.appendChild(document.createTextNode(line));
			console.appendChild(div);
		} catch (e) {
			try{
				// safari needs the output wrapped in an element for some reason
				document.write("<div>" + line + "</div>");
			}catch(e2){
				window.status = line;
			}
		}
	}
}

dojo.addOnLoad(function(){
	dojo.hostenv._println_safe = true;
	while(dojo.hostenv._println_buffer.length > 0){
		dojo.hostenv.println(dojo.hostenv._println_buffer.shift());
	}
});

function dj_addNodeEvtHdlr(node, evtName, fp, capture){
	var oldHandler = node["on"+evtName] || function(){};
	node["on"+evtName] = function(){
		fp.apply(node, arguments);
		oldHandler.apply(node, arguments);
	}
	return true;
}


/* Uncomment this to allow init after DOMLoad, not after window.onload

// Mozilla exposes the event we could use
if (dojo.render.html.mozilla) {
   document.addEventListener("DOMContentLoaded", dj_load_init, null);
}
// for Internet Explorer. readyState will not be achieved on init call, but dojo doesn't need it
//Tighten up the comments below to allow init after DOMLoad, not after window.onload
/ * @cc_on @ * /
/ * @if (@_win32)
    document.write("<script defer>dj_load_init()<"+"/script>");
/ * @end @ * /
*/

// default for other browsers
// potential TODO: apply setTimeout approach for other browsers
// that will cause flickering though ( document is loaded and THEN is processed)
// maybe show/hide required in this case..
// TODO: other browsers may support DOMContentLoaded/defer attribute. Add them to above.
dj_addNodeEvtHdlr(window, "load", function(){
	// allow multiple calls, only first one will take effect
	if(arguments.callee.initialized){ return; }
	arguments.callee.initialized = true;

	var initFunc = function(){
		//perform initialization
		if(dojo.render.html.ie){
			dojo.hostenv.makeWidgets();
		}
	};

	if(dojo.hostenv.inFlightCount == 0){
		initFunc();
		dojo.hostenv.modulesLoaded();
	}else{
		dojo.addOnLoad(initFunc);
	}
});

dj_addNodeEvtHdlr(window, "unload", function(){
	dojo.hostenv.unloaded();
});

dojo.hostenv.makeWidgets = function(){
	// you can put searchIds in djConfig and dojo.hostenv at the moment
	// we should probably eventually move to one or the other
	var sids = [];
	if(djConfig.searchIds && djConfig.searchIds.length > 0) {
		sids = sids.concat(djConfig.searchIds);
	}
	if(dojo.hostenv.searchIds && dojo.hostenv.searchIds.length > 0) {
		sids = sids.concat(dojo.hostenv.searchIds);
	}

	if((djConfig.parseWidgets)||(sids.length > 0)){
		if(dojo.evalObjPath("dojo.widget.Parse")){
			// we must do this on a delay to avoid:
			//	http://www.shaftek.org/blog/archives/000212.html
			// IE is such a tremendous peice of shit.
				var parser = new dojo.xml.Parse();
				if(sids.length > 0){
					for(var x=0; x<sids.length; x++){
						var tmpNode = document.getElementById(sids[x]);
						if(!tmpNode){ continue; }
						var frag = parser.parseElement(tmpNode, null, true);
						dojo.widget.getParser().createComponents(frag);
					}
				}else if(djConfig.parseWidgets){
					var frag  = parser.parseElement(document.getElementsByTagName("body")[0] || document.body, null, true);
					dojo.widget.getParser().createComponents(frag);
				}
		}
	}
}

dojo.addOnLoad(function(){
	if(!dojo.render.html.ie) {
		dojo.hostenv.makeWidgets();
	}
});

try {
	if (dojo.render.html.ie) {
		document.write('<style>v\:*{ behavior:url(#default#VML); }</style>');
		document.write('<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v"/>');
	}
} catch (e) { }

// stub, over-ridden by debugging code. This will at least keep us from
// breaking when it's not included
dojo.hostenv.writeIncludes = function(){}

dojo.byId = function(id, doc){
	if(id && (typeof id == "string" || id instanceof String)){
		if(!doc){ doc = document; }
		return doc.getElementById(id);
	}
	return id; // assume it's a node
}

__CPAN_FILE__ src/iCalendar.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.iCalendar");
dojo.require("dojo.text.textDirectory");
dojo.require("dojo.date");
dojo.require("dojo.lang");


dojo.iCalendar.fromText =  function (/* string */text) {
	// summary
	// Parse text of an iCalendar and return an array of iCalendar objects

	var properties = dojo.textDirectoryTokeniser.tokenise(text);
	var calendars = [];

	//dojo.debug("Parsing iCal String");
	for (var i = 0, begun = false; i < properties.length; i++) {
		var prop = properties[i];
		if (!begun) {
			if (prop.name == 'BEGIN' && prop.value == 'VCALENDAR') {
				begun = true;
				var calbody = [];
			}
		} else if (prop.name == 'END' && prop.value == 'VCALENDAR') {
			calendars.push(new dojo.iCalendar.VCalendar(calbody));
			begun = false;
		} else {
			calbody.push(prop);
		}
	}
	return /* array */calendars;
}


dojo.iCalendar.Component = function (/* string */ body ) {
	// summary
	// A component is the basic container of all this stuff. 

	if (!this.name) {
		this.name = "COMPONENT"
	}

	this.properties = [];
	this.components = [];

	if (body) {
		for (var i = 0, context = ''; i < body.length; i++) {
			if (context == '') {
				if (body[i].name == 'BEGIN') {
					context = body[i].value;
					var childprops = [];
				} else {
					this.addProperty(new dojo.iCalendar.Property(body[i]));
				}
			} else if (body[i].name == 'END' && body[i].value == context) {
				if (context=="VEVENT") {
					this.addComponent(new dojo.iCalendar.VEvent(childprops));
				} else if (context=="VTIMEZONE") {
					this.addComponent(new dojo.iCalendar.VTimeZone(childprops));
				} else if (context=="VTODO") {
					this.addComponent(new dojo.iCalendar.VTodo(childprops));
				} else if (context=="VJOURNAL") {
					this.addComponent(new dojo.iCalendar.VJournal(childprops));
				} else if (context=="VFREEBUSY") {
					this.addComponent(new dojo.iCalendar.VFreeBusy(childprops));
				} else if (context=="STANDARD") {
					this.addComponent(new dojo.iCalendar.Standard(childprops));
				} else if (context=="DAYLIGHT") {
					this.addComponent(new dojo.iCalendar.Daylight(childprops));
				} else if (context=="VALARM") {
					this.addComponent(new dojo.iCalendar.VAlarm(childprops));
				}else {
					dojo.unimplemented("dojo.iCalendar." + context);
				}
				context = '';
			} else {
				childprops.push(body[i]);
			}
		}

		if (this._ValidProperties) {
			this.postCreate();
		}
	}
}

dojo.lang.extend(dojo.iCalendar.Component, {

	addProperty: function (prop) {
		// summary
		// push a new property onto a component.
		this.properties.push(prop);
		this[prop.name.toLowerCase()] = prop;
	},

	addComponent: function (prop) {
		// summary
		// add a component to this components list of children.
		this.components.push(prop);
	},

	postCreate: function() {
		for (var x=0; x<this._ValidProperties.length; x++) {
			var evtProperty = this._ValidProperties[x];
			var found = false;
	
			for (var y=0; y<this.properties.length; y++) {	
				var prop = this.properties[y];
				var propName = prop.name.toLowerCase();
				if (dojo.lang.isArray(evtProperty)) {

					var alreadySet = false;
					for (var z=0; z<evtProperty.length; z++) {
						var evtPropertyName = evtProperty[z].name.toLowerCase();
						if((this[evtPropertyName])  && (evtPropertyName != propName )) {
							alreadySet=true;
						} 
					}
					if (!alreadySet) {
						this[propName] = prop;
					}
				} else {
					if (propName == evtProperty.name.toLowerCase()) {
						found = true;
						if (evtProperty.occurance == 1){
							this[propName] = prop;
						} else {
							found = true;
							if (!dojo.lang.isArray(this[propName])) {
							 	this[propName] = [];
							}
							this[propName].push(prop);
						}
					}
				}
			}

			if (evtProperty.required && !found) {	
				dojo.debug("iCalendar - " + this.name + ": Required Property not found: " + evtProperty.name);
			}
		}

		// parse any rrules		
		if (dojo.lang.isArray(this.rrule)) {
			for(var x=0; x<this.rrule.length; x++) {
				var rule = this.rrule[x].value;

				//add a place to cache dates we have checked for recurrance
				this.rrule[x].cache = function() {};
				
				var temp = rule.split(";");
				for (var y=0; y<temp.length; y++) {
					var pair = temp[y].split("=");
					var key = pair[0].toLowerCase();
					var val = pair[1];

					if ((key == "freq") || (key=="interval") || (key=="until")) {
						this.rrule[x][key]= val;
					} else {
						var valArray = val.split(",");
						this.rrule[x][key] = valArray; 
					}
				}	
			}
			this.recurring = true;
		}

	}, 

	toString: function () {
		// summary
		// output a string representation of this component.
		return "[iCalendar.Component; " + this.name + ", " + this.properties.length +
			" properties, " + this.components.length + " components]";
	}
});

dojo.iCalendar.Property = function (prop) {
	// summary
	// A single property of a component.

	// unpack the values
	this.name = prop.name;
	this.group = prop.group;
	this.params = prop.params;
	this.value = prop.value;

}

dojo.lang.extend(dojo.iCalendar.Property, {
	toString: function () {	
		// summary
		// output a string reprensentation of this component.
		return "[iCalenday.Property; " + this.name + ": " + this.value + "]";
	}
});

// This is just a little helper function for the Component Properties
var _P = function (n, oc, req) {
	return {name: n, required: (req) ? true : false,
		occurance: (oc == '*' || !oc) ? -1 : oc}
}

/*
 * VCALENDAR
 */

dojo.iCalendar.VCalendar = function (/* string */ calbody) {
	// summary
	// VCALENDAR Component

	this.name = "VCALENDAR";
	this.recurring = [];
	this.nonRecurringEvents = function(){};
	dojo.iCalendar.Component.call(this, calbody);
}

dojo.inherits(dojo.iCalendar.VCalendar, dojo.iCalendar.Component);

dojo.lang.extend(dojo.iCalendar.VCalendar, {

	addComponent: function (prop) {
		// summary
		// add component to the calenadar that makes it easy to pull them out again later.
		this.components.push(prop);
		if (prop.name.toLowerCase() == "vevent") {
			if (prop.rrule) {
				this.recurring.push(prop);
			} else {
				var startDate = prop.getDate();
				var month = startDate.getMonth() + 1;
				var dateString= month + "-" + startDate.getDate() + "-" + startDate.getFullYear();
				if (!dojo.lang.isArray(this[dateString])) {
					this.nonRecurringEvents[dateString] = [];
				}
				this.nonRecurringEvents[dateString].push(prop);
			}
		}
	},

	preComputeRecurringEvents: function(until) {
		var calculatedEvents = function(){};

		for(var x=0; x<this.recurring.length; x++) {
			var dates = this.recurring[x].getDates(until);
			for (var y=0; y<dates.length;y++) {
				var month = dates[y].getMonth() + 1;
				var dateStr = month + "-" + dates[y].getDate() + "-" + dates[y].getFullYear();
				if (!dojo.lang.isArray(calculatedEvents[dateStr])) {
					calculatedEvents[dateStr] = [];
				}

				if (!dojo.lang.inArray(calculatedEvents[dateStr], this.recurring[x])) { 
					calculatedEvents[dateStr].push(this.recurring[x]);
				} 
			}
		}
		this.recurringEvents = calculatedEvents;
	
	},

	getEvents: function(/* Date */ date) {
		// summary
		// Gets all events occuring on a particular date
		var events = [];
		var recur = [];
		var nonRecur = [];
		var month = date.getMonth() + 1;
		var dateStr= month + "-" + date.getDate() + "-" + date.getFullYear();
		if (dojo.lang.isArray(this.nonRecurringEvents[dateStr])) {
			nonRecur= this.nonRecurringEvents[dateStr];
			dojo.debug("Number of nonRecurring Events: " + nonRecur.length);
		} 
		

		if (dojo.lang.isArray(this.recurringEvents[dateStr])) {
			recur= this.recurringEvents[dateStr];
		} 

		events = recur.concat(nonRecur);

		if (events.length > 0) {
			return events;
		} 

		return null;			
	}
});

/*
 * STANDARD
 */

var StandardProperties = [
	_P("dtstart", 1, true), _P("tzoffsetto", 1, true), _P("tzoffsetfrom", 1, true),
	_P("comment"), _P("rdate"), _P("rrule"), _P("tzname")
];


dojo.iCalendar.Standard = function (/* string */ body) {
	// summary
	// STANDARD Component

	this.name = "STANDARD";
	this._ValidProperties = StandardProperties;
	dojo.iCalendar.Component.call(this, body);
}

dojo.inherits(dojo.iCalendar.Standard, dojo.iCalendar.Component);

/*
 * DAYLIGHT
 */

var DaylightProperties = [
	_P("dtstart", 1, true), _P("tzoffsetto", 1, true), _P("tzoffsetfrom", 1, true),
	_P("comment"), _P("rdate"), _P("rrule"), _P("tzname")
];

dojo.iCalendar.Daylight = function (/* string */ body) {
	// summary
	// Daylight Component
	this.name = "DAYLIGHT";
	this._ValidProperties = DaylightProperties;
	dojo.iCalendar.Component.call(this, body);
}

dojo.inherits(dojo.iCalendar.Daylight, dojo.iCalendar.Component);

/*
 * VEVENT
 */

var VEventProperties = [
	// these can occur once only
	_P("class", 1), _P("created", 1), _P("description", 1), _P("dtstart", 1),
	_P("geo", 1), _P("last-mod", 1), _P("location", 1), _P("organizer", 1),
	_P("priority", 1), _P("dtstamp", 1), _P("seq", 1), _P("status", 1),
	_P("summary", 1), _P("transp", 1), _P("uid", 1), _P("url", 1), _P("recurid", 1),
	// these two are exclusive
	[_P("dtend", 1), _P("duration", 1)],
	// these can occur many times over
	_P("attach"), _P("attendee"), _P("categories"), _P("comment"), _P("contact"),
	_P("exdate"), _P("exrule"), _P("rstatus"), _P("related"), _P("resources"),
	_P("rdate"), _P("rrule")
];

dojo.iCalendar.VEvent = function (/* string */ body) {
	// summary 
	// VEVENT Component
	this._ValidProperties = VEventProperties;
	this.name = "VEVENT";
	dojo.iCalendar.Component.call(this, body);
	this.recurring = false;
	this.startDate = dojo.date.fromIso8601(this.dtstart.value);
}

dojo.inherits(dojo.iCalendar.VEvent, dojo.iCalendar.Component);

dojo.lang.extend(dojo.iCalendar.VEvent, {
		getDates: function(until) {
			var dtstart = this.getDate();

			var recurranceSet = [];
			var weekdays=["su","mo","tu","we","th","fr","sa"];
			var order = { 
				"daily": 1, "weekly": 2, "monthly": 3, "yearly": 4,
				"byday": 1, "bymonthday": 1, "byweekno": 2, "bymonth": 3, "byyearday": 4};

			// expand rrules into the recurrance 
			for (var x=0; x<this.rrule.length; x++) {
				var rrule = this.rrule[x];
				var freq = rrule.freq.toLowerCase();
				var interval = 1;

				if (rrule.interval > interval) {
					interval = rrule.interval;
				}

				var set = [];
				var freqInt = order[freq];

				if (rrule.until) {
					var tmpUntil = dojo.date.fromIso8601(rrule.until);
				} else {
					var tmpUntil = until
				}

				if (tmpUntil > until) {
					tmpUntil = until
				}


				if (dtstart<tmpUntil) {

					var expandingRules = function(){};
					var cullingRules = function(){};
					expandingRules.length=0;
					cullingRules.length =0;

					switch(freq) {
						case "yearly":
							var nextDate = new Date(dtstart);
							set.push(nextDate);
							while(nextDate < tmpUntil) {
								nextDate.setYear(nextDate.getFullYear()+interval);
								tmpDate = new Date(nextDate);
								if(tmpDate < tmpUntil) {
									set.push(tmpDate);
								}
							}
							break;
						case "monthly":
							nextDate = new Date(dtstart);
							set.push(nextDate);
							while(nextDate < tmpUntil) {
								nextDate.setMonth(nextDate.getMonth()+interval);
								var tmpDate = new Date(nextDate);
								if (tmpDate < tmpUntil) {
									set.push(tmpDate);
								}
							}
							break;
						case "weekly":
							nextDate = new Date(dtstart);
							set.push(nextDate);
							while(nextDate < tmpUntil) {
								nextDate.setDate(nextDate.getDate()+(7*interval));
								var tmpDate = new Date(nextDate);
								if (tmpDate < tmpUntil) {
									set.push(tmpDate);
								}
							}
							break;	
						case "daily":
							nextDate = new Date(dtstart);
							set.push(nextDate);
							while(nextDate < tmpUntil) {
								nextDate.setDate(nextDate.getDate()+interval);
								var tmpDate = new Date(nextDate);
								if (tmpDate < tmpUntil) {
									set.push(tmpDate);
								}
							}
							break;
	
					}

					if ((rrule["bymonth"]) && (order["bymonth"]<freqInt))	{
						for (var z=0; z<rrule["bymonth"].length; z++) {
							if (z==0) {
								for (var zz=0; zz < set.length; zz++) {
									set[zz].setMonth(rrule["bymonth"][z]-1);
								}
							} else {
								var subset=[];
								for (var zz=0; zz < set.length; zz++) {
									var newDate = new Date(set[zz]);
									newDate.setMonth(rrule[z]);
									subset.push(newDate);
								}
								tmp = set.concat(subset);
								set = tmp;
							}
						}
					}

					
					// while the spec doesn't prohibit it, it makes no sense to have a bymonth and a byweekno at the same time
					// and if i'm wrong then i don't know how to apply that rule.  This is also documented elsewhere on the web
					if (rrule["byweekno"] && !rrule["bymonth"]) {	
						dojo.debug("TODO: no support for byweekno yet");
					}


					// while the spec doesn't prohibit it, it makes no sense to have a bymonth and a byweekno at the same time
					// and if i'm wrong then i don't know how to apply that rule.  This is also documented elsewhere on the web
					if (rrule["byyearday"] && !rrule["bymonth"] && !rrule["byweekno"] ) {	
						if (rrule["byyearday"].length > 1) {
							var regex = "([+-]?)([0-9]{1,3})";
							for (var z=1; x<rrule["byyearday"].length; z++) {
								var regexResult = rrule["byyearday"][z].match(regex);
								if (z==1) {
									for (var zz=0; zz < set.length; zz++) {
										if (regexResult[1] == "-") {
											dojo.date.setDayOfYear(set[zz],366-regexResult[2]);
										} else {
											dojo.date.setDayOfYear(set[zz],regexResult[2]);
										}
									}
								}	else {
									var subset=[];
									for (var zz=0; zz < set.length; zz++) {
										var newDate = new Date(set[zz]);
										if (regexResult[1] == "-") {
											dojo.date.setDayOfYear(newDate,366-regexResult[2]);
										} else {
											dojo.date.setDayOfYear(newDate,regexResult[2]);
										}
										subset.push(newDate);
									}
									tmp = set.concat(subset);
									set = tmp;
								}
							}
						}
					}

					if (rrule["bymonthday"]  && (order["bymonthday"]<freqInt)) {	
						if (rrule["bymonthday"].length > 0) {
							var regex = "([+-]?)([0-9]{1,3})";
							for (var z=0; z<rrule["bymonthday"].length; z++) {
								var regexResult = rrule["bymonthday"][z].match(regex);
								if (z==0) {
									for (var zz=0; zz < set.length; zz++) {
										if (regexResult[1] == "-") {
											if (regexResult[2] < dojo.date.getDaysInMonth(set[zz])) {
												set[zz].setDate(dojo.date.getDaysInMonth(set[zz]) - regexResult[2]);
											}
										} else {
											if (regexResult[2] < dojo.date.getDaysInMonth(set[zz])) {
												set[zz].setDate(regexResult[2]);
											}
										}
									}
								}	else {
									var subset=[];
									for (var zz=0; zz < set.length; zz++) {
										var newDate = new Date(set[zz]);
										if (regexResult[1] == "-") {
											if (regexResult[2] < dojo.date.getDaysInMonth(set[zz])) {
												newDate.setDate(dojo.date.getDaysInMonth(set[zz]) - regexResult[2]);
											}
										} else {
											if (regexResult[2] < dojo.date.getDaysInMonth(set[zz])) {
												newDate.setDate(regexResult[2]);
											}
										}
										subset.push(newDate);
									}
									tmp = set.concat(subset);
									set = tmp;
								}
							}
						}
					}

					if (rrule["byday"]  && (order["byday"]<freqInt)) {	
						if (rrule["bymonth"]) {
							if (rrule["byday"].length > 0) {
								var regex = "([+-]?)([0-9]{0,1}?)([A-Za-z]{1,2})";
								for (var z=0; z<rrule["byday"].length; z++) {
									var regexResult = rrule["byday"][z].match(regex);
									var occurance = regexResult[2];
									var day = regexResult[3].toLowerCase();


									if (z==0) {
										for (var zz=0; zz < set.length; zz++) {
											if (regexResult[1] == "-") {
												//find the nth to last occurance of date 
												var numDaysFound = 0;
												var lastDayOfMonth = dojo.date.getDaysInMonth(set[zz]);
												var daysToSubtract = 1;
												set[zz].setDate(lastDayOfMonth); 
												if (weekdays[set[zz].getDay()] == day) {
													numDaysFound++;
													daysToSubtract=7;
												}
												daysToSubtract = 1;
												while (numDaysFound < occurance) {
													set[zz].setDate(set[zz].getDate()-daysToSubtract);	
													if (weekdays[set[zz].getDay()] == day) {
														numDaysFound++;
														daysToSubtract=7;	
													}
												}
											} else {
												if (occurance) {
													var numDaysFound=0;
													set[zz].setDate(1);
													var daysToAdd=1;

													if(weekdays[set[zz].getDay()] == day) {
														numDaysFound++;
														daysToAdd=7;
													}

													while(numDaysFound < occurance) {
														set[zz].setDate(set[zz].getDate()+daysToAdd);
														if(weekdays[set[zz].getDay()] == day) {
															numDaysFound++;
															daysToAdd=7;
														}
													}
												} else {
													//we're gonna expand here to add a date for each of the specified days for each month
													var numDaysFound=0;
													var subset = [];

													lastDayOfMonth = new Date(set[zz]);
													var daysInMonth = dojo.date.getDaysInMonth(set[zz]);
													lastDayOfMonth.setDate(daysInMonth);

													set[zz].setDate(1);
												
													if (weekdays[set[zz].getDay()] == day) {
														numDaysFound++;
													}
													var tmpDate = new Date(set[zz]);
													daysToAdd = 1;
													while(tmpDate.getDate() < lastDayOfMonth) {
														if (weekdays[tmpDate.getDay()] == day) {
															numDaysFound++;
															if (numDaysFound==1) {
																set[zz] = tmpDate;
															} else {
																subset.push(tmpDate);
																tmpDate = new Date(tmpDate);
																daysToAdd=7;	
																tmpDate.setDate(tmpDate.getDate() + daysToAdd);
															}
														} else {
															tmpDate.setDate(tmpDate.getDate() + daysToAdd);
														}
													}
													var t = set.concat(subset);
													set = t; 
												}
											}
										}
									}	else {
										var subset=[];
										for (var zz=0; zz < set.length; zz++) {
											var newDate = new Date(set[zz]);
											if (regexResult[1] == "-") {
												if (regexResult[2] < dojo.date.getDaysInMonth(set[zz])) {
													newDate.setDate(dojo.date.getDaysInMonth(set[zz]) - regexResult[2]);
												}
											} else {
												if (regexResult[2] < dojo.date.getDaysInMonth(set[zz])) {
													newDate.setDate(regexResult[2]);
												}
											}
											subset.push(newDate);
										}
										tmp = set.concat(subset);
										set = tmp;
									}
								}
							}
						} else {
							dojo.debug("TODO: byday within a yearly rule without a bymonth");
						}
					}

					dojo.debug("TODO: Process BYrules for units larger than frequency");
			
					//add this set of events to the complete recurranceSet	
					var tmp = recurranceSet.concat(set);
					recurranceSet = tmp;
				}
			}

			// TODO: add rdates to the recurrance set here

			// TODO: subtract exdates from the recurrance set here

			//TODO:  subtract dates generated by exrules from recurranceSet here

			recurranceSet.push(dtstart);
			return recurranceSet;
		},

		getDate: function() {
			return dojo.date.fromIso8601(this.dtstart.value);
		}
});

/*
 * VTIMEZONE
 */

var VTimeZoneProperties = [
	_P("tzid", 1, true), _P("last-mod", 1), _P("tzurl", 1)

	// one of 'standardc' or 'daylightc' must occur
	// and each may occur more than once.
];

dojo.iCalendar.VTimeZone = function (/* string */ body) {
	// summary
	// VTIMEZONE Component
	this.name = "VTIMEZONE";
	this._ValidProperties = VTimeZoneProperties;
	dojo.iCalendar.Component.call(this, body);
}

dojo.inherits(dojo.iCalendar.VTimeZone, dojo.iCalendar.Component);

/*
 * VTODO
 */

var VTodoProperties = [
	// these can occur once only
	_P("class", 1), _P("completed", 1), _P("created", 1), _P("description", 1),
	_P("dtstart", 1), _P("geo", 1), _P("last-mod", 1), _P("location", 1),
	_P("organizer", 1), _P("percent", 1), _P("priority", 1), _P("dtstamp", 1),
	_P("seq", 1), _P("status", 1), _P("summary", 1), _P("uid", 1), _P("url", 1),
	_P("recurid", 1),
	// these two are exclusive
	[_P("due", 1), _P("duration", 1)],
	// these can occur many times over
	_P("attach"), _P("attendee"), _P("categories"), _P("comment"), _P("contact"),
	_P("exdate"), _P("exrule"), _P("rstatus"), _P("related"), _P("resources"),
	_P("rdate"), _P("rrule")
];

dojo.iCalendar.VTodo= function (/* string */ body) {
	// summary
	// VTODO Componenet
	this.name = "VTODO";
	this._ValidProperties = VTodoProperties;
	dojo.iCalendar.Component.call(this, body);
}

dojo.inherits(dojo.iCalendar.VTodo, dojo.iCalendar.Component);

/*
 * VJOURNAL
 */

var VJournalProperties = [
	// these can occur once only
	_P("class", 1), _P("created", 1), _P("description", 1), _P("dtstart", 1),
	_P("last-mod", 1), _P("organizer", 1), _P("dtstamp", 1), _P("seq", 1),
	_P("status", 1), _P("summary", 1), _P("uid", 1), _P("url", 1), _P("recurid", 1),
	// these can occur many times over
	_P("attach"), _P("attendee"), _P("categories"), _P("comment"), _P("contact"),
	_P("exdate"), _P("exrule"), _P("related"), _P("rstatus"), _P("rdate"), _P("rrule")
];

dojo.iCalendar.VJournal= function (/* string */ body) {
	// summary
	// VJOURNAL Component
	this.name = "VJOURNAL";
	this._ValidProperties = VJournalProperties;
	dojo.iCalendar.Component.call(this, body);
}

dojo.inherits(dojo.iCalendar.VJournal, dojo.iCalendar.Component);

/*
 * VFREEBUSY
 */

var VFreeBusyProperties = [
	// these can occur once only
	_P("contact"), _P("dtstart", 1), _P("dtend"), _P("duration"),
	_P("organizer", 1), _P("dtstamp", 1), _P("uid", 1), _P("url", 1),
	// these can occur many times over
	_P("attendee"), _P("comment"), _P("freebusy"), _P("rstatus")
];

dojo.iCalendar.VFreeBusy= function (/* string */ body) {
	// summary
	// VFREEBUSY Component
	this.name = "VFREEBUSY";
	this._ValidProperties = VFreeBusyProperties;
	dojo.iCalendar.Component.call(this, body);
}

dojo.inherits(dojo.iCalendar.VFreeBusy, dojo.iCalendar.Component);

/*
 * VALARM
 */

var VAlarmProperties = [
	[_P("action", 1, true), _P("trigger", 1, true), [_P("duration", 1), _P("repeat", 1)],
	_P("attach", 1)],

	[_P("action", 1, true), _P("description", 1, true), _P("trigger", 1, true),
	[_P("duration", 1), _P("repeat", 1)]],

	[_P("action", 1, true), _P("description", 1, true), _P("trigger", 1, true),
	_P("summary", 1, true), _P("attendee", "*", true),
	[_P("duration", 1), _P("repeat", 1)],
	_P("attach", 1)],

	[_P("action", 1, true), _P("attach", 1, true), _P("trigger", 1, true),
	[_P("duration", 1), _P("repeat", 1)],
	_P("description", 1)],
];

dojo.iCalendar.VAlarm= function (/* string */ body) {
	// summary
	// VALARM Component
	this.name = "VALARM";
	this._ValidProperties = VAlarmProperties;
	dojo.iCalendar.Component.call(this, body);
}

dojo.inherits(dojo.iCalendar.VAlarm, dojo.iCalendar.Component);


__CPAN_FILE__ src/profile.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.profile");

dojo.profile = new function(){
	var profiles = {};
	var pns = [];

	this.start = function(name){
		if(!profiles[name]){
			profiles[name] = {iters: 0, total: 0};
			pns[pns.length] = name;
		}else{
			if(profiles[name]["start"]){
				this.end(name);
			}
		}
		profiles[name].end = null;
		profiles[name].start = new Date();
	}

	this.end = function(name){
		var ed = new Date();
		if((profiles[name])&&(profiles[name]["start"])){
			with(profiles[name]){
				end = ed;
				total += (end - start);
				start = null;
				iters++;
			}
		}else{
			// oops! bad call to end(), what should we do here?
			return true;
		}
	}

	this.stop = this.end;

	this.dump = function(appendToDoc){
		var tbl = document.createElement("table");
		with(tbl.style){
			border = "1px solid black";
			borderCollapse = "collapse";
		}
		var hdr = tbl.createTHead();
		var hdrtr = hdr.insertRow(0);
		// document.createElement("tr");
		var cols = ["Identifier","Calls","Total","Avg"];
		for(var x=0; x<cols.length; x++){
			var ntd = hdrtr.insertCell(x);
			with(ntd.style){
				backgroundColor = "#225d94";
				color = "white";
				borderBottom = "1px solid black";
				borderRight = "1px solid black";
				fontFamily = "tahoma";
				fontWeight = "bolder";
				paddingLeft = paddingRight = "5px";
			}
			ntd.appendChild(document.createTextNode(cols[x]));
		}

		for(var x=0; x < pns.length; x++){
			var prf = profiles[pns[x]];
			this.end(pns[x]);
			if(prf.iters>0){
				var bdytr = tbl.insertRow(true);
				var vals = [pns[x], prf.iters, prf.total, parseInt(prf.total/prf.iters)];
				for(var y=0; y<vals.length; y++){
					var cc = bdytr.insertCell(y);
					cc.appendChild(document.createTextNode(vals[y]));
					with(cc.style){
						borderBottom = "1px solid gray";
						paddingLeft = paddingRight = "5px";
						if(x%2){
							backgroundColor = "#e1f1ff";
						}
						if(y>0){
							textAlign = "right";
							borderRight = "1px solid gray";
						}else{
							borderRight = "1px solid black";
						}
					}
				}
			}
		}

		if(appendToDoc){
			var ne = document.createElement("div");
			ne.id = "profileOutputTable";
			with(ne.style){
				fontFamily = "Courier New, monospace";
				fontSize = "12px";
				lineHeight = "16px";
				borderTop = "1px solid black";
				padding = "10px";
			}
			if(document.getElementById("profileOutputTable")){
				document.body.replaceChild(ne, document.getElementById("profileOutputTable"));
			}else{
				document.body.appendChild(ne);
			}
			ne.appendChild(tbl);
		}

		return tbl;
	}
}

__CPAN_FILE__ src/flash.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.flash");

dojo.require("dojo.string.*");
dojo.require("dojo.uri.*");


/** 
		The goal of dojo.flash is to make it easy to extend Flash's capabilities
		into an AJAX/DHTML environment. Robust, performant, reliable 
		JavaScript/Flash communication is harder than most realize when they
		delve into the topic, especially if you want it
		to work on Internet Explorer, Firefox, and Safari, and to be able to
		push around hundreds of K of information quickly. Dojo.flash makes it
		possible to support these platforms; you have to jump through a few
		hoops to get its capabilites, but if you are a library writer 
		who wants to bring Flash's storage or streaming sockets ability into
		DHTML, for example, then dojo.flash is perfect for you.
  
		Dojo.flash provides an easy object for interacting with the Flash plugin. 
		This object provides methods to determine the current version of the Flash
		plugin (dojo.flash.info); execute Flash instance methods 
		independent of the Flash version
		being used (dojo.flash.comm); write out the necessary markup to 
		dynamically insert a Flash object into the page (dojo.flash.Embed; and 
		do dynamic installation and upgrading of the current Flash plugin in 
		use (dojo.flash.Install).
		
		To use dojo.flash, you must first wait until Flash is finished loading 
		and initializing before you attempt communication or interaction. 
		To know when Flash is finished use dojo.event.connect:
		
		dojo.event.connect(dojo.flash, "loaded", myInstance, "myCallback");
		
		Then, while the page is still loading provide the file name
		and the major version of Flash that will be used for Flash/JavaScript
		communication (see "Flash Communication" below for information on the 
		different kinds of Flash/JavaScript communication supported and how they 
		depend on the version of Flash installed):
		
		dojo.flash.setSwf({flash6: "src/storage/storage_flash6.swf",
											 flash8: "src/storage/storage_flash8.swf"});
		
		This will cause dojo.flash to pick the best way of communicating
		between Flash and JavaScript based on the platform.
		
		If no SWF files are specified, then Flash is not initialized.
		
		Your Flash must use DojoExternalInterface to expose Flash methods and
		to call JavaScript; see "Flash Communication" below for details.
		
		setSwf can take an optional 'visible' attribute to control whether
		the Flash object is visible or not on the page; the default is visible:
		
		dojo.flash.setSwf({flash6: "src/storage/storage_flash6.swf",
											 flash8: "src/storage/storage_flash8.swf",
											 visible: false});
		
		Once finished, you can query Flash version information:
		
		dojo.flash.info.version
		
		Or can communicate with Flash methods that were exposed:
		
		var results = dojo.flash.comm.sayHello("Some Message");
		
		Only string values are currently supported for both arguments and
		for return results. Everything will be cast to a string on both
		the JavaScript and Flash sides.
		
		-------------------
		Flash Communication
		-------------------
		
		dojo.flash allows Flash/JavaScript communication in 
		a way that can pass large amounts of data back and forth reliably and
		very fast. The dojo.flash
		framework encapsulates the specific way in which this communication occurs,
		presenting a common interface to JavaScript irrespective of the underlying
		Flash version.
		
		There are currently three major ways to do Flash/JavaScript communication
		in the Flash community:
		
		1) Flash 6+ - Uses Flash methods, such as SetVariable and TCallLabel,
		and the fscommand handler to do communication. Strengths: Very fast,
		mature, and can send extremely large amounts of data; can do
		synchronous method calls. Problems: Does not work on Safari; works on 
		Firefox/Mac OS X only if Flash 8 plugin is installed; cryptic to work with.
		
		2) Flash 8+ - Uses ExternalInterface, which provides a way for Flash
		methods to register themselves for callbacks from JavaScript, and a way
		for Flash to call JavaScript. Strengths: Works on Safari; elegant to
		work with; can do synchronous method calls. Problems: Extremely buggy 
		(fails if there are new lines in the data, for example); performance
		degrades drastically in O(n^2) time as data grows; locks up the browser while
		it is communicating; does not work in Internet Explorer if Flash
		object is dynamically added to page with document.writeln, DOM methods,
		or innerHTML.
		
		3) Flash 6+ - Uses two seperate Flash applets, one that we 
		create over and over, passing input data into it using the PARAM tag, 
		which then uses a Flash LocalConnection to pass the data to the main Flash
		applet; communication back to Flash is accomplished using a getURL
		call with a javascript protocol handler, such as "javascript:myMethod()".
		Strengths: the most cross browser, cross platform pre-Flash 8 method
		of Flash communication known; works on Safari. Problems: Timing issues;
		clunky and complicated; slow; can only send very small amounts of
		data (several K); all method calls are asynchronous.
		
		dojo.flash.comm uses only the first two methods. This framework
		was created primarily for dojo.storage, which needs to pass very large
		amounts of data synchronously and reliably across the Flash/JavaScript
		boundary. We use the first method, the Flash 6 method, on all platforms
		that support it, while using the Flash 8 ExternalInterface method
		only on Safari with some special code to help correct ExternalInterface's
		bugs.
		
		Since dojo.flash needs to have two versions of the Flash
		file it wants to generate, a Flash 6 and a Flash 8 version to gain
		true cross-browser compatibility, several tools are provided to ease
		development on the Flash side.
		
		In your Flash file, if you want to expose Flash methods that can be
		called, use the DojoExternalInterface class to register methods. This
		class is an exact API clone of the standard ExternalInterface class, but
		can work in Flash 6+ browsers. Under the covers it uses the best
		mechanism to do communication:
		
		class HelloWorld{
			function HelloWorld(){
				// Initialize the DojoExternalInterface class
				DojoExternalInterface.initialize();
				
				// Expose your methods
				DojoExternalInterface.addCallback("sayHello", this, this.sayHello);
				
				// Tell JavaScript that you are ready to have method calls
				DojoExternalInterface.loaded();
				
				// Call some JavaScript
				var resultsReady = function(results){
					trace("Received the following results from JavaScript: " + results);
				}
				DojoExternalInterface.call("someJavaScriptMethod", resultsReady, 
																	 someParameter);
			}
			
			function sayHello(){ ... }
			
			static main(){ ... }
		}
		
		DojoExternalInterface adds two new functions to the ExternalInterface
		API: initialize() and loaded(). initialize() must be called before
		any addCallback() or call() methods are run, and loaded() must be
		called after you are finished adding your callbacks. Calling loaded()
		will fire the dojo.flash.loaded() event, so that JavaScript can know that
		Flash has finished loading and adding its callbacks, and can begin to
		interact with the Flash file.
		
		To generate your SWF files, use the ant task
		"buildFlash". You must have the open source Motion Twin ActionScript 
		compiler (mtasc) installed and in your path to use the "buildFlash"
		ant task; download and install mtasc from http://www.mtasc.org/.
		
		
		
		buildFlash usage:
		
		ant buildFlash -Ddojo.flash.file=../tests/flash/HelloWorld.as
		
		where "dojo.flash.file" is the relative path to your Flash 
		ActionScript file.
		
		This will generate two SWF files, one ending in _flash6.swf and the other
		ending in _flash8.swf in the same directory as your ActionScript method:
		
		HelloWorld_flash6.swf
		HelloWorld_flash8.swf
		
		Initialize dojo.flash with the filename and Flash communication version to
		use during page load; see the documentation for dojo.flash for details:
		
		dojo.flash.setSwf({flash6: "tests/flash/HelloWorld_flash6.swf",
											 flash8: "tests/flash/HelloWorld_flash8.swf"});
		
		Now, your Flash methods can be called from JavaScript as if they are native
		Flash methods, mirrored exactly on the JavaScript side:
		
		dojo.flash.comm.sayHello();
		
		Only Strings are supported being passed back and forth currently.
		
		JavaScript to Flash communication is synchronous; i.e., results are returned
		directly from the method call:
		
		var results = dojo.flash.comm.sayHello();
		
		Flash to JavaScript communication is asynchronous due to limitations in
		the underlying technologies; you must use a results callback to handle
		results returned by JavaScript in your Flash AS files:
		
		var resultsReady = function(results){
			trace("Received the following results from JavaScript: " + results);
		}
		DojoExternalInterface.call("someJavaScriptMethod", resultsReady);
		
		
		
		-------------------
		Notes
		-------------------
		
		If you have both Flash 6 and Flash 8 versions of your file:
		
		dojo.flash.setSwf({flash6: "tests/flash/HelloWorld_flash6.swf",
											 flash8: "tests/flash/HelloWorld_flash8.swf"});
											 
		but want to force the browser to use a certain version of Flash for
		all platforms (for testing, for example), use the djConfig
		variable 'forceFlashComm' with the version number to force:
		
		var djConfig = { forceFlashComm: 6 };
		
		Two values are currently supported, 6 and 8, for the two styles of
		communication described above. Just because you force dojo.flash
		to use a particular communication style is no guarantee that it will
		work; for example, Flash 8 communication doesn't work in Internet
		Explorer due to bugs in Flash, and Flash 6 communication does not work
		in Safari. It is best to let dojo.flash determine the best communication
		mechanism, and to use the value above only for debugging the dojo.flash
		framework itself.
		
		Also note that dojo.flash can currently only work with one Flash object
		on the page; it and the API do not yet support multiple Flash objects on
		the same page.
		
		We use some special tricks to get decent, linear performance
		out of Flash 8's ExternalInterface on Safari; see the blog
		post 
		http://codinginparadise.org/weblog/2006/02/how-to-speed-up-flash-8s.html
		for details.
		
		Your code can detect whether the Flash player is installing or having
		its version revved in two ways. First, if dojo.flash detects that
		Flash installation needs to occur, it sets dojo.flash.info.installing
		to true. Second, you can detect if installation is necessary with the
		following callback:
		
		dojo.event.connect(dojo.flash, "installing", myInstance, "myCallback");
		
		You can use this callback to delay further actions that might need Flash;
		when installation is finished the full page will be refreshed and the
		user will be placed back on your page with Flash installed.
		
		Two utility methods exist if you want to add loading and installing
		listeners without creating dependencies on dojo.event; these are
		'addLoadingListener' and 'addInstallingListener'.
		
		-------------------
		Todo/Known Issues
		-------------------

		There are several tasks I was not able to do, or did not need to fix
		to get dojo.storage out:		
		
		* When using Flash 8 communication, Flash method calls to JavaScript
		are not working properly; serialization might also be broken for certain
		invalid characters when it is Flash invoking JavaScript methods.
		The Flash side needs to have more sophisticated serialization/
		deserialization mechanisms like JavaScript currently has. The
		test_flash2.html unit tests should also be updated to have much more
		sophisticated Flash to JavaScript unit tests, including large
		amounts of data.
		
		* On Internet Explorer, after doing a basic install, the page is
		not refreshed or does not detect that Flash is now available. The way
		to fix this is to create a custom small Flash file that is pointed to
		during installation; when it is finished loading, it does a callback
		that says that Flash installation is complete on IE, and we can proceed
		to initialize the dojo.flash subsystem.
		
		@author Brad Neuberg, bkn3@columbia.edu
*/

dojo.flash = {
	flash6_version: null,
	flash8_version: null,
	ready: false,
	_visible: true,
	_loadedListeners: new Array(),
	_installingListeners: new Array(),
	
	/** Sets the SWF files and versions we are using. */
	setSwf: function(fileInfo){
		//dojo.debug("setSwf");
		if(fileInfo == null || dojo.lang.isUndefined(fileInfo)){
			return;
		}
		
		if(fileInfo.flash6 != null && !dojo.lang.isUndefined(fileInfo.flash6)){
			this.flash6_version = fileInfo.flash6;
		}
		
		if(fileInfo.flash8 != null && !dojo.lang.isUndefined(fileInfo.flash8)){
			this.flash8_version = fileInfo.flash8;
		}
		
		if(!dojo.lang.isUndefined(fileInfo.visible)){
			this._visible = fileInfo.visible;
		}
		
		// initialize ourselves		
		this._initialize();
	},
	
	/** Returns whether we are using Flash 6 for communication on this platform. */
	useFlash6: function(){
		if(this.flash6_version == null){
			return false;
		}else if (this.flash6_version != null && dojo.flash.info.commVersion == 6){
			// if we have a flash 6 version of this SWF, and this browser supports 
			// communicating using Flash 6 features...
			return true;
		}else{
			return false;
		}
	},
	
	/** Returns whether we are using Flash 8 for communication on this platform. */
	useFlash8: function(){
		if(this.flash8_version == null){
			return false;
		}else if (this.flash8_version != null && dojo.flash.info.commVersion == 8){
			// if we have a flash 8 version of this SWF, and this browser supports
			// communicating using Flash 8 features...
			return true;
		}else{
			return false;
		}
	},
	
	/** Adds a listener to know when Flash is finished loading. 
			Useful if you don't want a dependency on dojo.event. */
	addLoadedListener: function(listener){
		this._loadedListeners.push(listener);
	},

	/** Adds a listener to know if Flash is being installed. 
			Useful if you don't want a dependency on dojo.event. */
	addInstallingListener: function(listener){
		this._installingListeners.push(listener);
	},	
	
	/** 
			A callback when the Flash subsystem is finished loading and can be
			worked with. To be notified when Flash is finished loading, connect
			your callback to this method using the following:
			
			dojo.event.connect(dojo.flash, "loaded", myInstance, "myCallback");
	*/
	loaded: function(){
		//dojo.debug("dojo.flash.loaded");
		dojo.flash.ready = true;
		if(dojo.flash._loadedListeners.length > 0){
			for(var i = 0;i < dojo.flash._loadedListeners.length; i++){
				dojo.flash._loadedListeners[i].call(null);
			}
		}
	},
	
	/** 
			A callback to know if Flash is currently being installed or
			having its version revved. To be notified if Flash is installing, connect
			your callback to this method using the following:
			
			dojo.event.connect(dojo.flash, "installing", myInstance, "myCallback");
	*/
	installing: function(){
	 //dojo.debug("installing");
	 if(dojo.flash._installingListeners.length > 0){
			for(var i = 0; i < dojo.flash._installingListeners.length; i++){
				dojo.flash._installingListeners[i].call(null);
			}
		}
	},
	
	/** Initializes dojo.flash. */
	_initialize: function(){
		//dojo.debug("dojo.flash._initialize");
		// see if we need to rev or install Flash on this platform
		var installer = new dojo.flash.Install();
		dojo.flash.installer = installer;

		if(installer.needed() == true){		
			installer.install();
		}else{
			//dojo.debug("Writing object out");
			// write the flash object into the page
			dojo.flash.obj = new dojo.flash.Embed(this._visible);
			dojo.flash.obj.write(dojo.flash.info.commVersion);
			
			// initialize the way we do Flash/JavaScript communication
			dojo.flash.comm = new dojo.flash.Communicator();
		}
	}
};


/** 
		A class that helps us determine whether Flash is available,
		it's major and minor versions, and what Flash version features should
		be used for Flash/JavaScript communication. Parts of this code
		are adapted from the automatic Flash plugin detection code autogenerated 
		by the Macromedia Flash 8 authoring environment. 
		
		An instance of this class can be accessed on dojo.flash.info after
		the page is finished loading.
		
		This constructor must be called before the page is finished loading. 
*/
dojo.flash.Info = function(){
	// Visual basic helper required to detect Flash Player ActiveX control 
	// version information on Internet Explorer
	if(dojo.render.html.ie){
		document.writeln('<script language="VBScript" type="text/vbscript"\>');
		document.writeln('Function VBGetSwfVer(i)');
		document.writeln('  on error resume next');
		document.writeln('  Dim swControl, swVersion');
		document.writeln('  swVersion = 0');
		document.writeln('  set swControl = CreateObject("ShockwaveFlash.ShockwaveFlash." + CStr(i))');
		document.writeln('  if (IsObject(swControl)) then');
		document.writeln('    swVersion = swControl.GetVariable("$version")');
		document.writeln('  end if');
		document.writeln('  VBGetSwfVer = swVersion');
		document.writeln('End Function');
		document.writeln('</script\>');
	}
	
	this._detectVersion();
	this._detectCommunicationVersion();
}

dojo.flash.Info.prototype = {
	/** The full version string, such as "8r22". */
	version: -1,
	
	/** 
			The major, minor, and revisions of the plugin. For example, if the
			plugin is 8r22, then the major version is 8, the minor version is 0,
			and the revision is 22. 
	*/
	versionMajor: -1,
	versionMinor: -1,
	versionRevision: -1,
	
	/** Whether this platform has Flash already installed. */
	capable: false,
	
	/** 
			The major version number for how our Flash and JavaScript communicate.
			This can currently be the following values:
			6 - We use a combination of the Flash plugin methods, such as SetVariable
			and TCallLabel, along with fscommands, to do communication.
			8 - We use the ExternalInterface API. 
			-1 - For some reason neither method is supported, and no communication
			is possible. 
	*/
	commVersion: 6,
	
	/** Set if we are in the middle of a Flash installation session. */
	installing: false,
	
	/** 
			Asserts that this environment has the given major, minor, and revision
			numbers for the Flash player. Returns true if the player is equal
			or above the given version, false otherwise.
			
			Example: To test for Flash Player 7r14:
			
			dojo.flash.info.isVersionOrAbove(7, 0, 14)
	*/
	isVersionOrAbove: function(reqMajorVer, reqMinorVer, reqVer){
		// make the revision a decimal (i.e. transform revision 14 into
		// 0.14
		reqVer = parseFloat("." + reqVer);
		
		if(this.versionMajor >= reqMajorVer && this.versionMinor >= reqMinorVer
			 && this.versionRevision >= reqVer){
			return true;
		}else{
			return false;
		}
	},
	
	_detectVersion: function(){
		var versionStr;
		
		// loop backwards through the versions until we find the newest version	
		for(var testVersion = 25; testVersion > 0; testVersion--){
			if(dojo.render.html.ie){
				versionStr = VBGetSwfVer(testVersion);
			}else{
				versionStr = this._JSFlashInfo(testVersion);		
			}
				
			if(versionStr == -1 ){
				this.capable = false; 
				return;
			}else if(versionStr != 0){
				var versionArray;
				if(dojo.render.html.ie){
					var tempArray = versionStr.split(" ");
					var tempString = tempArray[1];
					versionArray = tempString.split(",");
				}else{
					versionArray = versionStr.split(".");
				}
					
				this.versionMajor = versionArray[0];
				this.versionMinor = versionArray[1];
				this.versionRevision = versionArray[2];
				
				// 7.0r24 == 7.24
				var versionString = this.versionMajor + "." + this.versionRevision;
				this.version = parseFloat(versionString);
				
				this.capable = true;
				
				break;
			}
		}
	},
	
	/** 
			JavaScript helper required to detect Flash Player PlugIn version 
			information. Internet Explorer uses a corresponding Visual Basic
			version to interact with the Flash ActiveX control. 
	*/
	_JSFlashInfo: function(testVersion){
		// NS/Opera version >= 3 check for Flash plugin in plugin array
		if(navigator.plugins != null && navigator.plugins.length > 0){
			if(navigator.plugins["Shockwave Flash 2.0"] || 
				 navigator.plugins["Shockwave Flash"]){
				var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
				var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
				var descArray = flashDescription.split(" ");
				var tempArrayMajor = descArray[2].split(".");
				var versionMajor = tempArrayMajor[0];
				var versionMinor = tempArrayMajor[1];
				if(descArray[3] != ""){
					var tempArrayMinor = descArray[3].split("r");
				}else{
					var tempArrayMinor = descArray[4].split("r");
				}
				var versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
				var version = versionMajor + "." + versionMinor + "." 
											+ versionRevision;
											
				return version;
			}
		}
		
		return -1;
	},
	
	/** 
			Detects the mechanisms that should be used for Flash/JavaScript 
			communication, setting 'commVersion' to either 6 or 8. If the value is
			6, we use Flash Plugin 6+ features, such as GetVariable, TCallLabel,
			and fscommand, to do Flash/JavaScript communication; if the value is
			8, we use the ExternalInterface API for communication. 
	*/
	_detectCommunicationVersion: function(){
		if(this.capable == false){
			this.commVersion = null;
			return;
		}
		
		// detect if the user has over-ridden the default flash version
		if (typeof djConfig["forceFlashComm"] != "undefined" &&
				typeof djConfig["forceFlashComm"] != null){
			this.commVersion = djConfig["forceFlashComm"];
			return;
		}
		
		// we prefer Flash 6 features over Flash 8, because they are much faster
		// and much less buggy
		
		// at this point, we don't have a flash file to detect features on,
		// so we need to instead look at the browser environment we are in
		if(dojo.render.html.safari == true || dojo.render.html.opera == true){
			this.commVersion = 8;
		}else{
			this.commVersion = 6;
		}
	}
};

/** A class that is used to write out the Flash object into the page. */
dojo.flash.Embed = function(visible){
	this._visible = visible;
}

dojo.flash.Embed.prototype = {
	/** 
			The width of this Flash applet. The default is the minimal width
			necessary to show the Flash settings dialog. 
	*/
	width: 215,
	
	/** 
			The height of this Flash applet. The default is the minimal height
			necessary to show the Flash settings dialog. 
	*/
	height: 138,
	
	/** The id of the Flash object. */
	id: "flashObject",
	
	/** Controls whether this is a visible Flash applet or not. */
	_visible: true,
			
	/** 
			Writes the Flash into the page. This must be called before the page
			is finished loading. 
			@param flashVer The Flash version to write.
			@param doExpressInstall Whether to write out Express Install
			information. Optional value; defaults to false.
	*/
	write: function(flashVer, doExpressInstall){
		//dojo.debug("write");
		if(dojo.lang.isUndefined(doExpressInstall)){
			doExpressInstall = false;
		}
		
		// determine our container div's styling
		var containerStyle = new dojo.string.Builder();
		containerStyle.append("width: " + this.width + "px; ");
		containerStyle.append("height: " + this.height + "px; ");
		if(this._visible == false){
			containerStyle.append("position: absolute; ");
			containerStyle.append("z-index: 10000; ");
			containerStyle.append("top: -1000px; ");
			containerStyle.append("left: -1000px; ");
		}
		containerStyle = containerStyle.toString();

		// figure out the SWF file to get and how to write out the correct HTML
		// for this Flash version
		var objectHTML;
		var swfloc;
		// Flash 6
		if(flashVer == 6){
			swfloc = dojo.flash.flash6_version;
			var dojoPath = djConfig.baseRelativePath;
			swfloc = swfloc + "?baseRelativePath=" + escape(dojoPath);
			
			objectHTML = 
						  '<embed id="' + this.id + '" src="' + swfloc + '" '
						+ '    quality="high" bgcolor="#ffffff" '
						+ '    width="' + this.width + '" height="' + this.height + '" '
						+ '    name="' + this.id + '" '
						+ '    align="middle" allowScriptAccess="sameDomain" '
						+ '    type="application/x-shockwave-flash" swLiveConnect="true" '
						+ '    pluginspage="http://www.macromedia.com/go/getflashplayer">';
		}else{ // Flash 8
			swfloc = dojo.flash.flash8_version;
			var swflocObject = swfloc;
			var swflocEmbed = swfloc;
			var dojoPath = djConfig.baseRelativePath;
			if(doExpressInstall){
				// the location to redirect to after installing
				var redirectURL = escape(window.location);
				document.title = document.title.slice(0, 47) + " - Flash Player Installation";
				var docTitle = escape(document.title);
				swflocObject += "?MMredirectURL=" + redirectURL
				                + "&MMplayerType=ActiveX"
				                + "&MMdoctitle=" + docTitle
								+ "&baseRelativePath=" + escape(dojoPath);
				swflocEmbed += "?MMredirectURL=" + redirectURL 
								+ "&MMplayerType=PlugIn"
								+ "&baseRelativePath=" + escape(dojoPath);
			}
			
			objectHTML =
				'<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '
				  + 'codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" '
				  + 'width="' + this.width + '" '
				  + 'height="' + this.height + '" '
				  + 'id="' + this.id + '" '
				  + 'align="middle"> '
				  + '<param name="allowScriptAccess" value="sameDomain" /> '
				  + '<param name="movie" value="' + swflocObject + '" /> '
				  + '<param name="quality" value="high" /> '
				  + '<param name="bgcolor" value="#ffffff" /> '
				  + '<embed src="' + swflocEmbed + '" '
				  + 'quality="high" '
				  + 'bgcolor="#ffffff" '
				  + 'width="' + this.width + '" '
				  + 'height="' + this.height + '" '
				  + 'id="' + this.id + '" '
				  + 'name="' + this.id + '" '
				  + 'swLiveConnect="true" '
				  + 'align="middle" '
				  + 'allowScriptAccess="sameDomain" '
				  + 'type="application/x-shockwave-flash" '+ "&baseRelativePath=" + escape(dojoPath);
				  + 'pluginspage="http://www.macromedia.com/go/getflashplayer" />'
				+ '</object>';
		}

		// now write everything out
		objectHTML = '<div id="' + this.id + 'Container" style="' + containerStyle + '"> '
						+ objectHTML
					 + '</div>';
		document.writeln(objectHTML);
	},  
	
	/** Gets the Flash object DOM node. */
	get: function(){
		//return (dojo.render.html.ie) ? window[this.id] : document[this.id];
		
		// more robust way to get Flash object; version above can break
		// communication on IE sometimes
		return document.getElementById(this.id);
	},
	
	/** Sets the visibility of this Flash object. */
	setVisible: function(visible){
		var container = dojo.byId(this.id + "Container");
		if(visible == true){
			container.style.visibility = "visible";
		}else{
			container.style.position = "absolute";
			container.style.x = "-1000px";
			container.style.y = "-1000px";
			container.style.visibility = "hidden";
		}
	},
	
	/** Centers the flash applet on the page. */
	center: function(){
		// FIXME: replace this with Dojo's centering code rather than our own
		// We want to center the Flash applet vertically and horizontally
		var elementWidth = this.width;
		var elementHeight = this.height;
    
		// get the browser width and height; the code below
		// works in IE and Firefox in compatibility, non-strict
		// mode
		var browserWidth = document.body.clientWidth;
		var browserHeight = document.body.clientHeight;
    
		// in Firefox if we are in standards compliant mode
		// (with a strict doctype), then the browser width
		// and height have to be computed from the root level
		// HTML element not the BODY element
		if(!dojo.render.html.ie && document.compatMode == "CSS1Compat"){
			browserWidth = document.body.parentNode.clientWidth;
			browserHeight = document.body.parentNode.clientHeight;
		}else if(dojo.render.html.ie && document.compatMode == "CSS1Compat"){
			// IE 6 in standards compliant mode has to be calculated
			// differently
			browserWidth = document.documentElement.clientWidth;
			browserHeight = document.documentElement.clientHeight;
		}else if(dojo.render.html.safari){ // Safari works different
			browserHeight = self.innerHeight;
		}
    
		// get where we are scrolled to in the document
		// the code below works in FireFox
		var scrolledByWidth = window.scrollX;
		var scrolledByHeight = window.scrollY;
		// compute these values differently for IE;
		// IE has two possibilities; it is either in standards
		// compatibility mode or it is not
		if(typeof scrolledByWidth == "undefined"){
			if(document.compatMode == "CSS1Compat"){ // standards mode
				scrolledByWidth = document.documentElement.scrollLeft;
				scrolledByHeight = document.documentElement.scrollTop;
			}else{ // Pre IE6 non-standards mode
				scrolledByWidth = document.body.scrollLeft;
				scrolledByHeight = document.body.scrollTop;
			}
		}

		// compute the centered position    
		var x = scrolledByWidth + (browserWidth - elementWidth) / 2;
		var y = scrolledByHeight + (browserHeight - elementHeight) / 2; 

		// set the centered position
		var container = dojo.byId(this.id + "Container");
		container.style.top = y + "px";
		container.style.left = x + "px";
	}
};


/** 
		A class that is used to communicate between Flash and JavaScript in 
		a way that can pass large amounts of data back and forth reliably,
		very fast, and with synchronous method calls. This class encapsulates the 
		specific way in which this communication occurs,
		presenting a common interface to JavaScript irrespective of the underlying
		Flash version.
*/
dojo.flash.Communicator = function(){
	if(dojo.flash.useFlash6()){
		this._writeFlash6();
	}else if (dojo.flash.useFlash8()){
		this._writeFlash8();
	}
}

dojo.flash.Communicator.prototype = {
	_writeFlash6: function(){
		var id = dojo.flash.obj.id;
		
		// global function needed for Flash 6 callback;
		// we write it out as a script tag because the VBScript hook for IE
		// callbacks does not work properly if this function is evalled() from
		// within the Dojo system
		document.writeln('<script language="JavaScript">');
		document.writeln('  function ' + id + '_DoFSCommand(command, args){ ');
		document.writeln('    dojo.flash.comm._handleFSCommand(command, args); ');
		document.writeln('}');
		document.writeln('</script>');
		
		// hook for Internet Explorer to receive FSCommands from Flash
		if(dojo.render.html.ie){
			document.writeln('<SCRIPT LANGUAGE=VBScript\> ');
			document.writeln('on error resume next ');
			document.writeln('Sub ' + id + '_FSCommand(ByVal command, ByVal args)');
			document.writeln(' call ' + id + '_DoFSCommand(command, args)');
			document.writeln('end sub');
			document.writeln('</SCRIPT\> ');
		}
	},
	
	_writeFlash8: function(){
		// nothing needs to be written out for Flash 8 communication; 
		// happens automatically
	},
	
	/** Flash 6 communication. */
	
	/** Handles fscommand's from Flash to JavaScript. Flash 6 communication. */
	_handleFSCommand: function(command, args){
		//dojo.debug("fscommand, command="+command+", args="+args);
		// Flash 8 on Mac/Firefox precedes all commands with the string "FSCommand:";
		// strip it off if it is present
		if(command != null && !dojo.lang.isUndefined(command)
			&& /^FSCommand:(.*)/.test(command) == true){
			command = command.match(/^FSCommand:(.*)/)[1];
		}
		 
		if(command == "addCallback"){ // add Flash method for JavaScript callback
			this._fscommandAddCallback(command, args);
		}else if(command == "call"){ // Flash to JavaScript method call
			this._fscommandCall(command, args);
		}else if(command == "fscommandReady"){ // see if fscommands are ready
			this._fscommandReady();
		}
	},
	
	/** Handles registering a callable Flash function. Flash 6 communication. */
	_fscommandAddCallback: function(command, args){
		var functionName = args;
			
		// do a trick, where we link this function name to our wrapper
		// function, _call, that does the actual JavaScript to Flash call
		var callFunc = function(){
			return dojo.flash.comm._call(functionName, arguments);
		};			
		dojo.flash.comm[functionName] = callFunc;
		
		// indicate that the call was successful
		dojo.flash.obj.get().SetVariable("_succeeded", true);
	},
	
	/** Handles Flash calling a JavaScript function. Flash 6 communication. */
	_fscommandCall: function(command, args){
		var plugin = dojo.flash.obj.get();
		var functionName = args;
		
		// get the number of arguments to this method call and build them up
		var numArgs = parseInt(plugin.GetVariable("_numArgs"));
		var flashArgs = new Array();
		for(var i = 0; i < numArgs; i++){
			var currentArg = plugin.GetVariable("_" + i);
			flashArgs.push(currentArg);
		}
		
		// get the function instance; we technically support more capabilities
		// than ExternalInterface, which can only call global functions; if
		// the method name has a dot in it, such as "dojo.flash.loaded", we
		// eval it so that the method gets run against an instance
		var runMe;
		if(functionName.indexOf(".") == -1){ // global function
			runMe = window[functionName];
		}else{
			// instance function
			runMe = eval(functionName);
		}
		
		// make the call and get the results
		var results = null;
		if(!dojo.lang.isUndefined(runMe) && runMe != null){
			results = runMe.apply(null, flashArgs);
		}
		
		// return the results to flash
		plugin.SetVariable("_returnResult", results);
	},
	
	/** Reports that fscommands are ready to run if executed from Flash. */
	_fscommandReady: function(){
		var plugin = dojo.flash.obj.get();
		plugin.SetVariable("fscommandReady", "true");
	},
	
	/** 
			The actual function that will execute a JavaScript to Flash call; used
			by the Flash 6 communication method. 
	*/
	_call: function(functionName, args){
		// we do JavaScript to Flash method calls by setting a Flash variable
		// "_functionName" with the function name; "_numArgs" with the number
		// of arguments; and "_0", "_1", etc for each numbered argument. Flash
		// reads these, executes the function call, and returns the result
		// in "_returnResult"
		var plugin = dojo.flash.obj.get();
		plugin.SetVariable("_functionName", functionName);
		plugin.SetVariable("_numArgs", args.length);
		for(var i = 0; i < args.length; i++){
			// unlike Flash 8's ExternalInterface, Flash 6 has no problem with
			// any special characters _except_ for the null character \0; double
			// encode this so the Flash side never sees it, but we can get it 
			// back if the value comes back to JavaScript
			var value = args[i];
			value = value.replace(/\0/g, "\\0");
			
			plugin.SetVariable("_" + i, value);
		}
		
		// now tell Flash to execute this method using the Flash Runner
		plugin.TCallLabel("/_flashRunner", "execute");
		
		// get the results
		var results = plugin.GetVariable("_returnResult");
		
		// we double encoded all null characters as //0 because Flash breaks
		// if they are present; turn the //0 back into /0
		results = results.replace(/\\0/g, "\0");
		
		return results;
	},
	
	/** Flash 8 communication. */
	
	/** 
			Registers the existence of a Flash method that we can call with
			JavaScript, using Flash 8's ExternalInterface. 
	*/
	_addExternalInterfaceCallback: function(methodName){
		var wrapperCall = function(){
			// some browsers don't like us changing values in the 'arguments' array, so
			// make a fresh copy of it
			var methodArgs = new Array(arguments.length);
			for(var i = 0; i < arguments.length; i++){
				methodArgs[i] = arguments[i];
			}
			return dojo.flash.comm._execFlash(methodName, methodArgs);
		};
		
		dojo.flash.comm[methodName] = wrapperCall;
	},
	
	/** 
			Encodes our data to get around ExternalInterface bugs.
			Flash 8 communication.
	*/
	_encodeData: function(data){
		// double encode all entity values, or they will be mis-decoded
		// by Flash when returned
		var entityRE = /\&([^;]*)\;/g;
		data = data.replace(entityRE, "&amp;$1;");
		
		// entity encode XML-ish characters, or Flash's broken XML serializer
		// breaks
		data = data.replace(/</g, "&lt;");
		data = data.replace(/>/g, "&gt;");
		
		// transforming \ into \\ doesn't work; just use a custom encoding
		data = data.replace("\\", "&custom_backslash;&custom_backslash;");
		
		data = data.replace(/\n/g, "\\n");
		data = data.replace(/\r/g, "\\r");
		data = data.replace(/\f/g, "\\f");
		data = data.replace(/\0/g, "\\0"); // null character
		data = data.replace(/\'/g, "\\\'");
		data = data.replace(/\"/g, '\\\"');
		
		return data;
	},
	
	/** 
			Decodes our data to get around ExternalInterface bugs.
			Flash 8 communication.
	*/
	_decodeData: function(data){
		if(data == null || typeof data == "undefined"){
			return data;
		}
		
		// certain XMLish characters break Flash's wire serialization for
		// ExternalInterface; these are encoded on the 
		// DojoExternalInterface side into a custom encoding, rather than
		// the standard entity encoding, because otherwise we won't be able to
		// differentiate between our own encoding and any entity characters
		// that are being used in the string itself
		data = data.replace(/\&custom_lt\;/g, "<");
		data = data.replace(/\&custom_gt\;/g, ">");
		
		// Unfortunately, Flash returns us our String with special characters
		// like newlines broken into seperate characters. So if \n represents
		// a new line, Flash returns it as "\" and "n". This means the character
		// is _not_ a newline. This forces us to eval() the string to cause
		// escaped characters to turn into their real special character values.
		data = eval('"' + data + '"');
		
		return data;
	},
	
	/** 
			Sends our method arguments over to Flash in chunks in order to
			have ExternalInterface's performance not be O(n^2).
			Flash 8 communication.
	*/
	_chunkArgumentData: function(value, argIndex){
		var plugin = dojo.flash.obj.get();
		
		// cut up the string into pieces, and push over each piece one
		// at a time
		var numSegments = Math.ceil(value.length / 1024);
		for(var i = 0; i < numSegments; i++){
			var startCut = i * 1024;
			var endCut = i * 1024 + 1024;
			if(i == (numSegments - 1)){
				endCut = i * 1024 + value.length;
			}
			
			var piece = value.substring(startCut, endCut);
			
			// encode each piece seperately, rather than the entire
			// argument data, because ocassionally a special 
			// character, such as an entity like &foobar;, will fall between
			// piece boundaries, and we _don't_ want to encode that value if
			// it falls between boundaries, or else we will end up with incorrect
			// data when we patch the pieces back together on the other side
			piece = this._encodeData(piece);
			
			// directly use the underlying CallFunction method used by
			// ExternalInterface, which is vastly faster for large strings
			// and lets us bypass some Flash serialization bugs
			plugin.CallFunction('<invoke name="chunkArgumentData" '
														+ 'returntype="javascript">'
														+ '<arguments>'
														+ '<string>' + piece + '</string>'
														+ '<number>' + argIndex + '</number>'
														+ '</arguments>'
														+ '</invoke>');
		}
	},
	
	/** 
			Gets our method return data in chunks for better performance.
			Flash 8 communication.
	*/
	_chunkReturnData: function(){
		var plugin = dojo.flash.obj.get();
		
		var numSegments = plugin.getReturnLength();
		var resultsArray = new Array();
		for(var i = 0; i < numSegments; i++){
			// directly use the underlying CallFunction method used by
			// ExternalInterface, which is vastly faster for large strings
			var piece = 
					plugin.CallFunction('<invoke name="chunkReturnData" '
															+ 'returntype="javascript">'
															+ '<arguments>'
															+ '<number>' + i + '</number>'
															+ '</arguments>'
															+ '</invoke>');
															
			// remove any leading or trailing JavaScript delimiters, which surround
			// our String when it comes back from Flash since we bypass Flash's
			// deserialization routines by directly calling CallFunction on the
			// plugin
			if(piece == '""' || piece == "''"){
				piece = "";
			}else{
				piece = piece.substring(1, piece.length-1);
			}
		
			resultsArray.push(piece);
		}
		var results = resultsArray.join("");
		
		return results;
	},
	
	/** 
			Executes a Flash method; called from the JavaScript wrapper proxy we
			create on dojo.flash.comm.
			Flash 8 communication.
	*/
	_execFlash: function(methodName, methodArgs){
		var plugin = dojo.flash.obj.get();
				
		// begin Flash method execution
		plugin.startExec();
		
		// set the number of arguments
		plugin.setNumberArguments(methodArgs.length);
		
		// chunk and send over each argument
		for(var i = 0; i < methodArgs.length; i++){
			this._chunkArgumentData(methodArgs[i], i);
		}
		
		// execute the method
		plugin.exec(methodName);
														
		// get the return result
		var results = this._chunkReturnData();
		
		// decode the results
		results = this._decodeData(results);
		
		// reset everything
		plugin.endExec();
		
		return results;

	}
}

/** 
		Figures out the best way to automatically install the Flash plugin
		for this browser and platform. Also determines if installation or
		revving of the current plugin is needed on this platform.
*/
dojo.flash.Install = function(){
}

dojo.flash.Install.prototype = {
	/** 
			Determines if installation or revving of the current plugin is 
			needed. 
	*/
	needed: function(){
		// do we even have flash?
		if(dojo.flash.info.capable == false){
			return true;
		}

		// are we on the Mac? Safari needs Flash version 8 to do Flash 8
		// communication, while Firefox/Mac needs Flash 8 to fix bugs it has
		// with Flash 6 communication
		if(dojo.render.os.mac == true && !dojo.flash.info.isVersionOrAbove(8, 0, 0)){
			return true;
		}

		// other platforms need at least Flash 6 or above
		if(!dojo.flash.info.isVersionOrAbove(6, 0, 0)){
			return true;
		}

		// otherwise we don't need installation
		return false;
	},

	/** Performs installation or revving of the Flash plugin. */
	install: function(){
		//dojo.debug("install");
		// indicate that we are installing
		dojo.flash.info.installing = true;
		dojo.flash.installing();
		
		if(dojo.flash.info.capable == false){ // we have no Flash at all
			//dojo.debug("Completely new install");
			// write out a simple Flash object to force the browser to prompt
			// the user to install things
			var installObj = new dojo.flash.Embed(false);
			installObj.write(8); // write out HTML for Flash 8 version+
		}else if(dojo.flash.info.isVersionOrAbove(6, 0, 65)){ // Express Install
			//dojo.debug("Express install");
			var installObj = new dojo.flash.Embed(false);
			installObj.write(8, true); // write out HTML for Flash 8 version+
			installObj.setVisible(true);
			installObj.center();
		}else{ // older Flash install than version 6r65
			alert("This content requires a more recent version of the Macromedia "
						+" Flash Player.");
			window.location.href = "http://www.macromedia.com/go/getflashplayer";
		}
	},
	
	/** 
			Called when the Express Install is either finished, failed, or was
			rejected by the user.
	*/
	_onInstallStatus: function(msg){
		if (msg == "Download.Complete"){
			// Installation is complete.
			dojo.flash._initialize();
		}else if(msg == "Download.Cancelled"){
			alert("This content requires a more recent version of the Macromedia "
						+" Flash Player.");
			window.location.href = "http://www.macromedia.com/go/getflashplayer";
		}else if (msg == "Download.Failed"){
			// The end user failed to download the installer due to a network failure
			alert("There was an error downloading the Flash Player update. "
						+ "Please try again later, or visit macromedia.com to download "
						+ "the latest version of the Flash plugin.");
		}	
	}
}

// find out if Flash is installed
dojo.flash.info = new dojo.flash.Info();

// vim:ts=4:noet:tw=0:

__CPAN_DIR__ src/rpc
__CPAN_FILE__ src/rpc/Deferred.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.rpc.Deferred");
dojo.require("dojo.Deferred");

dojo.rpc.Deferred = dojo.Deferred;
dojo.rpc.Deferred.prototype = dojo.Deferred.prototype;

__CPAN_FILE__ src/rpc/YahooService.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.rpc.YahooService");
dojo.require("dojo.rpc.RpcService");
dojo.require("dojo.rpc.JsonService");
dojo.require("dojo.json");
dojo.require("dojo.uri.*");
dojo.require("dojo.io.ScriptSrcIO");

dojo.rpc.YahooService = function(appId){
	this.appId = appId;
	if(!appId){
		this.appId = "dojotoolkit";
		dojo.debug(	"please initializae the YahooService class with your own",
					"application ID. Using the default may cause problems during",
					"deployment of your application");
	}
	this.connect(dojo.uri.dojoUri("src/rpc/yahoo.smd"));
	this.scrictArgChecks = false;
}

dojo.inherits(dojo.rpc.YahooService, dojo.rpc.JsonService);

dojo.lang.extend(dojo.rpc.YahooService, {
	strictArgChecks: false,

	bind: function(method, parameters, deferredRequestHandler, url){
		var params = parameters;
		if(	(dojo.lang.isArrayLike(parameters))&&
			(parameters.length == 1)){
			params = parameters[0];
		}
		params.output = "json";
		params.appid= this.appId;
		dojo.io.bind({
			url: url||this.serviceUrl,
			transport: "ScriptSrcTransport",
			// FIXME: need to get content interpolation fixed
			content: params,
			jsonParamName: "callback",
			mimetype: "text/json",
			load: this.resultCallback(deferredRequestHandler),
			error: this.errorCallback(deferredRequestHandler),
			preventCache: true
		});
	}
});

__CPAN_FILE__ src/rpc/yahoo.smd
{
	"SMDVersion":".1",
	"objectName":"yahoo",
	"serviceType":"JSON-P",
	"methods":[
		//
		// MAPS 
		//
		{
			// http://developer.yahoo.com/maps/rest/V1/mapImage.html
			"name":"mapImage",
			"serviceURL": "http://api.local.yahoo.com/MapsService/V1/mapImage",
			"parameters":[
				{ "name":"street", "type":"STRING" },
				{ "name":"city", "type":"STRING" },
				{ "name":"zip", "type":"INTEGER" },
				{ "name":"location", "type":"STRING" },
				{ "name":"longitude", "type":"FLOAT" },
				{ "name":"latitude", "type":"FLOAT" },
				{ "name":"image_type", "type":"STRING" },
				{ "name":"image_width", "type":"INTEGER" },
				{ "name":"image_height", "type":"INTEGER" },
				{ "name":"zoom", "type":"INTEGER" },
				{ "name":"radius", "type":"INTEGER" }
			]
		},
		{
			// http://developer.yahoo.com/traffic/rest/V1/index.html
			"name":"trafficData",
			"serviceURL": "http://api.local.yahoo.com/MapsService/V1/trafficData",
			"parameters":[
				{ "name":"street", "type":"STRING" },
				{ "name":"city", "type":"STRING" },
				{ "name":"zip", "type":"INTEGER" },
				{ "name":"location", "type":"STRING" },
				{ "name":"longitude", "type":"FLOAT" },
				{ "name":"latitude", "type":"FLOAT" },
				{ "name":"severity", "type":"INTEGER" },
				{ "name":"include_map", "type":"INTEGER" },
				{ "name":"image_type", "type":"STRING" },
				{ "name":"image_width", "type":"INTEGER" },
				{ "name":"image_height", "type":"INTEGER" },
				{ "name":"zoom", "type":"INTEGER" },
				{ "name":"radius", "type":"INTEGER" }
			]
		},
		/*
			// Yahoo's geocoding service is f'd for JSON and Y! advises that it
			// may not be returning
		{
			// http://developer.yahoo.com/maps/rest/V1/geocode.html
			"name":"geocode",
			"serviceURL": "http://api.local.yahoo.com/MapsService/V1/geocode",
			"parameters":[
				{ "name":"street", "type":"STRING" },
				{ "name":"city", "type":"STRING" },
				{ "name":"zip", "type":"INTEGER" },
				{ "name":"location", "type":"STRING" }
			]
		},
		*/
		//
		// LOCAL SEARCH
		//
		{
			// http://developer.yahoo.com/search/local/V3/localSearch.html
			"name":"localSearch",
			"serviceURL": "http://api.local.yahoo.com/LocalSearchService/V3/localSearch",
			"parameters":[
				{ "name":"street", "type":"STRING" },
				{ "name":"city", "type":"STRING" },
				{ "name":"zip", "type":"INTEGER" },
				{ "name":"location", "type":"STRING" },
				{ "name":"listing_id", "type":"STRING" },
				{ "name":"sort", "type":"STRING" }, // "relevence", "title", "distance", or "rating"
				{ "name":"start", "type":"INTEGER" },
				{ "name":"radius", "type":"FLOAT" },
				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
				{ "name":"longitude", "type":"FLOAT" },
				{ "name":"latitude", "type":"FLOAT" },
				{ "name":"category", "type":"INTEGER" },
				{ "name":"omit_category", "type":"INTEGER" },
				{ "name":"minimum_rating", "type":"INTEGER" }
			]
		},
		//
		// WEB SEARCH
		//

		// NOTE: contextual search and term extraction are not stubbed out
		// becaues I'm not sure if we can POST via script src inclusion method
		{
			// http://developer.yahoo.com/search/web/V1/webSearch.html 
			"name":"webSearch",
			"serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/webSearch",
			"parameters":[
				{ "name":"query", "type":"STRING" },
				{ "name":"type", "type":"STRING" }, // defaults to "all"
				{ "name":"region", "type":"STRING" }, // defaults to "us"
				{ "name":"results", "type":"INTEGER" }, // defaults to 10
				{ "name":"start", "type":"INTEGER" }, // defaults to 1
				{ "name":"format", "type":"STRING" }, // defaults to "any", can be "html", "msword", "pdf", "ppt", "rst", "txt", or "xls"
				{ "name":"adult_ok", "type":"INTEGER" }, // defaults to null
				{ "name":"similar_ok", "type":"INTEGER" }, // defaults to null
				{ "name":"language", "type":"STRING" }, // defaults to null
				{ "name":"country", "type":"STRING" }, // defaults to null
				{ "name":"site", "type":"STRING" }, // defaults to null
				{ "name":"subscription", "type":"STRING" }, // defaults to null
				{ "name":"license", "type":"STRING" } // defaults to "any"
			]
		},
		{
			// http://developer.yahoo.com/search/web/V1/spellingSuggestion.html
			"name":"spellingSuggestion",
			"serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/spellingSuggestion",
			"parameters":[ { "name":"query", "type":"STRING" } ]
		},
		{
			// http://developer.yahoo.com/search/web/V1/relatedSuggestion.html
			"name":"spellingSuggestion",
			"serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/relatedSuggestion",
			"parameters":[
				{ "name":"query", "type":"STRING" },
				{ "name":"results", "type":"INTEGER" } // 1-50, defaults to 10
			]
		},
		//
		// IMAGE SEARCH
		//
		{
			// http://developer.yahoo.com/search/image/V1/imageSearch.html
			"name":"imageSearch",
			"serviceURL": "http://api.search.yahoo.com/ImageSearchService/V1/imageSearch",
			"parameters":[
				{ "name":"query", "type":"STRING" },
				{ "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
				{ "name":"results", "type":"INTEGER" }, // defaults to 10
				{ "name":"start", "type":"INTEGER" }, // defaults to 1
				{ "name":"format", "type":"STRING" }, // defaults to "any", can be "bmp", "gif", "jpeg", or "png"
				{ "name":"adult_ok", "type":"INTEGER" }, // defaults to null
				{ "name":"coloration", "type":"STRING" }, // "any", "color", or "bw"
				{ "name":"site", "type":"STRING" } // defaults to null
			]
		},
		//
		// SITE EXPLORER
		//
		{
			// http://developer.yahoo.com/search/siteexplorer/V1/inlinkData.html 
			"name":"inlinkData",
			"serviceURL": "http://api.search.yahoo.com/SiteExplorerService/V1/inlinkData",
			"parameters":[
				{ "name":"query", "type":"STRING" },
				{ "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
				{ "name":"entire_site", "type":"INTEGER" }, // defaults to null
				{ "name":"omit_inlinks", "type":"STRING" }, // "domain" or "subdomain", defaults to null
				{ "name":"results", "type":"INTEGER" }, // defaults to 50
				{ "name":"start", "type":"INTEGER" }, // defaults to 1
				{ "name":"site", "type":"STRING" } // defaults to null
			]
		},
		{
			// http://developer.yahoo.com/search/siteexplorer/V1/pageData.html
			"name":"pageData",
			"serviceURL": "http://api.search.yahoo.com/SiteExplorerService/V1/pageData",
			"parameters":[
				{ "name":"query", "type":"STRING" },
				{ "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
				{ "name":"domain_only", "type":"INTEGER" }, // defaults to null
				{ "name":"results", "type":"INTEGER" }, // defaults to 50
				{ "name":"start", "type":"INTEGER" }, // defaults to 1
				{ "name":"site", "type":"STRING" } // defaults to null
			]
		},
		//
		// MUSIC SEARCH
		//
		{
			// http://developer.yahoo.com/search/audio/V1/artistSearch.html
			"name":"artistSearch",
			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/artistSearch",
			"parameters":[
				{ "name":"artist", "type":"STRING" },
				{ "name":"artistid", "type":"STRING" },
				{ "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
				{ "name":"start", "type":"INTEGER" } // defaults to 1
			]
		},
		{
			// http://developer.yahoo.com/search/audio/V1/albumSearch.html
			"name":"albumSearch",
			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/albumSearch",
			"parameters":[
				{ "name":"artist", "type":"STRING" },
				{ "name":"artistid", "type":"STRING" },
				{ "name":"album", "type":"STRING" },
				{ "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
				{ "name":"start", "type":"INTEGER" } // defaults to 1
			]
		},
		{
			// http://developer.yahoo.com/search/audio/V1/songSearch.html
			"name":"songSearch",
			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/songSearch",
			"parameters":[
				{ "name":"artist", "type":"STRING" },
				{ "name":"artistid", "type":"STRING" },
				{ "name":"album", "type":"STRING" },
				{ "name":"albumid", "type":"STRING" },
				{ "name":"song", "type":"STRING" },
				{ "name":"songid", "type":"STRING" },
				{ "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
				{ "name":"start", "type":"INTEGER" } // defaults to 1
			]
		},
		{
			// http://developer.yahoo.com/search/audio/V1/songDownloadLocation.html
			"name":"songDownloadLocation",
			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/songDownloadLocation",
			"parameters":[
				{ "name":"songid", "type":"STRING" },
				// "source" can contain:
				//	audiolunchbox artistdirect buymusic dmusic
				//	emusic epitonic garageband itunes yahoo
				//	livedownloads mp34u msn musicmatch mapster passalong
				//	rhapsody soundclick theweb
				{ "name":"source", "type":"STRING" },
				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
				{ "name":"start", "type":"INTEGER" } // defaults to 1
			]
		},
		//
		// NEWS SEARCH
		//
		{
			// http://developer.yahoo.com/search/news/V1/newsSearch.html
			"name":"newsSearch",
			"serviceURL": "http://api.search.yahoo.com/NewsSearchService/V1/newsSearch",
			"parameters":[
				{ "name":"query", "type":"STRING" },
				{ "name":"type", "type":"STRING" }, // defaults to "all"
				{ "name":"results", "type":"INTEGER" }, // defaults to 10
				{ "name":"start", "type":"INTEGER" }, // defaults to 1
				{ "name":"sort", "type":"STRING" }, // "rank" or "date"
				{ "name":"language", "type":"STRING" }, // defaults to null
				{ "name":"site", "type":"STRING" } // defaults to null
			]
		}
		/*
		{
			// 
			"name":"",
			"serviceURL": "",
			"parameters":[
				{ "name":"street", "type":"STRING" },
			]
		}
		*/
	]
}

__CPAN_FILE__ src/rpc/RpcService.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.rpc.RpcService");
dojo.require("dojo.io.*");
dojo.require("dojo.json");
dojo.require("dojo.lang.func");
dojo.require("dojo.rpc.Deferred");

dojo.rpc.RpcService = function(url){
	// summary
	// constructor for rpc base class
	if(url){
		this.connect(url);
	}
}

dojo.lang.extend(dojo.rpc.RpcService, {

	strictArgChecks: true,
	serviceUrl: "",

	parseResults: function(obj){
		// summary
		// parse the results coming back from an rpc request.  
   		// this base implementation, just returns the full object
		// subclasses should parse and only return the actual results
		return obj;
	},

	errorCallback: function(/* dojo.rpc.Deferred */ deferredRequestHandler){
		// summary
		// create callback that calls the Deferres errback method
		return function(type, obj, e){
			deferredRequestHandler.errback(e);
		}
	},

	resultCallback: function(/* dojo.rpc.Deferred */ deferredRequestHandler){
		// summary
		// create callback that calls the Deferred's callback method
		var tf = dojo.lang.hitch(this, 
			function(type, obj, e){
				var results = this.parseResults(obj||e);
				deferredRequestHandler.callback(results); 
			}
		);
		return tf;
	},


	generateMethod: function(/*string*/ method, /*array*/ parameters, /*string*/ url){
		// summary
		// generate the local bind methods for the remote object
		return dojo.lang.hitch(this, function(){
			var deferredRequestHandler = new dojo.rpc.Deferred();

			// if params weren't specified, then we can assume it's varargs
			if( (this.strictArgChecks) &&
				(parameters != null) &&
				(arguments.length != parameters.length)
			){
				// put error stuff here, no enough params
				dojo.raise("Invalid number of parameters for remote method.");
			} else {
				this.bind(method, arguments, deferredRequestHandler, url);
			}

			return deferredRequestHandler;
		});
	},

	processSmd: function(/*json*/ object){
		// summary
		// callback method for reciept of a smd object.  Parse the smd and
		// generate functions based on the description
		dojo.debug("RpcService: Processing returned SMD.");
		if(object.methods){
			dojo.lang.forEach(object.methods, function(m){
				if(m && m["name"]){
					dojo.debug("RpcService: Creating Method: this.", m.name, "()");
					this[m.name] = this.generateMethod(	m.name,
														m.parameters, 
														m["url"]||m["serviceUrl"]||m["serviceURL"]);
					if(dojo.lang.isFunction(this[m.name])){
						dojo.debug("RpcService: Successfully created", m.name, "()");
					}else{
						dojo.debug("RpcService: Failed to create", m.name, "()");
					}
				}
			}, this);
		}

		this.serviceUrl = object.serviceUrl||object.serviceURL;
		dojo.debug("RpcService: Dojo RpcService is ready for use.");
	},

	connect: function(/*String*/ smdUrl){
		// summary
		// connect to a remote url and retrieve a smd object
		dojo.debug("RpcService: Attempting to load SMD document from:", smdUrl);
		dojo.io.bind({
			url: smdUrl,
			mimetype: "text/json",
			load: dojo.lang.hitch(this, function(type, object, e){ return this.processSmd(object); }),
			sync: true
		});		
	}
});

__CPAN_FILE__ src/rpc/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: ["dojo.rpc.JsonService", false, false]
});
dojo.provide("dojo.rpc.*");

__CPAN_FILE__ src/rpc/JotService.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.rpc.JotService");
dojo.require("dojo.rpc.RpcService");
dojo.require("dojo.rpc.JsonService");
dojo.require("dojo.json");

dojo.rpc.JotService = function(){
	this.serviceUrl = "/_/jsonrpc";
}

dojo.inherits(dojo.rpc.JotService, dojo.rpc.JsonService);

dojo.lang.extend(dojo.rpc.JotService, {
	bind: function(method, parameters, deferredRequestHandler, url){
		dojo.io.bind({
			url: url||this.serviceUrl,
			content: {
				json: this.createRequest(method, parameters)
			},
			method: "POST",
			mimetype: "text/json",
			load: this.resultCallback(deferredRequestHandler),
			error: this.errorCallback(deferredRequestHandler),
			preventCache: true
		});
	},

	createRequest: function(method, params){
		var req = { "params": params, "method": method, "id": this.lastSubmissionId++ };
		return dojo.json.serialize(req);
	}
});

__CPAN_FILE__ src/rpc/JsonService.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.rpc.JsonService");
dojo.require("dojo.rpc.RpcService");
dojo.require("dojo.io.*");
dojo.require("dojo.json");
dojo.require("dojo.lang");

dojo.rpc.JsonService = function(args){
	// passing just the URL isn't terribly useful. It's expected that at
	// various times folks will want to specify:
	//	- just the serviceUrl (for use w/ remoteCall())
	//	- the text of the SMD to evaluate
	// 	- a raw SMD object
	//	- the SMD URL
	if(args){
		if(dojo.lang.isString(args)){
			// we assume it's an SMD file to be processed, since this was the
			// earlier function signature

			// FIXME: also accept dojo.uri.Uri objects?
			this.connect(args);
		}else{
			// otherwise we assume it's an arguments object with the following
			// (optional) properties:
			//	- serviceUrl
			//	- strictArgChecks
			//	- smdUrl
			//	- smdStr
			//	- smdObj
			if(args["smdUrl"]){
				this.connect(args.smdUrl);
			}
			if(args["smdStr"]){
				this.processSmd(dj_eval("("+args.smdStr+")"));
			}
			if(args["smdObj"]){
				this.processSmd(args.smdObj);
			}
			if(args["serviceUrl"]){
				this.serviceUrl = args.serviceUrl;
			}
			if(typeof args["strictArgChecks"] != "undefined"){
				this.strictArgChecks = args.strictArgChecks;
			}
		}
	}
}

dojo.inherits(dojo.rpc.JsonService, dojo.rpc.RpcService);

dojo.lang.extend(dojo.rpc.JsonService, {

	bustCache: false,
	
	contentType: "application/json-rpc",

	lastSubmissionId: 0,

	callRemote: function(method, params){
		var deferred = new dojo.rpc.Deferred();
		this.bind(method, params, deferred);
		return deferred;
	},

	bind: function(method, parameters, deferredRequestHandler, url){
		dojo.io.bind({
			url: url||this.serviceUrl,
			postContent: this.createRequest(method, parameters),
			method: "POST",
			contentType: this.contentType,
			mimetype: "text/json",
			load: this.resultCallback(deferredRequestHandler),
			preventCache:this.bustCache 
		});
	},

	createRequest: function(method, params){
		var req = { "params": params, "method": method, "id": ++this.lastSubmissionId };
		var data = dojo.json.serialize(req);
		dojo.debug("JsonService: JSON-RPC Request: " + data);
		return data;
	},

	parseResults: function(obj){
		if(!obj){ return; }
		if(obj["Result"]||obj["result"]){
			return obj["result"]||obj["Result"];
		}else if(obj["ResultSet"]){
			return obj["ResultSet"];
		}else{
			return obj;
		}
	}
});

__CPAN_DIR__ src/validate
__CPAN_FILE__ src/validate/common.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.validate.common");
dojo.require("dojo.validate");
dojo.require("dojo.regexp");

// *** Validation Functions ****

/**
  Checks if a string has non whitespace characters. 
  Parameters allow you to constrain the length.

  @param value  A string.
  @param flags  An object.
    flags.length  If set, checks if there are exactly flags.length number of characters.
    flags.minlength  If set, checks if there are at least flags.minlength number of characters.
    flags.maxlength  If set, checks if there are at most flags.maxlength number of characters.
  @return  true or false.
*/
dojo.validate.isText = function(value, flags) {
	flags = (typeof flags == "object") ? flags : {};

	// test for text
	if ( /^\s*$/.test(value) ) { return false; }

	// length tests
	if ( typeof flags.length == "number" && flags.length != value.length ) { return false; }
	if ( typeof flags.minlength == "number" && flags.minlength > value.length ) { return false; }
	if ( typeof flags.maxlength == "number" && flags.maxlength < value.length ) { return false; }

	return true;
}

/**
  Validates whether a string is in an integer format. 

  @param value  A string.
  @param flags  An object.
    flags.signed  The leading plus-or-minus sign.  Can be true, false, or [true, false].
      Default is [true, false], (i.e. sign is optional).
    flags.separator  The character used as the thousands separator.  Default is no separator.
      For more than one symbol use an array, e.g. [",", ""], makes ',' optional.
  @return  true or false.
*/
dojo.validate.isInteger = function(value, flags) {
	var re = new RegExp("^" + dojo.regexp.integer(flags) + "$");
	return re.test(value);
}

/**
  Validates whether a string is a real valued number. 
  Format is the usual exponential notation.

  @param value  A string.
  @param flags  An object.
    flags.places  The integer number of decimal places.
      If not given, the decimal part is optional and the number of places is unlimited.
    flags.decimal  The character used for the decimal point.  Default is ".".
    flags.exponent  Express in exponential notation.  Can be true, false, or [true, false].
      Default is [true, false], (i.e. the exponential part is optional).
    flags.eSigned  The leading plus-or-minus sign on the exponent.  Can be true, false, 
      or [true, false].  Default is [true, false], (i.e. sign is optional).
    flags in regexp.integer can be applied.
  @return  true or false.
*/
dojo.validate.isRealNumber = function(value, flags) {
	var re = new RegExp("^" + dojo.regexp.realNumber(flags) + "$");
	return re.test(value);
}

/**
  Validates whether a string denotes a monetary value. 

  @param value  A string.
  @param flags  An object.
    flags.signed  The leading plus-or-minus sign.  Can be true, false, or [true, false].
      Default is [true, false], (i.e. sign is optional).
    flags.symbol  A currency symbol such as Yen "ï¿½", Pound "ï¿½", or the Euro sign "ï¿½".  
      Default is "$".  For more than one symbol use an array, e.g. ["$", ""], makes $ optional.
    flags.placement  The symbol can come "before" the number or "after".  Default is "before".
    flags.separator  The character used as the thousands separator. The default is ",".
    flags.cents  The two decimal places for cents.  Can be true, false, or [true, false].
      Default is [true, false], (i.e. cents are optional).
    flags.decimal  The character used for the decimal point.  Default is ".".
  @return  true or false.
*/
dojo.validate.isCurrency = function(value, flags) {
	var re = new RegExp("^" + dojo.regexp.currency(flags) + "$");
	return re.test(value);
}

/**
  Validates whether a string denoting an integer, 
  real number, or monetary value is between a max and min. 

  @param value  A string.
  @param flags  An object.
    flags.max  A number, which the value must be less than or equal to for the validation to be true.
    flags.min  A number, which the value must be greater than or equal to for the validation to be true.
    flags.decimal  The character used for the decimal point.  Default is ".".
  @return  true or false.
*/
dojo.validate.isInRange = function(value, flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	var max = (typeof flags.max == "number") ? flags.max : Infinity;
	var min = (typeof flags.min == "number") ? flags.min : -Infinity;
	var dec = (typeof flags.decimal == "string") ? flags.decimal : ".";
	
	// splice out anything not part of a number
	var pattern = "[^" + dec + "\\deE+-]";
	value = value.replace(RegExp(pattern, "g"), "");

	// trim ends of things like e, E, or the decimal character
	value = value.replace(/^([+-]?)(\D*)/, "$1");
	value = value.replace(/(\D*)$/, "");

	// replace decimal with ".". The minus sign '-' could be the decimal!
	pattern = "(\\d)[" + dec + "](\\d)";
	value = value.replace(RegExp(pattern, "g"), "$1.$2");

	value = Number(value);
	if ( value < min || value > max ) { return false; }

	return true;
}


/**
  Validates any sort of number based format.
  Use it for phone numbers, social security numbers, zip-codes, etc.
  The value can be validated against one format or one of multiple formats.

  Format
    #        Stands for a digit, 0-9.
    ?        Stands for an optional digit, 0-9 or nothing.
    All other characters must appear literally in the expression.

  Example   
    "(###) ###-####"       ->   (510) 542-9742
    "(###) ###-#### x#???" ->   (510) 542-9742 x153
    "###-##-####"          ->   506-82-1089       i.e. social security number
    "#####-####"           ->   98225-1649        i.e. zip code

  @param value  A string.
  @param flags  An object.
    flags.format  A string or an Array of strings for multiple formats.
  @return  true or false
*/
dojo.validate.isNumberFormat = function(value, flags) {
	var re = new RegExp("^" + dojo.regexp.numberFormat(flags) + "$", "i");
	return re.test(value);
}

/**
	Procedural API Description

		The main aim is to make input validation expressible in a simple format.
		You define profiles which declare the required and optional fields and any constraints they might have.
		The results are provided as an object that makes it easy to handle missing and invalid input.

	Usage

		var results = dojo.validate.check(form, profile);

	Profile Object

		var profile = {
			// filters change the field value and are applied before validation.
			trim: ["tx1", "tx2"],
			uppercase: ["tx9"],
			lowercase: ["tx5", "tx6", "tx7"],
			ucfirst: ["tx10"],
			digit: ["tx11"],

			// required input fields that are blank will be reported missing.
			// required radio button groups and drop-down lists with no selection will be reported missing.
			// checkbox groups and selectboxes can be required to have more than one value selected.
			// List required fields by name and use this notation to require more than one value: {checkboxgroup: 2}, {selectboxname: 3}.
			required: ["tx7", "tx8", "pw1", "ta1", "rb1", "rb2", "cb3", "s1", {"doubledip":2}, {"tripledip":3}],

			// dependant/conditional fields are required if the target field is present and not blank.
			// At present only textbox, password, and textarea fields are supported.
			dependancies:	{
				cc_exp: "cc_no",	
				cc_type: "cc_no",	
			},

			// Fields can be validated using any boolean valued function.  
			// Use arrays to specify parameters in addition to the field value.
			constraints: {
				field_name1: myValidationFunction,
				field_name2: dojo.validate.isInteger,
				field_name3: [myValidationFunction, additional parameters],
				field_name4: [dojo.validate.isValidDate, "YYYY.MM.DD"],
				field_name5: [dojo.validate.isEmailAddress, false, true],
			},

			// Confirm is a sort of conditional validation.
			// It associates each field in its property list with another field whose value should be equal.
			// If the values are not equal, the field in the property list is reported as Invalid. Unless the target field is blank.
			confirm: {
				email_confirm: "email",	
				pw2: "pw1",	
			}
		};

	Results Object

		isSuccessful(): Returns true if there were no invalid or missing fields, else it returns false.
		hasMissing():  Returns true if the results contain any missing fields.
		getMissing():  Returns a list of required fields that have values missing.
		isMissing(field):  Returns true if the field is required and the value is missing.
		hasInvalid():  Returns true if the results contain fields with invalid data.
		getInvalid():  Returns a list of fields that have invalid values.
		isInvalid(field):  Returns true if the field has an invalid value.

*/

__CPAN_FILE__ src/validate/us.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.validate.us");
dojo.require("dojo.validate.common");

/**
  Validates U.S. currency.

  @param value  A string.
  @param flags  An object.
    flags in validate.isCurrency can be applied.
  @return  true or false.
*/
dojo.validate.us.isCurrency = function(value, flags) {
	return dojo.validate.isCurrency(value, flags);
}


/**
  Validates US state and territory abbreviations.

	@param value  A two character string.
  @param flags  An object.
    flags.allowTerritories  Allow Guam, Puerto Rico, etc.  Default is true.
    flags.allowMilitary  Allow military 'states', e.g. Armed Forces Europe (AE).  Default is true.
  @return  true or false
*/
dojo.validate.us.isState = function(value, flags) {
	var re = new RegExp("^" + dojo.regexp.us.state(flags) + "$", "i");
	return re.test(value);
}

/**
  Validates 10 US digit phone number for several common formats:

  @param value The telephone number string
  @return true or false
*/
dojo.validate.us.isPhoneNumber = function(value) {
	var flags = {
		format: [
			"###-###-####",
			"(###) ###-####",
			"(###) ### ####",
			"###.###.####",
			"###/###-####",
			"### ### ####",
			"###-###-#### x#???",
			"(###) ###-#### x#???",
			"(###) ### #### x#???",
			"###.###.#### x#???",
			"###/###-#### x#???",
			"### ### #### x#???",
			"##########"
		]
	};

	return dojo.validate.isNumberFormat(value, flags);
}

// Validates social security number
dojo.validate.us.isSocialSecurityNumber = function(value) {
	var flags = {
		format: [
			"###-##-####",
			"### ## ####",
			"#########"
		]
	};

	return dojo.validate.isNumberFormat(value, flags);
}

// Validates U.S. zip-code
dojo.validate.us.isZipCode = function(value) {
	var flags = {
		format: [
			"#####-####",
			"##### ####",
			"#########",
			"#####"
		]
	};

	return dojo.validate.isNumberFormat(value, flags);
}

__CPAN_FILE__ src/validate/de.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.validate.de");
dojo.require("dojo.validate.common");

/**
  Validates German currency.

  @param value  A string.
  @return  true or false.
*/
dojo.validate.isGermanCurrency = function(value) {
	var flags = {
		symbol: "ï¿½",
		placement: "after",
		decimal: ",",
		separator: "."
	};
	return dojo.validate.isCurrency(value, flags);
}



__CPAN_FILE__ src/validate/jp.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.validate.jp");
dojo.require("dojo.validate.common");

/**
  Validates Japanese currency.

  @param value  A string.
  @return  true or false.
*/
dojo.validate.isJapaneseCurrency = function(value) {
	var flags = {
		symbol: "ï¿½",
		cents: false
	};
	return dojo.validate.isCurrency(value, flags);
}



__CPAN_FILE__ src/validate/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.validate");
dojo.kwCompoundRequire({
	common:		["dojo.validate.check", 
						"dojo.validate.datetime", 
						"dojo.validate.de", 
						"dojo.validate.jp", 
						"dojo.validate.us", 
						"dojo.validate.web" 
	],
});
dojo.provide("dojo.validate.*");

__CPAN_FILE__ src/validate/datetime.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.validate.datetime");
dojo.require("dojo.validate.common");

/**
  Validates a time value in any International format.
  The value can be validated against one format or one of multiple formats.

  Format
  h        12 hour, no zero padding.
  hh       12 hour, has leading zero.
  H        24 hour, no zero padding.
  HH       24 hour, has leading zero.
  m        minutes, no zero padding.
  mm       minutes, has leading zero.
  s        seconds, no zero padding.
  ss       seconds, has leading zero.
  All other characters must appear literally in the expression.

  Example
    "h:m:s t"  ->   2:5:33 PM
    "HH:mm:ss" ->  14:05:33

  @param value  A string.
  @param flags  An object.
    flags.format  A string or an array of strings.  Default is "h:mm:ss t".
    flags.amSymbol  The symbol used for AM.  Default is "AM".
    flags.pmSymbol  The symbol used for PM.  Default is "PM".
  @return  true or false
*/
dojo.validate.isValidTime = function(value, flags) {
	var re = new RegExp("^" + dojo.regexp.time(flags) + "$", "i");
	return re.test(value);
}

/**
  Validates 12-hour time format.
  Zero-padding is not allowed for hours, required for minutes and seconds.
  Seconds are optional.

  @param value  A string.
  @return  true or false
*/
dojo.validate.is12HourTime = function(value) {
	return dojo.validate.isValidTime(value, {format: ["h:mm:ss t", "h:mm t"]});
}

/**
  Validates 24-hour military time format.
  Zero-padding is required for hours, minutes, and seconds.
  Seconds are optional.

  @param value  A string.
  @return  true or false
*/
dojo.validate.is24HourTime = function(value) {
	return dojo.validate.isValidTime(value, {format: ["HH:mm:ss", "HH:mm"]} );
}

/**
  Returns true if the date conforms to the format given and is a valid date. Otherwise returns false.

  @param dateValue  A string for the date.
  @param format  A string, default is  "MM/DD/YYYY".
  @return  true or false

  Accepts any type of format, including ISO8601.
  All characters in the format string are treated literally except the following tokens:

  YYYY - matches a 4 digit year
  M - matches a non zero-padded month
  MM - matches a zero-padded month
  D -  matches a non zero-padded date
  DD -  matches a zero-padded date
  DDD -  matches an ordinal date, 001-365, and 366 on leapyear
  ww - matches week of year, 01-53
  d - matches day of week, 1-7

  Examples: These are all today's date.

  Date          Format
  2005-W42-3    YYYY-Www-d
  2005-292      YYYY-DDD
  20051019      YYYYMMDD
  10/19/2005    M/D/YYYY
  19.10.2005    D.M.YYYY
*/
dojo.validate.isValidDate = function(dateValue, format) {
	// Default is the American format
	if (typeof format == "object" && typeof format.format == "string"){ format = format.format; }
	if (typeof format != "string") { format = "MM/DD/YYYY"; }

	// Create a literal regular expression based on format
	var reLiteral = format.replace(/([$^.*+?=!:|\/\\\(\)\[\]\{\}])/g, "\\$1");

	// Convert all the tokens to RE elements
	reLiteral = reLiteral.replace( "YYYY", "([0-9]{4})" );
	reLiteral = reLiteral.replace( "MM", "(0[1-9]|10|11|12)" );
	reLiteral = reLiteral.replace( "M", "([1-9]|10|11|12)" );
	reLiteral = reLiteral.replace( "DDD", "(00[1-9]|0[1-9][0-9]|[12][0-9][0-9]|3[0-5][0-9]|36[0-6])" );
	reLiteral = reLiteral.replace( "DD", "(0[1-9]|[12][0-9]|30|31)" );
	reLiteral = reLiteral.replace( "D", "([1-9]|[12][0-9]|30|31)" );
	reLiteral = reLiteral.replace( "ww", "(0[1-9]|[1-4][0-9]|5[0-3])" );
	reLiteral = reLiteral.replace( "d", "([1-7])" );

	// Anchor pattern to begining and end of string
	reLiteral = "^" + reLiteral + "$";

	// Dynamic RE that parses the original format given
	var re = new RegExp(reLiteral);
	
	// Test if date is in a valid format
	if (!re.test(dateValue))  return false;

	// Parse date to get elements and check if date is valid
	// Assume valid values for date elements not given.
	var year = 0, month = 1, date = 1, dayofyear = 1, week = 1, day = 1;

	// Capture tokens
	var tokens = format.match( /(YYYY|MM|M|DDD|DD|D|ww|d)/g );

	// Capture date values
	var values = re.exec(dateValue);

	// Match up tokens with date values
	for (var i = 0; i < tokens.length; i++) {
		switch (tokens[i]) {
		case "YYYY":
			year = Number(values[i+1]); break;
		case "M":
		case "MM":
			month = Number(values[i+1]); break;
		case "D":
		case "DD":
			date = Number(values[i+1]); break;
		case "DDD":
			dayofyear = Number(values[i+1]); break;
		case "ww":
			week = Number(values[i+1]); break;
		case "d":
			day = Number(values[i+1]); break;
		}
	}

	// Leap years are divisible by 4, but not by 100, unless by 400
	var leapyear = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));

	// 31st of a month with 30 days
	if (date == 31 && (month == 4 || month == 6 || month == 9 || month == 11)) return false; 

	// February 30th or 31st
	if (date >= 30 && month == 2) return false; 

	// February 29th outside a leap year
	if (date == 29 && month == 2 && !leapyear) return false; 
	if (dayofyear == 366 && !leapyear)  return false;

	return true;
}

__CPAN_FILE__ src/validate/web.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.validate.web");
dojo.require("dojo.validate.common");

/**
  Validates an IP address.
  Supports 5 formats for IPv4: dotted decimal, dotted hex, dotted octal, decimal and hexadecimal.
  Supports 2 formats for Ipv6.

  @param value  A string.
  @param flags  An object.  All flags are boolean with default = true.
    flags.allowDottedDecimal  Example, 207.142.131.235.  No zero padding.
    flags.allowDottedHex  Example, 0x18.0x11.0x9b.0x28.  Case insensitive.  Zero padding allowed.
    flags.allowDottedOctal  Example, 0030.0021.0233.0050.  Zero padding allowed.
    flags.allowDecimal  Example, 3482223595.  A decimal number between 0-4294967295.
    flags.allowHex  Example, 0xCF8E83EB.  Hexadecimal number between 0x0-0xFFFFFFFF.
      Case insensitive.  Zero padding allowed.
    flags.allowIPv6   IPv6 address written as eight groups of four hexadecimal digits.
    flags.allowHybrid   IPv6 address written as six groups of four hexadecimal digits
      followed by the usual 4 dotted decimal digit notation of IPv4. x:x:x:x:x:x:d.d.d.d
  @return  true or false
*/
dojo.validate.isIpAddress = function(value, flags) {
	var re = new RegExp("^" + dojo.regexp.ipAddress(flags) + "$", "i");
	return re.test(value);
}

/**
  Checks if a string could be a valid URL.

  @param value  A string.
  @param flags  An object.
    flags.scheme  Can be true, false, or [true, false]. 
      This means: required, not allowed, or either.
    flags in regexp.host can be applied.
    flags in regexp.ipAddress can be applied.
    flags in regexp.tld can be applied.
  @return  true or false
*/
dojo.validate.isUrl = function(value, flags) {
	var re = new RegExp("^" + dojo.regexp.url(flags) + "$", "i");
	return re.test(value);
}

/**
  Checks if a string could be a valid email address.

  @param value  A string.
  @param flags  An object.
    flags.allowCruft  Allow address like <mailto:foo@yahoo.com>.  Default is false.
    flags in regexp.host can be applied.
    flags in regexp.ipAddress can be applied.
    flags in regexp.tld can be applied.
  @return  true or false.
*/
dojo.validate.isEmailAddress = function(value, flags) {
	var re = new RegExp("^" + dojo.regexp.emailAddress(flags) + "$", "i");
	return re.test(value);
}

/**
  Checks if a string could be a valid email address list.

  @param value  A string.
  @param flags  An object.
    flags.listSeparator  The character used to separate email addresses.  Default is ";", ",", "\n" or " ".
    flags in regexp.emailAddress can be applied.
    flags in regexp.host can be applied.
    flags in regexp.ipAddress can be applied.
    flags in regexp.tld can be applied.
  @return  true or false.
*/
dojo.validate.isEmailAddressList = function(value, flags) {
	var re = new RegExp("^" + dojo.regexp.emailAddressList(flags) + "$", "i");
	return re.test(value);
}

/**
  Check if value is an email address list. If an empty list
  is returned, the value didn't pass the test or it was empty.

  @param value	A string
  @param flags	An object (same as isEmailAddressList)
  @return array of emails
*/
dojo.validate.getEmailAddressList = function(value, flags) {
	if(!flags) { flags = {}; }
	if(!flags.listSeparator) { flags.listSeparator = "\\s;,"; }

	if ( dojo.validate.isEmailAddressList(value, flags) ) {
		return value.split(new RegExp("\\s*[" + flags.listSeparator + "]\\s*"));
	}
	return [];
}



__CPAN_FILE__ src/validate/check.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.validate.check");
dojo.require("dojo.validate.common");
dojo.require("dojo.lang.common");

/**
  Validates user input of an HTML form based on input profile.

	@param form  The form object to be validated.
	@param profile  The input profile that specifies how the form fields are to be validated.
	@return results  An object that contains several methods summarizing the results of the validation.
*/
dojo.validate.check = function(form, profile) {
	// Essentially private properties of results object
	var missing = [];
	var invalid = [];

	// results object summarizes the validation
	var results = {
		isSuccessful: function() {return ( !this.hasInvalid() && !this.hasMissing() );},
		hasMissing: function() {return ( missing.length > 0 );},
		getMissing: function() {return missing;},
		isMissing: function(elemname) {
			for (var i = 0; i < missing.length; i++) {
				if ( elemname == missing[i] ) { return true; }
			}
			return false;
		},
		hasInvalid: function() {return ( invalid.length > 0 );},
		getInvalid: function() {return invalid;},
		isInvalid: function(elemname) {
			for (var i = 0; i < invalid.length; i++) {
				if ( elemname == invalid[i] ) { return true; }
			}
			return false;
		}
	};

	// Filters are applied before fields are validated.
	// Trim removes white space at the front and end of the fields.
	if ( profile.trim instanceof Array ) {
		for (var i = 0; i < profile.trim.length; i++) {
			var elem = form[profile.trim[i]];
			if ( elem.type != "text" && elem.type != "textarea" && elem.type != "password" ) { continue; }
			elem.value = elem.value.replace(/(^\s*|\s*$)/g, "");
		}
	}
	// Convert to uppercase
	if ( profile.uppercase instanceof Array ) {
		for (var i = 0; i < profile.uppercase.length; i++) {
			var elem = form[profile.uppercase[i]];
			if ( elem.type != "text" && elem.type != "textarea" && elem.type != "password" ) { continue; }
			elem.value = elem.value.toUpperCase();
		}
	}
	// Convert to lowercase
	if ( profile.lowercase instanceof Array ) {
		for (var i = 0; i < profile.lowercase.length; i++) {
			var elem = form[profile.lowercase[i]];
			if ( elem.type != "text" && elem.type != "textarea" && elem.type != "password" ) { continue; }
			elem.value = elem.value.toLowerCase();
		}
	}
	// Uppercase first letter
	if ( profile.ucfirst instanceof Array ) {
		for (var i = 0; i < profile.ucfirst.length; i++) {
			var elem = form[profile.ucfirst[i]];
			if ( elem.type != "text" && elem.type != "textarea" && elem.type != "password" ) { continue; }
			elem.value = elem.value.replace(/\b\w+\b/g, function(word) { return word.substring(0,1).toUpperCase() + word.substring(1).toLowerCase(); });
		}
	}
	// Remove non digits characters from the input.
	if ( profile.digit instanceof Array ) {
		for (var i = 0; i < profile.digit.length; i++) {
			var elem = form[profile.digit[i]];
			if ( elem.type != "text" && elem.type != "textarea" && elem.type != "password" ) { continue; }
			elem.value = elem.value.replace(/\D/g, "");
		}
	}

	// See if required input fields have values missing.
	if ( profile.required instanceof Array ) {
		for (var i = 0; i < profile.required.length; i++) { 
			if(!dojo.lang.isString(profile.required[i])){ continue; }
			var elem = form[profile.required[i]];
			// Are textbox, textarea, or password fields blank.
			if ( (elem.type == "text" || elem.type == "textarea" || elem.type == "password") && /^\s*$/.test(elem.value) ) {	
				missing[missing.length] = elem.name;
			}
			// Does drop-down box have option selected.
			else if ( (elem.type == "select-one" || elem.type == "select-multiple") && elem.selectedIndex == -1 ) {
				missing[missing.length] = elem.name;
			}
			// Does radio button group (or check box group) have option checked.
			else if ( elem instanceof Array )  {
				var checked = false;
				for (var j = 0; j < elem.length; j++) {
					if (elem[j].checked) { checked = true; }
				}
				if ( !checked ) {	
					missing[missing.length] = elem[0].name;
				}
			}
		}
	}

	// See if checkbox groups and select boxes have x number of required values.
	if ( profile.required instanceof Array ) {
		for (var i = 0; i < profile.required.length; i++) { 
			if(!dojo.lang.isObject(profile.required[i])){ continue; }
			var elem, numRequired;
			for (var name in profile.required[i]) { 
				elem = form[name]; 
				numRequired = profile.required[i][name];
			}
			// case 1: elem is a check box group
			if ( elem instanceof Array )  {
				var checked = 0;
				for (var j = 0; j < elem.length; j++) {
					if (elem[j].checked) { checked++; }
				}
				if ( checked < numRequired ) {	
					missing[missing.length] = elem[0].name;
				}
			}
			// case 2: elem is a select box
			else if ( elem.type == "select-multiple" ) {
				var selected = 0;
				for (var j = 0; j < elem.options.length; j++) {
					if (elem.options[j].selected) { selected++; }
				}
				if ( selected < numRequired ) {	
					missing[missing.length] = elem.name;
				}
			}
		}
	}

	// Dependant fields are required when the target field is present (not blank).
	// Todo: Support dependant and target fields that are radio button groups, or select drop-down lists.
	// Todo: Make the dependancy based on a specific value of the target field.
	// Todo: allow dependant fields to have several required values, like {checkboxgroup: 3}.
	if(dojo.lang.isObject(profile.dependancies)){
		// properties of dependancies object are the names of dependant fields to be checked
		for (name in profile.dependancies) {
			var elem = form[name];	// the dependant element
			if ( elem.type != "text" && elem.type != "textarea" && elem.type != "password" ) { continue; } // limited support
			if ( /\S+/.test(elem.value) ) { continue; }	// has a value already
			if ( results.isMissing(elem.name) ) { continue; }	// already listed as missing
			var target = form[profile.dependancies[name]];
			if ( target.type != "text" && target.type != "textarea" && target.type != "password" ) { continue; }	// limited support
			if ( /^\s*$/.test(target.value) ) { continue; }	// skip if blank
			missing[missing.length] = elem.name;	// ok the dependant field is missing
		}
	}

	// Find invalid input fields.
	if(dojo.lang.isObject(profile.constraints)){
		// constraint properties are the names of fields to be validated
		for(name in profile.constraints){
			var elem = form[name];
			if(	(elem.type != "text")&&
				(elem.type != "textarea")&&
				(elem.type != "password")){
				continue;
			}
			// skip if blank - its optional unless required, in which case it
			// is already listed as missing.
			if( /^\s*$/.test(elem.value)){ continue; }

			var isValid = true;
			// case 1: constraint value is validation function
			if(dojo.lang.isFunction(profile.constraints[name])){
				isValid = profile.constraints[name](elem.value);
			}else if(dojo.lang.isArray(profile.constraints[name])){
				// case 2: constraint value is array, first elem is function,
				// tail is parameters
				var isValidSomething = profile.constraints[name][0];
				var params = profile.constraints[name].slice(1);
				params.unshift(elem.value);
				if(typeof isValidSomething != "undefined"){
					isValid = isValidSomething.apply(null, params);
				}else{
					isValid = false; 
				}
			}

			if(!isValid){	
				invalid[invalid.length] = elem.name;
			}
		}
	}

	// Find unequal confirm fields and report them as Invalid.
	if(dojo.lang.isObject(profile.confirm)){
		for(name in profile.confirm){
			var elem = form[name];	// the confirm element
			var target = form[profile.confirm[name]];
			if ( (elem.type != "text" && elem.type != "textarea" && elem.type != "password") 
				||(target.type != elem.type)
				||(target.value == elem.value)	// it's valid
				||(results.isInvalid(elem.name))// already listed as invalid
				||(/^\s*$/.test(target.value))	)	// skip if blank - only confirm if target has a value
			{
				continue; 
			}	
			invalid[invalid.length] = elem.name;
		}
	}

	return results;
}

__CPAN_DIR__ src/animation
__CPAN_FILE__ src/animation/Timer.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.animation.Timer");
dojo.require("dojo.lang.func");

dojo.animation.Timer = function(intvl){
	var timer = null;
	this.isRunning = false;
	this.interval = intvl;

	this.onTick = function(){};
	this.onStart = null;
	this.onStop = null;

	this.setInterval = function(ms){
		if (this.isRunning) window.clearInterval(timer);
		this.interval = ms;
		if (this.isRunning) timer = window.setInterval(dojo.lang.hitch(this, "onTick"), this.interval);
	};

	this.start = function(){
		if (typeof this.onStart == "function") this.onStart();
		this.isRunning = true;
		timer = window.setInterval(this.onTick, this.interval);
	};
	this.stop = function(){
		if (typeof this.onStop == "function") this.onStop();
		this.isRunning = false;
		window.clearInterval(timer);
	};
};

__CPAN_FILE__ src/animation/Animation.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.animation.Animation");
dojo.require("dojo.animation.AnimationEvent");

dojo.require("dojo.lang.func");
dojo.require("dojo.math");
dojo.require("dojo.math.curves");

/*
Animation package based off of Dan Pupius' work on Animations:
http://pupius.co.uk/js/Toolkit.Drawing.js
*/

dojo.animation.Animation = function(/*dojo.math.curves.Line*/ curve, /*int*/ duration, /*Decimal?*/ accel, /*int?*/ repeatCount, /*int?*/ rate) {
	// public properties
	if(dojo.lang.isArray(curve)) {
		// curve: Array
		// id: i
		curve = new dojo.math.curves.Line(curve[0], curve[1]);
	}
	this.curve = curve;
	this.duration = duration;
	this.repeatCount = repeatCount || 0;
	this.rate = rate || 25;
	if(accel) {
		// accel: Decimal
		// id: j
		if(dojo.lang.isFunction(accel.getValue)) {
			// accel: dojo.math.curves.CatmullRom
			// id: k
			this.accel = accel;
		} else {
			var i = 0.35*accel+0.5;	// 0.15 <= i <= 0.85
			this.accel = new dojo.math.curves.CatmullRom([[0], [i], [1]], 0.45);
		}
	}
}

dojo.lang.extend(dojo.animation.Animation, {
	// public properties
	curve: null,
	duration: 0,
	repeatCount: 0,
	accel: null,

	// events
	onBegin: null,
	onAnimate: null,
	onEnd: null,
	onPlay: null,
	onPause: null,
	onStop: null,
	handler: null,

	// "private" properties
	_animSequence: null,
	_startTime: null,
	_endTime: null,
	_lastFrame: null,
	_timer: null,
	_percent: 0,
	_active: false,
	_paused: false,
	_startRepeatCount: 0,

	// public methods
	play: function(gotoStart) {
		if( gotoStart ) {
			clearTimeout(this._timer);
			this._active = false;
			this._paused = false;
			this._percent = 0;
		} else if( this._active && !this._paused ) {
			return;
		}

		this._startTime = new Date().valueOf();
		if( this._paused ) {
			this._startTime -= (this.duration * this._percent / 100);
		}
		this._endTime = this._startTime + this.duration;
		this._lastFrame = this._startTime;

		var e = new dojo.animation.AnimationEvent(this, null, this.curve.getValue(this._percent),
			this._startTime, this._startTime, this._endTime, this.duration, this._percent, 0);

		this._active = true;
		this._paused = false;

		if( this._percent == 0 ) {
			if(!this._startRepeatCount) {
				this._startRepeatCount = this.repeatCount;
			}
			e.type = "begin";
			if(typeof this.handler == "function") { this.handler(e); }
			if(typeof this.onBegin == "function") { this.onBegin(e); }
		}

		e.type = "play";
		if(typeof this.handler == "function") { this.handler(e); }
		if(typeof this.onPlay == "function") { this.onPlay(e); }

		if(this._animSequence) { this._animSequence._setCurrent(this); }

		this._cycle();
	},

	pause: function() {
		clearTimeout(this._timer);
		if( !this._active ) { return; }
		this._paused = true;
		var e = new dojo.animation.AnimationEvent(this, "pause", this.curve.getValue(this._percent),
			this._startTime, new Date().valueOf(), this._endTime, this.duration, this._percent, 0);
		if(typeof this.handler == "function") { this.handler(e); }
		if(typeof this.onPause == "function") { this.onPause(e); }
	},

	playPause: function() {
		if( !this._active || this._paused ) {
			this.play();
		} else {
			this.pause();
		}
	},

	gotoPercent: function(pct, andPlay) {
		clearTimeout(this._timer);
		this._active = true;
		this._paused = true;
		this._percent = pct;
		if( andPlay ) { this.play(); }
	},

	stop: function(gotoEnd) {
		clearTimeout(this._timer);
		var step = this._percent / 100;
		if( gotoEnd ) {
			step = 1;
		}
		var e = new dojo.animation.AnimationEvent(this, "stop", this.curve.getValue(step),
			this._startTime, new Date().valueOf(), this._endTime, this.duration, this._percent);
		if(typeof this.handler == "function") { this.handler(e); }
		if(typeof this.onStop == "function") { this.onStop(e); }
		this._active = false;
		this._paused = false;
	},

	status: function() {
		if( this._active ) {
			return this._paused ? "paused" : "playing";
		} else {
			return "stopped";
		}
	},

	// "private" methods
	_cycle: function() {
		clearTimeout(this._timer);
		if( this._active ) {
			var curr = new Date().valueOf();
			var step = (curr - this._startTime) / (this._endTime - this._startTime);
			var fps = 1000 / (curr - this._lastFrame);
			this._lastFrame = curr;

			if( step >= 1 ) {
				step = 1;
				this._percent = 100;
			} else {
				this._percent = step * 100;
			}
			
			// Perform accelleration
			if(this.accel && this.accel.getValue) {
				step = this.accel.getValue(step);
			}

			var e = new dojo.animation.AnimationEvent(this, "animate", this.curve.getValue(step),
				this._startTime, curr, this._endTime, this.duration, this._percent, Math.round(fps));

			if(typeof this.handler == "function") { this.handler(e); }
			if(typeof this.onAnimate == "function") { this.onAnimate(e); }

			if( step < 1 ) {
				this._timer = setTimeout(dojo.lang.hitch(this, "_cycle"), this.rate);
			} else {
				e.type = "end";
				this._active = false;
				if(typeof this.handler == "function") { this.handler(e); }
				if(typeof this.onEnd == "function") { this.onEnd(e); }

				if( this.repeatCount > 0 ) {
					this.repeatCount--;
					this.play(true);
				} else if( this.repeatCount == -1 ) {
					this.play(true);
				} else {
					if(this._startRepeatCount) {
						this.repeatCount = this._startRepeatCount;
						this._startRepeatCount = 0;
					}
					if( this._animSequence ) {
						this._animSequence._playNext();
					}
				}
			}
		}
	}
});

__CPAN_FILE__ src/animation/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: [
		"dojo.animation.AnimationEvent",
		"dojo.animation.Animation",
		"dojo.animation.AnimationSequence"
	]
});
dojo.provide("dojo.animation.*");

__CPAN_FILE__ src/animation/AnimationSequence.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.animation.AnimationSequence");
dojo.require("dojo.animation.AnimationEvent");
dojo.require("dojo.animation.Animation");

dojo.animation.AnimationSequence = function(repeatCount){
	this._anims = [];
	this.repeatCount = repeatCount || 0;
}

dojo.lang.extend(dojo.animation.AnimationSequence, {
	repeateCount: 0,

	_anims: [],
	_currAnim: -1,

	onBegin: null,
	onEnd: null,
	onNext: null,
	handler: null,

	add: function() {
		for(var i = 0; i < arguments.length; i++) {
			this._anims.push(arguments[i]);
			arguments[i]._animSequence = this;
		}
	},

	remove: function(anim) {
		for(var i = 0; i < this._anims.length; i++) {
			if( this._anims[i] == anim ) {
				this._anims[i]._animSequence = null;
				this._anims.splice(i, 1);
				break;
			}
		}
	},

	removeAll: function() {
		for(var i = 0; i < this._anims.length; i++) {
			this._anims[i]._animSequence = null;
		}
		this._anims = [];
		this._currAnim = -1;
	},

	clear: function() {
		this.removeAll();
	},

	play: function(gotoStart) {
		if( this._anims.length == 0 ) { return; }
		if( gotoStart || !this._anims[this._currAnim] ) {
			this._currAnim = 0;
		}
		if( this._anims[this._currAnim] ) {
			if( this._currAnim == 0 ) {
				var e = {type: "begin", animation: this._anims[this._currAnim]};
				if(typeof this.handler == "function") { this.handler(e); }
				if(typeof this.onBegin == "function") { this.onBegin(e); }
			}
			this._anims[this._currAnim].play(gotoStart);
		}
	},

	pause: function() {
		if( this._anims[this._currAnim] ) {
			this._anims[this._currAnim].pause();
		}
	},

	playPause: function() {
		if( this._anims.length == 0 ) { return; }
		if( this._currAnim == -1 ) { this._currAnim = 0; }
		if( this._anims[this._currAnim] ) {
			this._anims[this._currAnim].playPause();
		}
	},

	stop: function() {
		if( this._anims[this._currAnim] ) {
			this._anims[this._currAnim].stop();
		}
	},

	status: function() {
		if( this._anims[this._currAnim] ) {
			return this._anims[this._currAnim].status();
		} else {
			return "stopped";
		}
	},

	_setCurrent: function(anim) {
		for(var i = 0; i < this._anims.length; i++) {
			if( this._anims[i] == anim ) {
				this._currAnim = i;
				break;
			}
		}
	},

	_playNext: function() {
		if( this._currAnim == -1 || this._anims.length == 0 ) { return; }
		this._currAnim++;
		if( this._anims[this._currAnim] ) {
			var e = {type: "next", animation: this._anims[this._currAnim]};
			if(typeof this.handler == "function") { this.handler(e); }
			if(typeof this.onNext == "function") { this.onNext(e); }
			this._anims[this._currAnim].play(true);
		} else {
			var e = {type: "end", animation: this._anims[this._anims.length-1]};
			if(typeof this.handler == "function") { this.handler(e); }
			if(typeof this.onEnd == "function") { this.onEnd(e); }
			if(this.repeatCount > 0) {
				this._currAnim = 0;
				this.repeatCount--;
				this._anims[this._currAnim].play(true);
			} else if(this.repeatCount == -1) {
				this._currAnim = 0;
				this._anims[this._currAnim].play(true);
			} else {
				this._currAnim = -1;
			}
		}
	}
});

__CPAN_FILE__ src/animation/AnimationEvent.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.animation.AnimationEvent");

dojo.require("dojo.lang");

dojo.animation.AnimationEvent = function(anim, type, coords, sTime, cTime, eTime, dur, pct, fps) {
	this.type = type; // "animate", "begin", "end", "play", "pause", "stop"
	this.animation = anim;

	this.coords = coords;
	this.x = coords[0];
	this.y = coords[1];
	this.z = coords[2];

	this.startTime = sTime;
	this.currentTime = cTime;
	this.endTime = eTime;

	this.duration = dur;
	this.percent = pct;
	this.fps = fps;
};
dojo.lang.extend(dojo.animation.AnimationEvent, {
	coordsAsInts: function() {
		var cints = new Array(this.coords.length);
		for(var i = 0; i < this.coords.length; i++) {
			cints[i] = Math.round(this.coords[i]);
		}
		return cints;
	}
});

__CPAN_DIR__ src/debug
__CPAN_FILE__ src/debug/arrow_show.gif
GIF89a		Ä!/=)5*6$.",%4DZgt(8H&6F8HXAP_'3TaofrDSb*;Lht€q|ˆ,8!/<p|‡#1@#.(4ÿÿÿ!ù,		" †QbYF�YB†£bŒòjrTR`"À5¨“á%°¼0—W;
__CPAN_FILE__ src/debug/spacer.gif
GIF89a		÷@@@è×gÔˆ0ÿÿÿÔˆ*ç‘2¨ ÑPæàé$ç0‘2H ØØçL‘2H ØØç$‘ëéh�î‘8ÿÿÿ‘2‘«‘ëé¸éäéÜçdÝtuê¼�î�ûxÿÿÿ�ûqÝu!pÝu, ØØpéÜ@ê$éä@ê(HpéÜpÿÿÿè,Ý›‚çtHè(‚èŒÝ‚é@2ò€–Òæ‚°é@2S`è@è�‘È ÑHé\‘Q¨‘mé´è¸‘È ØÐé„‘QHèÔ‘È ØÐé ‘QH‘méäæ„Dº«Í0 ÑPÔˆýà0ç�ûl  ØØé@‘ÈH�ê‘Qá8‘mHr8H˜�ûq�Õ†�ç¼é`�çÈê�î�ûxÿÿèäê�î‘pÿÿÿ‘m‘	¼È ØØéÄ‘	’ ØØêÝíÝí b¦Èáb¦ÔéPH˜êD�î‘pÿÿÿ‘mÂÂÞáÂÂãHr8H˜ÝhªH˜H˜êPê ÿÿÿê¼Ã\”Á pÿÿÿÂÂãD•ÕH˜c c EµHHr8HÀê†Ôê†Ôê†Ôê†Ôpê Ýltê¨HÀHÀæà£æ‚°!ù,		H° Áƒ*\Èp`@;
__CPAN_FILE__ src/debug/Firebug.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.debug.Firebug");

if (console.log) {
	dojo.hostenv.println=console.log;
} else {
	dojo.debug("dojo.debug.Firebug requires Firebug > 0.4");
}

__CPAN_FILE__ src/debug/arrow_hide.gif
GIF89a		Ä)6'7H):K!/=)5%4C$/,9DSb%0)&5EO]kJXg;K[)9J )8HX .;$3Bdp|]jwÿÿÿ!ù,		  %Žd9VU1Ž°LVƒDO1c0IDRˆÉ¢‡!;
__CPAN_FILE__ src/debug/deep.html
<html>
<head>
<title>Deep Debugger</title>
<script>

var tableRows = {};
var tableCels = {};
var tableObjs = {};
var tablesBuilt = {};
var tableShows = {};
var tableHides = {};

// IE: nodes w/id need to be redeclared or getElementById is b0rked
var frame = null;

window.onload = function(){
	// if IE loads this page too quickly (instantly) then 
	// window.debugVar might not have been set
	window.setTimeout(startMeUp, 100);
}

function startMeUp(){
	frame = document.getElementById('frame');
	buildTable('root', frame, window.debugVar);
}

function buildTable(path, parent, obj){

	var keys = [];
	var vals = [];
	for(var prop in obj){
		keys.push(prop);
		try {
			vals[prop] = obj[prop];
		} catch(E) {
			vals[prop] = 'ERROR: ' + E.message;
		}
	}
	keys.sort(keySorter);

	if (!keys.length){

		var div = document.createElement('div');
		div.appendChild(document.createTextNode('Object has no properties.'));

		parent.appendChild(div);
		return;
	}


	var t = document.createElement('table');
	t.border = "1";

	var tb = document.createElement('tbody');
	t.appendChild(tb);


	for(var i = 0; i < keys.length; i++) {
		buildTableRow(path+'-'+keys[i], tb, keys[i], vals[keys[i]]);
	}

	if (path == 'root'){
		//t.style.width = '90%';
	}
	t.style.width = '100%';

	parent.appendChild(t);

	tablesBuilt[path] = true;
}

function buildTableRow(path, tb, name, value) {

	var simpleType = typeof(value);
	var createSubrow = (simpleType == 'object');
	var complexType = simpleType;

	if (simpleType == 'object'){
		var cls = getConstructorClass(value);
		if (cls){
			if (cls == 'Object'){
			}else if (cls == 'Array'){
				complexType = 'array';
			}else{
				complexType += ' ('+cls+')';
			}
		}
	}

/*var tr1 = document.createElement('tr');
	var td1 = document.createElement('td');
	var td2 = document.createElement('td');
	var td3 = document.createElement('td');
	var td4 = document.createElement('td');*/

	var row = tb.rows.length;
	var tr1 = tb.insertRow(row++);
	var td1 = tr1.insertCell(0);
	var td2 = tr1.insertCell(1);
	var td3 = tr1.insertCell(2);
	var td4 = tr1.insertCell(3);
	
	tr1.style.verticalAlign = 'top';
	td1.style.verticalAlign = 'middle';

	td1.className = 'propPlus';
	td2.className = 'propName';
	td3.className = 'propType';
	td4.className = 'propVal';

	//tr1.appendChild(td1);
	//tr1.appendChild(td2);
	//tr1.appendChild(td3);
	//tr1.appendChild(td4);

	if (createSubrow){
		var img1 = document.createElement('img');
		img1.width = 9;
		img1.height = 9;
		img1.src = 'arrow_show.gif';
		var a1 = document.createElement('a');
		a1.appendChild(img1);
		a1.href = '#';
		a1.onclick = function(){ showTableRow(path); return false; };

		var img2 = document.createElement('img');
		img2.width = 9;
		img2.height = 9;
		img2.src = 'arrow_hide.gif';
		var a2 = document.createElement('a');
		a2.appendChild(img2);
		a2.href = '#';
		a2.onclick = function(){ hideTableRow(path); return false; };
		a2.style.display = 'none';

		tableShows[path] = a1;
		tableHides[path] = a2;

		td1.appendChild(a1);
		td1.appendChild(a2);
	}else{
		var img = document.createElement('img');
		img.width = 9;
		img.height = 9;
		img.src = 'spacer.gif';

		td1.appendChild(img);
	}

	td2.appendChild(document.createTextNode(name));
	td3.appendChild(document.createTextNode(complexType));
	td4.appendChild(buildPreBlock(value));

	//tb.appendChild(tr1);

	if (createSubrow){
		var tr2 = tb.insertRow(row++);
		var td5 = tr2.insertCell(0);
		var td6 = tr2.insertCell(1);
		
		//var tr2 = document.createElement('tr');
		//var td5 = document.createElement('td');
		//var td6 = document.createElement('td');

		td5.innerHTML = '&nbsp;';
		//td6.innerHTML = '&nbsp;';

		td6.colSpan = '3';

		tr2.appendChild(td5);
		tr2.appendChild(td6);

		tr2.style.display = 'none';

		tb.appendChild(tr2);

		tableRows[path] = tr2;
		tableCels[path] = td6;
		tableObjs[path] = value;
	}
}

function showTableRow(path){

	var tr = tableRows[path];
	var td = tableCels[path];
	var a1 = tableShows[path];
	var a2 = tableHides[path];

	if (!tablesBuilt[path]){

		//alert('building table for '+path);
		buildTable(path, td, tableObjs[path]);
	}

	tr.style.display = 'table-row';

	a1.style.display = 'none';
	a2.style.display = 'inline';
}

function hideTableRow(path){

	var tr = tableRows[path];
	var a1 = tableShows[path];
	var a2 = tableHides[path];

	tr.style.display = 'none';

	a1.style.display = 'inline';
	a2.style.display = 'none';
}

function buildPreBlock(value){

	//
	// how many lines ?
	//

	var s = ''+value;
	s = s.replace("\r\n", "\n");
	s = s.replace("\r", "");
	var lines = s.split("\n");


	if (lines.length < 2){

		if (lines[0].length < 60){

			var pre = document.createElement('pre');
			pre.appendChild(document.createTextNode(s));
			return pre;
		}
	}


	//
	// multiple lines :(
	//

	var preview = lines[0].substr(0, 60) + ' ...';

	var pre1 = document.createElement('pre');
	pre1.appendChild(document.createTextNode(preview));
	pre1.className = 'clicky';

	var pre2 = document.createElement('pre');
	pre2.appendChild(document.createTextNode(s));
	pre2.style.display = 'none';
	pre2.className = 'clicky';

	pre1.onclick = function(){
		pre1.style.display = 'none';
		pre2.style.display = 'block';
	}

	pre2.onclick = function(){
		pre1.style.display = 'block';
		pre2.style.display = 'none';
	}

	var pre = document.createElement('div');

	pre.appendChild(pre1);
	pre.appendChild(pre2);

	return pre;
}

function getConstructorClass(obj){

	if (!obj.constructor || !obj.constructor.toString) return;

	var m = obj.constructor.toString().match(/function\s*(\w+)/);

	if (m && m.length == 2) return m[1];

	return null;
}

function keySorter(a, b){

	if (a == parseInt(a) && b == parseInt(b)){

		return (parseInt(a) > parseInt(b)) ? 1 : ((parseInt(a) < parseInt(b)) ? -1 : 0);
	}

	// sort by lowercase string

	var a2 = String(a).toLowerCase();
	var b2 = String(b).toLowerCase();

	return (a2 > b2) ? 1 : ((a2 < b2) ? -1 : 0);
}

</script>
<style>

body {
	font-family: arial, helvetica, sans-serif;
}

table {
	border-width: 0px;
	border-spacing: 1px;
	border-collapse: separate;
}

td {
	border-width: 0px;
	padding: 2px;
}

img {
	border: 0;
}

pre {
	margin: 0;
	padding: 0;
	white-space: -moz-pre-wrap;  /* Mozilla, supported since 1999 */
	white-space: -pre-wrap;      /* Opera 4 - 6 */
	white-space: -o-pre-wrap;    /* Opera 7 */
	white-space: pre-wrap;       /* CSS3 - Text module (Candidate Recommendation) http://www.w3.org/TR/css3-text/#white-space */
	word-wrap: break-word;       /* IE 5.5+ */
}

pre.clicky {
	cursor: hand;
	cursor: pointer;
}

td.propPlus {
	width: 9px;
	background-color: #ddd;
}

td.propName {
	background-color: #ddd;
}

td.propType {
	background-color: #ddd;
}

td.propVal {
	background-color: #ddd;
}

</style>
</head>
<body>

<h2>Javascript Object Browser</h2>

<div id="frame"></div>

</body>
</html>
__CPAN_DIR__ src/selection
__CPAN_FILE__ src/selection/Selection.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.selection.Selection");
dojo.require("dojo.lang.array");
dojo.require("dojo.lang.func");
dojo.require("dojo.math");

dojo.selection.Selection = function(items, isCollection) {
	this.items = [];
	this.selection = [];
	this._pivotItems = [];
	this.clearItems();

	if(items) {
		if(isCollection) {
			this.setItemsCollection(items);
		} else {
			this.setItems(items);
		}
	}
}
dojo.lang.extend(dojo.selection.Selection, {
	items: null, // items to select from, order matters for growable selections

	selection: null, // items selected, aren't stored in order (see sorted())
	lastSelected: null, // last item selected

	allowImplicit: true, // if true, grow selection will start from 0th item when nothing is selected
	length: 0, // number of *selected* items

	// if true, the selection is treated as an in-order and can grow by ranges, not just by single item
	isGrowable: true,

	_pivotItems: null, // stack of pivot items
	_pivotItem: null, // item we grow selections from, top of stack

	// event handlers
	onSelect: function(item) {},
	onDeselect: function(item) {},
	onSelectChange: function(item, selected) {},

	_find: function(item, inSelection) {
		if(inSelection) {
			return dojo.lang.find(item, this.selection);
		} else {
			return dojo.lang.find(item, this.items);
		}
	},

	isSelectable: function(item) {
		// user-customizable, will filter items through this
		return true;
	},

	setItems: function(/* ... */) {
		this.clearItems();
		this.addItems.call(this, arguments);
	},

	// this is in case you have an active collection array-like object
	// (i.e. getElementsByTagName collection) that manages its own order
	// and item list
	setItemsCollection: function(collection) {
		this.items = collection;
	},

	addItems: function(/* ... */) {
		var args = dojo.lang.unnest(arguments);
		for(var i = 0; i < args.length; i++) {
			this.items.push(args[i]);
		}
	},

	addItemsAt: function(item, before /* ... */) {
		if(this.items.length == 0) { // work for empy case
			return this.addItems(dojo.lang.toArray(arguments, 2));
		}

		if(!this.isItem(item)) {
			item = this.items[item];
		}
		if(!item) { throw new Error("addItemsAt: item doesn't exist"); }
		var idx = this._find(item);
		if(idx > 0 && before) { idx--; }
		for(var i = 2; i < arguments.length; i++) {
			if(!this.isItem(arguments[i])) {
				this.items.splice(idx++, 0, arguments[i]);
			}
		}
	},

	removeItem: function(item) {
		// remove item
		var idx = this._find(item);
		if(idx > -1) {
			this.items.splice(idx, 1);
		}
		// remove from selection
		// FIXME: do we call deselect? I don't think so because this isn't how
		// you usually want to deselect an item. For example, if you deleted an
		// item, you don't really want to deselect it -- you want it gone. -DS
		idx = this._find(item, true);
		if(idx > -1) {
			this.selection.splice(idx, 1);
		}
	},

	clearItems: function() {
		this.items = [];
		this.deselectAll();
	},

	isItem: function(item) {
		return this._find(item) > -1;
	},

	isSelected: function(item) {
		return this._find(item, true) > -1;
	},

	/**
	 * allows you to filter item in or out of the selection
	 * depending on the current selection and action to be taken
	**/
	selectFilter: function(item, selection, add, grow) {
		return true;
	},

	/**
	 * update -- manages selections, most selecting should be done here
	 *  item => item which may be added/grown to/only selected/deselected
	 *  add => behaves like ctrl in windows selection world
	 *  grow => behaves like shift
	 *  noToggle => if true, don't toggle selection on item
	**/
	update: function(item, add, grow, noToggle) {
		if(!this.isItem(item)) { return false; }

		if(this.isGrowable && grow) {
			if(!this.isSelected(item)
				&& this.selectFilter(item, this.selection, false, true)) {
				this.grow(item);
				this.lastSelected = item;
			}
		} else if(add) {
			if(this.selectFilter(item, this.selection, true, false)) {
				if(noToggle) {
					if(this.select(item)) {
						this.lastSelected = item;
					}
				} else if(this.toggleSelected(item)) {
					this.lastSelected = item;
				}
			}
		} else {
			this.deselectAll();
			this.select(item);
		}

		this.length = this.selection.length;
	},

	/**
	 * Grow a selection.
	 *  toItem => which item to grow selection to
	 *  fromItem => which item to start the growth from (it won't be selected)
	 *
	 * Any items in (fromItem, lastSelected] that aren't part of
	 * (fromItem, toItem] will be deselected
	**/
	grow: function(toItem, fromItem) {
		if(!this.isGrowable) { return; }

		if(arguments.length == 1) {
			fromItem = this._pivotItem;
			if(!fromItem && this.allowImplicit) {
				fromItem = this.items[0];
			}
		}
		if(!toItem || !fromItem) { return false; }

		var fromIdx = this._find(fromItem);

		// get items to deselect (fromItem, lastSelected]
		var toDeselect = {};
		var lastIdx = -1;
		if(this.lastSelected) {
			lastIdx = this._find(this.lastSelected);
			var step = fromIdx < lastIdx ? -1 : 1;
			var range = dojo.math.range(lastIdx, fromIdx, step);
			for(var i = 0; i < range.length; i++) {
				toDeselect[range[i]] = true;
			}
		}

		// add selection (fromItem, toItem]
		var toIdx = this._find(toItem);
		var step = fromIdx < toIdx ? -1 : 1;
		var shrink = lastIdx >= 0 && step == 1 ? lastIdx < toIdx : lastIdx > toIdx;
		var range = dojo.math.range(toIdx, fromIdx, step);
		if(range.length) {
			for(var i = range.length-1; i >= 0; i--) {
				var item = this.items[range[i]];
				if(this.selectFilter(item, this.selection, false, true)) {
					if(this.select(item, true) || shrink) {
						this.lastSelected = item;
					}
					if(range[i] in toDeselect) {
						delete toDeselect[range[i]];
					}
				}
			}
		} else {
			this.lastSelected = fromItem;
		}

		// now deselect...
		for(var i in toDeselect) {
			if(this.items[i] == this.lastSelected) {
				//dojo.debug("oops!");
			}
			this.deselect(this.items[i]);
		}

		// make sure everything is all kosher after selections+deselections
		this._updatePivot();
	},

	/**
	 * Grow selection upwards one item from lastSelected
	**/
	growUp: function() {
		if(!this.isGrowable) { return; }

		var idx = this._find(this.lastSelected) - 1;
		while(idx >= 0) {
			if(this.selectFilter(this.items[idx], this.selection, false, true)) {
				this.grow(this.items[idx]);
				break;
			}
			idx--;
		}
	},

	/**
	 * Grow selection downwards one item from lastSelected
	**/
	growDown: function() {
		if(!this.isGrowable) { return; }

		var idx = this._find(this.lastSelected);
		if(idx < 0 && this.allowImplicit) {
			this.select(this.items[0]);
			idx = 0;
		}
		idx++;
		while(idx > 0 && idx < this.items.length) {
			if(this.selectFilter(this.items[idx], this.selection, false, true)) {
				this.grow(this.items[idx]);
				break;
			}
			idx++;
		}
	},

	toggleSelected: function(item, noPivot) {
		if(this.isItem(item)) {
			if(this.select(item, noPivot)) { return 1; }
			if(this.deselect(item)) { return -1; }
		}
		return 0;
	},

	select: function(item, noPivot) {
		if(this.isItem(item) && !this.isSelected(item)
			&& this.isSelectable(item)) {
			this.selection.push(item);
			this.lastSelected = item;
			this.onSelect(item);
			this.onSelectChange(item, true);
			if(!noPivot) {
				this._addPivot(item);
			}
			return true;
		}
		return false;
	},

	deselect: function(item) {
		var idx = this._find(item, true);
		if(idx > -1) {
			this.selection.splice(idx, 1);
			this.onDeselect(item);
			this.onSelectChange(item, false);
			if(item == this.lastSelected) {
				this.lastSelected = null;
			}

			this._removePivot(item);

			return true;
		}
		return false;
	},

	selectAll: function() {
		for(var i = 0; i < this.items.length; i++) {
			this.select(this.items[i]);
		}
	},

	deselectAll: function() {
		while(this.selection && this.selection.length) {
			this.deselect(this.selection[0]);
		}
	},

	selectNext: function() {
		var idx = this._find(this.lastSelected);
		while(idx > -1 && ++idx < this.items.length) {
			if(this.isSelectable(this.items[idx])) {
				this.deselectAll();
				this.select(this.items[idx]);
				return true;
			}
		}
		return false;
	},

	selectPrevious: function() {
		//debugger;
		var idx = this._find(this.lastSelected);
		while(idx-- > 0) {
			if(this.isSelectable(this.items[idx])) {
				this.deselectAll();
				this.select(this.items[idx]);
				return true;
			}
		}
		return false;
	},

	// select first selectable item
	selectFirst: function() {
		this.deselectAll();
		var idx = 0;
		while(this.items[idx] && !this.select(this.items[idx])) {
			idx++;
		}
		return this.items[idx] ? true : false;
	},

	// select last selectable item
	selectLast: function() {
		this.deselectAll();
		var idx = this.items.length-1;
		while(this.items[idx] && !this.select(this.items[idx])) {
			idx--;
		}
		return this.items[idx] ? true : false;
	},

	_addPivot: function(item, andClear) {
		this._pivotItem = item;
		if(andClear) {
			this._pivotItems = [item];
		} else {
			this._pivotItems.push(item);
		}
	},

	_removePivot: function(item) {
		var i = dojo.lang.find(item, this._pivotItems);
		if(i > -1) {
			this._pivotItems.splice(i, 1);
			this._pivotItem = this._pivotItems[this._pivotItems.length-1];
		}

		this._updatePivot();
	},

	_updatePivot: function() {
		if(this._pivotItems.length == 0) {
			if(this.lastSelected) {
				this._addPivot(this.lastSelected);
			}
		}
	},

	sorted: function() {
		return dojo.lang.toArray(this.selection).sort(
			dojo.lang.hitch(this, function(a, b) {
				var A = this._find(a), B = this._find(b);
				if(A > B) {
					return 1;
				} else if(A < B) {
					return -1;
				} else {
					return 0;
				}
			})
		);
	},

	// remove any items from the selection that are no longer in this.items
	updateSelected: function() {
		for(var i = 0; i < this.selection.length; i++) {
			if(this._find(this.selection[i]) < 0) {
				var removed = this.selection.splice(i, 1);

				this._removePivot(removed[0]);
			}
		}

		this.length = this.selection.length;
	}
});

__CPAN_DIR__ src/string
__CPAN_FILE__ src/string/common.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.string.common");

dojo.require("dojo.string");

/**
 * Trim whitespace from 'str'. If 'wh' > 0,
 * only trim from start, if 'wh' < 0, only trim
 * from end, otherwise trim both ends
 */
dojo.string.trim = function(str, wh){
	if(!str.replace){ return str; }
	if(!str.length){ return str; }
	var re = (wh > 0) ? (/^\s+/) : (wh < 0) ? (/\s+$/) : (/^\s+|\s+$/g);
	return str.replace(re, "");
}

/**
 * Trim whitespace at the beginning of 'str'
 */
dojo.string.trimStart = function(str) {
	return dojo.string.trim(str, 1);
}

/**
 * Trim whitespace at the end of 'str'
 */
dojo.string.trimEnd = function(str) {
	return dojo.string.trim(str, -1);
}

/**
 * Return 'str' repeated 'count' times, optionally
 * placing 'separator' between each rep
 */
dojo.string.repeat = function(str, count, separator) {
	var out = "";
	for(var i = 0; i < count; i++) {
		out += str;
		if(separator && i < count - 1) {
			out += separator;
		}
	}
	return out;
}

/**
 * Pad 'str' to guarantee that it is at least 'len' length
 * with the character 'c' at either the start (dir=1) or
 * end (dir=-1) of the string
 */
dojo.string.pad = function(str, len/*=2*/, c/*='0'*/, dir/*=1*/) {
	var out = String(str);
	if(!c) {
		c = '0';
	}
	if(!dir) {
		dir = 1;
	}
	while(out.length < len) {
		if(dir > 0) {
			out = c + out;
		} else {
			out += c;
		}
	}
	return out;
}

/** same as dojo.string.pad(str, len, c, 1) */
dojo.string.padLeft = function(str, len, c) {
	return dojo.string.pad(str, len, c, 1);
}

/** same as dojo.string.pad(str, len, c, -1) */
dojo.string.padRight = function(str, len, c) {
	return dojo.string.pad(str, len, c, -1);
}

__CPAN_FILE__ src/string/Builder.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.string.Builder");
dojo.require("dojo.string");

// NOTE: testing shows that direct "+=" concatenation is *much* faster on
// Spidermoneky and Rhino, while arr.push()/arr.join() style concatenation is
// significantly quicker on IE (Jscript/wsh/etc.).

dojo.string.Builder = function(str){
	this.arrConcat = (dojo.render.html.capable && dojo.render.html["ie"]);

	var a = [];
	var b = str || "";
	var length = this.length = b.length;

	if(this.arrConcat){
		if(b.length > 0){
			a.push(b);
		}
		b = "";
	}

	this.toString = this.valueOf = function(){ 
		return (this.arrConcat) ? a.join("") : b;
	};

	this.append = function(s){
		if(this.arrConcat){
			a.push(s);
		}else{
			b+=s;
		}
		length += s.length;
		this.length = length;
		return this;
	};

	this.clear = function(){
		a = [];
		b = "";
		length = this.length = 0;
		return this;
	};

	this.remove = function(f,l){
		var s = ""; 
		if(this.arrConcat){
			b = a.join(""); 
		}
		a=[];
		if(f>0){
			s = b.substring(0, (f-1));
		}
		b = s + b.substring(f + l); 
		length = this.length = b.length; 
		if(this.arrConcat){
			a.push(b);
			b="";
		}
		return this;
	};

	this.replace = function(o,n){
		if(this.arrConcat){
			b = a.join(""); 
		}
		a = []; 
		b = b.replace(o,n); 
		length = this.length = b.length; 
		if(this.arrConcat){
			a.push(b);
			b="";
		}
		return this;
	};

	this.insert = function(idx,s){
		if(this.arrConcat){
			b = a.join(""); 
		}
		a=[];
		if(idx == 0){
			b = s + b;
		}else{
			var t = b.split("");
			t.splice(idx,0,s);
			b = t.join("")
		}
		length = this.length = b.length; 
		if(this.arrConcat){
			a.push(b); 
			b="";
		}
		return this;
	};
};

__CPAN_FILE__ src/string/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: [
		"dojo.string",
		"dojo.string.common",
		"dojo.string.extras",
		"dojo.string.Builder"
	]
});
dojo.provide("dojo.string.*");

__CPAN_FILE__ src/string/extras.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.string.extras");

dojo.require("dojo.string.common");
dojo.require("dojo.lang");

/**
 * Performs parameterized substitutions on a string.  For example,
 *   dojo.string.substituteParams("File '%{0}' is not found in directory '%{1}'.","foo.html","/temp");
 * returns
 *   "File 'foo.html' is not found in directory '/temp'."
 * 
 * @param template the original string template with %{values} to be replaced
 * @param hash name/value pairs (type object) to provide substitutions.  Alternatively, substitutions may be
 *  included as arguments 1..n to this function, corresponding to template parameters 0..n-1
 * @return the completed string. Throws an exception if any parameter is unmatched
 */
//TODO: use ${} substitution syntax instead, like widgets do?
dojo.string.substituteParams = function(template /*string */, hash /* object - optional or ... */) {
	var map = (typeof hash == 'object') ? hash : dojo.lang.toArray(arguments, 1);

	return template.replace(/\%\{(\w+)\}/g, function(match, key){
		return map[key] || dojo.raise("Substitution not found: " + key);
	});
};

/**
 * Parameterized string function
 * str - formatted string with %{values} to be replaces
 * pairs - object of name: "value" value pairs
 * killExtra - remove all remaining %{values} after pairs are inserted
 */
dojo.string.paramString = function(str, pairs, killExtra) {
	dojo.deprecated("dojo.string.paramString",
		"use dojo.string.substituteParams instead", "0.4");

	for(var name in pairs) {
		var re = new RegExp("\\%\\{" + name + "\\}", "g");
		str = str.replace(re, pairs[name]);
	}

	if(killExtra) { str = str.replace(/%\{([^\}\s]+)\}/g, ""); }
	return str;
}

/** Uppercases the first letter of each word */
dojo.string.capitalize = function (str) {
	if (!dojo.lang.isString(str)) { return ""; }
	if (arguments.length == 0) { str = this; }

	var words = str.split(' ');
	for(var i=0; i<words.length; i++){
		words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1);
	}
	return words.join(" ");
}

/**
 * Return true if the entire string is whitespace characters
 */
dojo.string.isBlank = function (str) {
	if(!dojo.lang.isString(str)) { return true; }
	return (dojo.string.trim(str).length == 0);
}

dojo.string.encodeAscii = function(str) {
	if(!dojo.lang.isString(str)) { return str; }
	var ret = "";
	var value = escape(str);
	var match, re = /%u([0-9A-F]{4})/i;
	while((match = value.match(re))) {
		var num = Number("0x"+match[1]);
		var newVal = escape("&#" + num + ";");
		ret += value.substring(0, match.index) + newVal;
		value = value.substring(match.index+match[0].length);
	}
	ret += value.replace(/\+/g, "%2B");
	return ret;
}

dojo.string.escape = function(type, str) {
	var args = dojo.lang.toArray(arguments, 1);
	switch(type.toLowerCase()) {
		case "xml":
		case "html":
		case "xhtml":
			return dojo.string.escapeXml.apply(this, args);
		case "sql":
			return dojo.string.escapeSql.apply(this, args);
		case "regexp":
		case "regex":
			return dojo.string.escapeRegExp.apply(this, args);
		case "javascript":
		case "jscript":
		case "js":
			return dojo.string.escapeJavaScript.apply(this, args);
		case "ascii":
			// so it's encode, but it seems useful
			return dojo.string.encodeAscii.apply(this, args);
		default:
			return str;
	}
}

dojo.string.escapeXml = function(str, noSingleQuotes) {
	str = str.replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
		.replace(/>/gm, "&gt;").replace(/"/gm, "&quot;");
	if(!noSingleQuotes) { str = str.replace(/'/gm, "&#39;"); }
	return str;
}

dojo.string.escapeSql = function(str) {
	return str.replace(/'/gm, "''");
}

dojo.string.escapeRegExp = function(str) {
	return str.replace(/\\/gm, "\\\\").replace(/([\f\b\n\t\r[\^$|?*+(){}])/gm, "\\$1");
}

dojo.string.escapeJavaScript = function(str) {
	return str.replace(/(["'\f\b\n\t\r])/gm, "\\$1");
}

dojo.string.escapeString = function(str){ 
	return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'
		).replace(/[\f]/g, "\\f"
		).replace(/[\b]/g, "\\b"
		).replace(/[\n]/g, "\\n"
		).replace(/[\t]/g, "\\t"
		).replace(/[\r]/g, "\\r");
}

// TODO: make an HTML version
dojo.string.summary = function(str, len) {
	if(!len || str.length <= len) {
		return str;
	} else {
		return str.substring(0, len).replace(/\.+$/, "") + "...";
	}
}

/**
 * Returns true if 'str' ends with 'end'
 */
dojo.string.endsWith = function(str, end, ignoreCase) {
	if(ignoreCase) {
		str = str.toLowerCase();
		end = end.toLowerCase();
	}
	if((str.length - end.length) < 0){
		return false;
	}
	return str.lastIndexOf(end) == str.length - end.length;
}

/**
 * Returns true if 'str' ends with any of the arguments[2 -> n]
 */
dojo.string.endsWithAny = function(str /* , ... */) {
	for(var i = 1; i < arguments.length; i++) {
		if(dojo.string.endsWith(str, arguments[i])) {
			return true;
		}
	}
	return false;
}

/**
 * Returns true if 'str' starts with 'start'
 */
dojo.string.startsWith = function(str, start, ignoreCase) {
	if(ignoreCase) {
		str = str.toLowerCase();
		start = start.toLowerCase();
	}
	return str.indexOf(start) == 0;
}

/**
 * Returns true if 'str' starts with any of the arguments[2 -> n]
 */
dojo.string.startsWithAny = function(str /* , ... */) {
	for(var i = 1; i < arguments.length; i++) {
		if(dojo.string.startsWith(str, arguments[i])) {
			return true;
		}
	}
	return false;
}

/**
 * Returns true if 'str' contains any of the arguments 2 -> n
 */
dojo.string.has = function(str /* , ... */) {
	for(var i = 1; i < arguments.length; i++) {
		if(str.indexOf(arguments[i]) > -1){
			return true;
		}
	}
	return false;
}

dojo.string.normalizeNewlines = function (text,newlineChar) {
	if (newlineChar == "\n") {
		text = text.replace(/\r\n/g, "\n");
		text = text.replace(/\r/g, "\n");
	} else if (newlineChar == "\r") {
		text = text.replace(/\r\n/g, "\r");
		text = text.replace(/\n/g, "\r");
	} else {
		text = text.replace(/([^\r])\n/g, "$1\r\n");
		text = text.replace(/\r([^\n])/g, "\r\n$1");
	}
	return text;
}

dojo.string.splitEscaped = function (str,charac) {
	var components = [];
	for (var i = 0, prevcomma = 0; i < str.length; i++) {
		if (str.charAt(i) == '\\') { i++; continue; }
		if (str.charAt(i) == charac) {
			components.push(str.substring(prevcomma, i));
			prevcomma = i + 1;
		}
	}
	components.push(str.substr(prevcomma));
	return components;
}

__CPAN_DIR__ src/html
__CPAN_FILE__ src/html/layout.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.html.layout");

dojo.require("dojo.lang");
dojo.require("dojo.string");
dojo.require("dojo.style");
dojo.require("dojo.html");

/**
 * Layout a bunch of child dom nodes within a parent dom node
 * Input is an array of objects like:
 * @ container - parent node
 * @ layoutPriority - "top-bottom" or "left-right"
 * @ children an array like [ {domNode: foo, layoutAlign: "bottom" }, {domNode: bar, layoutAlign: "client"} ]
 */
dojo.html.layout = function(container, children, layoutPriority) {
	dojo.html.addClass(container, "dojoLayoutContainer");

	// Copy children array and remove elements w/out layout.
	// Also record each child's position in the input array, for sorting purposes.
	children = dojo.lang.filter(children, function(child, idx){
		child.idx = idx;
		return dojo.lang.inArray(["top","bottom","left","right","client","flood"], child.layoutAlign)
	});

	// Order the children according to layoutPriority.
	// Multiple children w/the same layoutPriority will be sorted by their position in the input array.
	if(layoutPriority && layoutPriority!="none"){
		var rank = function(child){
			switch(child.layoutAlign){
				case "flood":
					return 1;
				case "left":
				case "right":
					return (layoutPriority=="left-right") ? 2 : 3;
				case "top":
				case "bottom":
					return (layoutPriority=="left-right") ? 3 : 2;
				default:
					return 4;
			}
		};
		children.sort(function(a,b){
			return (rank(a)-rank(b)) || (a.idx - b.idx);
		});
	}

	// remaining space (blank area where nothing has been written)
	var f={
		top: dojo.style.getPixelValue(container, "padding-top", true),
		left: dojo.style.getPixelValue(container, "padding-left", true),
		height: dojo.style.getContentHeight(container),
		width: dojo.style.getContentWidth(container)
	};

	// set positions/sizes
	dojo.lang.forEach(children, function(child){
		var elm=child.domNode;
		var pos=child.layoutAlign;
		// set elem to upper left corner of unused space; may move it later
		with(elm.style){
			left = f.left+"px";
			top = f.top+"px";
			bottom = "auto";
			right = "auto";
		}
		dojo.html.addClass(elm, "dojoAlign" + dojo.string.capitalize(pos));

		// set size && adjust record of remaining space.
		// note that setting the width of a <div> may affect it's height.
		// TODO: same is true for widgets but need to implement API to support that
		if ( (pos=="top")||(pos=="bottom") ) {
			dojo.style.setOuterWidth(elm, f.width);
			var h = dojo.style.getOuterHeight(elm);
			f.height -= h;
			if(pos=="top"){
				f.top += h;
			}else{
				elm.style.top = f.top + f.height + "px";
			}
		}else if(pos=="left" || pos=="right"){
			dojo.style.setOuterHeight(elm, f.height);
			var w = dojo.style.getOuterWidth(elm);
			f.width -= w;
			if(pos=="left"){
				f.left += w;
			}else{
				elm.style.left = f.left + f.width + "px";
			}
		} else if(pos=="flood" || pos=="client"){
			dojo.style.setOuterWidth(elm, f.width);
			dojo.style.setOuterHeight(elm, f.height);
		}
		
		// TODO: for widgets I want to call resizeTo(), but for top/bottom
		// alignment I only want to set the width, and have the size determined
		// dynamically.  (The thinner you make a div, the more height it consumes.)
		if(child.onResized){
			child.onResized();
		}
	});
};

// This is essential CSS to make layout work (it isn't "styling" CSS)
// make sure that the position:absolute in dojoAlign* overrides other classes
dojo.style.insertCssText(
	".dojoLayoutContainer{ position: relative; display: block; }\n" +
	"body .dojoAlignTop, body .dojoAlignBottom, body .dojoAlignLeft, body .dojoAlignRight { position: absolute; overflow: hidden; }\n" +
	"body .dojoAlignClient { position: absolute }\n" +
	".dojoAlignClient { overflow: auto; }\n"
);


__CPAN_FILE__ src/html/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: ["dojo.html", "dojo.html.extras", "dojo.html.shadow"]
});
dojo.provide("dojo.html.*");

__CPAN_FILE__ src/html/shadow.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.html.shadow");

dojo.require("dojo.lang");
dojo.require("dojo.uri");

dojo.html.shadow = function(node) {
	this.init(node);
}

dojo.lang.extend(dojo.html.shadow, {

	shadowPng: dojo.uri.dojoUri("src/html/images/shadow"),
	shadowThickness: 8,
	shadowOffset: 15,

	init: function(node){
		this.node=node;

		// make all the pieces of the shadow, and position/size them as much
		// as possible (but a lot of the coordinates are set in sizeShadow
		this.pieces={};
		var x1 = -1 * this.shadowThickness;
		var y0 = this.shadowOffset;
		var y1 = this.shadowOffset + this.shadowThickness;
		this._makePiece("tl", "top", y0, "left", x1);
		this._makePiece("l", "top", y1, "left", x1, "scale");
		this._makePiece("tr", "top", y0, "left", 0);
		this._makePiece("r", "top", y1, "left", 0, "scale");
		this._makePiece("bl", "top", 0, "left", x1);
		this._makePiece("b", "top", 0, "left", 0, "crop");
		this._makePiece("br", "top", 0, "left", 0);
	},

	_makePiece: function(name, vertAttach, vertCoord, horzAttach, horzCoord, sizing){
		var img;
		var url = this.shadowPng + name.toUpperCase() + ".png";
		if(dojo.render.html.ie){
			img=document.createElement("div");
			img.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+url+"'"+
			(sizing?", sizingMethod='"+sizing+"'":"") + ")";
		}else{
			img=document.createElement("img");
			img.src=url;
		}
		img.style.position="absolute";
		img.style[vertAttach]=vertCoord+"px";
		img.style[horzAttach]=horzCoord+"px";
		img.style.width=this.shadowThickness+"px";
		img.style.height=this.shadowThickness+"px";
		this.pieces[name]=img;
		this.node.appendChild(img);
	},

	size: function(width, height){
		var sideHeight = height - (this.shadowOffset+this.shadowThickness+1);
		with(this.pieces){
			l.style.height = sideHeight+"px";
			r.style.height = sideHeight+"px";
			b.style.width = (width-1)+"px";
			bl.style.top = (height-1)+"px";
			b.style.top = (height-1)+"px";
			br.style.top = (height-1)+"px";
			tr.style.left = (width-1)+"px";
			r.style.left = (width-1)+"px";
			br.style.left = (width-1)+"px";
		}
	}
});


__CPAN_FILE__ src/html/extras.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.html");
dojo.provide("dojo.html.extras");
dojo.require("dojo.string.extras"); 

/**
 * Calculates the mouse's direction of gravity relative to the centre
 * of the given node.
 * <p>
 * If you wanted to insert a node into a DOM tree based on the mouse
 * position you might use the following code:
 * <pre>
 * if (gravity(node, e) & gravity.NORTH) { [insert before]; }
 * else { [insert after]; }
 * </pre>
 *
 * @param node The node
 * @param e		The event containing the mouse coordinates
 * @return		 The directions, NORTH or SOUTH and EAST or WEST. These
 *						 are properties of the function.
 */
dojo.html.gravity = function(node, e){
	node = dojo.byId(node);
	var mouse = dojo.html.getCursorPosition(e);

	with (dojo.html) {
		var nodecenterx = getAbsoluteX(node, true) + (getInnerWidth(node) / 2);
		var nodecentery = getAbsoluteY(node, true) + (getInnerHeight(node) / 2);
	}
	
	with (dojo.html.gravity) {
		return ((mouse.x < nodecenterx ? WEST : EAST) |
			(mouse.y < nodecentery ? NORTH : SOUTH));
	}
}

dojo.html.gravity.NORTH = 1;
dojo.html.gravity.SOUTH = 1 << 1;
dojo.html.gravity.EAST = 1 << 2;
dojo.html.gravity.WEST = 1 << 3;


/**
 * Attempts to return the text as it would be rendered, with the line breaks
 * sorted out nicely. Unfinished.
 */
dojo.html.renderedTextContent = function(node){
	node = dojo.byId(node);
	var result = "";
	if (node == null) { return result; }
	for (var i = 0; i < node.childNodes.length; i++) {
		switch (node.childNodes[i].nodeType) {
			case 1: // ELEMENT_NODE
			case 5: // ENTITY_REFERENCE_NODE
				var display = "unknown";
				try {
					display = dojo.style.getStyle(node.childNodes[i], "display");
				} catch(E) {}
				switch (display) {
					case "block": case "list-item": case "run-in":
					case "table": case "table-row-group": case "table-header-group":
					case "table-footer-group": case "table-row": case "table-column-group":
					case "table-column": case "table-cell": case "table-caption":
						// TODO: this shouldn't insert double spaces on aligning blocks
						result += "\n";
						result += dojo.html.renderedTextContent(node.childNodes[i]);
						result += "\n";
						break;
					
					case "none": break;
					
					default:
						if(node.childNodes[i].tagName && node.childNodes[i].tagName.toLowerCase() == "br") {
							result += "\n";
						} else {
							result += dojo.html.renderedTextContent(node.childNodes[i]);
						}
						break;
				}
				break;
			case 3: // TEXT_NODE
			case 2: // ATTRIBUTE_NODE
			case 4: // CDATA_SECTION_NODE
				var text = node.childNodes[i].nodeValue;
				var textTransform = "unknown";
				try {
					textTransform = dojo.style.getStyle(node, "text-transform");
				} catch(E) {}
				switch (textTransform){
					case "capitalize": text = dojo.string.capitalize(text); break;
					case "uppercase": text = text.toUpperCase(); break;
					case "lowercase": text = text.toLowerCase(); break;
					default: break; // leave as is
				}
				// TODO: implement
				switch (textTransform){
					case "nowrap": break;
					case "pre-wrap": break;
					case "pre-line": break;
					case "pre": break; // leave as is
					default:
						// remove whitespace and collapse first space
						text = text.replace(/\s+/, " ");
						if (/\s$/.test(result)) { text.replace(/^\s/, ""); }
						break;
				}
				result += text;
				break;
			default:
				break;
		}
	}
	return result;
}

dojo.html.createNodesFromText = function(txt, trim){
	if(trim) { txt = dojo.string.trim(txt); }

	var tn = document.createElement("div");
	// tn.style.display = "none";
	tn.style.visibility= "hidden";
	document.body.appendChild(tn);
	var tableType = "none";
	if((/^<t[dh][\s\r\n>]/i).test(dojo.string.trimStart(txt))) {
		txt = "<table><tbody><tr>" + txt + "</tr></tbody></table>";
		tableType = "cell";
	} else if((/^<tr[\s\r\n>]/i).test(dojo.string.trimStart(txt))) {
		txt = "<table><tbody>" + txt + "</tbody></table>";
		tableType = "row";
	} else if((/^<(thead|tbody|tfoot)[\s\r\n>]/i).test(dojo.string.trimStart(txt))) {
		txt = "<table>" + txt + "</table>";
		tableType = "section";
	}
	tn.innerHTML = txt;
	if(tn["normalize"]){
		tn.normalize();
	}

	var parent = null;
	switch(tableType) {
		case "cell":
			parent = tn.getElementsByTagName("tr")[0];
			break;
		case "row":
			parent = tn.getElementsByTagName("tbody")[0];
			break;
		case "section":
			parent = tn.getElementsByTagName("table")[0];
			break;
		default:
			parent = tn;
			break;
	}

	/* this doesn't make much sense, I'm assuming it just meant trim() so wrap was replaced with trim
	if(wrap){ 
		var ret = [];
		// start hack
		var fc = tn.firstChild;
		ret[0] = ((fc.nodeValue == " ")||(fc.nodeValue == "\t")) ? fc.nextSibling : fc;
		// end hack
		// tn.style.display = "none";
		document.body.removeChild(tn);
		return ret;
	}
	*/
	var nodes = [];
	for(var x=0; x<parent.childNodes.length; x++){
		nodes.push(parent.childNodes[x].cloneNode(true));
	}
	tn.style.display = "none"; // FIXME: why do we do this?
	document.body.removeChild(tn);
	return nodes;
}

/* TODO: merge placeOnScreen and placeOnScreenPoint to make 1 function that allows you
 * to define which corner(s) you want to bind to. Something like so:
 *
 * kes(node, desiredX, desiredY, "TR")
 * kes(node, [desiredX, desiredY], ["TR", "BL"])
 *
 * TODO: make this function have variable call sigs
 *
 * kes(node, ptArray, cornerArray, padding, hasScroll)
 * kes(node, ptX, ptY, cornerA, cornerB, cornerC, paddingArray, hasScroll)
 */

/**
 * Keeps 'node' in the visible area of the screen while trying to
 * place closest to desiredX, desiredY. The input coordinates are
 * expected to be the desired screen position, not accounting for
 * scrolling. If you already accounted for scrolling, set 'hasScroll'
 * to true. Set padding to either a number or array for [paddingX, paddingY]
 * to put some buffer around the element you want to position.
 * NOTE: node is assumed to be absolutely or relatively positioned.
 *
 * Alternate call sig:
 *  placeOnScreen(node, [x, y], padding, hasScroll)
 *
 * Examples:
 *  placeOnScreen(node, 100, 200)
 *  placeOnScreen("myId", [800, 623], 5)
 *  placeOnScreen(node, 234, 3284, [2, 5], true)
 */
dojo.html.placeOnScreen = function(node, desiredX, desiredY, padding, hasScroll) {
	if(dojo.lang.isArray(desiredX)) {
		hasScroll = padding;
		padding = desiredY;
		desiredY = desiredX[1];
		desiredX = desiredX[0];
	}

	if(!isNaN(padding)) {
		padding = [Number(padding), Number(padding)];
	} else if(!dojo.lang.isArray(padding)) {
		padding = [0, 0];
	}

	var scroll = dojo.html.getScrollOffset();
	var view = dojo.html.getViewportSize();

	node = dojo.byId(node);
	var w = node.offsetWidth + padding[0];
	var h = node.offsetHeight + padding[1];

	if(hasScroll) {
		desiredX -= scroll.x;
		desiredY -= scroll.y;
	}

	var x = desiredX + w;
	if(x > view.w) {
		x = view.w - w;
	} else {
		x = desiredX;
	}
	x = Math.max(padding[0], x) + scroll.x;

	var y = desiredY + h;
	if(y > view.h) {
		y = view.h - h;
	} else {
		y = desiredY;
	}
	y = Math.max(padding[1], y) + scroll.y;

	node.style.left = x + "px";
	node.style.top = y + "px";

	var ret = [x, y];
	ret.x = x;
	ret.y = y;
	return ret;
}

/**
 * Like placeOnScreenPoint except that it attempts to keep one of the node's
 * corners at desiredX, desiredY.  Favors the bottom right position
 *
 * Examples placing node at mouse position (where e = [Mouse event]):
 *  placeOnScreenPoint(node, e.clientX, e.clientY);
 */
dojo.html.placeOnScreenPoint = function(node, desiredX, desiredY, padding, hasScroll) {
	if(dojo.lang.isArray(desiredX)) {
		hasScroll = padding;
		padding = desiredY;
		desiredY = desiredX[1];
		desiredX = desiredX[0];
	}

	if(!isNaN(padding)) {
		padding = [Number(padding), Number(padding)];
	} else if(!dojo.lang.isArray(padding)) {
		padding = [0, 0];
	}

	var scroll = dojo.html.getScrollOffset();
	var view = dojo.html.getViewportSize();

	node = dojo.byId(node);
	var oldDisplay = node.style.display;
	node.style.display="";
	var w = dojo.style.getInnerWidth(node);
	var h = dojo.style.getInnerHeight(node);
	node.style.display=oldDisplay;

	if(hasScroll) {
		desiredX -= scroll.x;
		desiredY -= scroll.y;
	}

	var x = -1, y = -1;
	//dojo.debug((desiredX+padding[0]) + w, "<=", view.w, "&&", (desiredY+padding[1]) + h, "<=", view.h);
	if((desiredX+padding[0]) + w <= view.w && (desiredY+padding[1]) + h <= view.h) { // TL
		x = (desiredX+padding[0]);
		y = (desiredY+padding[1]);
		//dojo.debug("TL", x, y);
	}

	//dojo.debug((desiredX-padding[0]), "<=", view.w, "&&", (desiredY+padding[1]) + h, "<=", view.h);
	if((x < 0 || y < 0) && (desiredX-padding[0]) <= view.w && (desiredY+padding[1]) + h <= view.h) { // TR
		x = (desiredX-padding[0]) - w;
		y = (desiredY+padding[1]);
		//dojo.debug("TR", x, y);
	}

	//dojo.debug((desiredX+padding[0]) + w, "<=", view.w, "&&", (desiredY-padding[1]), "<=", view.h);
	if((x < 0 || y < 0) && (desiredX+padding[0]) + w <= view.w && (desiredY-padding[1]) <= view.h) { // BL
		x = (desiredX+padding[0]);
		y = (desiredY-padding[1]) - h;
		//dojo.debug("BL", x, y);
	}

	//dojo.debug((desiredX-padding[0]), "<=", view.w, "&&", (desiredY-padding[1]), "<=", view.h);
	if((x < 0 || y < 0) && (desiredX-padding[0]) <= view.w && (desiredY-padding[1]) <= view.h) { // BR
		x = (desiredX-padding[0]) - w;
		y = (desiredY-padding[1]) - h;
		//dojo.debug("BR", x, y);
	}

	if(x < 0 || y < 0 || (x + w > view.w) || (y + h > view.h)) {
		return dojo.html.placeOnScreen(node, desiredX, desiredY, padding, hasScroll);
	}

	x += scroll.x;
	y += scroll.y;

	node.style.left = x + "px";
	node.style.top = y + "px";

	var ret = [x, y];
	ret.x = x;
	ret.y = y;
	return ret;
}

/**
 * For IE z-index schenanigans
 * Two possible uses:
 *   1. new dojo.html.BackgroundIframe(node)
 *        Makes a background iframe as a child of node, that fills area (and position) of node
 *
 *   2. new dojo.html.BackgroundIframe()
 *        Attaches frame to document.body.  User must call size() to set size.
 */
dojo.html.BackgroundIframe = function(node) {
	if(dojo.render.html.ie55 || dojo.render.html.ie60) {
		var html=
				 "<iframe "
				+"style='position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;"
				+        "z-index: -1; filter:Alpha(Opacity=\"0\");' "
				+">";
		this.iframe = document.createElement(html);
		if(node){
			node.appendChild(this.iframe);
			this.domNode=node;
		}else{
			document.body.appendChild(this.iframe);
			this.iframe.style.display="none";
		}
	}
}
dojo.lang.extend(dojo.html.BackgroundIframe, {
	iframe: null,

	// TODO: this function shouldn't be necessary but setting width=height=100% doesn't work!
	onResized: function(){
		if(this.iframe && this.domNode && this.domNode.parentElement){ // No parentElement if onResized() timeout event occurs on a removed domnode
			var w = dojo.style.getOuterWidth(this.domNode);
			var h = dojo.style.getOuterHeight(this.domNode);
			if (w  == 0 || h == 0 ){
				dojo.lang.setTimeout(this, this.onResized, 50);
				return;
			}
			var s = this.iframe.style;
			s.width = w + "px";
			s.height = h + "px";
		}
	},

	// Call this function if the iframe is connected to document.body rather
	// than the node being shadowed (TODO: erase)
	size: function(node) {
		if(!this.iframe) { return; }

		var coords = dojo.style.toCoordinateArray(node, true);

		var s = this.iframe.style;
		s.width = coords.w + "px";
		s.height = coords.h + "px";
		s.left = coords.x + "px";
		s.top = coords.y + "px";
	},

	setZIndex: function(node /* or number */) {
		if(!this.iframe) { return; }

		if(dojo.dom.isNode(node)) {
			this.iframe.style.zIndex = dojo.html.getStyle(node, "z-index") - 1;
		} else if(!isNaN(node)) {
			this.iframe.style.zIndex = node;
		}
	},

	show: function() {
		if(!this.iframe) { return; }
		this.iframe.style.display = "block";
	},

	hide: function() {
		if(!this.ie) { return; }
		var s = this.iframe.style;
		s.display = "none";
	},

	remove: function() {
		dojo.dom.removeNode(this.iframe);
	}
});

__CPAN_DIR__ src/html/images
__CPAN_FILE__ src/html/images/shadowBL.png
‰PNG


IHDRÄ¾‹gAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<¢IDATxÚ4ŽÉÃ DÙ²ô!‘ôóÿ—D•HÂÖçŠ"
c<ã1zß÷ ”òZë~ƒµ¿_ðèj­ÍÓ8Î4	8Õ¯Šˆ˜|ñ¨ÈŽ!U¦nêHs ^ýS\ŸNÖÚãGD8ÁÃÏpGY–å)¥˜qœ%	“Ãdœ÷¾ÄÓ4M"Êº§ÿÍ²NÛ‚Þ¶­�çÙæy.LeY�xSß_=5bËd5Ê¦IEND®B`‚
__CPAN_FILE__ src/html/images/shadowTR.png
‰PNG


IHDRÄ¾‹gAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<±IDATxÚ�„ D¡(bÔ%‘xïä]=�ÉXùt§’4˜×IÑÇq¸û¾yš&VJ±è”R;ÏSîŠZk£h‡²¥”.„`ö}':"òè`�ÎË²<1Æ¼m[™ç™;˜+Œ‚þ3Æ¤Z+
Ã ®ëbçKB`æŒ‘òµÖ*@Í{_%YÌ¨×Z‹Y>x{ài>¨×„ñ&ÉnÐ„]^`Ä´,œõ0äÍÈ4¾®ÿË`å÷Ò±IEND®B`‚
__CPAN_FILE__ src/html/images/shadowBR.png
‰PNG


IHDRÄ¾‹gAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<¡IDATxÚ4OIÃ Â�ŸÌúÑ<�sE¥„Ò„Õ�‰Z¤‘1³Øèu]"r*¥v Oô¬{ïýcqiZë†Ú‰‰ƒ*(b­UÍ	qÁÙŒ1ŠrÎÂ„ ™)„³Âéœ»sBô^–åâØŠK'ÉZ+ÇÕ”ÒÀwÂä`ìoáZJiÞûcœLà÷„3K'ÉÂÜ¶M¾œ„Ùïæ?IEND®B`‚
__CPAN_FILE__ src/html/images/shadowTR..png
‰PNG


IHDR;Ö•JbKGDÿÿÿ ½§“	pHYsšœtIMEÕ0^ÆtEXtCommentCreated with The GIMPïd%nÀIDATxÚ�“Û‚@D²€¯?˜o&"È-¾LÍˆDŒ›4´[N§ÛÍfMÓðï:ÉþZ	¸+0ð�ÿ3¼<ÈîGEPKyF�=P7Å‡ÊÑr¨Ê·Š¿Â[ÕÜ†¹îum/¦ÚißÁÙìCyíæ.6�vO9¦\7àÇy»�P•HÆ{à,«¶p­Ê…öB­7 T¾Øk»S<	ªv d�½à‹üÁ~N:{nW–Û[Xãa–Èì›©¨û¸ÿð‹J™q˜IEND®B`‚
__CPAN_FILE__ src/html/images/shadowR.png
‰PNG


IHDRãïCgAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<'IDATxÚbLII)g``øÄßüû÷ï
�ý†……å#H À´®@ßÙ@IEND®B`‚
__CPAN_FILE__ src/html/images/shadowB.png
‰PNG


IHDRÐ¡òdµgAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<hIDATxÚìÝ1nÃ0Ð
ðQ}ŒÜ¸èÐ¥C<°Éœ%†àˆß:¶>éÔAË¨mû¾ß¾€jZÇñvñÚpFtum ¡-"îÚËi�ÇG][6ê¼Y7�~N‹Aç¾s~Õlè°˜íñûŸ6Àr®7Ù.9æì²åÌ–yí•k“è²§[;îkÈ6e6ôÏ¯m@Å<w ÿj,§ê ¸ò½j¶•³[;ßÚ3gS{Æ¦Ù�>J¨[¶DÙBmË];s_£èÚ£³“yî@ÿÑ(ÇŽÞ|×o^ú&[ùç§÷�jM1@¿ŠAG½¾Énmµå¸¶MKØ_ßÚËñ§Ÿ­-›ljÓ7’‹ðûv^_Z oÕ&Û|Ù|°À3xƒèÀYvŽªMmú‚{ädˆãžè‹ÚÔæ{è´Çá 31 ÒWÜsøC7÷}Šù`|¤fZì³oNIEND®B`‚
__CPAN_FILE__ src/html/images/shadowL.png
‰PNG


IHDRãïCgAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<&IDATxÚbLHHfeeåÿÿÿ¿0ƒ(ˆfddñ¹€4@€³¢
ªÙZuIEND®B`‚
__CPAN_FILE__ src/html/images/shadowTL.png
‰PNG


IHDRÄ¾‹gAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<¡IDATxÚ,ŽA„0ëÔe[•.¸óÀÿÄqA°Îª‡(QÆv‚eY°ï;rÎVkEçyÂçû¾·m³yží8Ž(ø¯RŠ=Ï’àº®v][kIpHfÆ.Ýéð}ßc,Zf	>€qš&WµG‰‹º›ø�òØîÕ¿êÕ5“‚æ7=¶;«@Sù¹ä	è)ì±¹Ã¢ÒO€¨´9êuÈcIEND®B`‚
__CPAN_FILE__ src/html/images/shadowT.png
‰PNG


IHDR8•AgAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<*IDATxÚbHOOçdb``àbúóç?ˆ%Â"LÿÿÿqÁb\±7²™“)IEND®B`‚
__CPAN_DIR__ src/event
__CPAN_FILE__ src/event/browser.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.event.browser");
dojo.require("dojo.event");

// FIXME: any particular reason this is in the global scope?
dojo._ie_clobber = new function(){
	this.clobberNodes = [];

	function nukeProp(node, prop){
		// try{ node.removeAttribute(prop); 	}catch(e){ /* squelch */ }
		try{ node[prop] = null; 			}catch(e){ /* squelch */ }
		try{ delete node[prop]; 			}catch(e){ /* squelch */ }
		// FIXME: JotLive needs this, but I'm not sure if it's too slow or not
		try{ node.removeAttribute(prop);	}catch(e){ /* squelch */ }
	}

	this.clobber = function(nodeRef){
		var na;
		var tna;
		if(nodeRef){
			tna = nodeRef.all || nodeRef.getElementsByTagName("*");
			na = [nodeRef];
			for(var x=0; x<tna.length; x++){
				// if we're gonna be clobbering the thing, at least make sure
				// we aren't trying to do it twice
				if(tna[x]["__doClobber__"]){
					na.push(tna[x]);
				}
			}
		}else{
			try{ window.onload = null; }catch(e){}
			na = (this.clobberNodes.length) ? this.clobberNodes : document.all;
		}
		tna = null;
		var basis = {};
		for(var i = na.length-1; i>=0; i=i-1){
			var el = na[i];
			if(el["__clobberAttrs__"]){
				for(var j=0; j<el.__clobberAttrs__.length; j++){
					nukeProp(el, el.__clobberAttrs__[j]);
				}
				nukeProp(el, "__clobberAttrs__");
				nukeProp(el, "__doClobber__");
			}
		}
		na = null;
	}
}

if(dojo.render.html.ie){
	dojo.addOnUnload(function(){
		dojo._ie_clobber.clobber();
		try{
			if((dojo["widget"])&&(dojo.widget["manager"])){
				dojo.widget.manager.destroyAll();
			}
		}catch(e){}
		try{ window.onload = null; }catch(e){}
		try{ window.onunload = null; }catch(e){}
		dojo._ie_clobber.clobberNodes = [];
		// CollectGarbage();
	});
}

dojo.event.browser = new function(){

	var clobberIdx = 0;

	this.clean = function(node){
		if(dojo.render.html.ie){ 
			dojo._ie_clobber.clobber(node);
		}
	}

	this.addClobberNode = function(node){
		if(!dojo.render.html.ie){ return; }
		if(!node["__doClobber__"]){
			node.__doClobber__ = true;
			dojo._ie_clobber.clobberNodes.push(node);
			// this might not be the most efficient thing to do, but it's
			// much less error prone than other approaches which were
			// previously tried and failed
			node.__clobberAttrs__ = [];
		}
	}

	this.addClobberNodeAttrs = function(node, props){
		if(!dojo.render.html.ie){ return; }
		this.addClobberNode(node);
		for(var x=0; x<props.length; x++){
			node.__clobberAttrs__.push(props[x]);
		}
	}

	this.removeListener = function(node, evtName, fp, capture){
		if(!capture){ var capture = false; }
		evtName = evtName.toLowerCase();
		if(evtName.substr(0,2)=="on"){ evtName = evtName.substr(2); }
		// FIXME: this is mostly a punt, we aren't actually doing anything on IE
		if(node.removeEventListener){
			node.removeEventListener(evtName, fp, capture);
		}
	}

	this.addListener = function(node, evtName, fp, capture, dontFix){
		if(!node){ return; } // FIXME: log and/or bail?
		if(!capture){ var capture = false; }
		evtName = evtName.toLowerCase();
		if(evtName.substr(0,2)!="on"){ evtName = "on"+evtName; }

		if(!dontFix){
			// build yet another closure around fp in order to inject fixEvent
			// around the resulting event
			var newfp = function(evt){
				if(!evt){ evt = window.event; }
				var ret = fp(dojo.event.browser.fixEvent(evt, this));
				if(capture){
					dojo.event.browser.stopEvent(evt);
				}
				return ret;
			}
		}else{
			newfp = fp;
		}

		if(node.addEventListener){ 
			node.addEventListener(evtName.substr(2), newfp, capture);
			return newfp;
		}else{
			if(typeof node[evtName] == "function" ){
				var oldEvt = node[evtName];
				node[evtName] = function(e){
					oldEvt(e);
					return newfp(e);
				}
			}else{
				node[evtName]=newfp;
			}
			if(dojo.render.html.ie){
				this.addClobberNodeAttrs(node, [evtName]);
			}
			return newfp;
		}
	}

	this.isEvent = function(obj){
		// FIXME: event detection hack ... could test for additional attributes
		// if necessary
		return (typeof obj != "undefined")&&(typeof Event != "undefined")&&(obj.eventPhase);
		// Event does not support instanceof in Opera, otherwise:
		//return (typeof Event != "undefined")&&(obj instanceof Event);
	}

	this.currentEvent = null;
	
	this.callListener = function(listener, curTarget){
		if(typeof listener != 'function'){
			dojo.raise("listener not a function: " + listener);
		}
		dojo.event.browser.currentEvent.currentTarget = curTarget;
		return listener.call(curTarget, dojo.event.browser.currentEvent);
	}

	this.stopPropagation = function(){
		dojo.event.browser.currentEvent.cancelBubble = true;
	}

	this.preventDefault = function(){
	  dojo.event.browser.currentEvent.returnValue = false;
	}

	this.keys = {
		KEY_BACKSPACE: 8,
		KEY_TAB: 9,
		KEY_ENTER: 13,
		KEY_SHIFT: 16,
		KEY_CTRL: 17,
		KEY_ALT: 18,
		KEY_PAUSE: 19,
		KEY_CAPS_LOCK: 20,
		KEY_ESCAPE: 27,
		KEY_SPACE: 32,
		KEY_PAGE_UP: 33,
		KEY_PAGE_DOWN: 34,
		KEY_END: 35,
		KEY_HOME: 36,
		KEY_LEFT_ARROW: 37,
		KEY_UP_ARROW: 38,
		KEY_RIGHT_ARROW: 39,
		KEY_DOWN_ARROW: 40,
		KEY_INSERT: 45,
		KEY_DELETE: 46,
		KEY_LEFT_WINDOW: 91,
		KEY_RIGHT_WINDOW: 92,
		KEY_SELECT: 93,
		KEY_F1: 112,
		KEY_F2: 113,
		KEY_F3: 114,
		KEY_F4: 115,
		KEY_F5: 116,
		KEY_F6: 117,
		KEY_F7: 118,
		KEY_F8: 119,
		KEY_F9: 120,
		KEY_F10: 121,
		KEY_F11: 122,
		KEY_F12: 123,
		KEY_NUM_LOCK: 144,
		KEY_SCROLL_LOCK: 145
	};

	// reverse lookup
	this.revKeys = [];
	for(var key in this.keys){
		this.revKeys[this.keys[key]] = key;
	}

	this.fixEvent = function(evt, sender){
		if((!evt)&&(window["event"])){
			var evt = window.event;
		}
		
		if((evt["type"])&&(evt["type"].indexOf("key") == 0)){ // key events
			evt.keys = this.revKeys;
			// FIXME: how can we eliminate this iteration?
			for(var key in this.keys) {
				evt[key] = this.keys[key];
			}
			if((dojo.render.html.ie)&&(evt["type"] == "keypress")){
				evt.charCode = evt.keyCode;
			}
		}
	
		if(dojo.render.html.ie){
			if(!evt.target){ evt.target = evt.srcElement; }
			if(!evt.currentTarget){ evt.currentTarget = (sender ? sender : evt.srcElement); }
			if(!evt.layerX){ evt.layerX = evt.offsetX; }
			if(!evt.layerY){ evt.layerY = evt.offsetY; }
			// FIXME: scroll position query is duped from dojo.html to avoid dependency on that entire module
			var docBody = ((dojo.render.html.ie55)||(document["compatMode"] == "BackCompat")) ? document.body : document.documentElement;
			if(!evt.pageX){ evt.pageX = evt.clientX + (docBody.scrollLeft || 0) }
			if(!evt.pageY){ evt.pageY = evt.clientY + (docBody.scrollTop || 0) }
			// mouseover
			if(evt.type == "mouseover"){ evt.relatedTarget = evt.fromElement; }
			// mouseout
			if(evt.type == "mouseout"){ evt.relatedTarget = evt.toElement; }
			this.currentEvent = evt;
			evt.callListener = this.callListener;
			evt.stopPropagation = this.stopPropagation;
			evt.preventDefault = this.preventDefault;
		}
		return evt;
	}

	this.stopEvent = function(ev) {
		if(window.event){
			ev.returnValue = false;
			ev.cancelBubble = true;
		}else{
			ev.preventDefault();
			ev.stopPropagation();
		}
	}
}

__CPAN_FILE__ src/event/topic.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.event");
dojo.provide("dojo.event.topic");

dojo.event.topic = new function(){
	this.topics = {};

	this.getTopic = function(topicName){
		if(!this.topics[topicName]){
			this.topics[topicName] = new this.TopicImpl(topicName);
		}
		return this.topics[topicName];
	}

	this.registerPublisher = function(topic, obj, funcName){
		var topic = this.getTopic(topic);
		topic.registerPublisher(obj, funcName);
	}

	this.subscribe = function(topic, obj, funcName){
		var topic = this.getTopic(topic);
		topic.subscribe(obj, funcName);
	}

	this.unsubscribe = function(topic, obj, funcName){
		var topic = this.getTopic(topic);
		topic.unsubscribe(obj, funcName);
	}

	this.destroy = function(topic){
		this.getTopic(topic).destroy();
		delete this.topics[topic];
	}

	this.publishApply = function(topic, args){
		var topic = this.getTopic(topic);
		topic.sendMessage.apply(topic, args);
	}

	this.publish = function(topic, message){
		var topic = this.getTopic(topic);
		// if message is an array, we treat it as a set of arguments,
		// otherwise, we just pass on the arguments passed in as-is
		var args = [];
		// could we use concat instead here?
		for(var x=1; x<arguments.length; x++){
			args.push(arguments[x]);
		}
		topic.sendMessage.apply(topic, args);
	}
}

dojo.event.topic.TopicImpl = function(topicName){
	this.topicName = topicName;

	this.subscribe = function(listenerObject, listenerMethod){
		var tf = listenerMethod||listenerObject;
		var to = (!listenerMethod) ? dj_global : listenerObject;
		dojo.event.kwConnect({
			srcObj:		this, 
			srcFunc:	"sendMessage", 
			adviceObj:	to,
			adviceFunc: tf
		});
	}

	this.unsubscribe = function(listenerObject, listenerMethod){
		var tf = (!listenerMethod) ? listenerObject : listenerMethod;
		var to = (!listenerMethod) ? null : listenerObject;
		dojo.event.kwDisconnect({
			srcObj:		this, 
			srcFunc:	"sendMessage", 
			adviceObj:	to,
			adviceFunc: tf
		});
	}

	this.destroy = function(){
		dojo.event.MethodJoinPoint.getForMethod(this, "sendMessage").disconnect();
	}

	this.registerPublisher = function(publisherObject, publisherMethod){
		dojo.event.connect(publisherObject, publisherMethod, this, "sendMessage");
	}

	this.sendMessage = function(message){
		// The message has been propagated
	}
}


__CPAN_FILE__ src/event/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: ["dojo.event", "dojo.event.topic"],
	browser: ["dojo.event.browser"],
	dashboard: ["dojo.event.browser"]
});
dojo.provide("dojo.event.*");

__CPAN_DIR__ src/dnd
__CPAN_FILE__ src/dnd/DragAndDrop.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.lang");
dojo.provide("dojo.dnd.DragSource");
dojo.provide("dojo.dnd.DropTarget");
dojo.provide("dojo.dnd.DragObject");
dojo.provide("dojo.dnd.DragAndDrop");

dojo.dnd.DragSource = function(){
	var dm = dojo.dnd.dragManager;
	if(dm["registerDragSource"]){ // side-effect prevention
		dm.registerDragSource(this);
	}
}

dojo.lang.extend(dojo.dnd.DragSource, {
	type: "",

	onDragEnd: function(){
	},

	onDragStart: function(){
	},

	/*
	 * This function gets called when the DOM element was 
	 * selected for dragging by the HtmlDragAndDropManager.
	 */
	onSelected: function(){
	},

	unregister: function(){
		dojo.dnd.dragManager.unregisterDragSource(this);
	},

	reregister: function(){
		dojo.dnd.dragManager.registerDragSource(this);
	}
});

dojo.dnd.DragObject = function(){
	var dm = dojo.dnd.dragManager;
	if(dm["registerDragObject"]){ // side-effect prevention
		dm.registerDragObject(this);
	}
}

dojo.lang.extend(dojo.dnd.DragObject, {
	type: "",

	onDragStart: function(){
		// gets called directly after being created by the DragSource
		// default action is to clone self as icon
	},

	onDragMove: function(){
		// this changes the UI for the drag icon
		//	"it moves itself"
	},

	onDragOver: function(){
	},

	onDragOut: function(){
	},

	onDragEnd: function(){
	},

	// normal aliases
	onDragLeave: this.onDragOut,
	onDragEnter: this.onDragOver,

	// non-camel aliases
	ondragout: this.onDragOut,
	ondragover: this.onDragOver
});

dojo.dnd.DropTarget = function(){
	if (this.constructor == dojo.dnd.DropTarget) { return; } // need to be subclassed
	this.acceptedTypes = [];
	dojo.dnd.dragManager.registerDropTarget(this);
}

dojo.lang.extend(dojo.dnd.DropTarget, {

	acceptsType: function(type){
		if(!dojo.lang.inArray(this.acceptedTypes, "*")){ // wildcard
			if(!dojo.lang.inArray(this.acceptedTypes, type)) { return false; }
		}
		return true;
	},

	accepts: function(dragObjects){
		if(!dojo.lang.inArray(this.acceptedTypes, "*")){ // wildcard
			for (var i = 0; i < dragObjects.length; i++) {
				if (!dojo.lang.inArray(this.acceptedTypes,
					dragObjects[i].type)) { return false; }
			}
		}
		return true;
	},

	onDragOver: function(){
	},

	onDragOut: function(){
	},

	onDragMove: function(){
	},

	onDropStart: function(){
	},

	onDrop: function(){
	},

	onDropEnd: function(){
	}
});

// NOTE: this interface is defined here for the convenience of the DragManager
// implementor. It is expected that in most cases it will be satisfied by
// extending a native event (DOM event in HTML and SVG).
dojo.dnd.DragEvent = function(){
	this.dragSource = null;
	this.dragObject = null;
	this.target = null;
	this.eventStatus = "success";
	//
	// can be one of:
	//	[	"dropSuccess", "dropFailure", "dragMove",
	//		"dragStart", "dragEnter", "dragLeave"]
	//
}

dojo.dnd.DragManager = function(){
	/*
	 *	The DragManager handles listening for low-level events and dispatching
	 *	them to higher-level primitives like drag sources and drop targets. In
	 *	order to do this, it must keep a list of the items.
	 */
}

dojo.lang.extend(dojo.dnd.DragManager, {
	selectedSources: [],
	dragObjects: [],
	dragSources: [],
	registerDragSource: function(){},
	dropTargets: [],
	registerDropTarget: function(){},
	lastDragTarget: null,
	currentDragTarget: null,
	onKeyDown: function(){},
	onMouseOut: function(){},
	onMouseMove: function(){},
	onMouseUp: function(){}
});

// NOTE: despite the existance of the DragManager class, there will be a
// singleton drag manager provided by the renderer-specific D&D support code.
// It is therefore sane for us to assign instance variables to the DragManager
// prototype

// The renderer-specific file will define the following object:
// dojo.dnd.dragManager = null;

__CPAN_FILE__ src/dnd/Sortable.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.dnd.Sortable");
dojo.require("dojo.dnd.*");

dojo.dnd.Sortable = function () {}

dojo.lang.extend(dojo.dnd.Sortable, {

	ondragstart: function (e) {
		var dragObject = e.target;
		while (dragObject.parentNode && dragObject.parentNode != this) {
			dragObject = dragObject.parentNode;
		}
		// TODO: should apply HtmlDropTarget interface to self
		// TODO: should apply HtmlDragObject interface?
		return dragObject;
	}

});

__CPAN_FILE__ src/dnd/HtmlDragManager.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.dnd.HtmlDragManager");
dojo.require("dojo.dnd.DragAndDrop");
dojo.require("dojo.event.*");
dojo.require("dojo.lang.array");
dojo.require("dojo.html");
dojo.require("dojo.style");

// NOTE: there will only ever be a single instance of HTMLDragManager, so it's
// safe to use prototype properties for book-keeping.
dojo.dnd.HtmlDragManager = function(){
}

dojo.inherits(dojo.dnd.HtmlDragManager, dojo.dnd.DragManager);

dojo.lang.extend(dojo.dnd.HtmlDragManager, {
	/**
	 * There are several sets of actions that the DnD code cares about in the
	 * HTML context:
	 *	1.) mouse-down ->
	 *			(draggable selection)
	 *			(dragObject generation)
	 *		mouse-move ->
	 *			(draggable movement)
	 *			(droppable detection)
	 *			(inform droppable)
	 *			(inform dragObject)
	 *		mouse-up
	 *			(inform/destroy dragObject)
	 *			(inform draggable)
	 *			(inform droppable)
	 *	2.) mouse-down -> mouse-down
	 *			(click-hold context menu)
	 *	3.) mouse-click ->
	 *			(draggable selection)
	 *		shift-mouse-click ->
	 *			(augment draggable selection)
	 *		mouse-down ->
	 *			(dragObject generation)
	 *		mouse-move ->
	 *			(draggable movement)
	 *			(droppable detection)
	 *			(inform droppable)
	 *			(inform dragObject)
	 *		mouse-up
	 *			(inform draggable)
	 *			(inform droppable)
	 *	4.) mouse-up
	 *			(clobber draggable selection)
	 */
	disabled: false, // to kill all dragging!
	nestedTargets: false,
	mouseDownTimer: null, // used for click-hold operations
	dsCounter: 0,
	dsPrefix: "dojoDragSource",

	// dimension calculation cache for use durring drag
	dropTargetDimensions: [],

	currentDropTarget: null,
	// currentDropTargetPoints: null,
	previousDropTarget: null,
	_dragTriggered: false,

	selectedSources: [],
	dragObjects: [],

	// mouse position properties
	currentX: null,
	currentY: null,
	lastX: null,
	lastY: null,
	mouseDownX: null,
	mouseDownY: null,
	threshold: 7,

	dropAcceptable: false,

	cancelEvent: function(e){ e.stopPropagation(); e.preventDefault();},

	// method over-rides
	registerDragSource: function(ds){
		if(ds["domNode"]){
			// FIXME: dragSource objects SHOULD have some sort of property that
			// references their DOM node, we shouldn't just be passing nodes and
			// expecting it to work.
			var dp = this.dsPrefix;
			var dpIdx = dp+"Idx_"+(this.dsCounter++);
			ds.dragSourceId = dpIdx;
			this.dragSources[dpIdx] = ds;
			ds.domNode.setAttribute(dp, dpIdx);

			// so we can drag links
			if(dojo.render.html.ie){
				dojo.event.connect(ds.domNode, "ondragstart", this.cancelEvent);
			}
		}
	},

	unregisterDragSource: function(ds){
		if (ds["domNode"]){

			var dp = this.dsPrefix;
			var dpIdx = ds.dragSourceId;
			delete ds.dragSourceId;
			delete this.dragSources[dpIdx];
			ds.domNode.setAttribute(dp, null);
		}
		if(dojo.render.html.ie){
			dojo.event.disconnect(ds.domNode, "ondragstart", this.cancelEvent );
		}
	},

	registerDropTarget: function(dt){
		this.dropTargets.push(dt);
	},

	unregisterDropTarget: function(dt){
		var index = dojo.lang.find(this.dropTargets, dt, true);
		if (index>=0) {
			this.dropTargets.splice(index, 1);
		}
	},

	/**
	* Get the DOM element that is meant to drag.
	* Loop through the parent nodes of the event target until
	* the element is found that was created as a DragSource and 
	* return it.
	*
	* @param event object The event for which to get the drag source.
	*/
	getDragSource: function(e){
		var tn = e.target;
		if(tn === document.body){ return; }
		var ta = dojo.html.getAttribute(tn, this.dsPrefix);
		while((!ta)&&(tn)){
			tn = tn.parentNode;
			if((!tn)||(tn === document.body)){ return; }
			ta = dojo.html.getAttribute(tn, this.dsPrefix);
		}
		return this.dragSources[ta];
	},

	onKeyDown: function(e){
	},

	onMouseDown: function(e){
		if(this.disabled) { return; }

		// only begin on left click
		if(dojo.render.html.ie) {
			if(e.button != 1) { return; }
		} else if(e.which != 1) {
			return;
		}

		var target = e.target.nodeType == dojo.dom.TEXT_NODE ?
			e.target.parentNode : e.target;

		// do not start drag involvement if the user is interacting with
		// a form element.
		if(dojo.html.isTag(target, "button", "textarea", "input", "select", "option")) {
			return;
		}

		// find a selection object, if one is a parent of the source node
		var ds = this.getDragSource(e);
		
		// this line is important.  if we aren't selecting anything then
		// we need to return now, so preventDefault() isn't called, and thus
		// the event is propogated to other handling code
		if(!ds){ return; }

		if(!dojo.lang.inArray(this.selectedSources, ds)){
			this.selectedSources.push(ds);
			ds.onSelected();
		}

 		this.mouseDownX = e.pageX;
 		this.mouseDownY = e.pageY;

		// Must stop the mouse down from being propogated, or otherwise can't
		// drag links in firefox.
		// WARNING: preventing the default action on all mousedown events
		// prevents user interaction with the contents.
		e.preventDefault();

		dojo.event.connect(document, "onmousemove", this, "onMouseMove");
	},

	onMouseUp: function(e, cancel){
		// if we aren't dragging then ignore the mouse-up
		// (in particular, don't call preventDefault(), because other
		// code may need to process this event)
		if(this.selectedSources.length==0){
			return;
		}

		this.mouseDownX = null;
		this.mouseDownY = null;
		this._dragTriggered = false;
 		// e.preventDefault();
		e.dragSource = this.dragSource;
		if((!e.shiftKey)&&(!e.ctrlKey)){
			if(this.currentDropTarget) {
				this.currentDropTarget.onDropStart();
			}
			dojo.lang.forEach(this.dragObjects, function(tempDragObj){
				var ret = null;
				if(!tempDragObj){ return; }
				if(this.currentDropTarget) {
					e.dragObject = tempDragObj;

					// NOTE: we can't get anything but the current drop target
					// here since the drag shadow blocks mouse-over events.
					// This is probelematic for dropping "in" something
					var ce = this.currentDropTarget.domNode.childNodes;
					if(ce.length > 0){
						e.dropTarget = ce[0];
						while(e.dropTarget == tempDragObj.domNode){
							e.dropTarget = e.dropTarget.nextSibling;
						}
					}else{
						e.dropTarget = this.currentDropTarget.domNode;
					}
					if(this.dropAcceptable){
						ret = this.currentDropTarget.onDrop(e);
					}else{
						 this.currentDropTarget.onDragOut(e);
					}
				}

				e.dragStatus = this.dropAcceptable && ret ? "dropSuccess" : "dropFailure";
				// decouple the calls for onDragEnd, so they don't block the execution here
				// ie. if the onDragEnd would call an alert, the execution here is blocked until the
				// user has confirmed the alert box and then the rest of the dnd code is executed
				// while the mouse doesnt "hold" the dragged object anymore ... and so on
				dojo.lang.delayThese([
					function() {
						// in FF1.5 this throws an exception, see 
						// http://dojotoolkit.org/pipermail/dojo-interest/2006-April/006751.html
						try{
							tempDragObj.dragSource.onDragEnd(e)
						} catch(err) {
							// since the problem seems passing e, we just copy all 
							// properties and try the copy ...
							var ecopy = {};
							for (var i in e) {
								if (i=="type") { // the type property contains the exception, no idea why...
									ecopy.type = "mouseup";
									continue;
								}
								ecopy[i] = e[i];
							}
							tempDragObj.dragSource.onDragEnd(ecopy);
						}
					}
					, function() {tempDragObj.onDragEnd(e)}]);
			}, this);

			this.selectedSources = [];
			this.dragObjects = [];
			this.dragSource = null;
			if(this.currentDropTarget) {
				this.currentDropTarget.onDropEnd();
			}
		}

		dojo.event.disconnect(document, "onmousemove", this, "onMouseMove");
		this.currentDropTarget = null;
	},

	onScroll: function(){
		for(var i = 0; i < this.dragObjects.length; i++) {
			if(this.dragObjects[i].updateDragOffset) {
				this.dragObjects[i].updateDragOffset();
			}
		}
		// TODO: do not recalculate, only adjust coordinates
		this.cacheTargetLocations();
	},

	_dragStartDistance: function(x, y){
		if((!this.mouseDownX)||(!this.mouseDownX)){
			return;
		}
		var dx = Math.abs(x-this.mouseDownX);
		var dx2 = dx*dx;
		var dy = Math.abs(y-this.mouseDownY);
		var dy2 = dy*dy;
		return parseInt(Math.sqrt(dx2+dy2), 10);
	},

	cacheTargetLocations: function(){
		this.dropTargetDimensions = [];
		dojo.lang.forEach(this.dropTargets, function(tempTarget){
			var tn = tempTarget.domNode;
			if(!tn){ return; }
			var ttx = dojo.style.getAbsoluteX(tn, true);
			var tty = dojo.style.getAbsoluteY(tn, true);
			this.dropTargetDimensions.push([
				[ttx, tty],	// upper-left
				// lower-right
				[ ttx+dojo.style.getInnerWidth(tn), tty+dojo.style.getInnerHeight(tn) ],
				tempTarget
			]);
			//dojo.debug("Cached for "+tempTarget)
		}, this);
		//dojo.debug("Cache locations")
	},

	onMouseMove: function(e){
		if((dojo.render.html.ie)&&(e.button != 1)){
			// Oooops - mouse up occurred - e.g. when mouse was not over the
			// window. I don't think we can detect this for FF - but at least
			// we can be nice in IE.
			this.currentDropTarget = null;
			this.onMouseUp(e, true);
			return;
		}

		// if we've got some sources, but no drag objects, we need to send
		// onDragStart to all the right parties and get things lined up for
		// drop target detection

		if(	(this.selectedSources.length)&&
			(!this.dragObjects.length) ){
			var dx;
			var dy;
			if(!this._dragTriggered){
				this._dragTriggered = (this._dragStartDistance(e.pageX, e.pageY) > this.threshold);
				if(!this._dragTriggered){ return; }
				dx = e.pageX - this.mouseDownX;
				dy = e.pageY - this.mouseDownY;
			}

			// the first element is always our dragSource, if there are multiple
			// selectedSources (elements that move along) then the first one is the master
			// and for it the events will be fired etc.
			this.dragSource = this.selectedSources[0];
			
			dojo.lang.forEach(this.selectedSources, function(tempSource){
				if(!tempSource){ return; }
				var tdo = tempSource.onDragStart(e);
				if(tdo){
					tdo.onDragStart(e);

					// "bump" the drag object to account for the drag threshold
					tdo.dragOffset.top += dy;
					tdo.dragOffset.left += dx;
					tdo.dragSource = tempSource;

					this.dragObjects.push(tdo);
				}
			}, this);

			/* clean previous drop target in dragStart */
			this.previousDropTarget = null;

			this.cacheTargetLocations();
		}

		// FIXME: we need to add dragSources and dragObjects to e
		dojo.lang.forEach(this.dragObjects, function(dragObj){
			if(dragObj){ dragObj.onDragMove(e); }
		});

		// if we have a current drop target, check to see if we're outside of
		// it. If so, do all the actions that need doing.
		if(this.currentDropTarget){
			//dojo.debug(dojo.dom.hasParent(this.currentDropTarget.domNode))
			var c = dojo.style.toCoordinateArray(this.currentDropTarget.domNode, true);
			//		var dtp = this.currentDropTargetPoints;
			var dtp = [
				[c[0],c[1]], [c[0]+c[2], c[1]+c[3]]
			];
		}

		if((!this.nestedTargets)&&(dtp)&&(this.isInsideBox(e, dtp))){
			if(this.dropAcceptable){
				this.currentDropTarget.onDragMove(e, this.dragObjects);
			}
		}else{
			// FIXME: need to fix the event object!
			// see if we can find a better drop target
			var bestBox = this.findBestTarget(e);

			if(bestBox.target === null){
				if(this.currentDropTarget){
					this.currentDropTarget.onDragOut(e);
					this.previousDropTarget = this.currentDropTarget;
					this.currentDropTarget = null;
					// this.currentDropTargetPoints = null;
				}
				this.dropAcceptable = false;
				return;
			}

			if(this.currentDropTarget !== bestBox.target){
				if(this.currentDropTarget){
					this.previousDropTarget = this.currentDropTarget;
					this.currentDropTarget.onDragOut(e);
				}
				this.currentDropTarget = bestBox.target;
				// this.currentDropTargetPoints = bestBox.points;
				e.dragObjects = this.dragObjects;
				this.dropAcceptable = this.currentDropTarget.onDragOver(e);

			}else{
				if(this.dropAcceptable){
					this.currentDropTarget.onDragMove(e, this.dragObjects);
				}
			}
		}
	},

	findBestTarget: function(e) {
		var _this = this;
		var bestBox = new Object();
		bestBox.target = null;
		bestBox.points = null;
		dojo.lang.every(this.dropTargetDimensions, function(tmpDA) {
			if(!_this.isInsideBox(e, tmpDA))
				return true;
			bestBox.target = tmpDA[2];
			bestBox.points = tmpDA;
			// continue iterating only if _this.nestedTargets == true
			return Boolean(_this.nestedTargets);
		});

		return bestBox;
	},

	isInsideBox: function(e, coords){
		if(	(e.pageX > coords[0][0])&&
			(e.pageX < coords[1][0])&&
			(e.pageY > coords[0][1])&&
			(e.pageY < coords[1][1]) ){
			return true;
		}
		return false;
	},

	onMouseOver: function(e){
	},

	onMouseOut: function(e){
	}
});

dojo.dnd.dragManager = new dojo.dnd.HtmlDragManager();

// global namespace protection closure
(function(){
	var d = document;
	var dm = dojo.dnd.dragManager;
	// set up event handlers on the document
	dojo.event.connect(d, "onkeydown", 		dm, "onKeyDown");
	dojo.event.connect(d, "onmouseover",	dm, "onMouseOver");
	dojo.event.connect(d, "onmouseout", 	dm, "onMouseOut");
	dojo.event.connect(d, "onmousedown",	dm, "onMouseDown");
	dojo.event.connect(d, "onmouseup",		dm, "onMouseUp");
	// TODO: process scrolling of elements, not only window
	dojo.event.connect(window, "onscroll",	dm, "onScroll");
})();

__CPAN_FILE__ src/dnd/HtmlDragMove.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.dnd.HtmlDragMove");
dojo.provide("dojo.dnd.HtmlDragMoveSource");
dojo.provide("dojo.dnd.HtmlDragMoveObject");
dojo.require("dojo.dnd.*");

dojo.dnd.HtmlDragMoveSource = function(node, type){
	dojo.dnd.HtmlDragSource.call(this, node, type);
}
dojo.inherits(dojo.dnd.HtmlDragMoveSource, dojo.dnd.HtmlDragSource);
dojo.lang.extend(dojo.dnd.HtmlDragMoveSource, {
	onDragStart: function(){
		var dragObj =  new dojo.dnd.HtmlDragMoveObject(this.dragObject, this.type);
		if (this.constrainToContainer) {
			dragObj.constrainTo(this.constrainingContainer);
		}
		return dragObj;
	},
	/*
	 * see dojo.dnd.HtmlDragSource.onSelected
	 */
	onSelected: function() {
		for (var i=0; i<this.dragObjects.length; i++) {
			dojo.dnd.dragManager.selectedSources.push(new dojo.dnd.HtmlDragMoveSource(this.dragObjects[i]));
		}
	}
});

dojo.dnd.HtmlDragMoveObject = function(node, type){
	dojo.dnd.HtmlDragObject.call(this, node, type);
}
dojo.inherits(dojo.dnd.HtmlDragMoveObject, dojo.dnd.HtmlDragObject);
dojo.lang.extend(dojo.dnd.HtmlDragMoveObject, {
	onDragEnd: function(e){
		// shortly the browser will fire an onClick() event,
		// but since this was really a drag, just squelch it
		dojo.event.connect(this.domNode, "onclick", this, "squelchOnClick");
	},
	onDragStart: function(e){
		dojo.html.clearSelection();

		this.dragClone = this.domNode;

		this.scrollOffset = dojo.html.getScrollOffset();
		this.dragStartPosition = dojo.style.getAbsolutePosition(this.domNode, true);
		
		this.dragOffset = {y: this.dragStartPosition.y - e.pageY,
			x: this.dragStartPosition.x - e.pageX};

		this.containingBlockPosition = this.domNode.offsetParent ? 
			dojo.style.getAbsolutePosition(this.domNode.offsetParent, true) : {x:0, y:0};

		this.dragClone.style.position = "absolute";

		if (this.constrainToContainer) {
			this.constraints = this.getConstraints();
		}
	},
	/**
	 * Set the position of the drag node.  (x,y) is relative to <body>.
	 */
	setAbsolutePosition: function(x, y){
		// The drag clone is attached to it's constraining container so offset for that
		if(!this.disableY) { this.domNode.style.top = (y-this.containingBlockPosition.y) + "px"; }
		if(!this.disableX) { this.domNode.style.left = (x-this.containingBlockPosition.x) + "px"; }
	}
});

__CPAN_FILE__ src/dnd/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: ["dojo.dnd.DragAndDrop"],
	browser: ["dojo.dnd.HtmlDragAndDrop"],
	dashboard: ["dojo.dnd.HtmlDragAndDrop"]
});
dojo.provide("dojo.dnd.*");

__CPAN_FILE__ src/dnd/HtmlDragAndDrop.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.dnd.HtmlDragAndDrop");
dojo.provide("dojo.dnd.HtmlDragSource");
dojo.provide("dojo.dnd.HtmlDropTarget");
dojo.provide("dojo.dnd.HtmlDragObject");

dojo.require("dojo.dnd.HtmlDragManager");
dojo.require("dojo.dnd.DragAndDrop");

dojo.require("dojo.dom");
dojo.require("dojo.style");
dojo.require("dojo.html");
dojo.require("dojo.html.extras");
dojo.require("dojo.lang.extras");
dojo.require("dojo.lfx.*");
dojo.require("dojo.event");

dojo.dnd.HtmlDragSource = function(node, type){
	node = dojo.byId(node);
	this.dragObjects = [];
	this.constrainToContainer = false;
	if(node){
		this.domNode = node;
		this.dragObject = node;
		// register us
		dojo.dnd.DragSource.call(this);
		// set properties that might have been clobbered by the mixin
		this.type = (type)||(this.domNode.nodeName.toLowerCase());
	}
}
dojo.inherits(dojo.dnd.HtmlDragSource, dojo.dnd.DragSource);
dojo.lang.extend(dojo.dnd.HtmlDragSource, {
	dragClass: "", // CSS classname(s) applied to node when it is being dragged

	onDragStart: function(){
		var dragObj = new dojo.dnd.HtmlDragObject(this.dragObject, this.type);
		if(this.dragClass) { dragObj.dragClass = this.dragClass; }

		if (this.constrainToContainer) {
			dragObj.constrainTo(this.constrainingContainer || this.domNode.parentNode);
		}

		return dragObj;
	},

	setDragHandle: function(node){
		node = dojo.byId(node);
		dojo.dnd.dragManager.unregisterDragSource(this);
		this.domNode = node;
		dojo.dnd.dragManager.registerDragSource(this);
	},

	setDragTarget: function(node){
		this.dragObject = node;
	},

	constrainTo: function(container) {
		this.constrainToContainer = true;
		if (container) {
			this.constrainingContainer = container;
		}
	},
	
	/*
	*
	* see dojo.dnd.DragSource.onSelected
	*/
	onSelected: function() {
		for (var i=0; i<this.dragObjects.length; i++) {
			dojo.dnd.dragManager.selectedSources.push(new dojo.dnd.HtmlDragSource(this.dragObjects[i]));
		}
	},

	/**
	* Register elements that should be dragged along with
	* the actual DragSource.
	*
	* Example usage:
	* 	var dragSource = new dojo.dnd.HtmlDragSource(...);
	*	// add a single element
	*	dragSource.addDragObjects(dojo.byId('id1'));
	*	// add multiple elements to drag along
	*	dragSource.addDragObjects(dojo.byId('id2'), dojo.byId('id3'));
	*
	* el A dom node to add to the drag list.
	*/
	addDragObjects: function(/*DOMNode*/ el) {
		for (var i=0; i<arguments.length; i++) {
			this.dragObjects.push(arguments[i]);
		}
	}
});

dojo.dnd.HtmlDragObject = function(node, type){
	this.domNode = dojo.byId(node);
	this.type = type;
	this.constrainToContainer = false;
	this.dragSource = null;
}
dojo.inherits(dojo.dnd.HtmlDragObject, dojo.dnd.DragObject);
dojo.lang.extend(dojo.dnd.HtmlDragObject, {
	dragClass: "",
	opacity: 0.5,
	createIframe: true,		// workaround IE6 bug

	// if true, node will not move in X and/or Y direction
	disableX: false,
	disableY: false,

	createDragNode: function() {
		var node = this.domNode.cloneNode(true);
		if(this.dragClass) { dojo.html.addClass(node, this.dragClass); }
		if(this.opacity < 1) { dojo.style.setOpacity(node, this.opacity); }
		if(node.tagName.toLowerCase() == "tr"){
			// dojo.debug("Dragging table row")
			// Create a table for the cloned row
			var doc = this.domNode.ownerDocument;
			var table = doc.createElement("table");
			var tbody = doc.createElement("tbody");
			tbody.appendChild(node);
			table.appendChild(tbody);

			// Set a fixed width to the cloned TDs
			var domTds = this.domNode.childNodes;
			var cloneTds = node.childNodes;
			for(var i = 0; i < domTds.length; i++){
			    if((cloneTds[i])&&(cloneTds[i].style)){
				    cloneTds[i].style.width = dojo.style.getContentWidth(domTds[i]) + "px";
			    }
			}
			node = table;
		}

		if((dojo.render.html.ie55||dojo.render.html.ie60) && this.createIframe){
			with(node.style) {
				top="0px";
				left="0px";
			}
			var outer = document.createElement("div");
			outer.appendChild(node);
			this.bgIframe = new dojo.html.BackgroundIframe(outer);
			outer.appendChild(this.bgIframe.iframe);
			node = outer;
		}
		node.style.zIndex = 999;
		return node;
	},

	onDragStart: function(e){
		dojo.html.clearSelection();

		this.scrollOffset = dojo.html.getScrollOffset();
		this.dragStartPosition = dojo.style.getAbsolutePosition(this.domNode, true);

		this.dragOffset = {y: this.dragStartPosition.y - e.pageY,
			x: this.dragStartPosition.x - e.pageX};

		this.dragClone = this.createDragNode();

		this.containingBlockPosition = this.domNode.offsetParent ? 
			dojo.style.getAbsolutePosition(this.domNode.offsetParent) : {x:0, y:0};

		if (this.constrainToContainer) {
			this.constraints = this.getConstraints();
		}

		// set up for dragging
		with(this.dragClone.style){
			position = "absolute";
			top = this.dragOffset.y + e.pageY + "px";
			left = this.dragOffset.x + e.pageX + "px";
		}

		document.body.appendChild(this.dragClone);

		dojo.event.topic.publish('dragStart', { source: this } );
	},

	/** Return min/max x/y (relative to document.body) for this object) **/
	getConstraints: function() {
		if (this.constrainingContainer.nodeName.toLowerCase() == 'body') {
			var width = dojo.html.getViewportWidth();
			var height = dojo.html.getViewportHeight();
			var x = 0;
			var y = 0;
		} else {
			width = dojo.style.getContentWidth(this.constrainingContainer);
			height = dojo.style.getContentHeight(this.constrainingContainer);
			x =
				this.containingBlockPosition.x +
				dojo.style.getPixelValue(this.constrainingContainer, "padding-left", true) +
				dojo.style.getBorderExtent(this.constrainingContainer, "left");
			y =
				this.containingBlockPosition.y +
				dojo.style.getPixelValue(this.constrainingContainer, "padding-top", true) +
				dojo.style.getBorderExtent(this.constrainingContainer, "top");
		}

		return {
			minX: x,
			minY: y,
			maxX: x + width - dojo.style.getOuterWidth(this.domNode),
			maxY: y + height - dojo.style.getOuterHeight(this.domNode)
		}
	},

	updateDragOffset: function() {
		var scroll = dojo.html.getScrollOffset();
		if(scroll.y != this.scrollOffset.y) {
			var diff = scroll.y - this.scrollOffset.y;
			this.dragOffset.y += diff;
			this.scrollOffset.y = scroll.y;
		}
		if(scroll.x != this.scrollOffset.x) {
			var diff = scroll.x - this.scrollOffset.x;
			this.dragOffset.x += diff;
			this.scrollOffset.x = scroll.x;
		}
	},

	/** Moves the node to follow the mouse */
	onDragMove: function(e){
		this.updateDragOffset();
		var x = this.dragOffset.x + e.pageX;
		var y = this.dragOffset.y + e.pageY;

		if (this.constrainToContainer) {
			if (x < this.constraints.minX) { x = this.constraints.minX; }
			if (y < this.constraints.minY) { y = this.constraints.minY; }
			if (x > this.constraints.maxX) { x = this.constraints.maxX; }
			if (y > this.constraints.maxY) { y = this.constraints.maxY; }
		}

		this.setAbsolutePosition(x, y);

		dojo.event.topic.publish('dragMove', { source: this } );
	},

	/**
	 * Set the position of the drag clone.  (x,y) is relative to <body>.
	 */
	setAbsolutePosition: function(x, y){
		// The drag clone is attached to document.body so this is trivial
		if(!this.disableY) { this.dragClone.style.top = y + "px"; }
		if(!this.disableX) { this.dragClone.style.left = x + "px"; }
	},


	/**
	 * If the drag operation returned a success we reomve the clone of
	 * ourself from the original position. If the drag operation returned
	 * failure we slide back over to where we came from and end the operation
	 * with a little grace.
	 */
	onDragEnd: function(e){
		switch(e.dragStatus){

			case "dropSuccess":
				dojo.dom.removeNode(this.dragClone);
				this.dragClone = null;
				break;

			case "dropFailure": // slide back to the start
				var startCoords = dojo.style.getAbsolutePosition(this.dragClone, true);
				// offset the end so the effect can be seen
				var endCoords = [this.dragStartPosition.x + 1,
					this.dragStartPosition.y + 1];

				// animate
				var line = new dojo.lfx.Line(startCoords, endCoords);
				var anim = new dojo.lfx.Animation(500, line, dojo.lfx.easeOut);
				var dragObject = this;
				dojo.event.connect(anim, "onAnimate", function(e) {
					dragObject.dragClone.style.left = e[0] + "px";
					dragObject.dragClone.style.top = e[1] + "px";
				});
				dojo.event.connect(anim, "onEnd", function (e) {
					// pause for a second (not literally) and disappear
					dojo.lang.setTimeout(function() {
							dojo.dom.removeNode(dragObject.dragClone);
							// Allow drag clone to be gc'ed
							dragObject.dragClone = null;
						},
						200);
				});
				anim.play();
				break;
		}

		// shortly the browser will fire an onClick() event,
		// but since this was really a drag, just squelch it
		dojo.event.connect(this.domNode, "onclick", this, "squelchOnClick");

		dojo.event.topic.publish('dragEnd', { source: this } );
	},

	squelchOnClick: function(e){
		// squelch this onClick() event because it's the result of a drag (it's not a real click)
		e.preventDefault();

		// but if a real click comes along, allow it
		dojo.event.disconnect(this.domNode, "onclick", this, "squelchOnClick");
	},

	constrainTo: function(container) {
		this.constrainToContainer=true;
		if (container) {
			this.constrainingContainer = container;
		} else {
			this.constrainingContainer = this.domNode.parentNode;
		}
	}
});

dojo.dnd.HtmlDropTarget = function(node, types){
	if (arguments.length == 0) { return; }
	this.domNode = dojo.byId(node);
	dojo.dnd.DropTarget.call(this);
	if(types && dojo.lang.isString(types)) {
		types = [types];
	}
	this.acceptedTypes = types || [];
}
dojo.inherits(dojo.dnd.HtmlDropTarget, dojo.dnd.DropTarget);

dojo.lang.extend(dojo.dnd.HtmlDropTarget, {
	onDragOver: function(e){
		if(!this.accepts(e.dragObjects)){ return false; }

		// cache the positions of the child nodes
		this.childBoxes = [];
		for (var i = 0, child; i < this.domNode.childNodes.length; i++) {
			child = this.domNode.childNodes[i];
			if (child.nodeType != dojo.dom.ELEMENT_NODE) { continue; }
			var pos = dojo.style.getAbsolutePosition(child, true);
			var height = dojo.style.getInnerHeight(child);
			var width = dojo.style.getInnerWidth(child);
			this.childBoxes.push({top: pos.y, bottom: pos.y+height,
				left: pos.x, right: pos.x+width, node: child});
		}

		// TODO: use dummy node

		return true;
	},

	_getNodeUnderMouse: function(e){
		// find the child
		for (var i = 0, child; i < this.childBoxes.length; i++) {
			with (this.childBoxes[i]) {
				if (e.pageX >= left && e.pageX <= right &&
					e.pageY >= top && e.pageY <= bottom) { return i; }
			}
		}

		return -1;
	},

	createDropIndicator: function() {
		this.dropIndicator = document.createElement("div");
		with (this.dropIndicator.style) {
			position = "absolute";
			zIndex = 999;
			borderTopWidth = "1px";
			borderTopColor = "black";
			borderTopStyle = "solid";
			width = dojo.style.getInnerWidth(this.domNode) + "px";
			left = dojo.style.getAbsoluteX(this.domNode, true) + "px";
		}
	},

	onDragMove: function(e, dragObjects){
		var i = this._getNodeUnderMouse(e);

		if(!this.dropIndicator){
			this.createDropIndicator();
		}

		if(i < 0) {
			if(this.childBoxes.length) {
				var before = (dojo.html.gravity(this.childBoxes[0].node, e) & dojo.html.gravity.NORTH);
			} else {
				var before = true;
			}
		} else {
			var child = this.childBoxes[i];
			var before = (dojo.html.gravity(child.node, e) & dojo.html.gravity.NORTH);
		}
		this.placeIndicator(e, dragObjects, i, before);

		if(!dojo.html.hasParent(this.dropIndicator)) {
			document.body.appendChild(this.dropIndicator);
		}
	},

	/**
	 * Position the horizontal line that indicates "insert between these two items"
	 */
	placeIndicator: function(e, dragObjects, boxIndex, before) {
		with(this.dropIndicator.style){
			if (boxIndex < 0) {
				if (this.childBoxes.length) {
					top = (before ? this.childBoxes[0].top
						: this.childBoxes[this.childBoxes.length - 1].bottom) + "px";
				} else {
					top = dojo.style.getAbsoluteY(this.domNode, true) + "px";
				}
			} else {
				var child = this.childBoxes[boxIndex];
				top = (before ? child.top : child.bottom) + "px";
			}
		}
	},

	onDragOut: function(e) {
		if(this.dropIndicator) {
			dojo.dom.removeNode(this.dropIndicator);
			delete this.dropIndicator;
		}
	},

	/**
	 * Inserts the DragObject as a child of this node relative to the
	 * position of the mouse.
	 *
	 * @return true if the DragObject was inserted, false otherwise
	 */
	onDrop: function(e){
		this.onDragOut(e);

		var i = this._getNodeUnderMouse(e);

		if (i < 0) {
			if (this.childBoxes.length) {
				if (dojo.html.gravity(this.childBoxes[0].node, e) & dojo.html.gravity.NORTH) {
					return this.insert(e, this.childBoxes[0].node, "before");
				} else {
					return this.insert(e, this.childBoxes[this.childBoxes.length-1].node, "after");
				}
			}
			return this.insert(e, this.domNode, "append");
		}

		var child = this.childBoxes[i];
		if (dojo.html.gravity(child.node, e) & dojo.html.gravity.NORTH) {
			return this.insert(e, child.node, "before");
		} else {
			return this.insert(e, child.node, "after");
		}
	},

	insert: function(e, refNode, position) {
		var node = e.dragObject.domNode;

		if(position == "before") {
			return dojo.html.insertBefore(node, refNode);
		} else if(position == "after") {
			return dojo.html.insertAfter(node, refNode);
		} else if(position == "append") {
			refNode.appendChild(node);
			return true;
		}

		return false;
	}
});

__CPAN_FILE__ src/dnd/TreeDragAndDrop.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/**
 * TreeDrag* specialized on managing subtree drags
 * It selects nodes and visualises what's going on,
 * but delegates real actions upon tree to the controller
 *
 * This code is considered a part of controller
*/

dojo.provide("dojo.dnd.TreeDragAndDrop");
dojo.provide("dojo.dnd.TreeDragSource");
dojo.provide("dojo.dnd.TreeDropTarget");
dojo.provide("dojo.dnd.TreeDNDController");

dojo.require("dojo.dnd.HtmlDragAndDrop");
dojo.require("dojo.lang.func");
dojo.require("dojo.lang.array");
dojo.require("dojo.lang.extras");

dojo.dnd.TreeDragSource = function(node, syncController, type, treeNode){
	this.controller = syncController;
	this.treeNode = treeNode;

	dojo.dnd.HtmlDragSource.call(this, node, type);
}

dojo.inherits(dojo.dnd.TreeDragSource, dojo.dnd.HtmlDragSource);

dojo.lang.extend(dojo.dnd.TreeDragSource, {
	onDragStart: function(){
		/* extend adds functions to prototype */
		var dragObject = dojo.dnd.HtmlDragSource.prototype.onDragStart.call(this);
		//dojo.debugShallow(dragObject)

		dragObject.treeNode = this.treeNode;

		dragObject.onDragStart = dojo.lang.hitch(dragObject, function(e) {

			/* save selection */
			this.savedSelectedNode = this.treeNode.tree.selector.selectedNode;
			if (this.savedSelectedNode) {
				this.savedSelectedNode.unMarkSelected();
			}

			var result = dojo.dnd.HtmlDragObject.prototype.onDragStart.apply(this, arguments);


			/* remove background grid from cloned object */
			var cloneGrid = this.dragClone.getElementsByTagName('img');
			for(var i=0; i<cloneGrid.length; i++) {
				cloneGrid.item(i).style.backgroundImage='url()';
			}

			return result;


		});

		dragObject.onDragEnd = function(e) {

			/* restore selection */
			if (this.savedSelectedNode) {
				this.savedSelectedNode.markSelected();
			}
			//dojo.debug(e.dragStatus);

			return dojo.dnd.HtmlDragObject.prototype.onDragEnd.apply(this, arguments);
		}
		//dojo.debug(dragObject.domNode.outerHTML)


		return dragObject;
	},

	onDragEnd: function(e){


		 var res = dojo.dnd.HtmlDragSource.prototype.onDragEnd.call(this, e);


		 return res;
	}
});

// .......................................

dojo.dnd.TreeDropTarget = function(domNode, controller, type, treeNode, DNDMode){

	this.treeNode = treeNode;
	this.controller = controller; // I will sync-ly process drops
	this.DNDMode = DNDMode;

	dojo.dnd.HtmlDropTarget.apply(this, [domNode, type]);
}

dojo.inherits(dojo.dnd.TreeDropTarget, dojo.dnd.HtmlDropTarget);

dojo.lang.extend(dojo.dnd.TreeDropTarget, {

	autoExpandDelay: 1500,
	autoExpandTimer: null,


	position: null,

	indicatorStyle: "2px black solid",

	showIndicator: function(position) {

		// do not change style too often, cause of blinking possible
		if (this.position == position) {
			return;
		}

		//dojo.debug(position)

		this.hideIndicator();

		this.position = position;

		if (position == "before") {
			this.treeNode.labelNode.style.borderTop = this.indicatorStyle;
		} else if (position == "after") {
			this.treeNode.labelNode.style.borderBottom = this.indicatorStyle;
		} else if (position == "onto") {
			this.treeNode.markSelected();
		}


	},

	hideIndicator: function() {
		this.treeNode.labelNode.style.borderBottom="";
		this.treeNode.labelNode.style.borderTop="";
		this.treeNode.unMarkSelected();
		this.position = null;
	},



	// is the target possibly ok ?
	// This function is run on dragOver, but drop possibility is also determined by position over node
	// that's why acceptsWithPosition is called
	// doesnt take index into account ( can change while moving mouse w/o changing target )


	/**
	 * Coarse (tree-level) access check.
	 * We can't determine real accepts status w/o position
	*/
	onDragOver: function(e){
//dojo.debug("onDragOver for "+e);


		var accepts = dojo.dnd.HtmlDropTarget.prototype.onDragOver.apply(this, arguments);

		//dojo.debug("TreeDropTarget.onDragOver accepts:"+accepts)

		if (accepts && this.treeNode.isFolder && !this.treeNode.isExpanded) {
			this.setAutoExpandTimer();
		}

		return accepts;
	},

	/* Parent.onDragOver calls this function to get accepts status */
	accepts: function(dragObjects) {

		var accepts = dojo.dnd.HtmlDropTarget.prototype.accepts.apply(this, arguments);

		if (!accepts) return false;

		var sourceTreeNode = dragObjects[0].treeNode;

		if (dojo.lang.isUndefined(sourceTreeNode) || !sourceTreeNode || !sourceTreeNode.isTreeNode) {
			dojo.raise("Source is not TreeNode or not found");
		}

		if (sourceTreeNode === this.treeNode) return false;

		return true;
	},



	setAutoExpandTimer: function() {
		// set up autoexpand timer
		var _this = this;

		var autoExpand = function () {
			if (dojo.dnd.dragManager.currentDropTarget === _this) {
				_this.controller.expand(_this.treeNode);
			}
		}

		this.autoExpandTimer = dojo.lang.setTimeout(autoExpand, _this.autoExpandDelay);
	},


	getAcceptPosition: function(e, sourceTreeNode) {

		var DNDMode = this.DNDMode;

		if (DNDMode & dojo.widget.Tree.prototype.DNDModes.ONTO &&
			// check if ONTO is allowed localy
			!(
			  !this.treeNode.actionIsDisabled(dojo.widget.TreeNode.prototype.actions.ADDCHILD) // check dynamically cause may change w/o regeneration of dropTarget
			  && sourceTreeNode.parent !== this.treeNode
			  && this.controller.canMove(sourceTreeNode, this.treeNode)
			 )
		) {
			// disable ONTO if can't move
			DNDMode &= ~dojo.widget.Tree.prototype.DNDModes.ONTO;
		}


		var position = this.getPosition(e, DNDMode);

		//dojo.debug(DNDMode & +" : "+position);


		// if onto is here => it was allowed before, no accept check is needed
		if (position=="onto" ||
			(!this.isAdjacentNode(sourceTreeNode, position)
			 && this.controller.canMove(sourceTreeNode, this.treeNode.parent)
			)
		) {
			return position;
		} else {
			return false;
		}

	},

	onDragOut: function(e) {
		this.clearAutoExpandTimer();

		this.hideIndicator();
	},


	clearAutoExpandTimer: function() {
		if (this.autoExpandTimer) {
			clearTimeout(this.autoExpandTimer);
			this.autoExpandTimer = null;
		}
	},



	onDragMove: function(e, dragObjects){

		var sourceTreeNode = dragObjects[0].treeNode;

		var position = this.getAcceptPosition(e, sourceTreeNode);

		if (position) {
			this.showIndicator(position);
		}

	},

	isAdjacentNode: function(sourceNode, position) {

		if (sourceNode === this.treeNode) return true;
		if (sourceNode.getNextSibling() === this.treeNode && position=="before") return true;
		if (sourceNode.getPreviousSibling() === this.treeNode && position=="after") return true;

		return false;
	},


	/* get DNDMode and see which position e fits */
	getPosition: function(e, DNDMode) {
		node = dojo.byId(this.treeNode.labelNode);
		var mousey = e.pageY || e.clientY + document.body.scrollTop;
		var nodey = dojo.html.getAbsoluteY(node);
		var height = dojo.html.getInnerHeight(node);

		var relY = mousey - nodey;
		var p = relY / height;

		var position = ""; // "" <=> forbidden
		if (DNDMode & dojo.widget.Tree.prototype.DNDModes.ONTO
		  && DNDMode & dojo.widget.Tree.prototype.DNDModes.BETWEEN) {
			if (p<=0.3) {
				position = "before";
			} else if (p<=0.7) {
				position = "onto";
			} else {
				position = "after";
			}
		} else if (DNDMode & dojo.widget.Tree.prototype.DNDModes.BETWEEN) {
			if (p<=0.5) {
				position = "before";
			} else {
				position = "after";
			}
		}
		else if (DNDMode & dojo.widget.Tree.prototype.DNDModes.ONTO) {
			position = "onto";
		}


		return position;
	},



	getTargetParentIndex: function(sourceTreeNode, position) {

		var index = position == "before" ? this.treeNode.getParentIndex() : this.treeNode.getParentIndex()+1;
		if (this.treeNode.parent === sourceTreeNode.parent
		  && this.treeNode.getParentIndex() > sourceTreeNode.getParentIndex()) {
		  	index--;  // dragging a node is different for simple move bacause of before-after issues
		}

		return index;
	},


	onDrop: function(e){
		// onDragOut will clean position


		var position = this.position;

//dojo.debug(position);

		this.onDragOut(e);

		var sourceTreeNode = e.dragObject.treeNode;

		if (!dojo.lang.isObject(sourceTreeNode)) {
			dojo.raise("TreeNode not found in dragObject")
		}

		if (position == "onto") {
			return this.controller.move(sourceTreeNode, this.treeNode, 0);
		} else {
			var index = this.getTargetParentIndex(sourceTreeNode, position);
			return this.controller.move(sourceTreeNode, this.treeNode.parent, index);
		}

		//dojo.debug('drop2');



	}


});



dojo.dnd.TreeDNDController = function(treeController) {

	// I use this controller to perform actions
	this.treeController = treeController;

	this.dragSources = {};

	this.dropTargets = {};

}

dojo.lang.extend(dojo.dnd.TreeDNDController, {


	listenTree: function(tree) {
		//dojo.debug("Listen tree "+tree);
		dojo.event.topic.subscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
		dojo.event.topic.subscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
		dojo.event.topic.subscribe(tree.eventNames.moveTo, this, "onMoveTo");
		dojo.event.topic.subscribe(tree.eventNames.addChild, this, "onAddChild");
		dojo.event.topic.subscribe(tree.eventNames.removeNode, this, "onRemoveNode");
		dojo.event.topic.subscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");
	},


	unlistenTree: function(tree) {
		//dojo.debug("Listen tree "+tree);
		dojo.event.topic.unsubscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
		dojo.event.topic.unsubscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
		dojo.event.topic.unsubscribe(tree.eventNames.moveTo, this, "onMoveTo");
		dojo.event.topic.unsubscribe(tree.eventNames.addChild, this, "onAddChild");
		dojo.event.topic.unsubscribe(tree.eventNames.removeNode, this, "onRemoveNode");
		dojo.event.topic.unsubscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");
	},

	onTreeDestroy: function(message) {
		this.unlistenTree(message.source);
		// I'm not widget so don't use destroy() call and dieWithTree
	},

	onCreateDOMNode: function(message) {
		this.registerDNDNode(message.source);
	},

	onAddChild: function(message) {
		this.registerDNDNode(message.child);
	},

	onMoveFrom: function(message) {
		var _this = this;
		dojo.lang.forEach(
			message.child.getDescendants(),
			function(node) { _this.unregisterDNDNode(node); }
		);
	},

	onMoveTo: function(message) {
		var _this = this;
		dojo.lang.forEach(
			message.child.getDescendants(),
			function(node) { _this.registerDNDNode(node); }
		);
	},

	/**
	 * Controller(node model) creates DNDNodes because it passes itself to node for synchroneous drops processing
	 * I can't process DnD with events cause an event can't return result success/false
	*/
	registerDNDNode: function(node) {
		if (!node.tree.DNDMode) return;

//dojo.debug("registerDNDNode "+node);

		/* I drag label, not domNode, because large domNodes are very slow to copy and large to drag */

		var source = null;
		var target = null;

		if (!node.actionIsDisabled(node.actions.MOVE)) {
			//dojo.debug("reg source")
			var source = new dojo.dnd.TreeDragSource(node.labelNode, this, node.tree.widgetId, node);
			this.dragSources[node.widgetId] = source;
		}

		var target = new dojo.dnd.TreeDropTarget(node.labelNode, this.treeController, node.tree.DNDAcceptTypes, node, node.tree.DNDMode);

		this.dropTargets[node.widgetId] = target;

	},


	unregisterDNDNode: function(node) {

		if (this.dragSources[node.widgetId]) {
			dojo.dnd.dragManager.unregisterDragSource(this.dragSources[node.widgetId]);
			delete this.dragSources[node.widgetId];
		}

		if (this.dropTargets[node.widgetId]) {
			dojo.dnd.dragManager.unregisterDropTarget(this.dropTargets[node.widgetId]);
			delete this.dropTargets[node.widgetId];
		}
	}





});

__CPAN_DIR__ src/graphics
__CPAN_FILE__ src/graphics/color.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.graphics.color");
dojo.require("dojo.lang.array");

// TODO: rewrite the "x2y" methods to take advantage of the parsing
//       abilities of the Color object. Also, beef up the Color
//       object (as possible) to parse most common formats

// takes an r, g, b, a(lpha) value, [r, g, b, a] array, "rgb(...)" string, hex string (#aaa, #aaaaaa, aaaaaaa)
dojo.graphics.color.Color = function(r, g, b, a) {
	// dojo.debug("r:", r[0], "g:", r[1], "b:", r[2]);
	if(dojo.lang.isArray(r)) {
		this.r = r[0];
		this.g = r[1];
		this.b = r[2];
		this.a = r[3]||1.0;
	} else if(dojo.lang.isString(r)) {
		var rgb = dojo.graphics.color.extractRGB(r);
		this.r = rgb[0];
		this.g = rgb[1];
		this.b = rgb[2];
		this.a = g||1.0;
	} else if(r instanceof dojo.graphics.color.Color) {
		this.r = r.r;
		this.b = r.b;
		this.g = r.g;
		this.a = r.a;
	} else {
		this.r = r;
		this.g = g;
		this.b = b;
		this.a = a;
	}
}

dojo.graphics.color.Color.fromArray = function(arr) {
	return new dojo.graphics.color.Color(arr[0], arr[1], arr[2], arr[3]);
}

dojo.lang.extend(dojo.graphics.color.Color, {
	toRgb: function(includeAlpha) {
		if(includeAlpha) {
			return this.toRgba();
		} else {
			return [this.r, this.g, this.b];
		}
	},

	toRgba: function() {
		return [this.r, this.g, this.b, this.a];
	},

	toHex: function() {
		return dojo.graphics.color.rgb2hex(this.toRgb());
	},

	toCss: function() {
		return "rgb(" + this.toRgb().join() + ")";
	},

	toString: function() {
		return this.toHex(); // decent default?
	},

	blend: function(color, weight) {
		return dojo.graphics.color.blend(this.toRgb(), new dojo.graphics.color.Color(color).toRgb(), weight);
	}
});

dojo.graphics.color.named = {
	white:      [255,255,255],
	black:      [0,0,0],
	red:        [255,0,0],
	green:	    [0,255,0],
	blue:       [0,0,255],
	navy:       [0,0,128],
	gray:       [128,128,128],
	silver:     [192,192,192]
};

// blend colors a and b (both as RGB array or hex strings) with weight from -1 to +1, 0 being a 50/50 blend
dojo.graphics.color.blend = function(a, b, weight) {
	if(typeof a == "string") { return dojo.graphics.color.blendHex(a, b, weight); }
	if(!weight) { weight = 0; }
	else if(weight > 1) { weight = 1; }
	else if(weight < -1) { weight = -1; }
	var c = new Array(3);
	for(var i = 0; i < 3; i++) {
		var half = Math.abs(a[i] - b[i])/2;
		c[i] = Math.floor(Math.min(a[i], b[i]) + half + (half * weight));
	}
	return c;
}

// very convenient blend that takes and returns hex values
// (will get called automatically by blend when blend gets strings)
dojo.graphics.color.blendHex = function(a, b, weight) {
	return dojo.graphics.color.rgb2hex(dojo.graphics.color.blend(dojo.graphics.color.hex2rgb(a), dojo.graphics.color.hex2rgb(b), weight));
}

// get RGB array from css-style color declarations
dojo.graphics.color.extractRGB = function(color) {
	var hex = "0123456789abcdef";
	color = color.toLowerCase();
	if( color.indexOf("rgb") == 0 ) {
		var matches = color.match(/rgba*\((\d+), *(\d+), *(\d+)/i);
		var ret = matches.splice(1, 3);
		return ret;
	} else {
		var colors = dojo.graphics.color.hex2rgb(color);
		if(colors) {
			return colors;
		} else {
			// named color (how many do we support?)
			return dojo.graphics.color.named[color] || [255, 255, 255];
		}
	}
}

dojo.graphics.color.hex2rgb = function(hex) {
	var hexNum = "0123456789ABCDEF";
	var rgb = new Array(3);
	if( hex.indexOf("#") == 0 ) { hex = hex.substring(1); }
	hex = hex.toUpperCase();
	if(hex.replace(new RegExp("["+hexNum+"]", "g"), "") != "") {
		return null;
	}
	if( hex.length == 3 ) {
		rgb[0] = hex.charAt(0) + hex.charAt(0)
		rgb[1] = hex.charAt(1) + hex.charAt(1)
		rgb[2] = hex.charAt(2) + hex.charAt(2);
	} else {
		rgb[0] = hex.substring(0, 2);
		rgb[1] = hex.substring(2, 4);
		rgb[2] = hex.substring(4);
	}
	for(var i = 0; i < rgb.length; i++) {
		rgb[i] = hexNum.indexOf(rgb[i].charAt(0)) * 16 + hexNum.indexOf(rgb[i].charAt(1));
	}
	return rgb;
}

dojo.graphics.color.rgb2hex = function(r, g, b) {
	if(dojo.lang.isArray(r)) {
		g = r[1] || 0;
		b = r[2] || 0;
		r = r[0] || 0;
	}
	var ret = dojo.lang.map([r, g, b], function(x) {
		x = new Number(x);
		var s = x.toString(16);
		while(s.length < 2) { s = "0" + s; }
		return s;
	});
	ret.unshift("#");
	return ret.join("");
}

__CPAN_FILE__ src/graphics/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	browser:	["dojo.graphics.htmlEffects"],
	dashboard:	["dojo.graphics.htmlEffects"]
});
dojo.provide("dojo.graphics.*");

__CPAN_FILE__ src/graphics/Colorspace.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.graphics.Colorspace");

dojo.require("dojo.lang");
dojo.require("dojo.math.matrix");

//
// to convert to YUV:
//   c.whitePoint = 'D65';
//   c.RGBWorkingSpace = 'pal_secam_rgb';
//   var out = c.convert([r,g,b], 'RGB', 'XYZ');
//
// to convert to YIQ:
//   c.whitePoint = 'D65';
//   c.RGBWorkingSpace = 'ntsc_rgb';
//   var out = c.convert([r,g,b], 'RGB', 'XYZ');
//

dojo.graphics.Colorspace =function(){

	this.whitePoint = 'D65';
	this.stdObserver = '10';
	this.chromaticAdaptationAlg = 'bradford';
	this.RGBWorkingSpace = 's_rgb';
	this.useApproxCIELabMapping = 1; // see http://www.brucelindbloom.com/LContinuity.html

	this.chainMaps = {
		'RGB_to_xyY'  : ['XYZ'],
		'xyY_to_RGB'  : ['XYZ'],
		'RGB_to_Lab'  : ['XYZ'],
		'Lab_to_RGB'  : ['XYZ'],
		'RGB_to_LCHab': ['XYZ', 'Lab'],
		'LCHab_to_RGB': ['Lab'],
		'xyY_to_Lab'  : ['XYZ'],
		'Lab_to_xyY'  : ['XYZ'],
		'XYZ_to_LCHab': ['Lab'],
		'LCHab_to_XYZ': ['Lab'],
		'xyY_to_LCHab': ['XYZ', 'Lab'],
		'LCHab_to_xyY': ['Lab', 'XYZ'],
		'RGB_to_Luv'  : ['XYZ'],
		'Luv_to_RGB'  : ['XYZ'],
		'xyY_to_Luv'  : ['XYZ'],
		'Luv_to_xyY'  : ['XYZ'],
		'Lab_to_Luv'  : ['XYZ'],
		'Luv_to_Lab'  : ['XYZ'],
		'LCHab_to_Luv': ['Lab', 'XYZ'],
		'Luv_to_LCHab': ['XYZ', 'Lab'],
		'RGB_to_LCHuv'  : ['XYZ', 'Luv'],
		'LCHuv_to_RGB'  : ['Luv', 'XYZ'],
		'XYZ_to_LCHuv'  : ['Luv'],
		'LCHuv_to_XYZ'  : ['Luv'],
		'xyY_to_LCHuv'  : ['XYZ', 'Luv'],
		'LCHuv_to_xyY'  : ['Luv', 'XYZ'],
		'Lab_to_LCHuv'  : ['XYZ', 'Luv'],
		'LCHuv_to_Lab'  : ['Luv', 'XYZ'],
		'LCHab_to_LCHuv': ['Lab', 'XYZ', 'Luv'],
		'LCHuv_to_LCHab': ['Luv', 'XYZ', 'Lab'],
		'XYZ_to_CMY'    : ['RGB'],
		'CMY_to_XYZ'    : ['RGB'],
		'xyY_to_CMY'    : ['RGB'],
		'CMY_to_xyY'    : ['RGB'],
		'Lab_to_CMY'    : ['RGB'],
		'CMY_to_Lab'    : ['RGB'],
		'LCHab_to_CMY'  : ['RGB'],
		'CMY_to_LCHab'  : ['RGB'],
		'Luv_to_CMY'    : ['RGB'],
		'CMY_to_Luv'    : ['RGB'],
		'LCHuv_to_CMY'  : ['RGB'],
		'CMY_to_LCHuv'  : ['RGB'],
		'XYZ_to_HSL'    : ['RGB'],
		'HSL_to_XYZ'    : ['RGB'],
		'xyY_to_HSL'    : ['RGB'],
		'HSL_to_xyY'    : ['RGB'],
		'Lab_to_HSL'    : ['RGB'],
		'HSL_to_Lab'    : ['RGB'],
		'LCHab_to_HSL'  : ['RGB'],
		'HSL_to_LCHab'  : ['RGB'],
		'Luv_to_HSL'    : ['RGB'],
		'HSL_to_Luv'    : ['RGB'],
		'LCHuv_to_HSL'  : ['RGB'],
		'HSL_to_LCHuv'  : ['RGB'],
		'CMY_to_HSL'    : ['RGB'],
		'HSL_to_CMY'    : ['RGB'],
		'CMYK_to_HSL'   : ['RGB'],
		'HSL_to_CMYK'   : ['RGB'],
		'XYZ_to_HSV'    : ['RGB'],
		'HSV_to_XYZ'    : ['RGB'],
		'xyY_to_HSV'    : ['RGB'],
		'HSV_to_xyY'    : ['RGB'],
		'Lab_to_HSV'    : ['RGB'],
		'HSV_to_Lab'    : ['RGB'],
		'LCHab_to_HSV'  : ['RGB'],
		'HSV_to_LCHab'  : ['RGB'],
		'Luv_to_HSV'    : ['RGB'],
		'HSV_to_Luv'    : ['RGB'],
		'LCHuv_to_HSV'  : ['RGB'],
		'HSV_to_LCHuv'  : ['RGB'],
		'CMY_to_HSV'    : ['RGB'],
		'HSV_to_CMY'    : ['RGB'],
		'CMYK_to_HSV'   : ['RGB'],
		'HSV_to_CMYK'   : ['RGB'],
		'HSL_to_HSV'    : ['RGB'],
		'HSV_to_HSL'    : ['RGB'],
		'XYZ_to_CMYK'   : ['RGB'],
		'CMYK_to_XYZ'   : ['RGB'],
		'xyY_to_CMYK'   : ['RGB'],
		'CMYK_to_xyY'   : ['RGB'],
		'Lab_to_CMYK'   : ['RGB'],
		'CMYK_to_Lab'   : ['RGB'],
		'LCHab_to_CMYK' : ['RGB'],
		'CMYK_to_LCHab' : ['RGB'],
		'Luv_to_CMYK'   : ['RGB'],
		'CMYK_to_Luv'   : ['RGB'],
		'LCHuv_to_CMYK' : ['RGB'],
		'CMYK_to_LCHuv' : ['RGB']
	};


	return this;
}

dojo.graphics.Colorspace.prototype.convert = function(col, model_from, model_to){

	var k = model_from+'_to_'+model_to;

	if (this[k]){
		return this[k](col);
	}else{
		if (this.chainMaps[k]){

			var cur = model_from;
			var models = this.chainMaps[k].concat();
			models.push(model_to);

			for(var i=0; i<models.length; i++){

				col = this.convert(col, cur, models[i]);
				cur = models[i];
			}

			return col;

		}else{

			dojo.debug("Can't convert from "+model_from+' to '+model_to);
		}
	}
}

dojo.graphics.Colorspace.prototype.munge = function(keys, args){

	if (dojo.lang.isArray(args[0])){
		args = args[0];
	}

	var out = new Array();

	for (var i=0; i<keys.length; i++){
		out[keys.charAt(i)] = args[i];
	}

	return out;
}

dojo.graphics.Colorspace.prototype.getWhitePoint = function(){

	var x = 0;
	var y = 0;
	var t = 0;

	// ref: http://en.wikipedia.org/wiki/White_point
	// TODO: i need some good/better white point values

	switch(this.stdObserver){
		case '2' :
			switch(this.whitePoint){
				case 'E'   : x=1/3    ; y=1/3    ; t=5400; break; //Equal energy
				case 'D50' : x=0.34567; y=0.35850; t=5000; break;
				case 'D55' : x=0.33242; y=0.34743; t=5500; break;
				case 'D65' : x=0.31271; y=0.32902; t=6500; break;
				case 'D75' : x=0.29902; y=0.31485; t=7500; break;
				case 'A'   : x=0.44757; y=0.40745; t=2856; break; //Incandescent tungsten
				case 'B'   : x=0.34842; y=0.35161; t=4874; break;
				case 'C'   : x=0.31006; y=0.31616; t=6774; break;
				case '9300': x=0.28480; y=0.29320; t=9300; break; //Blue phosphor monitors
				case 'F2'  : x=0.37207; y=0.37512; t=4200; break; //Cool White Fluorescent
				case 'F7'  : x=0.31285; y=0.32918; t=6500; break; //Narrow Band Daylight Fluorescent
				case 'F11' : x=0.38054; y=0.37691; t=4000; break; //Narrow Band White Fluorescent
				default: dojo.debug('White point '+this.whitePoint+" isn't defined for Std. Observer "+this.strObserver);
			};
			break;
		case '10' :
			switch(this.whitePoint){
				case 'E'   : x=1/3    ; y=1/3    ; t=5400; break; //Equal energy
				case 'D50' : x=0.34773; y=0.35952; t=5000; break;
				case 'D55' : x=0.33411; y=0.34877; t=5500; break;
				case 'D65' : x=0.31382; y=0.33100; t=6500; break;
				case 'D75' : x=0.29968; y=0.31740; t=7500; break;
				case 'A'   : x=0.45117; y=0.40594; t=2856; break; //Incandescent tungsten
				case 'B'   : x=0.3498 ; y=0.3527 ; t=4874; break;
				case 'C'   : x=0.31039; y=0.31905; t=6774; break;
				case 'F2'  : x=0.37928; y=0.36723; t=4200; break; //Cool White Fluorescent
				case 'F7'  : x=0.31565; y=0.32951; t=6500; break; //Narrow Band Daylight Fluorescent
				case 'F11' : x=0.38543; y=0.37110; t=4000; break; //Narrow Band White Fluorescent
				default: dojo.debug('White point '+this.whitePoint+" isn't defined for Std. Observer "+this.strObserver);
			};
			break;
		default:
			dojo.debug("Std. Observer "+this.strObserver+" isn't defined");
	}

	var z = 1 - x - y;

	var wp = {'x':x, 'y':y, 'z':z, 't':t};

	wp.Y = 1;

	var XYZ = this.xyY_to_XYZ([wp.x, wp.y, wp.Y]);

	wp.X = XYZ[0];
	wp.Y = XYZ[1];
	wp.Z = XYZ[2];

	return wp
}

dojo.graphics.Colorspace.prototype.getPrimaries = function(){

	// ref: http://www.fho-emden.de/~hoffmann/ciexyz29082000.pdf
	// ref: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html

	var m = [];

	switch(this.RGBWorkingSpace){

		case 'adobe_rgb_1998'	: m = [2.2, 'D65', 0.6400, 0.3300, 0.297361, 0.2100, 0.7100, 0.627355, 0.1500, 0.0600, 0.075285]; break;
		case 'apple_rgb'	: m = [1.8, 'D65', 0.6250, 0.3400, 0.244634, 0.2800, 0.5950, 0.672034, 0.1550, 0.0700, 0.083332]; break;
		case 'best_rgb'		: m = [2.2, 'D50', 0.7347, 0.2653, 0.228457, 0.2150, 0.7750, 0.737352, 0.1300, 0.0350, 0.034191]; break;
		case 'beta_rgb'		: m = [2.2, 'D50', 0.6888, 0.3112, 0.303273, 0.1986, 0.7551, 0.663786, 0.1265, 0.0352, 0.032941]; break;
		case 'bruce_rgb'	: m = [2.2, 'D65', 0.6400, 0.3300, 0.240995, 0.2800, 0.6500, 0.683554, 0.1500, 0.0600, 0.075452]; break;
		case 'cie_rgb'		: m = [2.2, 'E'  , 0.7350, 0.2650, 0.176204, 0.2740, 0.7170, 0.812985, 0.1670, 0.0090, 0.010811]; break;
		case 'color_match_rgb'	: m = [1.8, 'D50', 0.6300, 0.3400, 0.274884, 0.2950, 0.6050, 0.658132, 0.1500, 0.0750, 0.066985]; break;
		case 'don_rgb_4'	: m = [2.2, 'D50', 0.6960, 0.3000, 0.278350, 0.2150, 0.7650, 0.687970, 0.1300, 0.0350, 0.033680]; break;
		case 'eci_rgb'		: m = [1.8, 'D50', 0.6700, 0.3300, 0.320250, 0.2100, 0.7100, 0.602071, 0.1400, 0.0800, 0.077679]; break;
		case 'ekta_space_ps5'	: m = [2.2, 'D50', 0.6950, 0.3050, 0.260629, 0.2600, 0.7000, 0.734946, 0.1100, 0.0050, 0.004425]; break;
		case 'ntsc_rgb'		: m = [2.2, 'C'  , 0.6700, 0.3300, 0.298839, 0.2100, 0.7100, 0.586811, 0.1400, 0.0800, 0.114350]; break;
		case 'pal_secam_rgb'	: m = [2.2, 'D65', 0.6400, 0.3300, 0.222021, 0.2900, 0.6000, 0.706645, 0.1500, 0.0600, 0.071334]; break;
		case 'pro_photo_rgb'	: m = [1.8, 'D50', 0.7347, 0.2653, 0.288040, 0.1596, 0.8404, 0.711874, 0.0366, 0.0001, 0.000086]; break;
		case 'smpte-c_rgb'	: m = [2.2, 'D65', 0.6300, 0.3400, 0.212395, 0.3100, 0.5950, 0.701049, 0.1550, 0.0700, 0.086556]; break;
		case 's_rgb'		: m = [2.2, 'D65', 0.6400, 0.3300, 0.212656, 0.3000, 0.6000, 0.715158, 0.1500, 0.0600, 0.072186]; break;
		case 'wide_gamut_rgb'	: m = [2.2, 'D50', 0.7350, 0.2650, 0.258187, 0.1150, 0.8260, 0.724938, 0.1570, 0.0180, 0.016875]; break;

		default: dojo.debug("RGB working space "+this.RGBWorkingSpace+" isn't defined");
	}

	var p = {};

	p.name = this.RGBWorkingSpace;
	p.gamma = m[0];
	p.wp = m[1];

	p.xr = m[2];
	p.yr = m[3];
	p.Yr = m[4];

	p.xg = m[5];
	p.yg = m[6];
	p.Yg = m[7];

	p.xb = m[8];
	p.yb = m[9];
	p.Yb = m[10];

	// if WP doesn't match current WP, convert the primaries over

	if (p.wp != this.whitePoint){

		var r = this.XYZ_to_xyY( this.chromaticAdaptation( this.xyY_to_XYZ([p.xr, p.yr, p.Yr]), p.wp, this.whitePoint ) );
		var g = this.XYZ_to_xyY( this.chromaticAdaptation( this.xyY_to_XYZ([p.xg, p.yg, p.Yg]), p.wp, this.whitePoint ) );
		var b = this.XYZ_to_xyY( this.chromaticAdaptation( this.xyY_to_XYZ([p.xb, p.yb, p.Yb]), p.wp, this.whitePoint ) );

		p.xr = r[0];
		p.yr = r[1];
		p.Yr = r[2];

		p.xg = g[0];
		p.yg = g[1];
		p.Yg = g[2];

		p.xb = b[0];
		p.yb = b[1];
		p.Yb = b[2];

		p.wp = this.whitePoint;
	}

	p.zr = 1 - p.xr - p.yr;
	p.zg = 1 - p.xg - p.yg;
	p.zb = 1 - p.xb - p.yb;

	return p;
}

dojo.graphics.Colorspace.prototype.epsilon = function(){

	return this.useApproxCIELabMapping ? 0.008856 : 216 / 24289;
}

dojo.graphics.Colorspace.prototype.kappa = function(){

	return this.useApproxCIELabMapping ? 903.3 : 24389 / 27;
}

dojo.graphics.Colorspace.prototype.XYZ_to_xyY = function(){
	var src = this.munge('XYZ', arguments);

	var sum = src.X + src.Y + src.Z;

	if (sum == 0){

		var wp = this.getWhitePoint();
		var x = wp.x;
		var y = wp.y;
	}else{
		var x = src.X / sum;
		var y = src.Y / sum;
	}

	var Y = src.Y;


	return [x, y, Y];
}

dojo.graphics.Colorspace.prototype.xyY_to_XYZ = function(){
	var src = this.munge('xyY', arguments);

	if (src.y == 0){

		var X = 0;
		var Y = 0;
		var Z = 0;
	}else{
		var X = (src.x * src.Y) / src.y;
		var Y = src.Y;
		var Z = ((1 - src.x - src.y) * src.Y) / src.y;
	}

	return [X, Y, Z];
}

dojo.graphics.Colorspace.prototype.RGB_to_XYZ = function(){
	var src = this.munge('RGB', arguments);

	var m = this.getRGB_XYZ_Matrix();
	var pr = this.getPrimaries();

	if (this.RGBWorkingSpace == 's_rgb'){

		var r = (src.R > 0.04045) ? Math.pow(((src.R + 0.055) / 1.055), 2.4) : src.R / 12.92;
		var g = (src.G > 0.04045) ? Math.pow(((src.G + 0.055) / 1.055), 2.4) : src.G / 12.92;
		var b = (src.B > 0.04045) ? Math.pow(((src.B + 0.055) / 1.055), 2.4) : src.B / 12.92;

	}else{

		var r = Math.pow(src.R, pr.gamma);
		var g = Math.pow(src.G, pr.gamma);
		var b = Math.pow(src.B, pr.gamma);
	}

	var XYZ = dojo.math.matrix.multiply([[r, g, b]], m);

	return [XYZ[0][0], XYZ[0][1], XYZ[0][2]];
}

dojo.graphics.Colorspace.prototype.XYZ_to_RGB = function(){
	var src = this.munge('XYZ', arguments);

	var mi = this.getXYZ_RGB_Matrix();
	var pr = this.getPrimaries();

	var rgb = dojo.math.matrix.multiply([[src.X, src.Y, src.Z]], mi);
	var r = rgb[0][0];
	var g = rgb[0][1];
	var b = rgb[0][2];

	if (this.RGBWorkingSpace == 's_rgb'){

		var R = (r > 0.0031308) ? (1.055 * Math.pow(r, 1.0/2.4)) - 0.055 : 12.92 * r;
		var G = (g > 0.0031308) ? (1.055 * Math.pow(g, 1.0/2.4)) - 0.055 : 12.92 * g;
		var B = (b > 0.0031308) ? (1.055 * Math.pow(b, 1.0/2.4)) - 0.055 : 12.92 * b;
	}else{
		var R = Math.pow(r, 1/pr.gamma);
		var G = Math.pow(g, 1/pr.gamma);
		var B = Math.pow(b, 1/pr.gamma);
	}

	return [R, G, B];
}

dojo.graphics.Colorspace.prototype.XYZ_to_Lab = function(){
	var src = this.munge('XYZ', arguments);

	var wp = this.getWhitePoint();

	var xr = src.X / wp.X;
	var yr = src.Y / wp.Y;
	var zr = src.Z / wp.Z;

	var fx = (xr > this.epsilon()) ? Math.pow(xr, 1/3) : (this.kappa() * xr + 16) / 116;
	var fy = (yr > this.epsilon()) ? Math.pow(yr, 1/3) : (this.kappa() * yr + 16) / 116;
	var fz = (zr > this.epsilon()) ? Math.pow(zr, 1/3) : (this.kappa() * zr + 16) / 116;

	var L = 116 * fy - 16;
	var a = 500 * (fx - fy);
	var b = 200 * (fy - fz);

	return [L, a, b];
}

dojo.graphics.Colorspace.prototype.Lab_to_XYZ = function(){
	var src = this.munge('Lab', arguments);

	var wp = this.getWhitePoint();

	var yr = (src.L > (this.kappa() * this.epsilon())) ? Math.pow((src.L + 16) / 116, 3) : src.L / this.kappa();

	var fy = (yr > this.epsilon()) ? (src.L + 16) / 116 : (this.kappa() * yr + 16) / 116;

	var fx = (src.a / 500) + fy;
	var fz = fy - (src.b / 200);

	var fxcube = Math.pow(fx, 3);
	var fzcube = Math.pow(fz, 3);

	var xr = (fxcube > this.epsilon()) ? fxcube : (116 * fx - 16) / this.kappa();
	var zr = (fzcube > this.epsilon()) ? fzcube : (116 * fz - 16) / this.kappa();

	var X = xr * wp.X;
	var Y = yr * wp.Y;
	var Z = zr * wp.Z;

	return [X, Y, Z];
}

dojo.graphics.Colorspace.prototype.Lab_to_LCHab = function(){
	var src = this.munge('Lab', arguments);

	var L = src.L;
	var C = Math.pow(src.a * src.a + src.b * src.b, 0.5);
	var H = Math.atan2(src.b, src.a) * (180 / Math.PI);

	if (H < 0){ H += 360; }
	if (H > 360){ H -= 360; }

	return [L, C, H];
}

dojo.graphics.Colorspace.prototype.LCHab_to_Lab = function(){
	var src = this.munge('LCH', arguments);

	var H_rad = src.H * (Math.PI / 180);

	var L = src.L;

	var a = src.C / Math.pow(Math.pow(Math.tan(H_rad), 2) + 1, 0.5);
	if ((90 < src.H) && (src.H < 270)){ a= -a; }

	var b = Math.pow(Math.pow(src.C, 2) - Math.pow(a, 2), 0.5);
	if (src.H > 180){ b = -b; }

	return [L, a, b];
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
//
// this function converts an XYZ color array (col) from one whitepoint (src_w) to another (dst_w)
//

dojo.graphics.Colorspace.prototype.chromaticAdaptation = function(col, src_w, dst_w){

	col = this.munge('XYZ', [col]);

	//
	// gather white point data for the source and dest
	//

	var old_wp = this.whitePoint;

	this.whitePoint = src_w;
	var wp_src = this.getWhitePoint();

	this.whitePoint = dst_w;
	var wp_dst = this.getWhitePoint();

	this.whitePoint = old_wp;


	//
	// get a transformation matricies
	//

	switch(this.chromaticAdaptationAlg){
		case 'xyz_scaling':
			var ma = [[1,0,0],[0,1,0],[0,0,1]];
			var mai = [[1,0,0],[0,1,0],[0,0,1]];
			break;
		case 'bradford':
			var ma = [[0.8951, -0.7502, 0.0389],[0.2664, 1.7135, -0.0685],[-0.1614, 0.0367, 1.0296]];
			var mai = [[0.986993, 0.432305, -0.008529],[-0.147054, 0.518360, 0.040043],[0.159963, 0.049291, 0.968487]];
			break;
		case 'von_kries':
			var ma = [[0.40024, -0.22630, 0.00000],[0.70760, 1.16532, 0.00000],[-0.08081, 0.04570, 0.91822]]
			var mai = [[1.859936, 0.361191, 0.000000],[-1.129382, 0.638812, 0.000000],[0.219897, -0.000006, 1.089064]]
			break;
		default:
			dojo.debug("The "+this.chromaticAdaptationAlg+" chromatic adaptation algorithm matricies are not defined");
	}


	//
	// calculate the cone response domains
	//

	var domain_src = dojo.math.matrix.multiply( [[wp_src.x, wp_src.y, wp_src.z]], ma);
	var domain_dst = dojo.math.matrix.multiply( [[wp_dst.x, wp_dst.y, wp_dst.z]], ma);


	//
	// construct the centre matrix
	//

	var centre = [
		[domain_dst[0][0]/domain_src[0][0], 0, 0],
		[0, domain_dst[0][1]/domain_src[0][1], 0],
		[0, 0, domain_dst[0][2]/domain_src[0][2]]
	];


	//
	// caclulate 'm'
	//

	var m = dojo.math.matrix.multiply( dojo.math.matrix.multiply( ma, centre ), mai );


	//
	// construct source color matrix
	//

	var dst = dojo.math.matrix.multiply( [[ col.X, col.Y, col.Z ]], m );

	return dst[0];
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

dojo.graphics.Colorspace.prototype.getRGB_XYZ_Matrix = function(){

	var wp = this.getWhitePoint();
	var pr = this.getPrimaries();

	var Xr = pr.xr / pr.yr;
	var Yr = 1;
	var Zr = (1 - pr.xr - pr.yr) / pr.yr;

	var Xg = pr.xg / pr.yg;
	var Yg = 1;
	var Zg = (1 - pr.xg - pr.yg) / pr.yg;

	var Xb = pr.xb / pr.yb;
	var Yb = 1;
	var Zb = (1 - pr.xb - pr.yb) / pr.yb;

	var m1 = [[Xr, Yr, Zr],[Xg, Yg, Zg],[Xb, Yb, Zb]];
	var m2 = [[wp.X, wp.Y, wp.Z]];
	var sm = dojo.math.matrix.multiply(m2, dojo.math.matrix.inverse(m1));

	var Sr = sm[0][0];
	var Sg = sm[0][1];
	var Sb = sm[0][2];

	var m4 = [[Sr*Xr, Sr*Yr, Sr*Zr],
		  [Sg*Xg, Sg*Yg, Sg*Zg],
		  [Sb*Xb, Sb*Yb, Sb*Zb]];

	return m4;
}

dojo.graphics.Colorspace.prototype.getXYZ_RGB_Matrix = function(){

	var m = this.getRGB_XYZ_Matrix();

	return dojo.math.matrix.inverse(m);
}

dojo.graphics.Colorspace.prototype.XYZ_to_Luv = function(){

	var src = this.munge('XYZ', arguments);

	var wp = this.getWhitePoint();

	var ud = (4 * src.X) / (src.X + 15 * src.Y + 3 * src.Z);
	var vd = (9 * src.Y) / (src.X + 15 * src.Y + 3 * src.Z);

	var udr = (4 * wp.X) / (wp.X + 15 * wp.Y + 3 * wp.Z);
	var vdr = (9 * wp.Y) / (wp.X + 15 * wp.Y + 3 * wp.Z);

	var yr = src.Y / wp.Y;

	var L = (yr > this.epsilon()) ? 116 * Math.pow(yr, 1/3) - 16 : this.kappa() * yr;
	var u = 13 * L * (ud-udr);
	var v = 13 * L * (vd-vdr);

	return [L, u, v];
}

dojo.graphics.Colorspace.prototype.Luv_to_XYZ = function(){

	var src = this.munge('Luv', arguments);

	var wp = this.getWhitePoint();

	var uz = (4 * wp.X) / (wp.X + 15 * wp.Y + 3 * wp.Z);
	var vz = (9 * wp.Y) / (wp.X + 15 * wp.Y + 3 * wp.Z);

	var Y = (src.L > this.kappa() * this.epsilon()) ? Math.pow((src.L + 16) / 116, 3) : src.L / this.kappa();

	var a = (1 / 3) * (((52 * src.L) / (src.u + 13 * src.L * uz)) - 1);
	var b = -5 * Y;
	var c = - (1 / 3);
	var d = Y * (((39 * src.L) / (src.v + 13 * src.L * vz)) - 5);

	var X = (d - b) / (a - c);
	var Z = X * a + b;

	return [X, Y, Z];
}

dojo.graphics.Colorspace.prototype.Luv_to_LCHuv = function(){

	var src = this.munge('Luv', arguments);

	var L = src.L;
	var C = Math.pow(src.u * src.u + src.v * src.v, 0.5);
	var H = Math.atan2(src.v, src.u) * (180 / Math.PI);

	if (H < 0){ H += 360; }
	if (H > 360){ H -= 360; }

	return [L, C, H];
}

dojo.graphics.Colorspace.prototype.LCHuv_to_Luv = function(){

	var src = this.munge('LCH', arguments);

	var H_rad = src.H * (Math.PI / 180);

	var L = src.L;
	var u = src.C / Math.pow(Math.pow(Math.tan(H_rad), 2) + 1, 0.5);
	var v = Math.pow(src.C * src.C - u * u, 0.5);

	if ((90 < src.H) && (src.H < 270)){ u *= -1; }
	if (src.H > 180){ v *= -1; }

	return [L, u, v];
}

dojo.graphics.Colorspace.colorTemp_to_whitePoint = function(T){

	if (T < 4000){
		dojo.debug("Can't find a white point for temperatures under 4000K");
		return [0,0];
	}

	if (T > 25000){
		dojo.debug("Can't find a white point for temperatures over 25000K");
		return [0,0];
	}

	var T1 = T;
	var T2 = T * T;
	var T3 = T2 * T;

	var ten9 = Math.pow(10, 9);
	var ten6 = Math.pow(10, 6);
	var ten3 = Math.pow(10, 3);

	if (T <= 7000){

		var x = (-4.6070 * ten9 / T3) + (2.9678 * ten6 / T2) + (0.09911 * ten3 / T) + 0.244063;
	}else{
		var x = (-2.0064 * ten9 / T3) + (1.9018 * ten6 / T2) + (0.24748 * ten3 / T) + 0.237040;
	}

	var y = -3.000 * x * x + 2.870 * x - 0.275;

	return [x, y];
}

dojo.graphics.Colorspace.prototype.RGB_to_CMY = function(){

	var src = this.munge('RGB', arguments);

	var C = 1 - src.R;
	var M = 1 - src.G;
	var Y = 1 - src.B;

	return [C, M, Y];
}

dojo.graphics.Colorspace.prototype.CMY_to_RGB = function(){

	var src = this.munge('CMY', arguments);

	var R = 1 - src.C;
	var G = 1 - src.M;
	var B = 1 - src.Y;

	return [R, G, B];
}

dojo.graphics.Colorspace.prototype.RGB_to_CMYK = function(){

	var src = this.munge('RGB', arguments);

	var K = Math.min(1-src.R, 1-src.G, 1-src.B);
	var C = (1 - src.R - K) / (1 - K);
	var M = (1 - src.G - K) / (1 - K);
	var Y = (1 - src.B - K) / (1 - K);

	return [C, M, Y, K];
}

dojo.graphics.Colorspace.prototype.CMYK_to_RGB = function(){

	var src = this.munge('CMYK', arguments);

	var R = 1 - Math.min(1, src.C * (1-src.K) + src.K);
	var G = 1 - Math.min(1, src.M * (1-src.K) + src.K);
	var B = 1 - Math.min(1, src.Y * (1-src.K) + src.K);

	return [R, G, B];
}

dojo.graphics.Colorspace.prototype.CMY_to_CMYK = function(){

	var src = this.munge('CMY', arguments);

	var K = Math.min(src.C, src.M, src.Y);
	var C = (src.C - K) / (1 - K);
	var M = (src.M - K) / (1 - K);
	var Y = (src.Y - K) / (1 - K);

	return [C, M, Y, K];
}

dojo.graphics.Colorspace.prototype.CMYK_to_CMY = function(){

	var src = this.munge('CMYK', arguments);

	var C = Math.min(1, src.C * (1-src.K) + src.K);
	var M = Math.min(1, src.M * (1-src.K) + src.K);
	var Y = Math.min(1, src.Y * (1-src.K) + src.K);

	return [C, M, Y];
}

dojo.graphics.Colorspace.prototype.RGB_to_HSV = function(){

	var src = this.munge('RGB', arguments);

	// Based on C Code in "Computer Graphics -- Principles and Practice,"
	// Foley et al, 1996, p. 592. 

	var min = Math.min(src.R, src.G, src.B);
	var V = Math.max(src.R, src.G, src.B);

	var delta = V - min;

	var H = null;
	var S = (V == 0) ? 0 : delta / V;

	if (S == 0){
		H = 0;
	}else{
		if (src.R == V){
			H = 60 * (src.G - src.B) / delta;
		}else{
			if (src.G == V){
				H = 120 + 60 * (src.B - src.R) / delta;
			}else{
				if (src.B == V){
					// between magenta and cyan
					H = 240 + 60 * (src.R - src.G) / delta;
				}
			}
		}
		if (H < 0){
			H += 360;
		}
	}

	H = (H == 0) ? 360 : H;

	return [H, S, V];
}

dojo.graphics.Colorspace.prototype.HSV_to_RGB = function(){
 
	var src = this.munge('HSV', arguments);

	if (src.H == 360){ src.H = 0;}

	// Based on C Code in "Computer Graphics -- Principles and Practice,"
	// Foley et al, 1996, p. 593.

	var r = null;
	var g = null;
	var b = null;

	if (src.S == 0){
		// color is on black-and-white center line
		// achromatic: shades of gray
		var R = src.V;
		var G = src.V;
		var B = src.V;
	}else{
		// chromatic color
		var hTemp = src.H / 60;		// h is now IN [0,6]
		var i = Math.floor(hTemp);	// largest integer <= h
		var f = hTemp - i;		// fractional part of h

		var p = src.V * (1 - src.S);
		var q = src.V * (1 - (src.S * f));
		var t = src.V * (1 - (src.S * (1 - f)));

		switch(i){
			case 0: R = src.V; G = t    ; B = p    ; break;
			case 1: R = q    ; G = src.V; B = p    ; break;
			case 2: R = p    ; G = src.V; B = t    ; break;
			case 3: R = p    ; G = q    ; B = src.V; break;
			case 4: R = t    ; G = p    ; B = src.V; break;
			case 5: R = src.V; G = p    ; B = q    ; break;
		}
	}

	return [R, G, B];
}

dojo.graphics.Colorspace.prototype.RGB_to_HSL = function(){

	var src = this.munge('RGB', arguments);

	//
	// based on C code from http://astronomy.swin.edu.au/~pbourke/colour/hsl/
	//


	var min = Math.min(src.R, src.G, src.B);
	var max = Math.max(src.R, src.G, src.B);
	var delta = max - min;

	var H = 0;
	var S = 0;
	var L = (min + max) / 2;

	if ((L > 0) && (L < 1)){
		S = delta / ((L < 0.5) ? (2 * L) : (2 - 2 * L));
	}

	if (delta > 0) {
		if ((max == src.R) && (max != src.G)){
			H += (src.G - src.B) / delta;
		}
		if ((max == src.G) && (max != src.B)){
			H += (2 + (src.B - src.R) / delta);
		}
		if ((max == src.B) && (max != src.R)){
			H += (4 + (src.R - src.G) / delta);
		}
		H *= 60;
	}

	H = (H == 0) ? 360 : H;

	return [H, S, L];
}

dojo.graphics.Colorspace.prototype.HSL_to_RGB = function(){
 
	var src = this.munge('HSL', arguments);

	//
	// based on C code from http://astronomy.swin.edu.au/~pbourke/colour/hsl/
	//

	while (src.H < 0){ src.H += 360; }
	while (src.H >= 360){ src.H -= 360; }

	var R = 0;
	var G = 0;
	var B = 0;

	if (src.H < 120){
		R = (120 - src.H) / 60;
		G = src.H / 60;
		B = 0;
	}else if (src.H < 240){
		R = 0;
		G = (240 - src.H) / 60;
		B = (src.H - 120) / 60;
	}else{
		R = (src.H - 240) / 60;
		G = 0;
		B = (360 - src.H) / 60;
	}

	R = 2 * src.S * Math.min(R, 1) + (1 - src.S);
	G = 2 * src.S * Math.min(G, 1) + (1 - src.S);
	B = 2 * src.S * Math.min(B, 1) + (1 - src.S);

	if (src.L < 0.5){
		R = src.L * R;
		G = src.L * G;
		B = src.L * B;
	}else{
		R = (1 - src.L) * R + 2 * src.L - 1;
		G = (1 - src.L) * G + 2 * src.L - 1;
		B = (1 - src.L) * B + 2 * src.L - 1;
	}

	return [R, G, B];
}

__CPAN_DIR__ src/graphics/color
__CPAN_FILE__ src/graphics/color/hsl.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.graphics.color.hsl");
dojo.require("dojo.lang.array");

dojo.lang.extend(dojo.graphics.color.Color, {

	toHsl: function() {
		return dojo.graphics.color.rgb2hsl(this.toRgb());
	}
});

dojo.graphics.color.rgb2hsl = function(r, g, b){

	if (dojo.lang.isArray(r)) {
		b = r[2] || 0;
		g = r[1] || 0;
		r = r[0] || 0;
	}

	r /= 255;
	g /= 255;
	b /= 255;

	//
	// based on C code from http://astronomy.swin.edu.au/~pbourke/colour/hsl/
	//

	var h = null;
	var s = null;
	var l = null;


	var min = Math.min(r, g, b);
	var max = Math.max(r, g, b);
	var delta = max - min;

	l = (min + max) / 2;

	s = 0;

	if ((l > 0) && (l < 1)){
		s = delta / ((l < 0.5) ? (2 * l) : (2 - 2 * l));
	}

	h = 0;

	if (delta > 0) {
		if ((max == r) && (max != g)){
			h += (g - b) / delta;
		}
		if ((max == g) && (max != b)){
			h += (2 + (b - r) / delta);
		}
		if ((max == b) && (max != r)){
			h += (4 + (r - g) / delta);
		}
		h *= 60;
	}

	h = (h == 0) ? 360 : Math.ceil((h / 360) * 255);
	s = Math.ceil(s * 255);
	l = Math.ceil(l * 255);

	return [h, s, l];
}

dojo.graphics.color.hsl2rgb = function(h, s, l){
 
	if (dojo.lang.isArray(h)) {
		l = h[2] || 0;
		s = h[1] || 0;
		h = h[0] || 0;
	}

	h = (h / 255) * 360;
	if (h == 360){ h = 0;}
	s = s / 255;
	l = l / 255;

	//
	// based on C code from http://astronomy.swin.edu.au/~pbourke/colour/hsl/
	//


	while (h < 0){ h += 360; }
	while (h > 360){ h -= 360; }
	var r, g, b;
	if (h < 120){
		r = (120 - h) / 60;
		g = h / 60;
		b = 0;
	}else if (h < 240){
		r = 0;
		g = (240 - h) / 60;
		b = (h - 120) / 60;
	}else{
		r = (h - 240) / 60;
		g = 0;
		b = (360 - h) / 60;
	}

	r = Math.min(r, 1);
	g = Math.min(g, 1);
	b = Math.min(b, 1);

	r = 2 * s * r + (1 - s);
	g = 2 * s * g + (1 - s);
	b = 2 * s * b + (1 - s);

	if (l < 0.5){
		r = l * r;
		g = l * g;
		b = l * b;
	}else{
		r = (1 - l) * r + 2 * l - 1;
		g = (1 - l) * g + 2 * l - 1;
		b = (1 - l) * b + 2 * l - 1;
	}

	r = Math.ceil(r * 255);
	g = Math.ceil(g * 255);
	b = Math.ceil(b * 255);

	return [r, g, b];
}

dojo.graphics.color.hsl2hex = function(h, s, l){
	var rgb = dojo.graphics.color.hsl2rgb(h, s, l);
	return dojo.graphics.color.rgb2hex(rgb[0], rgb[1], rgb[2]);
}

dojo.graphics.color.hex2hsl = function(hex){
	var rgb = dojo.graphics.color.hex2rgb(hex);
	return dojo.graphics.color.rgb2hsl(rgb[0], rgb[1], rgb[2]);
}

__CPAN_FILE__ src/graphics/color/hsv.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.graphics.color.hsv");
dojo.require("dojo.lang.array");

dojo.lang.extend(dojo.graphics.color.Color, {

	toHsv: function() {
		return dojo.graphics.color.rgb2hsv(this.toRgb());
	}

});

dojo.graphics.color.rgb2hsv = function(r, g, b){

	if (dojo.lang.isArray(r)) {
		b = r[2] || 0;
		g = r[1] || 0;
		r = r[0] || 0;
	}

	// r,g,b, each 0 to 255, to HSV.
	// h = 0.0 to 360.0 (corresponding to 0..360.0 degrees around hexcone)
	// s = 0.0 (shade of gray) to 1.0 (pure color)
	// v = 0.0 (black) to 1.0 {white)
	//
	// Based on C Code in "Computer Graphics -- Principles and Practice,"
	// Foley et al, 1996, p. 592. 
	//
	// our calculatuions are based on 'regular' values (0-360, 0-1, 0-1) 
	// but we return bytes values (0-255, 0-255, 0-255)

	var h = null;
	var s = null;
	var v = null;

	var min = Math.min(r, g, b);
	v = Math.max(r, g, b);

	var delta = v - min;

	// calculate saturation (0 if r, g and b are all 0)

	s = (v == 0) ? 0 : delta/v;

	if (s == 0){
		// achromatic: when saturation is, hue is undefined
		h = 0;
	}else{
		// chromatic
		if (r == v){
			// between yellow and magenta
			h = 60 * (g - b) / delta;
		}else{
			if (g == v){
				// between cyan and yellow
				h = 120 + 60 * (b - r) / delta;
			}else{
				if (b == v){
					// between magenta and cyan
					h = 240 + 60 * (r - g) / delta;
				}
			}
		}
		if (h < 0){
			h += 360;
		}
	}


	h = (h == 0) ? 360 : Math.ceil((h / 360) * 255);
	s = Math.ceil(s * 255);

	return [h, s, v];
}

dojo.graphics.color.hsv2rgb = function(h, s, v){
 
	if (dojo.lang.isArray(h)) {
		v = h[2] || 0;
		s = h[1] || 0;
		h = h[0] || 0;
	}

	h = (h / 255) * 360;
	if (h == 360){ h = 0;}

	s = s / 255;
	v = v / 255;

	// Based on C Code in "Computer Graphics -- Principles and Practice,"
	// Foley et al, 1996, p. 593.
	//
	// H = 0.0 to 360.0 (corresponding to 0..360 degrees around hexcone) 0 for S = 0
	// S = 0.0 (shade of gray) to 1.0 (pure color)
	// V = 0.0 (black) to 1.0 (white)

	var r = null;
	var g = null;
	var b = null;

	if (s == 0){
		// color is on black-and-white center line
		// achromatic: shades of gray
		r = v;
		g = v;
		b = v;
	}else{
		// chromatic color
		var hTemp = h / 60;		// h is now IN [0,6]
		var i = Math.floor(hTemp);	// largest integer <= h
		var f = hTemp - i;		// fractional part of h

		var p = v * (1 - s);
		var q = v * (1 - (s * f));
		var t = v * (1 - (s * (1 - f)));

		switch(i){
			case 0: r = v; g = t; b = p; break;
			case 1: r = q; g = v; b = p; break;
			case 2: r = p; g = v; b = t; break;
			case 3: r = p; g = q; b = v; break;
			case 4: r = t; g = p; b = v; break;
			case 5: r = v; g = p; b = q; break;
		}
	}

	r = Math.ceil(r * 255);
	g = Math.ceil(g * 255);
	b = Math.ceil(b * 255);

	return [r, g, b];
}

__CPAN_DIR__ src/widget
__CPAN_FILE__ src/widget/Widget.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Widget");
dojo.provide("dojo.widget.tags");

dojo.require("dojo.lang.func");
dojo.require("dojo.lang.array");
dojo.require("dojo.lang.extras");
dojo.require("dojo.lang.declare");
dojo.require("dojo.widget.Manager");
dojo.require("dojo.event.*");

dojo.declare("dojo.widget.Widget", null, {
	initializer: function() {								 
		// these properties aren't primitives and need to be created on a per-item
		// basis.
		this.children = [];
		// this.selection = new dojo.widget.Selection();
		// FIXME: need to replace this with context menu stuff
		this.extraArgs = {};
	},
	// FIXME: need to be able to disambiguate what our rendering context is
	//        here!
	//
	// needs to be a string with the end classname. Every subclass MUST
	// over-ride.
	//
	// base widget properties
	parent: null,
	// obviously, top-level and modal widgets should set these appropriately
	isTopLevel:  false,
	isModal: false,

	isEnabled: true,
	isHidden: false,
	isContainer: false, // can we contain other widgets?
	widgetId: "",
	widgetType: "Widget", // used for building generic widgets

	toString: function() {
		return '[Widget ' + this.widgetType + ', ' + (this.widgetId || 'NO ID') + ']';
	},

	repr: function(){
		return this.toString();
	},

	enable: function(){
		// should be over-ridden
		this.isEnabled = true;
	},

	disable: function(){
		// should be over-ridden
		this.isEnabled = false;
	},

	hide: function(){
		// should be over-ridden
		this.isHidden = true;
	},

	show: function(){
		// should be over-ridden
		this.isHidden = false;
	},

	onResized: function(){
		// Clients should override this function to do special processing,
		// then call this.notifyChildrenOfResize() to notify children of resize
		this.notifyChildrenOfResize();
	},
	
	notifyChildrenOfResize: function(){
		for(var i=0; i<this.children.length; i++){
			var child = this.children[i];
			//dojo.debug(this.widgetId + " resizing child " + child.widgetId);
			if( child.onResized ){
				child.onResized();
			}
		}
	},

	create: function(args, fragment, parentComp){
		// dojo.debug(this.widgetType, "create");
		this.satisfyPropertySets(args, fragment, parentComp);
		// dojo.debug(this.widgetType, "-> mixInProperties");
		this.mixInProperties(args, fragment, parentComp);
		// dojo.debug(this.widgetType, "-> postMixInProperties");
		this.postMixInProperties(args, fragment, parentComp);
		// dojo.debug(this.widgetType, "-> dojo.widget.manager.add");
		dojo.widget.manager.add(this);
		// dojo.debug(this.widgetType, "-> buildRendering");
		this.buildRendering(args, fragment, parentComp);
		// dojo.debug(this.widgetType, "-> initialize");
		this.initialize(args, fragment, parentComp);
		// dojo.debug(this.widgetType, "-> postInitialize");
		this.postInitialize(args, fragment, parentComp);
		// dojo.debug(this.widgetType, "-> postCreate");
		this.postCreate(args, fragment, parentComp);
		// dojo.debug(this.widgetType, "done!");
		return this;
	},

	// Destroy this widget and it's descendants
	destroy: function(finalize){
		// FIXME: this is woefully incomplete
		this.destroyChildren();
		this.uninitialize();
		this.destroyRendering(finalize);
		dojo.widget.manager.removeById(this.widgetId);
	},

	// Destroy the children of this widget, and their descendents
	destroyChildren: function(){
		while(this.children.length > 0){
			var tc = this.children[0];
			this.removeChild(tc);
			tc.destroy();
		}
	},

	getChildrenOfType: function(type, recurse){
		var ret = [];
		var isFunc = dojo.lang.isFunction(type);
		if(!isFunc){
			type = type.toLowerCase();
		}
		for(var x=0; x<this.children.length; x++){
			if(isFunc){
				if(this.children[x] instanceof type){
					ret.push(this.children[x]);
				}
			}else{
				if(this.children[x].widgetType.toLowerCase() == type){
					ret.push(this.children[x]);
				}
			}
			if(recurse){
				ret = ret.concat(this.children[x].getChildrenOfType(type, recurse));
			}
		}
		return ret;
	},

	getDescendants: function(){
		var result = [];
		var stack = [this];
		var elem;
		while (elem = stack.pop()){
			result.push(elem);
			dojo.lang.forEach(elem.children, function(elem) { stack.push(elem); });
		}
		return result;
	},

	satisfyPropertySets: function(args){
		// dojo.profile.start("satisfyPropertySets");
		// get the default propsets for our component type
		/*
		var typePropSets = []; // FIXME: need to pull these from somewhere!
		var localPropSets = []; // pull out propsets from the parser's return structure

		// for(var x=0; x<args.length; x++){
		// }

		for(var x=0; x<typePropSets.length; x++){
		}

		for(var x=0; x<localPropSets.length; x++){
		}
		*/
		// dojo.profile.end("satisfyPropertySets");
		
		return args;
	},

	mixInProperties: function(args, frag){
		if((args["fastMixIn"])||(frag["fastMixIn"])){
			// dojo.profile.start("mixInProperties_fastMixIn");
			// fast mix in assumes case sensitivity, no type casting, etc...
			// dojo.lang.mixin(this, args);
			for(var x in args){
				this[x] = args[x];
			}
			// dojo.profile.end("mixInProperties_fastMixIn");
			return;
		}
		// dojo.profile.start("mixInProperties");
		/*
		 * the actual mix-in code attempts to do some type-assignment based on
		 * PRE-EXISTING properties of the "this" object. When a named property
		 * of a propset is located, it is first tested to make sure that the
		 * current object already "has one". Properties which are undefined in
		 * the base widget are NOT settable here. The next step is to try to
		 * determine type of the pre-existing property. If it's a string, the
		 * property value is simply assigned. If a function, the property is
		 * replaced with a "new Function()" declaration. If an Array, the
		 * system attempts to split the string value on ";" chars, and no
		 * further processing is attempted (conversion of array elements to a
		 * integers, for instance). If the property value is an Object
		 * (testObj.constructor === Object), the property is split first on ";"
		 * chars, secondly on ":" chars, and the resulting key/value pairs are
		 * assigned to an object in a map style. The onus is on the property
		 * user to ensure that all property values are converted to the
		 * expected type before usage.
		 */

		var undef;

		// NOTE: we cannot assume that the passed properties are case-correct
		// (esp due to some browser bugs). Therefore, we attempt to locate
		// properties for assignment regardless of case. This may cause
		// problematic assignments and bugs in the future and will need to be
		// documented with big bright neon lights.

		// FIXME: fails miserably if a mixin property has a default value of null in 
		// a widget

		// NOTE: caching lower-cased args in the prototype is only 
		// acceptable if the properties are invariant.
		// if we have a name-cache, get it
		var lcArgs = dojo.widget.lcArgsCache[this.widgetType];
		if ( lcArgs == null ){
			// build a lower-case property name cache if we don't have one
			lcArgs = {};
			for(var y in this){
				lcArgs[((new String(y)).toLowerCase())] = y;
			}
			dojo.widget.lcArgsCache[this.widgetType] = lcArgs;
		}
		var visited = {};
		for(var x in args){
			if(!this[x]){ // check the cache for properties
				var y = lcArgs[(new String(x)).toLowerCase()];
				if(y){
					args[y] = args[x];
					x = y; 
				}
			}
			if(visited[x]){ continue; }
			visited[x] = true;
			if((typeof this[x]) != (typeof undef)){
				if(typeof args[x] != "string"){
					this[x] = args[x];
				}else{
					if(dojo.lang.isString(this[x])){
						this[x] = args[x];
					}else if(dojo.lang.isNumber(this[x])){
						this[x] = new Number(args[x]); // FIXME: what if NaN is the result?
					}else if(dojo.lang.isBoolean(this[x])){
						this[x] = (args[x].toLowerCase()=="false") ? false : true;
					}else if(dojo.lang.isFunction(this[x])){

						// FIXME: need to determine if always over-writing instead
						// of attaching here is appropriate. I suspect that we
						// might want to only allow attaching w/ action items.
						
						// RAR, 1/19/05: I'm going to attach instead of
						// over-write here. Perhaps function objects could have
						// some sort of flag set on them? Or mixed-into objects
						// could have some list of non-mutable properties
						// (although I'm not sure how that would alleviate this
						// particular problem)? 

						// this[x] = new Function(args[x]);

						// after an IRC discussion last week, it was decided
						// that these event handlers should execute in the
						// context of the widget, so that the "this" pointer
						// takes correctly.
						
						// argument that contains no punctuation other than . is 
						// considered a function spec, not code
						if(args[x].search(/[^\w\.]+/i) == -1){
							this[x] = dojo.evalObjPath(args[x], false);
						}else{
							var tn = dojo.lang.nameAnonFunc(new Function(args[x]), this);
							dojo.event.connect(this, x, this, tn);
						}
					}else if(dojo.lang.isArray(this[x])){ // typeof [] == "object"
						this[x] = args[x].split(";");
					} else if (this[x] instanceof Date) {
						this[x] = new Date(Number(args[x])); // assume timestamp
					}else if(typeof this[x] == "object"){ 
						// FIXME: should we be allowing extension here to handle
						// other object types intelligently?

						// if we defined a URI, we probablt want to allow plain strings
						// to override it
						if (this[x] instanceof dojo.uri.Uri){

							this[x] = args[x];
						}else{

							// FIXME: unlike all other types, we do not replace the
							// object with a new one here. Should we change that?
							var pairs = args[x].split(";");
							for(var y=0; y<pairs.length; y++){
								var si = pairs[y].indexOf(":");
								if((si != -1)&&(pairs[y].length>si)){
									this[x][pairs[y].substr(0, si).replace(/^\s+|\s+$/g, "")] = pairs[y].substr(si+1);
								}
							}
						}
					}else{
						// the default is straight-up string assignment. When would
						// we ever hit this?
						this[x] = args[x];
					}
				}
			}else{
				// collect any extra 'non mixed in' args
				this.extraArgs[x.toLowerCase()] = args[x];
			}
		}
		// dojo.profile.end("mixInProperties");
	},
	
	postMixInProperties: function(){
	},

	initialize: function(args, frag){
		// dojo.unimplemented("dojo.widget.Widget.initialize");
		return false;
	},

	postInitialize: function(args, frag){
		return false;
	},

	postCreate: function(args, frag){
		return false;
	},

	uninitialize: function(){
		// dojo.unimplemented("dojo.widget.Widget.uninitialize");
		return false;
	},

	buildRendering: function(){
		// SUBCLASSES MUST IMPLEMENT
		dojo.unimplemented("dojo.widget.Widget.buildRendering, on "+this.toString()+", ");
		return false;
	},

	destroyRendering: function(){
		// SUBCLASSES MUST IMPLEMENT
		dojo.unimplemented("dojo.widget.Widget.destroyRendering");
		return false;
	},

	cleanUp: function(){
		// SUBCLASSES MUST IMPLEMENT
		dojo.unimplemented("dojo.widget.Widget.cleanUp");
		return false;
	},

	addedTo: function(parent){
		// this is just a signal that can be caught
	},

	addChild: function(child){
		// SUBCLASSES MUST IMPLEMENT
		dojo.unimplemented("dojo.widget.Widget.addChild");
		return false;
	},

	// Detach the given child widget from me, but don't destroy it
	removeChild: function(widget){
		for(var x=0; x<this.children.length; x++){
			if(this.children[x] === widget){
				this.children.splice(x, 1);
				break;
			}
		}
		return widget;
	},

	resize: function(width, height){
		// both width and height may be set as percentages. The setWidth and
		// setHeight  functions attempt to determine if the passed param is
		// specified in percentage or native units. Integers without a
		// measurement are assumed to be in the native unit of measure.
		this.setWidth(width);
		this.setHeight(height);
	},

	setWidth: function(width){
		if((typeof width == "string")&&(width.substr(-1) == "%")){
			this.setPercentageWidth(width);
		}else{
			this.setNativeWidth(width);
		}
	},

	setHeight: function(height){
		if((typeof height == "string")&&(height.substr(-1) == "%")){
			this.setPercentageHeight(height);
		}else{
			this.setNativeHeight(height);
		}
	},

	setPercentageHeight: function(height){
		// SUBCLASSES MUST IMPLEMENT
		return false;
	},

	setNativeHeight: function(height){
		// SUBCLASSES MUST IMPLEMENT
		return false;
	},

	setPercentageWidth: function(width){
		// SUBCLASSES MUST IMPLEMENT
		return false;
	},

	setNativeWidth: function(width){
		// SUBCLASSES MUST IMPLEMENT
		return false;
	},

	getPreviousSibling: function() {
		var idx = this.getParentIndex();
 
		 // first node is idx=0 not found is idx<0
		if (idx<=0) return null;
 
		return this.getSiblings()[idx-1];
	},
 
	getSiblings: function() {
		return this.parent.children;
	},
 
	getParentIndex: function() {
		return dojo.lang.indexOf( this.getSiblings(), this, true);
	},
 
	getNextSibling: function() {
 
		var idx = this.getParentIndex();
 
		if (idx == this.getSiblings().length-1) return null; // last node
		if (idx < 0) return null; // not found
 
		return this.getSiblings()[idx+1];
 
	}
});

// Lower case name cache: listing of the lower case elements in each widget.
// We can't store the lcArgs in the widget itself because if B subclasses A,
// then B.prototype.lcArgs might return A.prototype.lcArgs, which is not what we
// want
dojo.widget.lcArgsCache = {};

// TODO: should have a more general way to add tags or tag libraries?
// TODO: need a default tags class to inherit from for things like getting propertySets
// TODO: parse properties/propertySets into component attributes
// TODO: parse subcomponents
// TODO: copy/clone raw markup fragments/nodes as appropriate
dojo.widget.tags = {};
dojo.widget.tags.addParseTreeHandler = function(type){
	var ltype = type.toLowerCase();
	this[ltype] = function(fragment, widgetParser, parentComp, insertionIndex, localProps){ 
		return dojo.widget.buildWidgetFromParseTree(ltype, fragment, widgetParser, parentComp, insertionIndex, localProps);
	}
}
dojo.widget.tags.addParseTreeHandler("dojo:widget");

dojo.widget.tags["dojo:propertyset"] = function(fragment, widgetParser, parentComp){
	// FIXME: Is this needed?
	// FIXME: Not sure that this parses into the structure that I want it to parse into...
	// FIXME: add support for nested propertySets
	var properties = widgetParser.parseProperties(fragment["dojo:propertyset"]);
}

// FIXME: need to add the <dojo:connect />
dojo.widget.tags["dojo:connect"] = function(fragment, widgetParser, parentComp){
	var properties = widgetParser.parseProperties(fragment["dojo:connect"]);
}

// FIXME: if we know the insertion point (to a reasonable location), why then do we:
//	- create a template node
//	- clone the template node
//	- render the clone and set properties
//	- remove the clone from the render tree
//	- place the clone
// this is quite dumb
dojo.widget.buildWidgetFromParseTree = function(type, frag, 
												parser, parentComp, 
												insertionIndex, localProps){
	var stype = type.split(":");
	stype = (stype.length == 2) ? stype[1] : type;
	// FIXME: we don't seem to be doing anything with this!
	// var propertySets = parser.getPropertySets(frag);
	var localProperties = localProps || parser.parseProperties(frag["dojo:"+stype]);
	// var tic = new Date();
	var twidget = dojo.widget.manager.getImplementation(stype);
	if(!twidget){
		throw new Error("cannot find \"" + stype + "\" widget");
	}else if (!twidget.create){
		throw new Error("\"" + stype + "\" widget object does not appear to implement *Widget");
	}
	localProperties["dojoinsertionindex"] = insertionIndex;
	// FIXME: we loose no less than 5ms in construction!
	var ret = twidget.create(localProperties, frag, parentComp);
	// dojo.debug(new Date() - tic);
	return ret;
}

/*
 * Create a widget constructor function (aka widgetClass)
 */
dojo.widget.defineWidget = function(widgetClass /*string*/, renderer /*string*/, superclasses /*function||array*/, init /*function*/, props /*object*/){
	// This meta-function does parameter juggling for backward compat and overloading
	// if 4th argument is a string, we are using the old syntax
	// old sig: widgetClass, superclasses, props (object), renderer (string), init (function)
	if(dojo.lang.isString(arguments[3])){
		dojo.widget._defineWidget(arguments[0], arguments[3], arguments[1], arguments[4], arguments[2]);
	}else{
		// widgetClass
		var args = [ arguments[0] ], p = 3;
		if(dojo.lang.isString(arguments[1])){
			// renderer, superclass
			args.push(arguments[1], arguments[2]);
		}else{
			// superclass
			args.push('', arguments[1]);
			p = 2;
		}
		if(dojo.lang.isFunction(arguments[p])){
			// init (function), props (object) 
			args.push(arguments[p], arguments[p+1]);
		}else{
			// props (object) 
			args.push(null, arguments[p]);
		}
		dojo.widget._defineWidget.apply(this, args);
	}
}

dojo.widget.defineWidget.renderers = "html|svg|vml";

dojo.widget._defineWidget = function(widgetClass /*string*/, renderer /*string*/, superclasses /*function||array*/, init /*function*/, props /*object*/){
	// FIXME: uncomment next line to test parameter juggling ... remove when confidence improves
	//dojo.debug('(c:)' + widgetClass + '\n\n(r:)' + renderer + '\n\n(i:)' + init + '\n\n(p:)' + props);
	// widgetClass takes the form foo.bar.baz<.renderer>.WidgetName (e.g. foo.bar.baz.WidgetName or foo.bar.baz.html.WidgetName)
	var namespace = widgetClass.split(".");
	var type = namespace.pop(); // type <= WidgetName, namespace <= foo.bar.baz<.renderer>
	var regx = "\\.(" + (renderer ? renderer + '|' : '') + dojo.widget.defineWidget.renderers + ")\\.";
	var r = widgetClass.search(new RegExp(regx));
	namespace = (r < 0 ? namespace.join(".") : widgetClass.substr(0, r));

	dojo.widget.manager.registerWidgetPackage(namespace);
	dojo.widget.tags.addParseTreeHandler("dojo:"+type.toLowerCase());

	props=(props)||{};
	props.widgetType = type;
	if((!init)&&(props["classConstructor"])){
		init = props.classConstructor;
		delete props.classConstructor;
	}
	dojo.declare(widgetClass, superclasses, init, props);
}
__CPAN_FILE__ src/widget/DropdownDatePicker.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.DropdownDatePicker");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.DropdownContainer");
dojo.require("dojo.widget.DatePicker");
dojo.require("dojo.event.*");
dojo.require("dojo.html");

dojo.widget.defineWidget(
	"dojo.widget.DropdownDatePicker",
	dojo.widget.DropdownContainer,
	{
		iconURL: dojo.uri.dojoUri("src/widget/templates/images/dateIcon.gif"),
		iconAlt: "Select a Date",
		zIndex: "10",
		datePicker: null,
		
		dateFormat: "%m/%d/%Y",
		date: null,
		
		fillInTemplate: function(args, frag){
			dojo.widget.DropdownDatePicker.superclass.fillInTemplate.call(this, args, frag);
			var source = this.getFragNodeRef(frag);
			
			if(args.date){ this.date = new Date(args.date); }
			
			var dpNode = document.createElement("div");
			this.containerNode.appendChild(dpNode);
			
			var dateProps = { widgetContainerId: this.widgetId };
			if(this.date){
				dateProps["date"] = this.date;
				dateProps["storedDate"] = dojo.widget.DatePicker.util.toRfcDate(this.date);
				this.inputNode.value = dojo.date.format(this.date, this.dateFormat);
			}
			this.datePicker = dojo.widget.createWidget("DatePicker", dateProps, dpNode);
			dojo.event.connect(this.datePicker, "onSetDate", this, "onSetDate");
			this.containerNode.style.zIndex = this.zIndex;
			this.containerNode.style.backgroundColor = "transparent";
		},
		
		onSetDate: function(){
			this.inputNode.value = dojo.date.format(this.datePicker.date, this.dateFormat);
			this.hideContainer();
		},
		
		onInputChange: function(){
			var tmp = new Date(this.inputNode.value);
			this.datePicker.date = tmp;
			this.datePicker.setDate(dojo.widget.DatePicker.util.toRfcDate(tmp));
			this.datePicker.initData();
			this.datePicker.initUI();
		}
	},
	"html"
);

dojo.widget.tags.addParseTreeHandler("dojo:dropdowndatepicker");

__CPAN_FILE__ src/widget/CiviCrmDatePicker.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.CiviCrmDatePicker");
dojo.provide("dojo.widget.HtmlCiviCrmDatePicker");
dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.DatePicker");
dojo.require("dojo.widget.html.DatePicker");
dojo.require("dojo.widget.html.TimePicker");
dojo.require("dojo.html");

dojo.widget.HtmlCiviCrmDatePicker = function(){
	this.widgetType = "CiviCrmDatePicker";
	this.idPrefix = "scheduled_date_time";
	this.mode = "datetime"; // can also be date or time

	this.datePicker = null;
	this.timePicker = null;

	// html nodes
	this.dateHolderTd = null;
	this.timeHolderTd = null;
	this.formItemsTd = null;
	this.formItemsTr = null;

	this.monthSelect = null;
	this.daySelect = null;
	this.yearSelect = null;
	this.hourSelect = null;
	this.minSelect = null;
	this.apSelect = null;

	this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlCiviCrmDatePicker.html");

	this.modeFormats = {
		date: "MdY",
		time: "hiA"
	};

	this.formatMappings = {
		"M": "monthSelect",
		"d": "daySelect",
		"Y": "yearSelect",
		"h": "hourSelect",
		"i": "minSelect",
		"A": "apSelect"
	};

	this.setDateSelects = function(){
		var dateObj = this.datePicker.date;
		this.monthSelect.value = new String(dateObj.getMonth()+1);
		this.daySelect.value = new String(dateObj.getDate());
		this.yearSelect.value = new String(dateObj.getFullYear());
	}

	this.setTimeSelects = function(){
		var st = this.timePicker.selectedTime;
		this.hourSelect.value = new String(st.hour);
		this.minSelect.value = new String(st.minute);
		this.apSelect.value = st.amPm.toUpperCase();
	}

	this.fillInTemplate = function(args, frag){
		var nr = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];
		var sref = {};
		while(nr.firstChild){
			if(nr.firstChild.name){
				sref[nr.firstChild.name] = nr.firstChild;
			}
			this.formItemsTd.appendChild(nr.firstChild);
		}

		if(this.mode.indexOf("date") != -1){
			this.datePicker = dojo.widget.createWidget("DatePicker", {}, this.dateHolderTd);
			dojo.event.connect(	this.datePicker, "onSetDate", 
								this, "setDateSelects");

			var mfd = this.modeFormats.date;
			for(var x=0; x<mfd.length; x++){
				this[this.formatMappings[mfd[x]]] = sref[this.idPrefix+"["+mfd[x]+"]"];
			}
		}
		if(this.mode.indexOf("time") != -1){
			this.timePicker = dojo.widget.createWidget("TimePicker", {}, this.timeHolderTd);
			dojo.event.connect(	this.timePicker, "onSetTime", 
								this, "setTimeSelects");
			var mfd = this.modeFormats.time;
			for(var x=0; x<mfd.length; x++){
				this[this.formatMappings[mfd[x]]] = sref[this.idPrefix+"["+mfd[x]+"]"];
			}
		}
	}

	this.unhide = function(){
		this.formItemsTr.style.display = "";
	}

	this.postCreate = function(){
		dojo.event.kwConnect({
			type: "before", 
			srcObj: dojo.html.getParentByType(this.domNode, "form"),
			srcFunc: "onsubmit", 
			targetObj: this,
			targetFunc: "unhide"
		});
	}
}
dojo.inherits(dojo.widget.HtmlCiviCrmDatePicker, dojo.widget.HtmlWidget);
dojo.widget.tags.addParseTreeHandler("dojo:civicrmdatepicker");


__CPAN_FILE__ src/widget/Button.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Button");
dojo.provide("dojo.widget.html.Button");

dojo.require("dojo.lang.extras");
dojo.require("dojo.html");
dojo.require("dojo.style");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");

dojo.widget.defineWidget(
	"dojo.widget.html.Button",
	dojo.widget.HtmlWidget,
	{
		widgetType: "Button",
		isContainer: true,
	
		// Constructor arguments
		caption: "",
		disabled: false,
	
		templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlButtonTemplate.html"),
		templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlButtonTemplate.css"),
		
		// button images
		inactiveImg: "src/widget/templates/images/soriaButton-",
		activeImg: "src/widget/templates/images/soriaActive-",
		pressedImg: "src/widget/templates/images/soriaPressed-",
		disabledImg: "src/widget/templates/images/soriaDisabled-",
		width2height: 1.0/3.0,
	
		// attach points
		containerNode: null,
		leftImage: null,
		centerImage: null,
		rightImage: null,
	
		fillInTemplate: function(args, frag){
			if(this.caption != ""){
				this.containerNode.appendChild(document.createTextNode(this.caption));
			}
			dojo.html.disableSelection(this.containerNode);
		},

		postCreate: function(args, frag){
			this.sizeMyself();
		},
	
		sizeMyself: function(){
			// we cannot size correctly if any of our ancestors are hidden (display:none),
			// so temporarily attach to document.body
			if(this.domNode.parentNode){
				var placeHolder = document.createElement("span");
				dojo.dom.insertBefore(placeHolder, this.domNode);
			}
			dojo.html.body().appendChild(this.domNode);
			
			this.sizeMyselfHelper();
			
			// Put this.domNode back where it was originally
			if(placeHolder){
				dojo.dom.insertBefore(this.domNode, placeHolder);
				dojo.dom.removeNode(placeHolder);
			}
		},

		sizeMyselfHelper: function(){
			this.height = dojo.style.getOuterHeight(this.containerNode);
			this.containerWidth = dojo.style.getOuterWidth(this.containerNode);
			var endWidth= this.height * this.width2height;
	
			this.containerNode.style.left=endWidth+"px";
	
			this.leftImage.height = this.rightImage.height = this.centerImage.height = this.height;
			this.leftImage.width = this.rightImage.width = endWidth+1;
			this.centerImage.width = this.containerWidth;
			this.centerImage.style.left=endWidth+"px";
			this._setImage(this.disabled ? this.disabledImg : this.inactiveImg);

			if ( this.disabled ) {
				dojo.html.prependClass(this.domNode, "dojoButtonDisabled");
			} else {
				dojo.html.removeClass(this.domNode, "dojoButtonDisabled");
			}
				
			this.domNode.style.height=this.height + "px";
			this.domNode.style.width= (this.containerWidth+2*endWidth) + "px";
		},
	
		onMouseOver: function(e){
			if( this.disabled ){ return; }
			dojo.html.prependClass(this.domNode, "dojoButtonHover");
			this._setImage(this.activeImg);
		},
	
		onMouseDown: function(e){
			if( this.disabled ){ return; }
			dojo.html.prependClass(this.domNode, "dojoButtonDepressed");
			dojo.html.removeClass(this.domNode, "dojoButtonHover");
			this._setImage(this.pressedImg);
		},
		onMouseUp: function(e){
			if( this.disabled ){ return; }
			dojo.html.prependClass(this.domNode, "dojoButtonHover");
			dojo.html.removeClass(this.domNode, "dojoButtonDepressed");
			this._setImage(this.activeImg);
		},
	
		onMouseOut: function(e){
			if( this.disabled ){ return; }
			dojo.html.removeClass(this.domNode, "dojoButtonHover");
			this._setImage(this.inactiveImg);
		},
	
		buttonClick: function(e){
			if( !this.disabled ) { this.onClick(e); }
		},

		onClick: function(e) { },

		_setImage: function(prefix){
			this.leftImage.src=dojo.uri.dojoUri(prefix + "l.gif");
			this.centerImage.src=dojo.uri.dojoUri(prefix + "c.gif");
			this.rightImage.src=dojo.uri.dojoUri(prefix + "r.gif");
		},
		
		_toggleMenu: function(menuId){
			var menu = dojo.widget.getWidgetById(menuId);
			if ( !menu ) { return; }
	
			if ( menu.open && !menu.isShowingNow) {
				var pos = dojo.style.getAbsolutePosition(this.domNode, false);
				menu.open(pos.x, pos.y+this.height, this);
			} else if ( menu.close && menu.isShowingNow ){
				menu.close();
			} else {
				menu.toggle();
			}
		},
		
		setCaption: function(content){
			this.caption=content;
			this.containerNode.innerHTML=content;
			this.sizeMyself();
		},
		
		setDisabled: function(disabled){
			this.disabled=disabled;
			this.sizeMyself();
		}
	});

/**** DropDownButton - push the button and a menu shows up *****/
dojo.widget.defineWidget(
	"dojo.widget.html.DropDownButton",
	dojo.widget.html.Button,
	{
		widgetType: "DropDownButton",
	
		menuId: "",

		arrow: null,
	
		downArrow: "src/widget/templates/images/whiteDownArrow.gif",
		disabledDownArrow: "src/widget/templates/images/whiteDownArrow.gif",
	
		fillInTemplate: function(args, frag){
			dojo.widget.html.DropDownButton.superclass.fillInTemplate.call(this, args, frag);
	
			this.arrow = document.createElement("img");
			dojo.html.setClass(this.arrow, "downArrow");
		},

		sizeMyselfHelper: function(){
			// draw the arrow (todo: why is the arror in containerNode rather than outside it?)
			this.arrow.src = dojo.uri.dojoUri(this.disabled ? this.disabledDownArrow : this.downArrow);
			this.containerNode.appendChild(this.arrow);

			dojo.widget.html.DropDownButton.superclass.sizeMyselfHelper.call(this);
		},

		onClick: function (e){
			this._toggleMenu(this.menuId);
		}
	});

/**** ComboButton - left side is normal button, right side shows menu *****/
dojo.widget.defineWidget(
	"dojo.widget.html.ComboButton",
	dojo.widget.html.Button,
	{
		widgetType: "ComboButton",
	
		menuId: "",
	
		templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlComboButtonTemplate.html"),
	
		// attach points
		leftPart: null,
		rightPart: null,
		arrowBackgroundImage: null,
	
		// constants
		splitWidth: 2,		// pixels between left&right part of button
		arrowWidth: 5,		// width of segment holding down arrow
	
		sizeMyselfHelper: function(e){
			this.height = dojo.style.getOuterHeight(this.containerNode);
			this.containerWidth = dojo.style.getOuterWidth(this.containerNode);
			var endWidth= this.height/3;
	
			// left part
			this.leftImage.height = this.rightImage.height = this.centerImage.height = 
				this.arrowBackgroundImage.height = this.height;
			this.leftImage.width = endWidth+1;
			this.centerImage.width = this.containerWidth;
			this.leftPart.style.height = this.height + "px";
			this.leftPart.style.width = endWidth + this.containerWidth + "px";
			this._setImageL(this.disabled ? this.disabledImg : this.inactiveImg);
	
			// right part
			this.arrowBackgroundImage.width=this.arrowWidth;
			this.rightImage.width = endWidth+1;
			this.rightPart.style.height = this.height + "px";
			this.rightPart.style.width = this.arrowWidth + endWidth + "px";
			this._setImageR(this.disabled ? this.disabledImg : this.inactiveImg);
	
			// outer container
			this.domNode.style.height=this.height + "px";
			var totalWidth = this.containerWidth+this.splitWidth+this.arrowWidth+2*endWidth;
			this.domNode.style.width= totalWidth + "px";
		},
	
		/** functions on left part of button**/
		leftOver: function(e){
			if( this.disabled ){ return; }
			dojo.html.prependClass(this.leftPart, "dojoButtonHover");
			this._setImageL(this.activeImg);
		},
	
		leftDown: function(e){
			if( this.disabled ){ return; }
			dojo.html.prependClass(this.leftPart, "dojoButtonDepressed");
			dojo.html.removeClass(this.leftPart, "dojoButtonHover");
			this._setImageL(this.pressedImg);
		},
		leftUp: function(e){
			if( this.disabled ){ return; }
			dojo.html.prependClass(this.leftPart, "dojoButtonHover");
			dojo.html.removeClass(this.leftPart, "dojoButtonDepressed");
			this._setImageL(this.activeImg);
		},
	
		leftOut: function(e){
			if( this.disabled ){ return; }
			dojo.html.removeClass(this.leftPart, "dojoButtonHover");
			this._setImageL(this.inactiveImg);
		},
	
		leftClick: function(e){
			if ( !this.disabled ) {
				this.onClick(e);
			}
		},
	
		_setImageL: function(prefix){
			this.leftImage.src=dojo.uri.dojoUri(prefix + "l.gif");
			this.centerImage.src=dojo.uri.dojoUri(prefix + "c.gif");
		},
	
		/*** functions on right part of button ***/
		rightOver: function(e){
			if( this.disabled ){ return; }
			dojo.html.prependClass(this.rightPart, "dojoButtonHover");
			this._setImageR(this.activeImg);
		},
	
		rightDown: function(e){
			if( this.disabled ){ return; }
			dojo.html.prependClass(this.rightPart, "dojoButtonDepressed");
			dojo.html.removeClass(this.rightPart, "dojoButtonHover");
			this._setImageR(this.pressedImg);
		},
		rightUp: function(e){
			if( this.disabled ){ return; }
			dojo.html.prependClass(this.rightPart, "dojoButtonHover");
			dojo.html.removeClass(this.rightPart, "dojoButtonDepressed");
			this._setImageR(this.activeImg);
		},
	
		rightOut: function(e){
			if( this.disabled ){ return; }
			dojo.html.removeClass(this.rightPart, "dojoButtonHover");
			this._setImageR(this.inactiveImg);
		},
	
		rightClick: function(e){
			if( this.disabled ){ return; }
			this._toggleMenu(this.menuId);
		},
	
		_setImageR: function(prefix){
			this.arrowBackgroundImage.src=dojo.uri.dojoUri(prefix + "c.gif");
			this.rightImage.src=dojo.uri.dojoUri(prefix + "r.gif");
		}
	});
__CPAN_FILE__ src/widget/Tooltip.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Tooltip");
dojo.require("dojo.widget.Widget");

dojo.requireAfterIf("html", "dojo.widget.html.Tooltip");

__CPAN_FILE__ src/widget/ContentPane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

// This widget doesn't do anything; is basically the same as <div>.
// It's useful as a child of LayoutContainer, SplitContainer, or TabContainer.
// But note that those classes can contain any widget as a child.

dojo.provide("dojo.widget.ContentPane");
dojo.requireAfterIf("html", "dojo.widget.html.ContentPane");

__CPAN_FILE__ src/widget/Select.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Select");
dojo.provide("dojo.widget.html.Select");

dojo.require("dojo.widget.html.ComboBox");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.html.stabile");

/*
 * The Select widget is an enhanced version of HTML's <select> tag.
 *
 * Similar features:
 *   - There is a drop down list of possible values.
 *   - You can only enter a value from the drop down list.  (You can't enter an arbitrary value.)
 *   - The value submitted with the form is the hidden value (ex: CA),
       not the displayed value a.k.a. label (ex: California)
 *
 * Enhancements over plain HTML version:
 *   - If you type in some text then it will filter down the list of possible values in the drop down list.
 *   - List can be specified either as a static list or via a javascript function (that can get the list from a server)
 */

dojo.widget.defineWidget(
	"dojo.widget.html.Select",
	dojo.widget.html.ComboBox,
	{
		widgetType: "Select",
		forceValidOption: true,

		setValue: function(value) {
			this.comboBoxValue.value = value;
			dojo.widget.html.stabile.setState(this.widgetId, this.getState(), true);
		},

		setLabel: function(value){
			// FIXME, not sure what to do here!
			this.comboBoxSelectionValue.value = value;
			if (this.textInputNode.value != value) { // prevent mucking up of selection
				this.textInputNode.value = value;
			}
		},	  

		getLabel: function(){
			return this.comboBoxSelectionValue.value;
		},

		getState: function() {
			return {
				value: this.getValue(),
				label: this.getLabel()
			};
		},

		onKeyUp: function(evt){
			this.setLabel(this.textInputNode.value);
		},

		setState: function(state) {
			this.setValue(state.value);
			this.setLabel(state.label);
		},

		setAllValues: function(value1, value2){
			this.setValue(value2);
			this.setLabel(value1);
		}
	});

__CPAN_FILE__ src/widget/DocPane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.DocPane");
dojo.requireAfterIf("html", "dojo.widget.html.DocPane");

__CPAN_FILE__ src/widget/Editor2Toolbar.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Editor2Toolbar");
dojo.provide("dojo.widget.html.Editor2Toolbar");

dojo.require("dojo.lang.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.RichText");
dojo.require("dojo.widget.ColorPalette");

dojo.widget.defineWidget(
	"dojo.widget.html.Editor2Toolbar",
	dojo.widget.HtmlWidget,
	{
		commandList: [ "bold", "italic", "underline", "subscript", "superscript",
			"fontname", "fontsize", "forecolor", "hilitecolor", "justifycenter",
			"justifyfull", "justifyleft", "justifyright", "cut", "copy", "paste",
			"delete", "undo", "redo", "createlink", "unlink", "removeformat",
			"inserthorizontalrule", "insertimage", "insertorderedlist",
			"insertunorderedlist", "indent", "outdent", "formatblock", "strikethrough", 
			"inserthtml", "blockdirltr", "blockdirrtl", "dirltr", "dirrtl",
			"inlinedirltr", "inlinedirrtl", "inserttable", "insertcell",
			"insertcol", "insertrow", "deletecells", "deletecols", "deleterows",
			"mergecells", "splitcell"
		],

		templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlEditorToolbar.html"),
		templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlEditorToolbar.css"),

		forecolorPalette: null,
		hilitecolorPalette: null,

		// DOM Nodes
		wikiwordButton: null,
		htmltoggleButton: null,
		insertimageButton: null,
		styleDropdownButton: null,
		styleDropdownContainer: null,
		copyButton: null,
		boldButton: null,
		italicButton: null,
		underlineButton: null,
		justifycenterButton: null,
		justifyleftButton: null,
		justifyfullButton: null,
		justifyrightButton: null,
		pasteButton: null,
		undoButton: null,
		redoButton: null,
		linkButton: null,
		insertunorderedlistButton: null,
		insertorderedlistButton: null,
		forecolorButton: null,
		forecolorDropDown: null,
		hilitecolorButton: null,
		hilitecolorDropDown: null,
		formatSelectBox: null,
		inserthorizontalruleButton: null,
		strikethroughButton: null,
		clickInterceptDiv: null,
		oneLineTr: null,

		buttonClick: function(e){ e.preventDefault(); /* dojo.debug("buttonClick"); */ },

		buttonMouseOver: function(e){  },
		buttonMouseOut: function(e){  },


		// event signals
		preventSelect: function(e){ if(dojo.render.html.safari){ e.preventDefault(); } },
		wikiwordClick: function(){ },
		insertimageClick: function(){ },
		htmltoggleClick: function(){ },

		styleDropdownClick: function(){
			dojo.debug("styleDropdownClick:", this.styleDropdownContainer);
			dojo.style.toggleShowing(this.styleDropdownContainer);
		},


		copyClick: function(){ this.exec("copy"); },
		boldClick: function(){ this.exec("bold"); },
		italicClick: function(){ this.exec("italic"); },
		underlineClick: function(){ this.exec("underline"); },
		justifyleftClick: function(){ this.exec("justifyleft"); },
		justifycenterClick: function(){ this.exec("justifycenter"); },
		justifyfullClick: function(){ this.exec("justifyfull"); },
		justifyrightClick: function(){ this.exec("justifyright"); },
		pasteClick: function(){ this.exec("paste"); },
		undoClick: function(){ this.exec("undo"); },
		redoClick: function(){ this.exec("redo"); },
		linkClick: function(){ 
			// FIXME: we need to alert the user if they haven't selected any text
			// this.exec(	"createlink", 
			// 			prompt("Please enter the URL of the link:", "http://"));
		},
		insertunorderedlistClick: function(){ this.exec("insertunorderedlist"); },
		insertorderedlistClick: function(){ this.exec("insertorderedlist"); },
		inserthorizontalruleClick: function(){ this.exec("inserthorizontalrule"); },
		strikethroughClick: function(){ this.exec("strikethrough"); },

		formatSelectClick: function(){ 
			var sv = this.formatSelectBox.value.toLowerCase();
			this.exec("formatblock", sv);
		},

		normalTextClick: function(){ this.exec("formatblock", "p"); },
		h1TextClick: function(){ this.exec("formatblock", "h1"); },
		h2TextClick: function(){ this.exec("formatblock", "h2"); },
		h3TextClick: function(){ this.exec("formatblock", "h3"); },
		h4TextClick: function(){ this.exec("formatblock", "h4"); },
		indentClick: function(){ this.exec("indent"); },
		outdentClick: function(){ this.exec("outdent"); },


		hideAllDropDowns: function(){
			this.domNode.style.height = "";
			dojo.lang.forEach(dojo.widget.byType("Editor2Toolbar"), function(tb){
				try{
					dojo.style.hide(tb.forecolorDropDown);
					dojo.style.hide(tb.hilitecolorDropDown);
					dojo.style.hide(tb.styleDropdownContainer);
					if(tb.clickInterceptDiv){
						dojo.style.hide(tb.clickInterceptDiv);
					}
				}catch(e){}
				if(dojo.render.html.ie){
					try{
						dojo.style.hide(tb.forecolorPalette.bgIframe);
					}catch(e){}
					try{
						dojo.style.hide(tb.hilitecolorPalette.bgIframe);
					}catch(e){}
				}
			});
		},

		selectFormat: function(format){
			dojo.lang.forEach(this.formatSelectBox.options, function(item){
				if(item.value.toLowerCase() == format.toLowerCase()){
					item.selected = true;
				}
			});
		},

		forecolorClick: function(e){
			this.colorClick(e, "forecolor");
		},

		hilitecolorClick: function(e){
			this.colorClick(e, "hilitecolor");
		},

		// FIXME: these methods aren't currently dealing with clicking in the
		// general document to hide the menu
		colorClick: function(e, type){
			var h = dojo.render.html;
			this.hideAllDropDowns();
			// FIXME: if we've been "popped out", we need to set the height of the toolbar.
			e.stopPropagation();
			var dd = this[type+"DropDown"];
			var pal = this[type+"Palette"];
			dojo.style.toggleShowing(dd);
			if(!pal){
				pal = this[type+"Palette"] = dojo.widget.createWidget("ColorPalette", {}, dd, "first");
				var fcp = pal.domNode;
				with(dd.style){
					width = dojo.html.getOuterWidth(fcp) + "px";
					height = dojo.html.getOuterHeight(fcp) + "px";
					zIndex = 1002;
					position = "absolute";
				}

				dojo.event.connect(	"after",
									pal, "onColorSelect",
									this, "exec",
									function(mi){ mi.args.unshift(type); return mi.proceed(); }
				);

				dojo.event.connect(	"after",
									pal, "onColorSelect",
									dojo.style, "toggleShowing",
									this, function(mi){ mi.args.unshift(dd); return mi.proceed(); }
				);

				var cid = this.clickInterceptDiv;
				if(!cid){
					cid = this.clickInterceptDiv = document.createElement("div");
					document.body.appendChild(cid);
					with(cid.style){
						backgroundColor = "transparent";
						top = left = "0px";
						height = width = "100%";
						position = "absolute";
						border = "none";
						display = "none";
						zIndex = 1001;
					}
					dojo.event.connect(cid, "onclick", function(){ cid.style.display = "none"; });
				}
				dojo.event.connect(pal, "onColorSelect", function(){ cid.style.display = "none"; });

				dojo.event.kwConnect({
					srcObj:		document.body, 
					srcFunc:	"onclick", 
					targetObj:	this,
					targetFunc:	"hideAllDropDowns",
					once:		true
				});
				document.body.appendChild(dd);
			}
			dojo.style.toggleShowing(this.clickInterceptDiv);
			var pos = dojo.style.abs(this[type+"Button"]);
			dojo.html.placeOnScreenPoint(dd, pos.x, pos.y, 0, false);
			if(pal.bgIframe){
				with(pal.bgIframe.style){
					display = "block";
					left = dd.style.left;
					top = dd.style.top;
					width = dojo.style.getOuterWidth(dd)+"px";
					height = dojo.style.getOuterHeight(dd)+"px";
				}
			}
		},

		uninitialize: function(){
			if(!dojo.render.html.ie){
				// apparently this causes leakage on IE!
				dojo.event.kwDisconnect({
					srcObj:		document.body, 
					srcFunc:	"onclick", 
					targetObj:	this,
					targetFunc:	"hideAllDropDowns",
					once:		true
				});
			}
		},

		// stub for observers
		exec: function(what, arg){ /* dojo.debug(what, new Date()); */ },

		hideUnusableButtons: function(obj){
			var op = obj||dojo.widget.html.RichText.prototype;
			dojo.lang.forEach(this.commandList,
				function(cmd){
					if(this[cmd+"Button"]){
						var cb = this[cmd+"Button"];
						if(!op.queryCommandAvailable(cmd)){
							cb.style.display = "none";
							cb.parentNode.style.display = "none";
						}
					}
				},
				this);
				if(this.oneLineTr){
					var lastVisibleIsSpacer = false;
					var lastVisible = false;
					var tds = this.oneLineTr.getElementsByTagName("td");
					dojo.lang.forEach(tds, function(td){
						if(td.getAttribute("isSpacer")){
							if(td.style.display != "none"){
								if(lastVisibleIsSpacer){
									td.style.display = "none";
								}
								lastVisibleIsSpacer = true;
							}else{
								lastVisible = td;
								lastVisibleIsSpacer = true;
							}
						}else{
							if(td.style.display != "none"){
								lastVisible = td;
								lastVisibleIsSpacer = false;
							}
						}
					});
				}
		},

		highlightButton: function(name){
			var bn = name+"Button";
			if(this[bn]){
				with(this[bn].style){
					backgroundColor = "White";
					border = "1px solid #aeaeab";
				}
			}
		},

		unhighlightButton: function(name){
			var bn = name+"Button";
			if(this[bn]){
				// dojo.debug("unhighlighting:", name);
				with(this[bn].style){
					backgroundColor = "";
					border = "";
				}
			}
		}
	},
	"html",
	function(){
		// dojo.event.connect(this, "fillInTemplate", this, "hideUnusableButtons");
		dojo.event.connect(this, "fillInTemplate", dojo.lang.hitch(this, function(){
			if(dojo.render.html.ie){
				this.domNode.style.zoom = 1.0;
			}
		}));
	}
);

__CPAN_FILE__ src/widget/AnimatedPng.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.AnimatedPng");
dojo.provide("dojo.widget.html.AnimatedPng");

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");


dojo.widget.defineWidget(
	"dojo.widget.html.AnimatedPng",
	dojo.widget.HtmlWidget,
	{

		widgetType: "AnimatedPng",
		isContainer: false,

		domNode: null,
		width: 0,
		height: 0,
		aniSrc: '',
		interval: 100,

		cellWidth: 0,
		cellHeight: 0,
		aniCols: 1,
		aniRows: 1,
		aniCells: 1,

		blankSrc: dojo.uri.dojoUri("src/widget/templates/images/blank.gif"),

		templateString: '<img class="dojoAnimatedPng" />',

		postCreate: function(){
			this.cellWidth = this.width;
			this.cellHeight = this.height;

			var img = new Image();
			var self = this;

			img.onload = function(){ self.initAni(img.width, img.height); };
			img.src = this.aniSrc;
		},

		initAni: function(w, h){

			this.domNode.src = this.blankSrc;
			this.domNode.width = this.cellWidth;
			this.domNode.height = this.cellHeight;
			this.domNode.style.backgroundImage = 'url('+this.aniSrc+')';
			this.domNode.style.backgroundRepeat = 'no-repeat';

			this.aniCols = Math.floor(w/this.cellWidth);
			this.aniRows = Math.floor(h/this.cellHeight);
			this.aniCells = this.aniCols * this.aniRows;
			this.aniFrame = 0;

			window.setInterval(dojo.lang.hitch(this, 'tick'), this.interval);
		},

		tick: function(){

			this.aniFrame++;
			if (this.aniFrame == this.aniCells) this.aniFrame = 0;

			var col = this.aniFrame % this.aniCols;
			var row = Math.floor(this.aniFrame / this.aniCols);

			var bx = -1 * col * this.cellWidth;
			var by = -1 * row * this.cellHeight;

			this.domNode.style.backgroundPosition = bx+'px '+by+'px';
		}
	}
);

__CPAN_FILE__ src/widget/TreeRPCController.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/


dojo.provide("dojo.widget.TreeRPCController");

dojo.require("dojo.event.*");
dojo.require("dojo.json")
dojo.require("dojo.io.*");
dojo.require("dojo.widget.TreeLoadingController");

dojo.widget.tags.addParseTreeHandler("dojo:TreeRPCController");

dojo.widget.TreeRPCController = function(){
	dojo.widget.TreeLoadingController.call(this);
}

dojo.inherits(dojo.widget.TreeRPCController, dojo.widget.TreeLoadingController);

dojo.lang.extend(dojo.widget.TreeRPCController, {
	widgetType: "TreeRPCController",

	/**
	 * Make request to server about moving children.
	 *
	 * Request returns "true" if move succeeded,
	 * object with error field if failed
	 *
	 * I can't leave DragObject floating until async request returns, need to return false/true
	 * so making it sync way...
	 *
	 * Also, "loading" icon is not shown until function finishes execution, so no indication for remote request.
	*/
	doMove: function(child, newParent, index){

		//if (newParent.isTreeNode) newParent.markLoading();

		var params = {
			// where from
			child: this.getInfo(child),
			childTree: this.getInfo(child.tree),
			// where to
			newParent: this.getInfo(newParent),
			newParentTree: this.getInfo(newParent.tree),
			newIndex: index
		};

		var success;

		this.runRPC({		
			url: this.getRPCUrl('move'),
			/* I hitch to get this.loadOkHandler */
			load: function(response){
				success = this.doMoveProcessResponse(response, child, newParent, index) ;
			},
			sync: true,
			lock: [child, newParent],
			params: params
		});


		return success;
	},

	doMoveProcessResponse: function(response, child, newParent, index){

		if(!dojo.lang.isUndefined(response.error)){
			this.RPCErrorHandler("server", response.error);
			return false;
		}

		var args = [child, newParent, index];
		return dojo.widget.TreeLoadingController.prototype.doMove.apply(this, args);

	},


	doRemoveNode: function(node, callObj, callFunc){

		var params = {
			node: this.getInfo(node),
			tree: this.getInfo(node.tree)
		}

		this.runRPC({
				url: this.getRPCUrl('removeNode'),
				/* I hitch to get this.loadOkHandler */
				load: function(response){
					this.doRemoveNodeProcessResponse(response, node, callObj, callFunc) 
				},
				params: params,
				lock: [node]
		});

	},


	doRemoveNodeProcessResponse: function(response, node, callObj, callFunc){
		if(!dojo.lang.isUndefined(response.error)){
			this.RPCErrorHandler("server", response.error);
			return false;
		}

		if(!response){ return false; }

		if(response == true){
			/* change parent succeeded */
			var args = [ node, callObj, callFunc ];
			dojo.widget.TreeLoadingController.prototype.doRemoveNode.apply(this, args);

			return;
		}else if(dojo.lang.isObject(response)){
			dojo.raise(response.error);
		}else{
			dojo.raise("Invalid response "+response)
		}


	},



	// -----------------------------------------------------------------------------
	//                             Create node stuff
	// -----------------------------------------------------------------------------


	doCreateChild: function(parent, index, output, callObj, callFunc){

			var params = {
				tree: this.getInfo(parent.tree),
				parent: this.getInfo(parent),
				index: index,
				data: output
			}

			this.runRPC({
				url: this.getRPCUrl('createChild'),
				load: function(response) {
					// suggested data is dead, fresh data from server is used
					this.doCreateChildProcessResponse( response, parent, index, callObj, callFunc) 
				},
				params: params,
				lock: [parent]
			});

	},

	doCreateChildProcessResponse: function(response, parent, index, callObj, callFunc){

		if(!dojo.lang.isUndefined(response.error)){
			this.RPCErrorHandler("server",response.error);
			return false;
		}

		if(!dojo.lang.isObject(response)){
			dojo.raise("Invalid result "+response)
		}

		var args = [parent, index, response, callObj, callFunc];
		
		dojo.widget.TreeLoadingController.prototype.doCreateChild.apply(this, args);
	}
});

__CPAN_FILE__ src/widget/TaskBar.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.TaskBar");
dojo.provide("dojo.widget.TaskBarItem");
dojo.require("dojo.widget.Widget");

dojo.widget.TaskBar = function(){
	dojo.widget.Widget.call(this);

	this.widgetType = "TaskBar";
	this.isContainer = true;
}
dojo.inherits(dojo.widget.TaskBar, dojo.widget.Widget);
dojo.widget.tags.addParseTreeHandler("dojo:taskbar");

dojo.widget.TaskBarItem = function(){
	dojo.widget.Widget.call(this);

	this.widgetType = "TaskBarItem";
}
dojo.inherits(dojo.widget.TaskBarItem, dojo.widget.Widget);
dojo.widget.tags.addParseTreeHandler("dojo:taskbaritem");

dojo.requireAfterIf("html", "dojo.widget.html.TaskBar");

__CPAN_FILE__ src/widget/TabContainer.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.TabContainer");
dojo.provide("dojo.widget.html.TabContainer");
dojo.provide("dojo.widget.Tab");

dojo.require("dojo.lang.func");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.event.*");
dojo.require("dojo.html");
dojo.require("dojo.style");
dojo.require("dojo.html.layout");

//////////////////////////////////////////
// TabContainer -- a set of Tabs
//////////////////////////////////////////
dojo.widget.html.TabContainer = function() {
	dojo.widget.HtmlWidget.call(this);
}

dojo.inherits(dojo.widget.html.TabContainer, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.TabContainer, {
	widgetType: "TabContainer",
    isContainer: true,

	// Constructor arguments
	labelPosition: "top",
	closeButton: "none",

	useVisibility: false,		// true-->use visibility:hidden instead of display:none
	
	// if false, TabContainers size changes according to size of currently selected tab
	doLayout: true,

	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlTabContainer.html"),
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlTabContainer.css"),

	selectedTab: "",		// initially selected tab (widgetId)

	fillInTemplate: function(args, frag) {
		// Copy style info from input node to output node
		var source = this.getFragNodeRef(frag);
		dojo.html.copyStyle(this.domNode, source);

		dojo.widget.html.TabContainer.superclass.fillInTemplate.call(this, args, frag);
	},

	postCreate: function(args, frag) {
		// Load all the tabs, creating a label for each one
		for(var i=0; i<this.children.length; i++){
			this._setupTab(this.children[i]);
		}

		if (this.closeButton=="pane") {
			var div = document.createElement("div");
			dojo.html.addClass(div, "dojoTabPanePaneClose");
			var self = this;
			dojo.event.connect(div, "onclick", function(){ self._runOnCloseTab(self.selectedTabWidget); });
			dojo.event.connect(div, "onmouseover", function(){ dojo.html.addClass(div, "dojoTabPanePaneCloseHover"); });
			dojo.event.connect(div, "onmouseout", function(){ dojo.html.removeClass(div, "dojoTabPanePaneCloseHover"); });
			this.dojoTabLabels.appendChild(div);
		}

		if(this.doLayout){
			dojo.html.addClass(this.dojoTabLabels, "dojoTabLabels-"+this.labelPosition);
		} else {
			dojo.html.addClass(this.dojoTabLabels, "dojoTabLabels-"+this.labelPosition+"-noLayout");
		}

        this._doSizing();

		// Display the selected tab
		if(this.selectedTabWidget){
			this.selectTab(this.selectedTabWidget, true);
		}
	},

	addChild: function(child, overrideContainerNode, pos, ref, insertIndex){
		this._setupTab(child);
		dojo.widget.html.TabContainer.superclass.addChild.call(this,child, overrideContainerNode, pos, ref, insertIndex);

		// in case the tab labels have overflowed from one line to two lines
		this._doSizing();
	},

	_setupTab: function(tab){
		tab.domNode.style.display="none";

		// Create label
		tab.div = document.createElement("div");
		dojo.widget.wai.setAttr(tab.div, "waiRole", "tab");
		dojo.html.addClass(tab.div, "dojoTabPaneTab");
		var span = document.createElement("span");
		span.innerHTML = tab.label;
		dojo.html.disableSelection(span);
		if (this.closeButton=="tab") {
			var img = document.createElement("div");
			dojo.html.addClass(img, "dojoTabPaneTabClose");
			var self = this;
			dojo.event.connect(img, "onclick", function(evt){ self._runOnCloseTab(tab); dojo.event.browser.stopEvent(evt); });
			dojo.event.connect(img, "onmouseover", function(){ dojo.html.addClass(img,"dojoTabPaneTabCloseHover"); });
			dojo.event.connect(img, "onmouseout", function(){ dojo.html.removeClass(img,"dojoTabPaneTabCloseHover"); });
			span.appendChild(img);
		}
		tab.div.appendChild(span);
		this.dojoTabLabels.appendChild(tab.div);
		
		var self = this;
		dojo.event.connect(tab.div, "onclick", function(){ self.selectTab(tab); });

		if(!this.selectedTabWidget || this.selectedTab==tab.widgetId || tab.selected){
    		this.selectedTabWidget = tab;
        } else {
            this._hideTab(tab);
        }

		dojo.html.addClass(tab.domNode, "dojoTabPane");
		with(tab.domNode.style){
			top = dojo.style.getPixelValue(this.containerNode, "padding-top", true);
			left = dojo.style.getPixelValue(this.containerNode, "padding-left", true);
		}
	},

	// Configure the content pane to take up all the space except for where the tab labels are
	_doSizing: function(){
		// position the labels and the container node
		var labelAlign=this.labelPosition.replace(/-h/,"");
		var children = [
			{domNode: this.dojoTabLabels, layoutAlign: labelAlign},
			{domNode: this.containerNode, layoutAlign: "client"}
		];


		if (this.doLayout) {
			dojo.html.layout(this.domNode, children);
		} 
			
		// size the current tab
		// TODO: should have ptr to current tab rather than searching
		var cw=dojo.style.getContentWidth(this.containerNode);
		var ch=dojo.style.getContentHeight(this.containerNode);
		dojo.lang.forEach(this.children, function(child){
			//if (this.doLayout) {
				if(child.selected){
					child.resizeTo(cw, ch);
				} 
			//} else {
			//	child.onResized();
			//}
		});
		
	},

    removeChild: function(tab) {

		// remove tab event handlers
		dojo.event.disconnect(tab.div, "onclick", function () { });
		if (this.closeButton=="tab") {
			var img = tab.div.lastChild.lastChild;
			if (img) {
				dojo.html.removeClass(img, "dojoTabPaneTabClose", function () { });
				dojo.event.disconnect(img, "onclick", function () { });
				dojo.event.disconnect(img, "onmouseover", function () { });
				dojo.event.disconnect(img, "onmouseout", function () { });
			}
		}

        dojo.widget.html.TabContainer.superclass.removeChild.call(this, tab);

        dojo.html.removeClass(tab.domNode, "dojoTabPane");
        this.dojoTabLabels.removeChild(tab.div);
        delete(tab.div);

        if (this.selectedTabWidget === tab) {
            this.selectedTabWidget = undefined;
            if (this.children.length > 0) {
                this.selectTab(this.children[0], true);
            }
        }

		// in case the tab labels have overflowed from one line to two lines
		this._doSizing();
    },

    selectTab: function(tab, _noRefresh) {
		// Deselect old tab and select new one
		if (this.selectedTabWidget) {
			this._hideTab(this.selectedTabWidget);
		}
		this.selectedTabWidget = tab;
		this._showTab(tab, _noRefresh);
	},

	_showTab: function(tab, _noRefresh) {
		dojo.html.addClass(tab.div, "current");
		tab.selected=true;
		if ( this.useVisibility && !dojo.render.html.ie ) {
			tab.domNode.style.visibility="visible";
		} else {
			// make sure we dont refresh onClose and on postCreate
			// speeds up things a bit when using refreshOnShow and fixes #646
			if(_noRefresh && tab.refreshOnShow){
				var tmp = tab.refreshOnShow;
				tab.refreshOnShow = false;
				tab.show();
				tab.refreshOnShow = tmp;
			}else{
				tab.show();
			}

			tab.resizeTo(
				dojo.style.getContentWidth(this.containerNode),
				dojo.style.getContentHeight(this.containerNode)
			);
		}
	},

	_hideTab: function(tab) {
		dojo.html.removeClass(tab.div, "current");
		tab.selected=false;
		if( this.useVisibility ){
			tab.domNode.style.visibility="hidden";
		}else{
			tab.hide();
		}
	},

	_runOnCloseTab: function(tab) {
		var onc = tab.extraArgs.onClose || tab.extraArgs.onclose;
		var fcn = dojo.lang.isFunction(onc) ? onc : window[onc];
		var remove = dojo.lang.isFunction(fcn) ? fcn(this,tab) : true;
		if(remove) {
			this.removeChild(tab);
			// makes sure we can clean up executeScripts in ContentPane onUnLoad
			tab.destroy();
		}
	},

	onResized: function() {
		this._doSizing();
	}
});
dojo.widget.tags.addParseTreeHandler("dojo:TabContainer");

// These arguments can be specified for the children of a TabContainer.
// Since any widget can be specified as a TabContainer child, mix them
// into the base widget class.  (This is a hack, but it's effective.)
dojo.lang.extend(dojo.widget.Widget, {
	label: "",
	selected: false	// is this tab currently selected?
});

__CPAN_FILE__ src/widget/TitlePane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.TitlePane");
dojo.requireAfterIf("html", "dojo.widget.html.TitlePane");

__CPAN_FILE__ src/widget/Toggler.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Toggler");
dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");

// clicking on this node shows/hides another widget

dojo.widget.Toggler = function(){
	dojo.widget.DomWidget.call(this);
}

dojo.inherits(dojo.widget.Toggler, dojo.widget.DomWidget);

dojo.lang.extend(dojo.widget.Toggler, {
	widgetType: "Toggler",
	
	// Associated widget 
	targetId: '',
	
	fillInTemplate: function() {
		dojo.event.connect(this.domNode, "onclick", this, "onClick");
	},
	
	onClick: function() {
		var pane = dojo.widget.byId(this.targetId);
		if(!pane){ return; }
		pane.explodeSrc = this.domNode;
		pane.toggleShowing();
	}
});
dojo.widget.tags.addParseTreeHandler("dojo:toggler");

__CPAN_FILE__ src/widget/TreeLoadingController.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/


dojo.provide("dojo.widget.TreeLoadingController");

dojo.require("dojo.widget.TreeBasicController");
dojo.require("dojo.event.*");
dojo.require("dojo.json")
dojo.require("dojo.io.*");


dojo.widget.tags.addParseTreeHandler("dojo:TreeLoadingController");


dojo.widget.TreeLoadingController = function() {
	dojo.widget.TreeBasicController.call(this);
}

dojo.inherits(dojo.widget.TreeLoadingController, dojo.widget.TreeBasicController);


dojo.lang.extend(dojo.widget.TreeLoadingController, {
	widgetType: "TreeLoadingController",

	RPCUrl: "",

	RPCActionParam: "action", // used for GET for RPCUrl


	/**
	 * Common RPC error handler (dies)
	*/
	RPCErrorHandler: function(type, obj, evt) {
		alert( "RPC Error: " + (obj.message||"no message"));
	},



	getRPCUrl: function(action) {

		// RPCUrl=local meant SOLELY for DEMO and LOCAL TESTS.
		// May lead to widgetId collisions
		if (this.RPCUrl == "local") {
			var dir = document.location.href.substr(0, document.location.href.lastIndexOf('/'));
			var localUrl = dir+"/"+action;
			//dojo.debug(localUrl);
			return localUrl;
		}

		if (!this.RPCUrl) {
			dojo.raise("Empty RPCUrl: can't load");
		}

		return this.RPCUrl + ( this.RPCUrl.indexOf("?") > -1 ? "&" : "?") + this.RPCActionParam+"="+action;
	},


	/**
	 * Add all loaded nodes from array obj as node children and expand it
	*/
	loadProcessResponse: function(node, result, callObj, callFunc) {

		if (!dojo.lang.isUndefined(result.error)) {
			this.RPCErrorHandler("server", result.error);
			return false;
		}

		//dojo.debugShallow(result);

		var newChildren = result;

		if (!dojo.lang.isArray(newChildren)) {
			dojo.raise('loadProcessResponse: Not array loaded: '+newChildren);
		}

		for(var i=0; i<newChildren.length; i++) {
			// looks like dojo.widget.manager needs no special "add" command
			newChildren[i] = dojo.widget.createWidget(node.widgetType, newChildren[i]);
			node.addChild(newChildren[i]);
		}


		//node.addAllChildren(newChildren);

		node.state = node.loadStates.LOADED;

		//dojo.debug(callFunc);

		if (dojo.lang.isFunction(callFunc)) {
			callFunc.apply(dojo.lang.isUndefined(callObj) ? this : callObj, [node, newChildren]);
		}
		//this.expand(node);
	},

	getInfo: function(obj) {
		return obj.getInfo();
	},

	runRPC: function(kw) {
		var _this = this;

		var handle = function(type, data, evt) {
			// unlock BEFORE any processing is done
			// so errorHandler may apply locking
			if (kw.lock) {
				dojo.lang.forEach(kw.lock,
					function(t) { t.unlock() }
				);
			}

			if(type == "load"){
				kw.load.call(this, data);
			}else{
				this.RPCErrorHandler(type, data, evt);
			}

		}

		if (kw.lock) {
			dojo.lang.forEach(kw.lock,
				function(t) { t.lock() }
			);
		}


		dojo.io.bind({
			url: kw.url,
			/* I hitch to get this.loadOkHandler */
			handle: dojo.lang.hitch(this, handle),
			mimetype: "text/json",
			preventCache: true,
			sync: kw.sync,
			content: { data: dojo.json.serialize(kw.params) }
		});
	},



	/**
	 * Load children of the node from server
	 * Synchroneous loading doesn't break control flow
	 * I need sync mode for DnD
	*/
	loadRemote: function(node, sync, callObj, callFunc){
		var _this = this;

		var params = {
			node: this.getInfo(node),
			tree: this.getInfo(node.tree)
		};

		//dojo.debug(callFunc)

		this.runRPC({
			url: this.getRPCUrl('getChildren'),
			load: function(result) {
				_this.loadProcessResponse(node, result, callObj, callFunc) ;
			},
			sync: sync,
			lock: [node],
			params: params
		});

	},


	expand: function(node, sync, callObj, callFunc) {

		if (node.state == node.loadStates.UNCHECKED && node.isFolder) {

			this.loadRemote(node, sync,
				this,
				function(node, newChildren) {
					this.expand(node, sync, callObj, callFunc);
				}
			);

			return;
		}

		dojo.widget.TreeBasicController.prototype.expand.apply(this, arguments);

	},



	doMove: function(child, newParent, index) {
		/* load nodes into newParent in sync mode, if needed, first */
		if (newParent.isTreeNode && newParent.state == newParent.loadStates.UNCHECKED) {
			this.loadRemote(newParent, true);
		}

		return dojo.widget.TreeBasicController.prototype.doMove.apply(this, arguments);
	},


	doCreateChild: function(parent, index, data, callObj, callFunc) {

		/* load nodes into newParent in sync mode, if needed, first */
		if (parent.state == parent.loadStates.UNCHECKED) {
			this.loadRemote(parent, true);
		}

		return dojo.widget.TreeBasicController.prototype.doCreateChild.apply(this, arguments);
	}



});

__CPAN_FILE__ src/widget/Tree.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/**
 * Tree model does all the drawing, visual node management etc.
 * Throws events about clicks on it, so someone may catch them and process
 * Tree knows nothing about DnD stuff, covered in TreeDragAndDrop and (if enabled) attached by controller
*/

/**
 * TODO: use domNode.cloneNode instead of createElement for grid
 * Should be faster (lyxsus)
 */
dojo.provide("dojo.widget.Tree");

dojo.require("dojo.event.*");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.TreeNode");



// make it a tag
dojo.widget.tags.addParseTreeHandler("dojo:Tree");


dojo.widget.Tree = function() {
	dojo.widget.HtmlWidget.call(this);

	this.eventNames = {};

	this.tree = this;
	this.DNDAcceptTypes = [];
	this.actionsDisabled = [];

}
dojo.inherits(dojo.widget.Tree, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.Tree, {
	widgetType: "Tree",

	eventNamesDefault: {
		// new child does not get domNode filled in (only template draft)
		// until addChild->createDOMNode is called(program way) OR createDOMNode (html-way)
		// hook events to operate on new DOMNode, create dropTargets etc
		createDOMNode: "createDOMNode",
		// tree created.. Perform tree-wide actions if needed
		treeCreate: "treeCreate",
		treeDestroy: "treeDestroy",
		// expand icon clicked
		treeClick: "treeClick",
		// node icon clicked
		iconClick: "iconClick",
		// node title clicked
		titleClick: "titleClick",

		moveFrom: "moveFrom",
		moveTo: "moveTo",
		addChild: "addChild",
		removeNode: "removeNode",
		expand: "expand",
		collapse: "collapse"
	},

	isContainer: true,

	DNDMode: "off",

	lockLevel: 0, // lock ++ unlock --, so nested locking works fine

	strictFolders: true,

	DNDModes: {
		BETWEEN: 1,
		ONTO: 2
	},

	DNDAcceptTypes: "",

	templateCssPath: dojo.uri.dojoUri("src/widget/templates/images/Tree/Tree.css"),

	templateString: '<div class="dojoTree"></div>',

	isExpanded: true, // consider this "root node" to be always expanded

	isTree: true,

	objectId: "",

	// autoCreate if not "off"
	// used to get the autocreated controller ONLY.
	// generally, tree DOES NOT KNOW about its CONTROLLER, it just doesn't care
	// controller gets messages via dojo.event
	controller: "",

	// autoCreate if not "off"
	// used to get the autocreated selector ONLY.
	// generally, tree DOES NOT KNOW its SELECTOR
	// binding is made with dojo.event
	selector: "",

	// used ONLY at initialization time
	menu: "", // autobind menu if menu's widgetId is set here

	expandLevel: "", // expand to level automatically

	//
	// these icons control the grid and expando buttons for the whole tree
	//

	blankIconSrc: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_blank.gif"),

	gridIconSrcT: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_t.gif"), // for non-last child grid
	gridIconSrcL: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_l.gif"), // for last child grid
	gridIconSrcV: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_v.gif"), // vertical line
	gridIconSrcP: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_p.gif"), // for under parent item child icons
	gridIconSrcC: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_c.gif"), // for under child item child icons
	gridIconSrcX: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_x.gif"), // grid for sole root item
	gridIconSrcY: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_y.gif"), // grid for last rrot item
	gridIconSrcZ: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_z.gif"), // for under root parent item child icon

	expandIconSrcPlus: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_expand_plus.gif"),
	expandIconSrcMinus: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_expand_minus.gif"),
	expandIconSrcLoading: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_loading.gif"),


	iconWidth: 18,
	iconHeight: 18,


	//
	// tree options
	//

	showGrid: true,
	showRootGrid: true,

	actionIsDisabled: function(action) {
		var _this = this;
		return dojo.lang.inArray(_this.actionsDisabled, action)
	},


	actions: {
    	ADDCHILD: "ADDCHILD"
	},


	getInfo: function() {
		var info = {
			widgetId: this.widgetId,
			objectId: this.objectId
		}

		return info;
	},

	initializeController: function() {
		if (this.controller != "off") {
			if (this.controller) {
				this.controller = dojo.widget.byId(this.controller);
			}
			else {
				// create default controller here
				dojo.require("dojo.widget.TreeBasicController");
				this.controller = dojo.widget.createWidget("TreeBasicController",
					{ DNDController: (this.DNDMode ? "create" : ""), dieWithTree: true }
				 );

			}
			this.controller.listenTree(this); // controller listens to my events

		} else {
			this.controller = null;
		}
	},

	initializeSelector: function() {

		if (this.selector != "off") {
			if (this.selector) {
				this.selector = dojo.widget.byId(this.selector);
			}
			else {
				// create default controller here
				dojo.require("dojo.widget.TreeSelector");
				this.selector = dojo.widget.createWidget("TreeSelector", {dieWithTree: true});
			}

			this.selector.listenTree(this);

		} else {
			this.selector = null;
		}
	},

	initialize: function(args, frag){

		var _this = this;

		for(name in this.eventNamesDefault) {
			if (dojo.lang.isUndefined(this.eventNames[name])) {
				this.eventNames[name] = this.widgetId+"/"+this.eventNamesDefault[name];
			}
		}

		for(var i=0; i<this.actionsDisabled.length; i++) {
			this.actionsDisabled[i] = this.actionsDisabled[i].toUpperCase();
		}

		if (this.DNDMode == "off") {
			this.DNDMode = 0;
		} else if (this.DNDMode == "between") {
			this.DNDMode = this.DNDModes.ONTO | this.DNDModes.BETWEEN;
		} else if (this.DNDMode == "onto") {
			this.DNDMode = this.DNDModes.ONTO;
		}

		this.expandLevel = parseInt(this.expandLevel);

		this.initializeSelector();
		this.initializeController();

		if (this.menu) {
			this.menu = dojo.widget.byId(this.menu);
			this.menu.listenTree(this);
		}


		this.containerNode = this.domNode;

	},


	postCreate: function() {
		this.createDOMNode();
	},


	createDOMNode: function() {

		dojo.html.disableSelection(this.domNode);

		for(var i=0; i<this.children.length; i++){
			this.children[i].parent = this; // root nodes have tree as parent

			var node = this.children[i].createDOMNode(this, 0);


			this.domNode.appendChild(node);
		}


		if (!this.showRootGrid){
			for(var i=0; i<this.children.length; i++){
				this.children[i].expand();
			}
		}

		dojo.event.topic.publish(this.eventNames.treeCreate, { source: this } );

	},


	destroy: function() {
		dojo.event.topic.publish(this.tree.eventNames.treeDestroy, { source: this } );

		return dojo.widget.HtmlWidget.prototype.destroy.apply(this, arguments);
	},


	addChild: function(child, index) {

//		dojo.debug("doAddChild "+index+" called for "+child);

		var message = {
			child: child,
			index: index,
			parent: this,
			// remember if dom was already initialized
			// initialized => no createDOMNode => no createDOMNode event
			domNodeInitialized: child.domNodeInitialized
		}

		this.doAddChild.apply(this, arguments);

		dojo.event.topic.publish(this.tree.eventNames.addChild, message);
	},


	// not called for initial tree building. See createDOMNode instead.
	// builds child html node if needed
	// index is "last node" by default
	/**
	 * FIXME: Is it possible that removeNode from the tree will cause leaks cause of attached events ?
	 * if yes, then only attach events in addChild and detach in remove.. Seems all ok yet.
	*/
	doAddChild: function(child, index){

		if (dojo.lang.isUndefined(index)) {
			index = this.children.length;
		}

		if (!child.isTreeNode){
			dojo.raise("You can only add TreeNode widgets to a "+this.widgetType+" widget!");
			return;
		}

		// usually it is impossible to change "isFolder" state, but if anyone wants to add a child to leaf,
		// it is possible program-way.
		if (this.isTreeNode){
			if (!this.isFolder) { // just became a folder.
				//dojo.debug("becoming folder "+this);
				this.setFolder();
			}
		}

		// adjust tree
		var _this = this;
		dojo.lang.forEach(child.getDescendants(), function(elem) { elem.tree = _this.tree; });

		// fix parent
		child.parent = this;


		// no dynamic loading for those who become parents
		if (this.isTreeNode) {
			this.state = this.loadStates.LOADED;
		}

		// add new child into DOM after it was added into children
		if (index < this.children.length) { // children[] already has child
			//dojo.debug("Inserting before "+this.children[index].title);
			dojo.dom.insertBefore(child.domNode, this.children[index].domNode);
		} else {
			this.containerNode.appendChild(child.domNode);
			if (this.isExpanded && this.isTreeNode) {
				/* When I add children to hidden containerNode => show container w/ them */
				this.showChildren();
			}
		}


		this.children.splice(index, 0, child);

		//dojo.debugShallow(this.children);


		// if node exists - adjust its depth, otherwise build it
		if (child.domNodeInitialized) {
			var d = this.isTreeNode ? this.depth : -1;
			child.adjustDepth( d - child.depth + 1 );


			// update icons to link generated dom with Tree => updateParentGrid
			// if I moved child from LastNode inside the tree => need to link it up'n'down =>
			// updateExpandGridColumn
			// if I change depth => need to update all grid..
			child.updateIconTree();
		} else {
			//dojo.debug("Create domnode ");
			child.depth = this.isTreeNode ? this.depth+1 : 0;
			child.createDOMNode(child.tree, child.depth);
		}



		// Use-case:
		// When previous sibling was created => it was last, no children after it
		// so it did not create link down => let's add it for all descendants
		// Use-case:
		// a child was moved down under the last node so last node should be updated
		var prevSibling = child.getPreviousSibling();
		if (child.isLastNode() && prevSibling) {
			prevSibling.updateExpandGridColumn();
		}


		//dojo.debug("Added child "+child);



	},




	makeBlankImg: function() {
		var img = document.createElement('img');

		img.style.width = this.iconWidth + 'px';
		img.style.height = this.iconHeight + 'px';
		img.src = this.blankIconSrc;
		img.style.verticalAlign = 'middle';

		return img;
	},


	updateIconTree: function(){

		//dojo.debug("Update icons for "+this)
		if (!this.isTree) {
			this.updateIcons();
		}

		for(var i=0; i<this.children.length; i++){
			this.children[i].updateIconTree();
		}

	},

	toString: function() {
		return "["+this.widgetType+" ID:"+this.widgetId+"]"
	},




	/**
	 * Move child to newParent as last child
	 * redraw tree and update icons.
	 *
	 * Called by target, saves source in event.
	 * events are published for BOTH trees AFTER update.
	*/
	move: function(child, newParent, index) {

		//dojo.debug(child+" "+newParent+" at "+index);

		var oldParent = child.parent;
		var oldTree = child.tree;

		this.doMove.apply(this, arguments);

		var newParent = child.parent;
		var newTree = child.tree;

		var message = {
				oldParent: oldParent, oldTree: oldTree,
				newParent: newParent, newTree: newTree,
				child: child
		};

		/* publish events here about structural changes for both source and target trees */
		dojo.event.topic.publish(oldTree.eventNames.moveFrom, message);
		dojo.event.topic.publish(newTree.eventNames.moveTo, message);

	},


	/* do actual parent change here. Write remove child first */
	doMove: function(child, newParent, index) {
		//var parent = child.parent;
		child.parent.doRemoveNode(child);

		newParent.doAddChild(child, index);
	},



// ================================ removeNode ===================================

	removeNode: function(child) {
		if (!child.parent) return;

		var oldTree = child.tree;
		var oldParent = child.parent;

		var removedChild = this.doRemoveNode.apply(this, arguments);


		dojo.event.topic.publish(this.tree.eventNames.removeNode,
			{ child: removedChild, tree: oldTree, parent: oldParent }
		);

		return removedChild;
	},


	doRemoveNode: function(child) {
		if (!child.parent) return;

		var parent = child.parent;

		var children = parent.children;


		var index = child.getParentIndex();
		if (index < 0) {
			dojo.raise("Couldn't find node "+child+" for removal");
		}


		children.splice(index,1);
		dojo.dom.removeNode(child.domNode);

		if (parent.children.length == 0) {
			parent.containerNode.style.display = "none";
		}

		// if WAS last node (children.length decreased already) and has prevSibling
		if (index == children.length && index>0) {
			children[index-1].updateExpandGridColumn();
		}
		// if it WAS first node in WHOLE TREE -
		// update link up of its former lower neighbour(if exists still)
		if (parent instanceof dojo.widget.Tree && index == 0 && children.length>0) {
			children[0].updateExpandGrid();
		}

		//parent.updateIconTree();


		child.parent = child.tree = null;

		return child;
	},

	markLoading: function() {
		// no way to mark tree loading
	},

	unMarkLoading: function() {
		// no way to show that tree finished loading
	},


	lock: function() {
		!this.lockLevel && this.markLoading();
		this.lockLevel++;
	},
	unlock: function() {
		if (!this.lockLevel) {
			dojo.raise("unlock: not locked");
		}
		this.lockLevel--;
		!this.lockLevel && this.unMarkLoading();
	},

	isLocked: function() {
		var node = this;
		while (true) {
			if (node.lockLevel) {
				return true;
			}
			if (node instanceof dojo.widget.Tree) {
				break;
			}
			node = node.parent;
		}

		return false;
	},

	flushLock: function() {
		this.lockLevel = 0;
		this.unMarkLoading();
	}
});



__CPAN_FILE__ src/widget/Chart.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Chart");
dojo.provide("dojo.widget.Chart.PlotTypes");
dojo.provide("dojo.widget.Chart.DataSeries");

dojo.require("dojo.widget.*");
dojo.require("dojo.graphics.color");
dojo.require("dojo.graphics.color.hsl");
dojo.widget.tags.addParseTreeHandler("dojo:chart");

dojo.widget.Chart = function(){
	dojo.widget.Widget.call(this);
	this.widgetType = "Chart";
	this.isContainer = false;
	this.series = [];
	// FIXME: why is this a mixin method?
	this.assignColors = function(){
		var hue=30;
		var sat=120;
		var lum=120;
		var steps = Math.round(330/this.series.length);

		for(var i=0; i<this.series.length; i++){
			var c=dojo.graphics.color.hsl2rgb(hue,sat,lum);
			if(!this.series[i].color){
				this.series[i].color = dojo.graphics.color.rgb2hex(c[0],c[1],c[2]);
			}
			hue += steps;
		}
	};
}
dojo.inherits(dojo.widget.Chart, dojo.widget.Widget);

dojo.widget.Chart.PlotTypes = {
	Bar:"bar",
	Line:"line",
	Scatter:"scatter",
	Bubble:"bubble"
};

/*
 *	Every chart has a set of data series; this is the series.  Note that each
 *	member of value is an object and in the minimum has 2 properties: .x and
 *	.value.
 */
dojo.widget.Chart.DataSeries = function(key, label, plotType, color){
	// FIXME: why the hell are plot types specified neumerically? What is this? C?
	this.id = "DataSeries"+dojo.widget.Chart.DataSeries.count++;
	this.key = key;
	this.label = label||this.id;
	this.plotType = plotType||0;
	this.color = color;
	this.values = [];
};

dojo.lang.extend(dojo.widget.Chart.DataSeries, {
	add: function(v){
		if(v.x==null||v.value==null){
			dojo.raise("dojo.widget.Chart.DataSeries.add: v must have both an 'x' and 'value' property.");
		}
		this.values.push(v);
	},

	clear: function(){
		this.values=[];
	},

	createRange: function(len){
		var idx = this.values.length-1;
		var length = (len||this.values.length);
		return { "index": idx, "length": length, "start":Math.max(idx-length,0) };
	},

	//	trend values
	getMean: function(len){
		var range = this.createRange(len);
		if(range.index<0){ return 0; }
		var t = 0;
		var c = 0;
		for(var i=range.index; i>=range.start; i--){
			var n = parseFloat(this.values[i].value);
			if(!isNaN(n)){ t += n; c++; }
		}
		t /= Math.max(c,1);
		return t;
	},

	getMovingAverage: function(len){
		var range = this.createRange(len);
		if(range.index<0){ return 0; }
		var t = 0;
		var c = 0;
		for(var i=range.index; i>=range.start; i--){
			var n = parseFloat(this.values[i].value);
			if(!isNaN(n)){ t += n; c++; }
		}
		t /= Math.max(c,1);
		return t;
	},

	getVariance: function(len){
		var range = this.createRange(len);
		if(range.index < 0){ return 0; }
		var t = 0; // FIXME: for tom: wtf are t, c, and s?
		var s = 0;
		var c = 0;
		for(var i=range.index; i>=range.start; i--){
			var n = parseFloat(this.values[i].value);
			if(!isNaN(n)){
				t += n;
				s += Math.pow(n,2);
				c++;
			}
		}
		return (s/c)-Math.pow(t/c,2);
	},

	getStandardDeviation: function(len){
		return Math.sqrt(this.getVariance(len));
	},

	getMax: function(len){
		var range = this.createRange(len);
		if(range.index < 0){ return 0; }
		var t = 0;
		for (var i=range.index; i>=range.start; i--){
			var n=parseFloat(this.values[i].value);
			if (!isNaN(n)){
				t=Math.max(n,t);
			}
		}
		return t;
	},

	getMin: function(len){
		var range=this.createRange(len);
		if(range.index < 0){ return 0; }
		var t = 0;
		for(var i=range.index; i>=range.start; i--){
			var n = parseFloat(this.values[i].value);
			if(!isNaN(n)){
				t=Math.min(n,t);
			}
		}
		return t;
	},

	getMedian: function(len){
		var range = this.createRange(len);

		if(range.index<0){ return 0; }

		var a = [];
		for (var i=range.index; i>=range.start; i--){
			var n=parseFloat(this.values[i].value);
			if (!isNaN(n)){
				var b=false;
				for(var j=0; j<a.length&&!b; j++){
					if (n==a[j]) b=true; 
				}
				if(!b){ a.push(n); }
			}
		}
		a.sort();
		if(a.length>0){ return a[Math.ceil(a.length/2)]; }
		return 0;
	},

	getMode: function(len){
		var range=this.createRange(len);
		if(range.index<0){ return 0; }
		var o = {};
		var ret = 0
		var m = 0;
		for(var i=range.index; i>=range.start; i--){
			var n=parseFloat(this.values[i].value);
			if(!isNaN(n)){
				if (!o[this.values[i].value]) o[this.values[i].value] = 1;
				else o[this.values[i].value]++;
			}
		}
		for(var p in o){
			if(m<o[p]){ m=o[p]; ret=p; }
		}
		return parseFloat(ret);
	}
});

dojo.requireIf(dojo.render.svg.support.builtin, "dojo.widget.svg.Chart");
dojo.requireIf(dojo.render.html.ie, "dojo.widget.vml.Chart");

__CPAN_FILE__ src/widget/GoogleMap.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.GoogleMap");
dojo.provide("dojo.widget.GoogleMap.Controls");
dojo.require("dojo.widget.*");
dojo.widget.tags.addParseTreeHandler("dojo:googlemap");

dojo.widget.GoogleMap=function(){
	//	summary
	//	base class for the Google Map widget
	dojo.widget.Widget.call(this);
	this.widgetType="GoogleMap";
	this.isContainer=false;
}
dojo.inherits(dojo.widget.GoogleMap, dojo.widget.Widget);

dojo.widget.GoogleMap.Controls={
	LargeMap:"largemap",
	SmallMap:"smallmap",
	SmallZoom:"smallzoom",
	Scale:"scale",
	MapType:"maptype",
	Overview:"overview",
	get:function(s){
		for(var p in this){
			if(typeof(this[p])=="string"
				&& this[p]==s
			){
				return p;
			}
		}
		return null;
	}
};

dojo.requireAfterIf("html", "dojo.widget.html.GoogleMap");

__CPAN_FILE__ src/widget/MonthlyCalendar.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.MonthlyCalendar");
dojo.provide("dojo.widget.MonthlyCalendar.util");
dojo.require("dojo.widget.DomWidget");
dojo.require("dojo.date");

dojo.widget.MonthlyCalendar= function(){
	dojo.widget.Widget.call(this);
	this.widgetType = "MonthlyCalendar";
	this.isContainer = false;
	// the following aliases prevent breaking people using 0.2.x
	this.months = dojo.date.months;
	this.weekdays = dojo.date.days;
	this.toRfcDate = dojo.widget.MonthlyCalendar.util.toRfcDate;
	this.fromRfcDate = dojo.widget.MonthlyCalendar.util.fromRfcDate;
	this.initFirstSaturday = dojo.widget.MonthlyCalendar.util.initFirstSaturday;
}

dojo.inherits(dojo.widget.MonthlyCalendar, dojo.widget.Widget);
dojo.widget.tags.addParseTreeHandler("dojo:monthlycalendar");

dojo.requireAfterIf("html", "dojo.widget.html.MonthlyCalendar");

dojo.widget.MonthlyCalendar.util= new function() {
	this.months = dojo.date.months;
	this.weekdays = dojo.date.days;
	
	this.toRfcDate = function(jsDate) {
		if(!jsDate) {
			jsDate = this.today;
		}
		var year = jsDate.getFullYear();
		var month = jsDate.getMonth() + 1;
		if (month < 10) {
			month = "0" + month.toString();
		}
		var date = jsDate.getDate();
		if (date < 10) {
			date = "0" + date.toString();
		}
		// because this is a date picker and not a time picker, we treat time 
		// as zero
		return year + "-" + month + "-" + date + "T00:00:00+00:00";
	}
	
	this.fromRfcDate = function(rfcDate) {
		var tempDate = rfcDate.split("-");
		if(tempDate.length < 3) {
			return new Date();
		}
		// fullYear, month, date
		return new Date(parseInt(tempDate[0]), (parseInt(tempDate[1], 10) - 1), parseInt(tempDate[2].substr(0,2), 10));
	}
	
	this.initFirstSaturday = function(month, year) {
		if(!month) {
			month = this.date.getMonth();
		}
		if(!year) {
			year = this.date.getFullYear();
		}
		var firstOfMonth = new Date(year, month, 1);
		return {year: year, month: month, date: 7 - firstOfMonth.getDay()};
	}
}

__CPAN_FILE__ src/widget/DropdownContainer.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.DropdownContainer");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.event.*");
dojo.require("dojo.html");

dojo.widget.defineWidget(
	"dojo.widget.DropdownContainer",
	dojo.widget.HtmlWidget,
	{
		initializer: function(){
		},

		inputWidth: "7em",
		inputId: "",
		inputName: "",
		iconURL: dojo.uri.dojoUri("src/widget/templates/images/combo_box_arrow.png"),
		iconAlt: "",

		inputNode: null,
		buttonNode: null,
		containerNode: null,
		subWidgetNode: null,

		containerToggle: "plain",
		containerToggleDuration: 150,
		containerAnimInProgress: false,

		templateString: '<div><span style="white-space:nowrap"><input type="text" value="" style="vertical-align:middle;" dojoAttachPoint="inputNode" autocomplete="off" /> <img src="${this.iconURL}" alt="${this.iconAlt}" dojoAttachPoint="buttonNode" dojoAttachEvent="onclick: onIconClick;" style="vertical-align:middle; cursor:pointer; cursor:hand;" /></span><br /><div dojoAttachPoint="containerNode" style="display:none;position:absolute;width:12em;background-color:#fff;"></div></div>',
		templateCssPath: "",

		fillInTemplate: function(args, frag){
			var source = this.getFragNodeRef(frag);
			
			this.containerNode.style.left = "";
			this.containerNode.style.top = "";

			if(this.inputId){ this.inputNode.id = this.inputId; }
			if(this.inputName){ this.inputNode.name = this.inputName; }
			this.inputNode.style.width = this.inputWidth;

			dojo.event.connect(this.inputNode, "onchange", this, "onInputChange");
			
			this.containerIframe = new dojo.html.BackgroundIframe(this.containerNode);
			this.containerIframe.size([0,0,0,0]);
		},

		postMixInProperties: function(args, frag, parentComp){
			// now that we know the setting for toggle, get toggle object
			// (default to plain toggler if user specified toggler not present)
			this.containerToggleObj =
				dojo.lfx.toggle[this.containerToggle.toLowerCase()] || dojo.lfx.toggle.plain;
			dojo.widget.DropdownContainer.superclass.postMixInProperties.call(this, args, frag, parentComp);
		},

		onIconClick: function(evt){
			this.toggleContainerShow();
		},

		toggleContainerShow: function(){
			if(dojo.html.isShowing(this.containerNode)){
				this.hideContainer();
			}else{
				this.showContainer();
			}
		},
		
		showContainer: function(){
			this.containerAnimInProgress=true;
			this.containerToggleObj.show(this.containerNode, this.containerToggleDuration, null,
				dojo.lang.hitch(this, this.onContainerShow), this.explodeSrc);
			dojo.lang.setTimeout(this, this.sizeBackgroundIframe, this.containerToggleDuration);
		},

		onContainerShow: function(){
			this.containerAnimInProgress=false;
		},

		hideContainer: function(){
			this.containerAnimInProgress=true;
			this.containerToggleObj.hide(this.containerNode, this.containerToggleDuration, null,
				dojo.lang.hitch(this, this.onContainerHide), this.explodeSrc);
			dojo.lang.setTimeout(this, this.sizeBackgroundIframe, this.containerToggleDuration);
		},

		onContainerHide: function(){
			this.containerAnimInProgress=false;
		},
		
		sizeBackgroundIframe: function(){
			var w = dojo.style.getOuterWidth(this.containerNode);
			var h = dojo.style.getOuterHeight(this.containerNode);
			if(w==0||h==0){
				// need more time to calculate size
				dojo.lang.setTimeout(this, "sizeBackgroundIframe", 100);
				return;
			}
			if(dojo.html.isShowing(this.containerNode)){
				this.containerIframe.size([0,0,w,h]);
			}
		},

		onInputChange: function(){}
	},
	"html"
);

dojo.widget.tags.addParseTreeHandler("dojo:dropdowncontainer");

__CPAN_FILE__ src/widget/validate.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.validate");

dojo.provide("dojo.widget.validate.Textbox");
dojo.provide("dojo.widget.validate.ValidationTextbox");
dojo.provide("dojo.widget.validate.IntegerTextbox");
dojo.provide("dojo.widget.validate.RealNumberTextbox");
dojo.provide("dojo.widget.validate.CurrencyTextbox");
dojo.provide("dojo.widget.validate.IpAddressTextbox");
dojo.provide("dojo.widget.validate.UrlTextbox");
dojo.provide("dojo.widget.validate.EmailTextbox");
dojo.provide("dojo.widget.validate.EmailListTextbox");
dojo.provide("dojo.widget.validate.DateTextbox");
dojo.provide("dojo.widget.validate.TimeTextbox");
dojo.provide("dojo.widget.validate.UsStateTextbox");
dojo.provide("dojo.widget.validate.UsZipTextbox");
dojo.provide("dojo.widget.validate.UsPhoneNumberTextbox");

dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.Manager");
dojo.require("dojo.widget.Parse");
dojo.require("dojo.xml.Parse");
dojo.require("dojo.lang");

dojo.require("dojo.validate.common");
dojo.require("dojo.validate.datetime");
dojo.require("dojo.validate.check");
dojo.require("dojo.validate.web");
dojo.require("dojo.validate.us");

dojo.widget.manager.registerWidgetPackage("dojo.widget.validate");


/*
  ****** Textbox ******

  This widget is a generic textbox field.
  Serves as a base class to derive more specialized functionality in subclasses.
  Has the following properties that can be specified as attributes in the markup.

  @attr id         The textbox id attribute.
  @attr className  The textbox class attribute.
  @attr name       The textbox name attribute.
  @attr value      The textbox value attribute.
  @attr trim       Removes leading and trailing whitespace if true.  Default is false.
  @attr uppercase  Converts all characters to uppercase if true.  Default is false.
  @attr lowercase  Converts all characters to lowercase if true.  Default is false.
  @attr ucFirst    Converts the first character of each word to uppercase if true.
  @attr lowercase  Removes all characters that are not digits if true.  Default is false.
*/
dojo.widget.validate.Textbox = function() {  }

dojo.inherits(dojo.widget.validate.Textbox, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.validate.Textbox, {
	// default values for new subclass properties
	widgetId: "", 
	widgetType: "Textbox", 
	id: "",
	className: "",
	name: "",
	value: "",
	trim: false,
	uppercase: false,
	lowercase: false,
	ucFirst: false,
	digit: false,
	htmlfloat: "none",
	
	templateString: "<span style='float:${this.htmlfloat};'><input dojoAttachPoint='textbox' dojoAttachEvent='onblur;onfocus'"
					+ " id='${this.widgetId}' name='${this.name}' "
					+ " value='${this.value}' class='${this.className}'></input></span>",

	// our DOM nodes
	textbox: null,

	// Apply various filters to textbox value
	filter: function() { 
		if (this.trim) {
			this.textbox.value = this.textbox.value.replace(/(^\s*|\s*$)/g, "");
		} 
		if (this.uppercase) {
			this.textbox.value = this.textbox.value.toUpperCase();
		} 
		if (this.lowercase) {
			this.textbox.value = this.textbox.value.toLowerCase();
		} 
		if (this.ucFirst) {
			this.textbox.value = this.textbox.value.replace(/\b\w+\b/g, 
				function(word) { return word.substring(0,1).toUpperCase() + word.substring(1).toLowerCase(); });
		} 
		if (this.digit) {
			this.textbox.value = this.textbox.value.replace(/\D/g, "");
		} 
	},

	// event handlers, you can over-ride these in your own subclasses
	onfocus: function() {},
	onblur: function() { this.filter(); },

	// All functions below are called by create from dojo.widget.Widget
	mixInProperties: function(localProperties, frag) {
		dojo.widget.validate.Textbox.superclass.mixInProperties.apply(this, arguments);
		if ( localProperties["class"] ) { 
			this.className = localProperties["class"];
		}
	},

	fillInTemplate: function() {
		// apply any filters to initial value
		this.filter();
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:Textbox");


/*
  ****** ValidationTextbox ******

  A subclass of Textbox.
  Over-ride isValid in subclasses to perform specific kinds of validation.
  Has several new properties that can be specified as attributes in the markup.

	@attr type          		Basic input tag type declaration.
	@attr size          		Basic input tag size declaration.
	@attr type          		Basic input tag maxlength declaration.	
  @attr required          Can be true or false, default is false.
  @attr validColor        The color textbox is highlighted for valid input. Default is #cfc.
  @attr invalidColor      The color textbox is highlighted for invalid input. Default is #fcc.
  @attr invalidClass			Class used to format displayed text in page if necessary to override default class
  @attr invalidMessage    The message to display if value is invalid.
  @attr missingMessage    The message to display if value is missing.
  @attr missingClass		  Override default class used for missing input data
  @attr listenOnKeyPress  Updates messages on each key press.  Default is true.
  @attr promptMessage			Will not issue invalid message if field is populated with default user-prompt text
*/
dojo.widget.validate.ValidationTextbox = function() {}

dojo.inherits(dojo.widget.validate.ValidationTextbox, dojo.widget.validate.Textbox);

dojo.lang.extend(dojo.widget.validate.ValidationTextbox, {
	// default values for new subclass properties
	widgetType: "ValidationTextbox", 
	type: "",
	required: false,
	validColor: "#cfc",
	invalidColor: "#fcc",
	rangeClass: "range",
	invalidClass: "invalid",
	missingClass: "missing",
	size: "",
	maxlength: "",
	promptMessage: "",
	invalidMessage: "* The value entered is not valid.",
	missingMessage: "* This value is required.",
	rangeMessage: "* This value out of range.",
	listenOnKeyPress: true,
	htmlfloat: "none",
	lastCheckedValue: null,

	templateString:   "<span style='float:${this.htmlfloat};'>"
					+   "<input dojoAttachPoint='textbox' type='${this.type}' dojoAttachEvent='onblur;onfocus;onkeyup'"
					+     " id='${this.widgetId}' name='${this.name}' size='${this.size}' maxlength='${this.maxlength}'"
					+     " value='${this.value}' class='${this.className}' style=''></input>"
					+   "<span dojoAttachPoint='invalidSpan' class='${this.invalidClass}'>${this.invalidMessage}</span>"
					+   "<span dojoAttachPoint='missingSpan' class='${this.missingClass}'>${this.missingMessage}</span>"
					+   "<span dojoAttachPoint='rangeSpan' class='${this.rangeClass}'>${this.rangeMessage}</span>"
					+ "</span>",

	// new DOM nodes
	invalidSpan: null,
	missingSpan: null,
	rangeSpan: null,

	getValue: function() {
		return this.textbox.value;
	},

	setValue: function(value) {
		this.textbox.value = value;
		this.update();
	},

	// Need to over-ride with your own validation code in subclasses
	isValid: function() { return true; },

	// Need to over-ride with your own validation code in subclasses
	isInRange: function() { return true; },

	// Returns true if value is all whitespace
	isEmpty: function() { 
		return ( /^\s*$/.test(this.textbox.value) );
	},

	// Returns true if value is required and it is all whitespace.
	isMissing: function() { 
		return ( this.required && this.isEmpty() );
	},

	// Called oninit, onblur, and onkeypress.
	// Show missing or invalid messages if appropriate, and highlight textbox field.
	update: function() {
		this.lastCheckedValue = this.textbox.value;
		this.missingSpan.style.display = "none";
		this.invalidSpan.style.display = "none";
		this.rangeSpan.style.display = "none";

		var empty = this.isEmpty();
		var valid = true;
		if(this.promptMessage != this.textbox.value){ 
			valid = this.isValid(); 
		}
		var missing = this.isMissing();

		// Display at most one error message
		if(missing){
			this.missingSpan.style.display = "";
		}else if( !empty && !valid ){
			this.invalidSpan.style.display = "";
		}else if( !empty && !this.isInRange() ){
			this.rangeSpan.style.display = "";
		}
		this.highlight();
	},

	// Called oninit, and onblur.
	highlight: function() {
		// highlight textbox background 
		if ( this.isEmpty() ) {
			this.textbox.style.backgroundColor = "";
		}else if ( this.isValid() && this.isInRange() ){
			this.textbox.style.backgroundColor = this.validColor;
		}else if( this.textbox.value != this.promptMessage){ 
			this.textbox.style.backgroundColor = this.invalidColor;
		}
	},

	onfocus: function() {
		if ( !this.listenOnKeyPress) {
		    this.textbox.style.backgroundColor = "";
		}
	},

	onblur: function() { 
		this.filter();
		this.update(); 
	},

	onkeyup: function(){ 
		if(this.listenOnKeyPress){ 
			//this.filter();  trim is problem if you have to type two words
			this.update(); 
		}else if (this.textbox.value != this.lastCheckedValue){
		    this.textbox.style.backgroundColor = "";
		}
	},

	// FIXME: why are there to fillInTemplate methods defined here?
	fillInTemplate: function() {
		// Attach isMissing and isValid methods to the textbox.
		// We may use them later in connection with a submit button widget.
		// TODO: this is unorthodox; it seems better to do it another way -- Bill
		this.textbox.isValid = function() { this.isValid.call(this); };
		this.textbox.isMissing = function() { this.isMissing.call(this); };
		this.textbox.isInRange = function() { this.isInRange.call(this); };
		this.filter();
		this.update(); 
	}
});

dojo.widget.tags.addParseTreeHandler("dojo:ValidationTextbox");


/*
  ****** IntegerTextbox ******

  A subclass of ValidationTextbox.
  Over-rides isValid/isInRange to test for integer input.
  Has 4 new properties that can be specified as attributes in the markup.

  @attr signed     The leading plus-or-minus sign. Can be true or false, default is either.
  @attr separator  The character used as the thousands separator.  Default is no separator.
  @attr min  Minimum signed value.  Default is -Infinity
  @attr max  Maximum signed value.  Default is +Infinity
*/
dojo.widget.validate.IntegerTextbox = function(node) {
	// this property isn't a primitive and needs to be created on a per-item basis.
	this.flags = {};
}

dojo.inherits(dojo.widget.validate.IntegerTextbox, dojo.widget.validate.ValidationTextbox);

dojo.lang.extend(dojo.widget.validate.IntegerTextbox, {
	// new subclass properties
	widgetType: "IntegerTextbox", 

	mixInProperties: function(localProperties, frag) {
		// First initialize properties in super-class.
		dojo.widget.validate.IntegerTextbox.superclass.mixInProperties.apply(this, arguments);

		// Get properties from markup attibutes, and assign to flags object.
		if((localProperties.signed == "true")||
			(localProperties.signed == "always")){
			this.flags.signed = true;
		}else if((localProperties.signed == "false")||
				(localProperties.signed == "never")){
			this.flags.signed = false;
			this.flags.min = 0;
		}else{
			this.flags.signed = [ true, false ]; // optional
		}
		if(localProperties.separator){ 
			this.flags.separator = localProperties.separator;
		}
		if(localProperties.min){ 
			this.flags.min = parseInt(localProperties.min);
		}
		if(localProperties.max){ 
			this.flags.max = parseInt(localProperties.max);
		}
	},

	// Over-ride for integer validation
	isValid: function() { 
		return dojo.validate.isInteger(this.textbox.value, this.flags);
	},
	isInRange: function() { 
		return dojo.validate.isInRange(this.textbox.value, this.flags);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:IntegerTextbox");


/*
  ****** RealNumberTextbox ******

  A subclass that extends IntegerTextbox.
  Over-rides isValid/isInRange to test for real number input.
  Has 5 new properties that can be specified as attributes in the markup.

  @attr places    The exact number of decimal places.  If omitted, it's unlimited and optional.
  @attr exponent  Can be true or false.  If omitted the exponential part is optional.
  @attr eSigned   Is the exponent signed?  Can be true or false, if omitted the sign is optional.
  @attr min  Minimum signed value.  Default is -Infinity
  @attr max  Maximum signed value.  Default is +Infinity
*/
dojo.widget.validate.RealNumberTextbox = function(node) {
	this.flags = {};
}

dojo.inherits(dojo.widget.validate.RealNumberTextbox, dojo.widget.validate.IntegerTextbox);

dojo.lang.extend(dojo.widget.validate.RealNumberTextbox, {
	// new subclass properties
	widgetType: "RealNumberTextbox", 

	mixInProperties: function(localProperties, frag) {
		// First initialize properties in super-class.
		dojo.widget.validate.RealNumberTextbox.superclass.mixInProperties.apply(this, arguments);

		// Get properties from markup attibutes, and assign to flags object.
		if ( localProperties.places ) { 
			this.flags.places = Number( localProperties.places );
		}
		if((localProperties.exponent == "true")||
			(localProperties.exponent == "always")){
			this.flags.exponent = true;
		}else if((localProperties.exponent == "false")||(localProperties.exponent == "never")){
			this.flags.exponent = false;
		}else{
			this.flags.exponent = [ true, false ]; // optional
		}
		if((localProperties.esigned == "true")||(localProperties.esigned == "always")){
			this.flags.eSigned = true;
		}else if((localProperties.esigned == "false")||(localProperties.esigned == "never")){
			this.flags.eSigned = false;
		}else{
			this.flags.eSigned = [ true, false ]; // optional
		}
		if(localProperties.min){ 
			this.flags.min = parseFloat(localProperties.min);
		}
		if(localProperties.max){ 
			this.flags.max = parseFloat(localProperties.max);
		}
	},

	// Over-ride for real number validation
	isValid: function() { 
		return dojo.validate.isRealNumber(this.textbox.value, this.flags);
	},
	isInRange: function() { 
		return dojo.validate.isInRange(this.textbox.value, this.flags);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:RealNumberTextbox");


/*
  ****** CurrencyTextbox ******

  A subclass that extends IntegerTextbox.
  Over-rides isValid/isInRange to test if input denotes a monetary value .
  Has 5 new properties that can be specified as attributes in the markup.

  @attr cents      The two decimal places for cents.  Can be true or false, optional if omitted.
  @attr symbol     A currency symbol such as Yen "???", Pound "???", or the Euro "???". Default is "$".
  @attr separator  Default is "," instead of no separator as in IntegerTextbox.
  @attr min  Minimum signed value.  Default is -Infinity
  @attr max  Maximum signed value.  Default is +Infinity
*/
dojo.widget.validate.CurrencyTextbox = function(node) {
	this.flags = {};
}

dojo.inherits(dojo.widget.validate.CurrencyTextbox, dojo.widget.validate.IntegerTextbox);

dojo.lang.extend(dojo.widget.validate.CurrencyTextbox, {
	// new subclass properties
	widgetType: "CurrencyTextbox", 

	mixInProperties: function(localProperties, frag) {
		// First initialize properties in super-class.
		dojo.widget.validate.CurrencyTextbox.superclass.mixInProperties.apply(this, arguments);

		// Get properties from markup attibutes, and assign to flags object.
		if ( localProperties.cents ) { 
			this.flags.cents = ( localProperties.cents == "true" );
		}
		if ( localProperties.symbol ) { 
			this.flags.symbol = localProperties.symbol;
		}
		if(localProperties.min){ 
			this.flags.min = parseFloat(localProperties.min);
		}
		if(localProperties.max){ 
			this.flags.max = parseFloat(localProperties.max);
		}
	},

	// Over-ride for currency validation
	isValid: function() { 
		return dojo.validate.isCurrency(this.textbox.value, this.flags);
	},
	isInRange: function() { 
		return dojo.validate.isInRange(this.textbox.value, this.flags);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:CurrencyTextbox");


/*
  ****** IpAddressTextbox ******

  A subclass of ValidationTextbox.
  Over-rides isValid to test for IP addresses.
  Can specify formats for ipv4 or ipv6 as attributes in the markup.

  @attr allowDottedDecimal  true or false, default is true.
  @attr allowDottedHex      true or false, default is true.
  @attr allowDottedOctal    true or false, default is true.
  @attr allowDecimal        true or false, default is true.
  @attr allowHex            true or false, default is true.
  @attr allowIPv6           true or false, default is true.
  @attr allowHybrid         true or false, default is true.
*/
dojo.widget.validate.IpAddressTextbox = function(node) {
	this.flags = {};
}

dojo.inherits(dojo.widget.validate.IpAddressTextbox, dojo.widget.validate.ValidationTextbox);

dojo.lang.extend(dojo.widget.validate.IpAddressTextbox, {
	// new subclass properties
	widgetType: "IpAddressTextbox", 

	mixInProperties: function(localProperties, frag) {
		// First initialize properties in super-class.
		dojo.widget.validate.IpAddressTextbox.superclass.mixInProperties.apply(this, arguments);

		// Get properties from markup attibutes, and assign to flags object.
		if ( localProperties.allowdotteddecimal ) { 
			this.flags.allowDottedDecimal = ( localProperties.allowdotteddecimal == "true" );
		}
		if ( localProperties.allowdottedhex ) { 
			this.flags.allowDottedHex = ( localProperties.allowdottedhex == "true" );
		}
		if ( localProperties.allowdottedoctal ) { 
			this.flags.allowDottedOctal = ( localProperties.allowdottedoctal == "true" );
		}
		if ( localProperties.allowdecimal ) { 
			this.flags.allowDecimal = ( localProperties.allowdecimal == "true" );
		}
		if ( localProperties.allowhex ) { 
			this.flags.allowHex = ( localProperties.allowhex == "true" );
		}
		if ( localProperties.allowipv6 ) { 
			this.flags.allowIPv6 = ( localProperties.allowipv6 == "true" );
		}
		if ( localProperties.allowhybrid ) { 
			this.flags.allowHybrid = ( localProperties.allowhybrid == "true" );
		}
	},

	// Over-ride for IP address validation
	isValid: function() { 
		return dojo.validate.isIpAddress(this.textbox.value, this.flags);
	}
});

dojo.widget.tags.addParseTreeHandler("dojo:IpAddressTextbox");


/*
  ****** UrlTextbox ******

  A subclass of IpAddressTextbox.
  Over-rides isValid to test for URL's.
  Can specify 5 additional attributes in the markup.

  @attr scheme        Can be true or false.  If omitted the scheme is optional.
  @attr allowIP       Allow an IP address for hostname.  Default is true.
  @attr allowLocal    Allow the host to be "localhost".  Default is false.
  @attr allowCC       Allow 2 letter country code domains.  Default is true.
  @attr allowGeneric  Allow generic domains.  Can be true or false, default is true.
*/
dojo.widget.validate.UrlTextbox = function(node) {
	this.flags = {};
}

dojo.inherits(dojo.widget.validate.UrlTextbox, dojo.widget.validate.IpAddressTextbox);

dojo.lang.extend(dojo.widget.validate.UrlTextbox, {
	// new subclass properties
	widgetType: "UrlTextbox", 

	mixInProperties: function(localProperties, frag) {
		// First initialize properties in super-class.
		dojo.widget.validate.UrlTextbox.superclass.mixInProperties.apply(this, arguments);

		// Get properties from markup attibutes, and assign to flags object.
		if ( localProperties.scheme ) { 
			this.flags.scheme = ( localProperties.scheme == "true" );
		}
		if ( localProperties.allowip ) { 
			this.flags.allowIP = ( localProperties.allowip == "true" );
		}
		if ( localProperties.allowlocal ) { 
			this.flags.allowLocal = ( localProperties.allowlocal == "true" );
		}
		if ( localProperties.allowcc ) { 
			this.flags.allowCC = ( localProperties.allowcc == "true" );
		}
		if ( localProperties.allowgeneric ) { 
			this.flags.allowGeneric = ( localProperties.allowgeneric == "true" );
		}
	},

	// Over-ride for URL validation
	isValid: function() { 
		return dojo.validate.isUrl(this.textbox.value, this.flags);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:UrlTextbox");


/*
  ****** EmailTextbox ******

  A subclass of UrlTextbox.
  Over-rides isValid to test for email addresses.
  Can use all markup attributes/properties of UrlTextbox except scheme.
  One new attribute available in the markup.

  @attr allowCruft  Allow address like <mailto:foo@yahoo.com>.  Default is false.
*/
dojo.widget.validate.EmailTextbox = function(node) {
	this.flags = {};
}

dojo.inherits(dojo.widget.validate.EmailTextbox, dojo.widget.validate.UrlTextbox);

dojo.lang.extend(dojo.widget.validate.EmailTextbox, {
	// new subclass properties
	widgetType: "EmailTextbox", 

	mixInProperties: function(localProperties, frag) {
		// First initialize properties in super-class.
		dojo.widget.validate.EmailTextbox.superclass.mixInProperties.apply(this, arguments);

		// Get properties from markup attibutes, and assign to flags object.
		if ( localProperties.allowcruft ) { 
			this.flags.allowCruft = ( localProperties.allowcruft == "true" );
		}
	},

	// Over-ride for email address validation
	isValid: function() { 
		return dojo.validate.isEmailAddress(this.textbox.value, this.flags);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:EmailTextbox");


/*
  ****** EmailListTextbox ******

  A subclass of EmailTextbox.
  Over-rides isValid to test for a list of email addresses.
  Can use all markup attributes/properties of EmailTextbox and ...

  @attr listSeparator  The character used to separate email addresses.  
    Default is ";", ",", "\n" or " ".
*/
dojo.widget.validate.EmailListTextbox = function(node) {
	this.flags = {};
}

dojo.inherits(dojo.widget.validate.EmailListTextbox, dojo.widget.validate.EmailTextbox);

dojo.lang.extend(dojo.widget.validate.EmailListTextbox, {
	// new subclass properties
	widgetType: "EmailListTextbox", 

	mixInProperties: function(localProperties, frag) {
		// First initialize properties in super-class.
		dojo.widget.validate.EmailListTextbox.superclass.mixInProperties.apply(this, arguments);

		// Get properties from markup attibutes, and assign to flags object.
		if ( localProperties.listseparator ) { 
			this.flags.listSeparator = localProperties.listseparator;
		}
	},

	// Over-ride for email address list validation
	isValid: function() { 
		return dojo.validate.isEmailAddressList(this.textbox.value, this.flags);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:EmailListTextbox");


/*
  ****** DateTextbox ******

  A subclass of ValidationTextbox.
  Over-rides isValid to test if input is in a valid date format.

  @attr format  Described in dojo.validate.js.  Default is  "MM/DD/YYYY".
*/
dojo.widget.validate.DateTextbox = function(node) {
	this.flags = {};
}

dojo.inherits(dojo.widget.validate.DateTextbox, dojo.widget.validate.ValidationTextbox);

dojo.lang.extend(dojo.widget.validate.DateTextbox, {
	// new subclass properties
	widgetType: "DateTextbox", 

	mixInProperties: function(localProperties, frag) {
		// First initialize properties in super-class.
		dojo.widget.validate.DateTextbox.superclass.mixInProperties.apply(this, arguments);

		// Get properties from markup attibutes, and assign to flags object.
		if ( localProperties.format ) { 
			this.flags.format = localProperties.format;
		}
	},

	// Over-ride for date validation
	isValid: function() { 
		return dojo.validate.isValidDate(this.textbox.value, this.flags.format);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:DateTextbox");


/*
  ****** TimeTextbox ******

  A subclass of ValidationTextbox.
  Over-rides isValid to test if input is in a valid time format.

  @attr format    Described in dojo.validate.js.  Default is  "h:mm:ss t".
  @attr amSymbol  The symbol used for AM.  Default is "AM" or "am".
  @attr pmSymbol  The symbol used for PM.  Default is "PM" or "pm".
*/
dojo.widget.validate.TimeTextbox = function(node) {
	this.flags = {};
}

dojo.inherits(dojo.widget.validate.TimeTextbox, dojo.widget.validate.ValidationTextbox);

dojo.lang.extend(dojo.widget.validate.TimeTextbox, {
	// new subclass properties
	widgetType: "TimeTextbox", 

	mixInProperties: function(localProperties, frag) {
		// First initialize properties in super-class.
		dojo.widget.validate.TimeTextbox.superclass.mixInProperties.apply(this, arguments);

		// Get properties from markup attibutes, and assign to flags object.
		if ( localProperties.format ) { 
			this.flags.format = localProperties.format;
		}
		if ( localProperties.amsymbol ) { 
			this.flags.amSymbol = localProperties.amsymbol;
		}
		if ( localProperties.pmsymbol ) { 
			this.flags.pmSymbol = localProperties.pmsymbol;
		}
	},

	// Over-ride for time validation
	isValid: function() { 
		return dojo.validate.isValidTime(this.textbox.value, this.flags);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:TimeTextbox");


/*
  ****** UsStateTextbox ******

  A subclass of ValidationTextbox.
  Over-rides isValid to test if input is a US state abbr.

  @attr allowTerritories  Allow Guam, Puerto Rico, etc.  Default is true.
  @attr allowMilitary     Allow military 'states', e.g. Armed Forces Europe (AE). Default is true.
*/
dojo.widget.validate.UsStateTextbox = function(node) {
	this.flags = {};
}

dojo.inherits(dojo.widget.validate.UsStateTextbox, dojo.widget.validate.ValidationTextbox);

dojo.lang.extend(dojo.widget.validate.UsStateTextbox, {
	// new subclass properties
	widgetType: "UsStateTextbox", 

	mixInProperties: function(localProperties, frag) {
		// Initialize properties in super-class.
		dojo.widget.validate.UsStateTextbox.superclass.mixInProperties.apply(this, arguments);

		// Get properties from markup attibutes, and assign to flags object.
		if ( localProperties.allowterritories ) { 
			this.flags.allowTerritories = ( localProperties.allowterritories == "true" );
		}
		if ( localProperties.allowmilitary ) { 
			this.flags.allowMilitary = ( localProperties.allowmilitary == "true" );
		}
	},

	isValid: function() { 
		return dojo.validate.us.isState(this.textbox.value, this.flags);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:UsStateTextbox");


/*
  ****** UsZipTextbox ******

  A subclass of ValidationTextbox.
  Over-rides isValid to test if input is a US zip code.
  Validates zip-5 and zip-5 plus 4.
*/
dojo.widget.validate.UsZipTextbox = function(node) {}

dojo.inherits(dojo.widget.validate.UsZipTextbox, dojo.widget.validate.ValidationTextbox);

dojo.lang.extend(dojo.widget.validate.UsZipTextbox, {
	// new subclass properties
	widgetType: "UsZipTextbox", 

	isValid: function() { 
		return dojo.validate.us.isZipCode(this.textbox.value);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:UsZipTextbox");


/*
  ****** UsSocialSecurityNumberTextbox ******

  A subclass of ValidationTextbox.
  Over-rides isValid to test if input is a US Social Security Number.
*/
dojo.widget.validate.UsSocialSecurityNumberTextbox = function(node) {}

dojo.inherits(dojo.widget.validate.UsSocialSecurityNumberTextbox, dojo.widget.validate.ValidationTextbox);

dojo.lang.extend(dojo.widget.validate.UsSocialSecurityNumberTextbox, {
	// new subclass properties
	widgetType: "UsSocialSecurityNumberTextbox", 

	isValid: function() { 
		return dojo.validate.us.isSocialSecurityNumber(this.textbox.value);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:UsSocialSecurityNumberTextbox");


/*
  ****** UsPhoneNumberTextbox ******

  A subclass of ValidationTextbox.
  Over-rides isValid to test if input is a 10-digit US phone number, an extension is optional.
*/
dojo.widget.validate.UsPhoneNumberTextbox = function(node) {}

dojo.inherits(dojo.widget.validate.UsPhoneNumberTextbox, dojo.widget.validate.ValidationTextbox);

dojo.lang.extend(dojo.widget.validate.UsPhoneNumberTextbox, {
	// new subclass properties
	widgetType: "UsPhoneNumberTextbox", 

	isValid: function() { 
		return dojo.validate.us.isPhoneNumber(this.textbox.value);
	}

});

dojo.widget.tags.addParseTreeHandler("dojo:UsPhoneNumberTextbox");

__CPAN_FILE__ src/widget/LinkPane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.LinkPane");

dojo.require("dojo.widget.*");
dojo.requireAfterIf("html", "dojo.widget.html.LinkPane");
dojo.widget.tags.addParseTreeHandler("dojo:LinkPane");

// NOTE: there's no stub file for this widget

__CPAN_FILE__ src/widget/SimpleDropdownButtons.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/* TODO:
 * - make the dropdowns "smart" so they can't get cutoff on bottom of page, sides of page, etc.
 * - unify menus with the MenuItem and Menu classes so we can add stuff to all menus at once
 * - allow buttons to be enabled/disabled at runtime
 *     - this probably means creating all menus upfront and then triggering a disable action
 *       for disabled buttons in the constructor loop. we'll need a disable and enable action anyway
 * - should each button with menu be a widget object of it's own?
 */
dojo.provide("dojo.widget.SimpleDropdownButtons");
dojo.provide("dojo.widget.HtmlSimpleDropdownButtons");

dojo.deprecated("dojo.widget.SimpleDropdownButtons",  "use dojo.widget.DropDownButton", "0.4");

dojo.require("dojo.event.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.uri.Uri");
dojo.require("dojo.dom");
dojo.require("dojo.style");
dojo.require("dojo.html");

dojo.widget.tags.addParseTreeHandler("dojo:simpledropdownbuttons");

dojo.widget.HtmlSimpleDropdownButtons = function() {
	dojo.widget.HtmlWidget.call(this);

	this.widgetType = "SimpleDropdownButtons";
	this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlSimpleDropdownButtons.css");

	this.menuTriggerClass = "dojoSimpleDropdownButtons";
	this.menuClass = "dojoSimpleDropdownButtonsMenu";

	// overwrite buildRendering so we don't clobber our list
	this.buildRendering = function(args, frag) {
		if(this.templateCssPath) {
			dojo.style.insertCssFile(this.templateCssPath, null, true);
		}
		this.domNode = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];

		var menu = this.domNode;
		if( !dojo.html.hasClass(menu, this.menuTriggerClass) ) {
			dojo.html.addClass(menu, this.menuTriggerClass);
		}
		var li = dojo.dom.getFirstChildElement(menu);
		var menuIDs = [];
		var arrowIDs = [];

		while(li) {
			if(li.getElementsByTagName("ul").length > 0) {
				var a = dojo.dom.getFirstChildElement(li);
				var arrow = document.createElement("a");
				arrow.href = "javascript:;";
				arrow.innerHTML = "&nbsp;";
				dojo.html.setClass(arrow, "downArrow");
				if(!arrow.id) {
					arrow.id = dojo.dom.getUniqueId();
				}
				arrowIDs.push(arrow.id);
				var submenu = dojo.dom.getNextSiblingElement(a);
				if(!submenu.id) {
					submenu.id = dojo.dom.getUniqueId();
				}
				menuIDs.push(submenu.id);

				if( dojo.html.hasClass(a, "disabled") ) {
					dojo.html.addClass(arrow, "disabled");
					dojo.html.disableSelection(li);
					arrow.onfocus = function(){ this.blur(); }
				} else {
					dojo.html.addClass(submenu, this.menuClass);
					document.body.appendChild(submenu);
					dojo.event.connect(arrow, "onmousedown", (function() {
						var ar = arrow;
						return function(e) {
							dojo.html.addClass(ar, "pressed");
						}
					})());
					dojo.event.connect(arrow, "onclick", (function() {
						var aa = a;
						var ar = arrow;
						var sm = submenu;
						var setWidth = false;

						return function(e) {
							hideAll(sm, ar);
							sm.style.left = (dojo.html.getScrollLeft()
								+ e.clientX - e.layerX + aa.offsetLeft) + "px";
							sm.style.top = (dojo.html.getScrollTop() + e.clientY
								- e.layerY + aa.offsetTop + aa.offsetHeight) + "px";
							sm.style.display = sm.style.display == "block" ? "none" : "block";
							if(sm.style.display == "none") {
								dojo.html.removeClass(ar, "pressed");
								e.target.blur()
							}
							if(!setWidth && sm.style.display == "block"
								&& sm.offsetWidth < aa.offsetWidth + ar.offsetWidth) {
								sm.style.width = aa.offsetWidth + ar.offsetWidth + "px";
								setWidth = true;
							}
							e.preventDefault();
						}
					})());
				}

				dojo.event.connect(a, "onclick", function(e) {
					if(e && e.target && e.target.blur) {
						e.target.blur();
					}
				});

				if(a.nextSibling) {
					li.insertBefore(arrow, a.nextSibling);
				} else {
					li.appendChild(arrow);
				}

			}
			li = dojo.dom.getNextSiblingElement(li);
		}

		function hideAll(excludeMenu, excludeArrow) {
			// hide menus
			for(var i = 0; i < menuIDs.length; i++) {
				var m = document.getElementById(menuIDs[i]);
				if(!excludeMenu || m != excludeMenu) {
					document.getElementById(menuIDs[i]).style.display = "none";
				}
			}
			// restore arrows to non-pressed state
			for(var i = 0; i < arrowIDs.length; i++) {
				var m = document.getElementById(arrowIDs[i]);
				if(!excludeArrow || m != excludeArrow) {
					dojo.html.removeClass(m, "pressed");
				}
			}
		}

		dojo.event.connect(document.documentElement, "onmousedown", function(e) {
			if( dojo.html.hasClass(e.target, "downArrow") ) { return };
			for(var i = 0; i < menuIDs.length; i++) {
				if( dojo.dom.isDescendantOf(e.target, document.getElementById(menuIDs[i])) ) {
					return;
				}
			}
			hideAll();
		});
	}
}
dojo.inherits(dojo.widget.HtmlSimpleDropdownButtons, dojo.widget.HtmlWidget);

__CPAN_FILE__ src/widget/ResizableTextarea.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.ResizableTextarea");
dojo.require("dojo.html");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.LayoutContainer");
dojo.require("dojo.widget.ResizeHandle");

dojo.widget.tags.addParseTreeHandler("dojo:resizabletextarea");

dojo.widget.ResizableTextarea = function(){
	dojo.widget.HtmlWidget.call(this);
}

dojo.inherits(dojo.widget.ResizableTextarea, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.ResizableTextarea, {
	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlResizableTextarea.html"),
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlResizableTextarea.css"),
	widgetType: "ResizableTextarea",
	tagName: "dojo:resizabletextarea",
	isContainer: false,
	textAreaNode: null,
	textAreaContainer: null,
	textAreaContainerNode: null,
	statusBar: null,
	statusBarContainerNode: null,
	statusLabelNode: null,
	statusLabel: null,
	rootLayoutNode: null,
	resizeHandleNode: null,
	resizeHandle: null,

	fillInTemplate: function(args, frag){
		this.textAreaNode = this.getFragNodeRef(frag).cloneNode(true);

		// FIXME: Safari apparently needs this!
		document.body.appendChild(this.domNode);

		this.rootLayout = dojo.widget.createWidget(
			"LayoutContainer",
			{
				minHeight: 50,
				minWidth: 100
			},
			this.rootLayoutNode
		);


		this.textAreaContainer = dojo.widget.createWidget(
			"LayoutContainer",
			{ layoutAlign: "client" },
			this.textAreaContainerNode
		);
		this.rootLayout.addChild(this.textAreaContainer);

		this.textAreaContainer.domNode.appendChild(this.textAreaNode);
		with(this.textAreaNode.style){
			width="100%";
			height="100%";
		}

		this.statusBar = dojo.widget.createWidget(
			"LayoutContainer",
			{ 
				layoutAlign: "bottom", 
				minHeight: 28
			},
			this.statusBarContainerNode
		);
		this.rootLayout.addChild(this.statusBar);

		this.statusLabel = dojo.widget.createWidget(
			"LayoutContainer",
			{ 
				layoutAlign: "client", 
				minWidth: 50
			},
			this.statusLabelNode
		);
		this.statusBar.addChild(this.statusLabel);

		this.resizeHandle = dojo.widget.createWidget(
			"ResizeHandle", 
			{ targetElmId: this.rootLayout.widgetId },
			this.resizeHandleNode
		);
		this.statusBar.addChild(this.resizeHandle);
		// dojo.debug(this.rootLayout.widgetId);

		// dojo.event.connect(this.resizeHandle, "beginSizing", this, "hideContent");
		// dojo.event.connect(this.resizeHandle, "endSizing", this, "showContent");
	},

	hideContent: function(){
		this.textAreaNode.style.display = "none";
	},

	showContent: function(){
		this.textAreaNode.style.display = "";
	}
});

__CPAN_FILE__ src/widget/DomWidget.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.DomWidget");

dojo.require("dojo.event.*");
dojo.require("dojo.widget.Widget");
dojo.require("dojo.dom");
dojo.require("dojo.xml.Parse");
dojo.require("dojo.uri.*");
dojo.require("dojo.lang.func");
dojo.require("dojo.lang.extras");

dojo.widget._cssFiles = {};
dojo.widget._cssStrings = {};
dojo.widget._templateCache = {};

dojo.widget.defaultStrings = {
	dojoRoot: dojo.hostenv.getBaseScriptUri(),
	baseScriptUri: dojo.hostenv.getBaseScriptUri()
};

dojo.widget.buildFromTemplate = function() {
	dojo.lang.forward("fillFromTemplateCache");
}

// static method to build from a template w/ or w/o a real widget in place
dojo.widget.fillFromTemplateCache = function(obj, templatePath, templateCssPath, templateString, avoidCache){
	// dojo.debug("avoidCache:", avoidCache);
	var tpath = templatePath || obj.templatePath;
	var cpath = templateCssPath || obj.templateCssPath;

	// DEPRECATED: use Uri objects, not strings
	if (tpath && !(tpath instanceof dojo.uri.Uri)) {
		tpath = dojo.uri.dojoUri(tpath);
		dojo.deprecated("templatePath should be of type dojo.uri.Uri", null, "0.4");
	}
	if (cpath && !(cpath instanceof dojo.uri.Uri)) {
		cpath = dojo.uri.dojoUri(cpath);
		dojo.deprecated("templateCssPath should be of type dojo.uri.Uri", null, "0.4");
	}
	
	var tmplts = dojo.widget._templateCache;
	if(!obj["widgetType"]) { // don't have a real template here
		do {
			var dummyName = "__dummyTemplate__" + dojo.widget._templateCache.dummyCount++;
		} while(tmplts[dummyName]);
		obj.widgetType = dummyName;
	}
	var wt = obj.widgetType;

	if(cpath && !dojo.widget._cssFiles[cpath.toString()]){
		if((!obj.templateCssString)&&(cpath)){
			obj.templateCssString = dojo.hostenv.getText(cpath);
			obj.templateCssPath = null;
		}
		if((obj["templateCssString"])&&(!obj.templateCssString["loaded"])){
			dojo.style.insertCssText(obj.templateCssString, null, cpath);
			if(!obj.templateCssString){ obj.templateCssString = ""; }
			obj.templateCssString.loaded = true;
		}
		dojo.widget._cssFiles[cpath.toString()] = true;
	}

	var ts = tmplts[wt];
	if(!ts){
		tmplts[wt] = { "string": null, "node": null };
		if(avoidCache){
			ts = {};
		}else{
			ts = tmplts[wt];
		}
	}
	if((!obj.templateString)&&(!avoidCache)){
		obj.templateString = templateString || ts["string"];
	}
	if((!obj.templateNode)&&(!avoidCache)){
		obj.templateNode = ts["node"];
	}
	if((!obj.templateNode)&&(!obj.templateString)&&(tpath)){
		// fetch a text fragment and assign it to templateString
		// NOTE: we rely on blocking IO here!
		var tstring = dojo.hostenv.getText(tpath);
		if(tstring){
			// strip <?xml ...?> declarations so that external SVG and XML
			// documents can be added to a document without worry
			tstring = tstring.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
			var matches = tstring.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
			if(matches){
				tstring = matches[1];
			}
		}else{
			tstring = "";
		}
		obj.templateString = tstring;
		if(!avoidCache){
			tmplts[wt]["string"] = tstring;
		}
	}
	if((!ts["string"])&&(!avoidCache)){
		ts.string = obj.templateString;
	}
}
dojo.widget._templateCache.dummyCount = 0;

dojo.widget.attachProperties = ["dojoAttachPoint", "id"];
dojo.widget.eventAttachProperty = "dojoAttachEvent";
dojo.widget.onBuildProperty = "dojoOnBuild";
dojo.widget.waiNames  = ["waiRole", "waiState"];
dojo.widget.wai = {
	waiRole: { 	name: "waiRole", 
				namespace: "http://www.w3.org/TR/xhtml2", 
				alias: "x2",
				prefix: "wairole:",
				nsName: "role"
	},
	waiState: { name: "waiState", 
				namespace: "http://www.w3.org/2005/07/aaa" , 
				alias: "aaa",
				prefix: "",
				nsName: "state"
	},
	setAttr: function(node, attr, value){
		if(dojo.render.html.ie){
			node.setAttribute(this[attr].alias+":"+this[attr].nsName, this[attr].prefix+value);
		}else{
			node.setAttributeNS(this[attr].namespace, this[attr].nsName, this[attr].prefix+value);
		}
	}
};

dojo.widget.attachTemplateNodes = function(rootNode, targetObj, events){
	// FIXME: this method is still taking WAAAY too long. We need ways of optimizing:
	//	a.) what we are looking for on each node
	//	b.) the nodes that are subject to interrogation (use xpath instead?)
	//	c.) how expensive event assignment is (less eval(), more connect())
	// var start = new Date();
	var elementNodeType = dojo.dom.ELEMENT_NODE;

	function trim(str){
		return str.replace(/^\s+|\s+$/g, "");
	}

	if(!rootNode){ 
		rootNode = targetObj.domNode;
	}

	if(rootNode.nodeType != elementNodeType){
		return;
	}
	// alert(events.length);

	var nodes = rootNode.all || rootNode.getElementsByTagName("*");
	var _this = targetObj;
	for(var x=-1; x<nodes.length; x++){
		var baseNode = (x == -1) ? rootNode : nodes[x];
		// FIXME: is this going to have capitalization problems?  Could use getAttribute(name, 0); to get attributes case-insensitve
		var attachPoint = [];
		for(var y=0; y<this.attachProperties.length; y++){
			var tmpAttachPoint = baseNode.getAttribute(this.attachProperties[y]);
			if(tmpAttachPoint){
				attachPoint = tmpAttachPoint.split(";");
				for(var z=0; z<attachPoint.length; z++){
					if(dojo.lang.isArray(targetObj[attachPoint[z]])){
						targetObj[attachPoint[z]].push(baseNode);
					}else{
						targetObj[attachPoint[z]]=baseNode;
					}
				}
				break;
			}
		}
		// continue;

		// FIXME: we need to put this into some kind of lookup structure
		// instead of direct assignment
		var tmpltPoint = baseNode.getAttribute(this.templateProperty);
		if(tmpltPoint){
			targetObj[tmpltPoint]=baseNode;
		}

		dojo.lang.forEach(dojo.widget.waiNames, function(name){
			var wai = dojo.widget.wai[name];
			var val = baseNode.getAttribute(wai.name);
			if(val){
				dojo.widget.wai.setAttr(baseNode, wai.name, val);
			}
		}, this);

		var attachEvent = baseNode.getAttribute(this.eventAttachProperty);
		if(attachEvent){
			// NOTE: we want to support attributes that have the form
			// "domEvent: nativeEvent; ..."
			var evts = attachEvent.split(";");
			for(var y=0; y<evts.length; y++){
				if((!evts[y])||(!evts[y].length)){ continue; }
				var thisFunc = null;
				var tevt = trim(evts[y]);
				if(evts[y].indexOf(":") >= 0){
					// oh, if only JS had tuple assignment
					var funcNameArr = tevt.split(":");
					tevt = trim(funcNameArr[0]);
					thisFunc = trim(funcNameArr[1]);
				}
				if(!thisFunc){
					thisFunc = tevt;
				}

				var tf = function(){ 
					var ntf = new String(thisFunc);
					return function(evt){
						if(_this[ntf]){
							_this[ntf](dojo.event.browser.fixEvent(evt, this));
						}
					};
				}();
				dojo.event.browser.addListener(baseNode, tevt, tf, false, true);
				// dojo.event.browser.addListener(baseNode, tevt, dojo.lang.hitch(_this, thisFunc));
			}
		}

		for(var y=0; y<events.length; y++){
			//alert(events[x]);
			var evtVal = baseNode.getAttribute(events[y]);
			if((evtVal)&&(evtVal.length)){
				var thisFunc = null;
				var domEvt = events[y].substr(4); // clober the "dojo" prefix
				thisFunc = trim(evtVal);
				var funcs = [thisFunc];
				if(thisFunc.indexOf(";")>=0){
					funcs = dojo.lang.map(thisFunc.split(";"), trim);
				}
				for(var z=0; z<funcs.length; z++){
					if(!funcs[z].length){ continue; }
					var tf = function(){ 
						var ntf = new String(funcs[z]);
						return function(evt){
							if(_this[ntf]){
								_this[ntf](dojo.event.browser.fixEvent(evt, this));
							}
						}
					}();
					dojo.event.browser.addListener(baseNode, domEvt, tf, false, true);
					// dojo.event.browser.addListener(baseNode, domEvt, dojo.lang.hitch(_this, funcs[z]));
				}
			}
		}

		var onBuild = baseNode.getAttribute(this.onBuildProperty);
		if(onBuild){
			eval("var node = baseNode; var widget = targetObj; "+onBuild);
		}
	}

}

dojo.widget.getDojoEventsFromStr = function(str){
	// var lstr = str.toLowerCase();
	var re = /(dojoOn([a-z]+)(\s?))=/gi;
	var evts = str ? str.match(re)||[] : [];
	var ret = [];
	var lem = {};
	for(var x=0; x<evts.length; x++){
		if(evts[x].legth < 1){ continue; }
		var cm = evts[x].replace(/\s/, "");
		cm = (cm.slice(0, cm.length-1));
		if(!lem[cm]){
			lem[cm] = true;
			ret.push(cm);
		}
	}
	return ret;
}

/*
dojo.widget.buildAndAttachTemplate = function(obj, templatePath, templateCssPath, templateString, targetObj) {
	this.buildFromTemplate(obj, templatePath, templateCssPath, templateString);
	var node = dojo.dom.createNodesFromText(obj.templateString, true)[0];
	this.attachTemplateNodes(node, targetObj||obj, dojo.widget.getDojoEventsFromStr(templateString));
	return node;
}
*/

dojo.declare("dojo.widget.DomWidget", dojo.widget.Widget, {
	initializer: function() {
		if((arguments.length>0)&&(typeof arguments[0] == "object")){
			this.create(arguments[0]);
		}
	},
								 
	templateNode: null,
	templateString: null,
	templateCssString: null,
	preventClobber: false,
	domNode: null, // this is our visible representation of the widget!
	containerNode: null, // holds child elements

	// Process the given child widget, inserting it's dom node as a child of our dom node
	// FIXME: should we support addition at an index in the children arr and
	// order the display accordingly? Right now we always append.
	addChild: function(widget, overrideContainerNode, pos, ref, insertIndex){
		if(!this.isContainer){ // we aren't allowed to contain other widgets, it seems
			dojo.debug("dojo.widget.DomWidget.addChild() attempted on non-container widget");
			return null;
		}else{
			this.addWidgetAsDirectChild(widget, overrideContainerNode, pos, ref, insertIndex);
			this.registerChild(widget, insertIndex);
		}
		return widget;
	},
	
	addWidgetAsDirectChild: function(widget, overrideContainerNode, pos, ref, insertIndex){
		if((!this.containerNode)&&(!overrideContainerNode)){
			this.containerNode = this.domNode;
		}
		var cn = (overrideContainerNode) ? overrideContainerNode : this.containerNode;
		if(!pos){ pos = "after"; }
		if(!ref){ 
			// if(!cn){ cn = document.body; }
			if(!cn){ cn = document.body; }
			ref = cn.lastChild; 
		}
		if(!insertIndex) { insertIndex = 0; }
		widget.domNode.setAttribute("dojoinsertionindex", insertIndex);

		// insert the child widget domNode directly underneath my domNode, in the
		// specified position (by default, append to end)
		if(!ref){
			cn.appendChild(widget.domNode);
		}else{
			// FIXME: was this meant to be the (ugly hack) way to support insert @ index?
			//dojo.dom[pos](widget.domNode, ref, insertIndex);

			// CAL: this appears to be the intended way to insert a node at a given position...
			if (pos == 'insertAtIndex'){
				// dojo.debug("idx:", insertIndex, "isLast:", ref === cn.lastChild);
				dojo.dom.insertAtIndex(widget.domNode, ref.parentNode, insertIndex);
			}else{
				// dojo.debug("pos:", pos, "isLast:", ref === cn.lastChild);
				if((pos == "after")&&(ref === cn.lastChild)){
					cn.appendChild(widget.domNode);
				}else{
					dojo.dom.insertAtPosition(widget.domNode, cn, pos);
				}
			}
		}
	},

	// Record that given widget descends from me
	registerChild: function(widget, insertionIndex){

		// we need to insert the child at the right point in the parent's 
		// 'children' array, based on the insertionIndex

		widget.dojoInsertionIndex = insertionIndex;

		var idx = -1;
		for(var i=0; i<this.children.length; i++){
			if (this.children[i].dojoInsertionIndex < insertionIndex){
				idx = i;
			}
		}

		this.children.splice(idx+1, 0, widget);

		widget.parent = this;
		widget.addedTo(this);
		
		// If this widget was created programatically, then it was erroneously added
		// to dojo.widget.manager.topWidgets.  Fix that here.
		delete dojo.widget.manager.topWidgets[widget.widgetId];
	},

	removeChild: function(widget){
		// detach child domNode from parent domNode
		dojo.dom.removeNode(widget.domNode);

		// remove child widget from parent widget
		return dojo.widget.DomWidget.superclass.removeChild.call(this, widget);
	},

	getFragNodeRef: function(frag){
		if( !frag || !frag["dojo:"+this.widgetType.toLowerCase()] ){
			dojo.raise("Error: no frag for widget type " + this.widgetType +
				", id " + this.widgetId + " (maybe a widget has set it's type incorrectly)");
		}
		return (frag ? frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"] : null);
	},
	
	// Replace source domNode with generated dom structure, and register
	// widget with parent.
	postInitialize: function(args, frag, parentComp){
		var sourceNodeRef = this.getFragNodeRef(frag);
		// Stick my generated dom into the output tree
		//alert(this.widgetId + ": replacing " + sourceNodeRef + " with " + this.domNode.innerHTML);
		if (parentComp && (parentComp.snarfChildDomOutput || !sourceNodeRef)){
			// Add my generated dom as a direct child of my parent widget
			// This is important for generated widgets, and also cases where I am generating an
			// <li> node that can't be inserted back into the original DOM tree
			parentComp.addWidgetAsDirectChild(this, "", "insertAtIndex", "",  args["dojoinsertionindex"], sourceNodeRef);
		} else if (sourceNodeRef){
			// Do in-place replacement of the my source node with my generated dom
			if(this.domNode && (this.domNode !== sourceNodeRef)){
				var oldNode = sourceNodeRef.parentNode.replaceChild(this.domNode, sourceNodeRef);
			}
		}

		// Register myself with my parent, or with the widget manager if
		// I have no parent
		// TODO: the code below erroneously adds all programatically generated widgets
		// to topWidgets (since we don't know who the parent is until after creation finishes)
		if ( parentComp ) {
			parentComp.registerChild(this, args.dojoinsertionindex);
		} else {
			dojo.widget.manager.topWidgets[this.widgetId]=this;
		}

		// Expand my children widgets
		if(this.isContainer){
			//alert("recurse from " + this.widgetId);
			// build any sub-components with us as the parent
			var fragParser = dojo.widget.getParser();
			fragParser.createSubComponents(frag, this);
		}
	},

	// method over-ride
	buildRendering: function(args, frag){
		// DOM widgets construct themselves from a template
		var ts = dojo.widget._templateCache[this.widgetType];
		if(	
			(!this.preventClobber)&&(
				(this.templatePath)||
				(this.templateNode)||
				(
					(this["templateString"])&&(this.templateString.length) 
				)||
				(
					(typeof ts != "undefined")&&( (ts["string"])||(ts["node"]) )
				)
			)
		){
			// if it looks like we can build the thing from a template, do it!
			this.buildFromTemplate(args, frag);
		}else{
			// otherwise, assign the DOM node that was the source of the widget
			// parsing to be the root node
			this.domNode = this.getFragNodeRef(frag);
		}
		this.fillInTemplate(args, frag); 	// this is where individual widgets
											// will handle population of data
											// from properties, remote data
											// sets, etc.
	},

	buildFromTemplate: function(args, frag){
		// var start = new Date();
		// copy template properties if they're already set in the templates object
		// dojo.debug("buildFromTemplate:", this);
		var avoidCache = false;
		if(args["templatecsspath"]){
			args["templateCssPath"] = args["templatecsspath"];
		}
		if(args["templatepath"]){
			avoidCache = true;
			args["templatePath"] = args["templatepath"];
		}
		dojo.widget.fillFromTemplateCache(	this, 
											args["templatePath"], 
											args["templateCssPath"],
											null,
											avoidCache);
		var ts = dojo.widget._templateCache[this.widgetType];
		if((ts)&&(!avoidCache)){
			if(!this.templateString.length){
				this.templateString = ts["string"];
			}
			if(!this.templateNode){
				this.templateNode = ts["node"];
			}
		}
		var matches = false;
		var node = null;
		// var tstr = new String(this.templateString); 
		var tstr = this.templateString; 
		// attempt to clone a template node, if there is one
		if((!this.templateNode)&&(this.templateString)){
			matches = this.templateString.match(/\$\{([^\}]+)\}/g);
			if(matches) {
				// if we do property replacement, don't create a templateNode
				// to clone from.
				var hash = this.strings || {};
				// FIXME: should this hash of default replacements be cached in
				// templateString?
				for(var key in dojo.widget.defaultStrings) {
					if(dojo.lang.isUndefined(hash[key])) {
						hash[key] = dojo.widget.defaultStrings[key];
					}
				}
				// FIXME: this is a lot of string munging. Can we make it faster?
				for(var i = 0; i < matches.length; i++) {
					var key = matches[i];
					key = key.substring(2, key.length-1);
					var kval = (key.substring(0, 5) == "this.") ? dojo.lang.getObjPathValue(key.substring(5), this) : hash[key];
					var value;
					if((kval)||(dojo.lang.isString(kval))){
						value = (dojo.lang.isFunction(kval)) ? kval.call(this, key, this.templateString) : kval;
						tstr = tstr.replace(matches[i], value);
					}
				}
			}else{
				// otherwise, we are required to instantiate a copy of the template
				// string if one is provided.
				
				// FIXME: need to be able to distinguish here what should be done
				// or provide a generic interface across all DOM implementations
				// FIMXE: this breaks if the template has whitespace as its first 
				// characters
				// node = this.createNodesFromText(this.templateString, true);
				// this.templateNode = node[0].cloneNode(true); // we're optimistic here
				this.templateNode = this.createNodesFromText(this.templateString, true)[0];
				if(!avoidCache){
					ts.node = this.templateNode;
				}
			}
		}
		if((!this.templateNode)&&(!matches)){ 
			dojo.debug("weren't able to create template!");
			return false;
		}else if(!matches){
			node = this.templateNode.cloneNode(true);
			if(!node){ return false; }
		}else{
			node = this.createNodesFromText(tstr, true)[0];
		}

		// recurse through the node, looking for, and attaching to, our
		// attachment points which should be defined on the template node.

		this.domNode = node;
		// dojo.profile.start("attachTemplateNodes");
		this.attachTemplateNodes(this.domNode, this);
		// dojo.profile.end("attachTemplateNodes");
		
		// relocate source contents to templated container node
		// this.containerNode must be able to receive children, or exceptions will be thrown
		if (this.isContainer && this.containerNode){
			var src = this.getFragNodeRef(frag);
			if (src){
				dojo.dom.moveChildren(src, this.containerNode);
			}
		}
	},

	attachTemplateNodes: function(baseNode, targetObj){
		if(!targetObj){ targetObj = this; }
		return dojo.widget.attachTemplateNodes(baseNode, targetObj, 
					dojo.widget.getDojoEventsFromStr(this.templateString));
	},

	fillInTemplate: function(){
		// dojo.unimplemented("dojo.widget.DomWidget.fillInTemplate");
	},
	
	// method over-ride
	destroyRendering: function(){
		try{
			delete this.domNode;
		}catch(e){ /* squelch! */ }
	},

	// FIXME: method over-ride
	cleanUp: function(){},
	
	getContainerHeight: function(){
		dojo.unimplemented("dojo.widget.DomWidget.getContainerHeight");
	},

	getContainerWidth: function(){
		dojo.unimplemented("dojo.widget.DomWidget.getContainerWidth");
	},

	createNodesFromText: function(){
		dojo.unimplemented("dojo.widget.DomWidget.createNodesFromText");
	}
});

__CPAN_FILE__ src/widget/FisheyeList.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.FisheyeList");
dojo.provide("dojo.widget.html.FisheyeList");
dojo.provide("dojo.widget.html.FisheyeListItem");

//
// TODO
// fix SVG support, and turn it on only if the browser supports it
// fix really long labels in vertical mode
//

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.dom");
dojo.require("dojo.html");
dojo.require("dojo.style");
dojo.require("dojo.event");

dojo.widget.tags.addParseTreeHandler("dojo:FisheyeList");
dojo.widget.tags.addParseTreeHandler("dojo:FisheyeListItem");

dojo.widget.html.FisheyeList = function(){
	dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.FisheyeList, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.FisheyeList, {

	templateString: '<div class="dojoHtmlFisheyeListBar"></div>',
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlFisheyeList.css"),
	widgetType: "FisheyeList",

	EDGE: {
		CENTER: 0,
		LEFT: 1,
		RIGHT: 2,
		TOP: 3,
		BOTTOM: 4
	},

	isContainer: true,
	snarfChildDomOutput: true,
	
	pos: {x: -1, y: -1},		// current cursor position, relative to the grid
	
	// for conservative trigger mode, when triggered, timerScale is gradually increased from 0 to 1
	timerScale: 1.0,

	/////////////////////////////////////////////////////////////////
	//
	// i spy OPTIONS!!!!
	//

	itemWidth: 40,
	itemHeight: 40,

	itemMaxWidth: 150,
	itemMaxHeight: 150,

	orientation: 'horizontal',
	
	conservativeTrigger: false,		// don't active menu until mouse is over an image (macintosh style)

	effectUnits: 2,
	itemPadding: 10,

	attachEdge: 'center',
	labelEdge: 'bottom',

	enableCrappySvgSupport: false,


	//
	//
	//
	/////////////////////////////////////////////////////////////////

	fillInTemplate: function(args, frag) {
		//dojo.debug(this.orientation);

		dojo.html.disableSelection(this.domNode);

		this.isHorizontal = (this.orientation == 'horizontal') ? 1 : 0;
		this.selectedNode = -1;

		this.isOver = false;
		this.hitX1 = -1;
		this.hitY1 = -1;
		this.hitX2 = -1;
		this.hitY2 = -1;

		//
		// only some edges make sense...
		//

		this.anchorEdge = this.toEdge(this.attachEdge, this.EDGE.CENTER);
		this.labelEdge  = this.toEdge(this.labelEdge,  this.EDGE.TOP);

		if ( this.isHorizontal && (this.anchorEdge == this.EDGE.LEFT  )){ this.anchorEdge = this.EDGE.CENTER; }
		if ( this.isHorizontal && (this.anchorEdge == this.EDGE.RIGHT )){ this.anchorEdge = this.EDGE.CENTER; }
		if (!this.isHorizontal && (this.anchorEdge == this.EDGE.TOP   )){ this.anchorEdge = this.EDGE.CENTER; }
		if (!this.isHorizontal && (this.anchorEdge == this.EDGE.BOTTOM)){ this.anchorEdge = this.EDGE.CENTER; }

		if (this.labelEdge == this.EDGE.CENTER){ this.labelEdge = this.EDGE.TOP; }
		if ( this.isHorizontal && (this.labelEdge == this.EDGE.LEFT  )){ this.labelEdge = this.EDGE.TOP; }
		if ( this.isHorizontal && (this.labelEdge == this.EDGE.RIGHT )){ this.labelEdge = this.EDGE.TOP; }
		if (!this.isHorizontal && (this.labelEdge == this.EDGE.TOP   )){ this.labelEdge = this.EDGE.LEFT; }
		if (!this.isHorizontal && (this.labelEdge == this.EDGE.BOTTOM)){ this.labelEdge = this.EDGE.LEFT; }


		//
		// figure out the proximity size
		//

		this.proximityLeft   = this.itemWidth  * (this.effectUnits - 0.5);
		this.proximityRight  = this.itemWidth  * (this.effectUnits - 0.5);
		this.proximityTop    = this.itemHeight * (this.effectUnits - 0.5);
		this.proximityBottom = this.itemHeight * (this.effectUnits - 0.5);

		if (this.anchorEdge == this.EDGE.LEFT){
			this.proximityLeft = 0;
		}
		if (this.anchorEdge == this.EDGE.RIGHT){
			this.proximityRight = 0;
		}
		if (this.anchorEdge == this.EDGE.TOP){
			this.proximityTop = 0;
		}
		if (this.anchorEdge == this.EDGE.BOTTOM){
			this.proximityBottom = 0;
		}
		if (this.anchorEdge == this.EDGE.CENTER){
			this.proximityLeft   /= 2;
			this.proximityRight  /= 2;
			this.proximityTop    /= 2;
			this.proximityBottom /= 2;
		}
	},
	
	postCreate: function(args, frag) {
		this.initializePositioning();

		//
		// in liberal trigger mode, activate menu whenever mouse is close
		//
		if( !this.conservativeTrigger ){
			dojo.event.connect(document.documentElement, "onmousemove", this, "mouseHandler");
		}
		
		// Deactivate the menu if mouse is moved off screen (doesn't work for FF?)
		dojo.event.connect(document.documentElement, "onmouseout", this, "onBodyOut");
		dojo.event.connect(this, "addChild", this, "initializePositioning");
	},

	initializePositioning: function(){
		this.itemCount = this.children.length;

		this.barWidth  = (this.isHorizontal ? this.itemCount : 1) * this.itemWidth;
		this.barHeight = (this.isHorizontal ? 1 : this.itemCount) * this.itemHeight;

		this.totalWidth  = this.proximityLeft + this.proximityRight  + this.barWidth;
		this.totalHeight = this.proximityTop  + this.proximityBottom + this.barHeight;

		//
		// calculate effect ranges for each item
		//

		for (var i=0; i<this.children.length; i++){

			this.children[i].posX = this.itemWidth  * (this.isHorizontal ? i : 0);
			this.children[i].posY = this.itemHeight * (this.isHorizontal ? 0 : i);

			this.children[i].cenX = this.children[i].posX + (this.itemWidth  / 2);
			this.children[i].cenY = this.children[i].posY + (this.itemHeight / 2);

			var isz = this.isHorizontal ? this.itemWidth : this.itemHeight;
			var r = this.effectUnits * isz;
			var c = this.isHorizontal ? this.children[i].cenX : this.children[i].cenY;
			var lhs = this.isHorizontal ? this.proximityLeft : this.proximityTop;
			var rhs = this.isHorizontal ? this.proximityRight : this.proximityBottom;
			var siz = this.isHorizontal ? this.barWidth : this.barHeight;

			var range_lhs = r;
			var range_rhs = r;

			if (range_lhs > c+lhs){ range_lhs = c+lhs; }
			if (range_rhs > (siz-c+rhs)){ range_rhs = siz-c+rhs; }

			this.children[i].effectRangeLeft = range_lhs / isz;
			this.children[i].effectRangeRght = range_rhs / isz;

			//dojo.debug('effect range for '+i+' is '+range_lhs+'/'+range_rhs);
		}


		//
		// create the bar
		//

		this.domNode.style.width = this.barWidth + 'px';
		this.domNode.style.height = this.barHeight + 'px';


		//
		// position the items
		//
		for (var i=0; i<this.children.length; i++){
			var itm = this.children[i];
			var elm = itm.domNode;
			elm.style.left   = itm.posX + 'px';
			elm.style.top    = itm.posY + 'px';
			elm.style.width  = this.itemWidth + 'px';
			elm.style.height = this.itemHeight + 'px';
			
			if ( itm.svgNode ) {
				itm.svgNode.style.position = 'absolute';
				itm.svgNode.style.left = this.itemPadding+'%';
				itm.svgNode.style.top = this.itemPadding+'%';
				itm.svgNode.style.width = (100 - 2 * this.itemPadding) + '%';
				itm.svgNode.style.height = (100 - 2 * this.itemPadding) + '%';
				itm.svgNode.style.zIndex = 1;
	
				itm.svgNode.setSize(this.itemWidth, this.itemHeight);
			} else {
				itm.imgNode.style.left = this.itemPadding+'%';
				itm.imgNode.style.top = this.itemPadding+'%';
				itm.imgNode.style.width = (100 - 2 * this.itemPadding) + '%';
				itm.imgNode.style.height = (100 - 2 * this.itemPadding) + '%';
			}
		}

		//
		// calc the grid
		//

		this.calcHitGrid();
	},

	onBodyOut: function(e){
		// clicking over an object inside of body causes this event to fire; ignore that case
		if( dojo.html.overElement(document.body, e) ){
			return;
		}
		this.setDormant(e);
	},

	// when mouse moves out of menu's range
	setDormant: function(e){
		if( !this.isOver ){ return; }	// already dormant?
		this.isOver = false;

		if ( this.conservativeTrigger ) {
			// user can't re-trigger the menu expansion
			// until he mouses over a icon again
			dojo.event.disconnect(document.documentElement, "onmousemove", this, "mouseHandler");
		}
		this.onGridMouseMove(-1, -1);
	},

	// when mouse is moved into menu's range
	setActive: function(e){
		if( this.isOver ){ return; }	// already activated?
		this.isOver = true;

		if ( this.conservativeTrigger ) {
			// switch event handlers so that we handle mouse events from anywhere near
			// the menu
			dojo.event.connect(document.documentElement, "onmousemove", this, "mouseHandler");

			this.timerScale=0.0;

			// call mouse handler to do some initial necessary calculations/positioning
			this.mouseHandler(e);

			// slowly expand the icon size so it isn't jumpy
			this.expandSlowly();
		}
	},

	// when mouse is moved
	mouseHandler: function(e) {
		if ((e.pageX >= this.hitX1) && (e.pageX <= this.hitX2) &&
			(e.pageY >= this.hitY1) && (e.pageY <= this.hitY2)){
			if( !this.isOver ){
				this.setActive(e);
			}
			this.onGridMouseMove(e.pageX-this.hitX1, e.pageY-this.hitY1);
		}else{
			if (this.isOver){
				this.setDormant(e);
			}
		}
	},

	onResized: function() {
		this.calcHitGrid();
	},

	onGridMouseMove: function(x, y){
		this.pos = {x:x, y:y};
		this.paint();
	},
	
	paint: function(){
		var x=this.pos.x;
		var y=this.pos.y;

		if( this.itemCount <= 0 ){ return; }

		//
		// figure out our main index
		//

		var pos = this.isHorizontal ? x : y;
		var prx = this.isHorizontal ? this.proximityLeft : this.proximityTop;
		var siz = this.isHorizontal ? this.itemWidth : this.itemHeight;
		var sim = this.isHorizontal ? 
			(1.0-this.timerScale)*this.itemWidth + this.timerScale*this.itemMaxWidth :
			(1.0-this.timerScale)*this.itemHeight + this.timerScale*this.itemMaxHeight ;

		var cen = ((pos - prx) / siz) - 0.5;
		var max_off_cen = (sim / siz) - 0.5;

		if (max_off_cen > this.effectUnits){ max_off_cen = this.effectUnits; }


		//
		// figure out our off-axis weighting
		//

		var off_weight = 0;

		if (this.anchorEdge == this.EDGE.BOTTOM){
			var cen2 = (y - this.proximityTop) / this.itemHeight;
			off_weight = (cen2 > 0.5) ? 1 : y / (this.proximityTop + (this.itemHeight / 2));
		}
		if (this.anchorEdge == this.EDGE.TOP){
			var cen2 = (y - this.proximityTop) / this.itemHeight;
			off_weight = (cen2 < 0.5) ? 1 : (this.totalHeight - y) / (this.proximityBottom + (this.itemHeight / 2));
		}
		if (this.anchorEdge == this.EDGE.RIGHT){
			var cen2 = (x - this.proximityLeft) / this.itemWidth;
			off_weight = (cen2 > 0.5) ? 1 : x / (this.proximityLeft + (this.itemWidth / 2));
		}
		if (this.anchorEdge == this.EDGE.LEFT){
			var cen2 = (x - this.proximityLeft) / this.itemWidth;
			off_weight = (cen2 < 0.5) ? 1 : (this.totalWidth - x) / (this.proximityRight + (this.itemWidth / 2));
		}
		if (this.anchorEdge == this.EDGE.CENTER){

			if (this.isHorizontal){
				off_weight = y / (this.totalHeight);
			}else{
				off_weight = x / (this.totalWidth);
			}

			if (off_weight > 0.5){
				off_weight = 1 - off_weight;
			}

			off_weight *= 2;
		}


		//
		// set the sizes
		//

		for(var i=0; i<this.itemCount; i++){

			var weight = this.weightAt(cen, i);

			if (weight < 0){weight = 0;}

			this.setitemsize(i, weight * off_weight);
		}

		//
		// set the positions
		//

		var main_p = Math.round(cen);
		var offset = 0;

		if (cen < 0){
			main_p = 0;

		}else if (cen > this.itemCount - 1){

			main_p = this.itemCount -1;

		}else{

			offset = (cen - main_p) * ((this.isHorizontal ? this.itemWidth : this.itemHeight) - this.children[main_p].sizeMain);
		}

		this.positionElementsFrom(main_p, offset);
	},

	weightAt: function(cen, i){

		var dist = Math.abs(cen - i);

		var limit = ((cen - i) > 0) ? this.children[i].effectRangeRght : this.children[i].effectRangeLeft;

		return (dist > limit) ? 0 : (1 - dist / limit);
	},

	positionFromNode: function(p, w){

		//
		// we need to grow all the nodes growing out from node 'i'
		//

		this.setitemsize(p, w);

		var wx = w;
		for(var i=p; i<this.itemCount; i++){
			wx = 0.8 * wx;
			this.setitemsize(i, wx);
		}

		var wx = w;
		for(var i=p; i>=0; i--){
			wx = 0.8 * wx;
			this.setitemsize(i, wx);
		}
	},

	setitemsize: function(p, scale){
		scale *= this.timerScale;
		var w = Math.round(this.itemWidth  + ((this.itemMaxWidth  - this.itemWidth ) * scale));
		var h = Math.round(this.itemHeight + ((this.itemMaxHeight - this.itemHeight) * scale));

		if (this.isHorizontal){

			this.children[p].sizeW = w;
			this.children[p].sizeH = h;

			this.children[p].sizeMain = w;
			this.children[p].sizeOff  = h;

			var y = 0;

			if (this.anchorEdge == this.EDGE.TOP){

				y = (this.children[p].cenY - (this.itemHeight / 2));

			}else if (this.anchorEdge == this.EDGE.BOTTOM){

				y = (this.children[p].cenY - (h - (this.itemHeight / 2)));

			}else{

				y = (this.children[p].cenY - (h / 2));
			}

			this.children[p].usualX = Math.round(this.children[p].cenX - (w / 2));
			
			this.children[p].domNode.style.top  = y + 'px';

			this.children[p].domNode.style.left  = this.children[p].usualX + 'px';

		}else{

			this.children[p].sizeW = w;
			this.children[p].sizeH = h;

			this.children[p].sizeOff  = w;
			this.children[p].sizeMain = h;

			var x = 0;

			if (this.anchorEdge == this.EDGE.LEFT){

				x = this.children[p].cenX - (this.itemWidth / 2);

			}else if (this.anchorEdge == this.EDGE.RIGHT){

				x = this.children[p].cenX - (w - (this.itemWidth / 2));
			}else{

				x = this.children[p].cenX - (w / 2);
			}

			this.children[p].domNode.style.left = x + 'px';
			this.children[p].usualY = Math.round(this.children[p].cenY - (h / 2));

			this.children[p].domNode.style.top  = this.children[p].usualY + 'px';
		}

		this.children[p].domNode.style.width  = w + 'px';
		this.children[p].domNode.style.height = h + 'px';

		if (this.children[p].svgNode){
			this.children[p].svgNode.setSize(w, h);
		}
	},

	positionElementsFrom: function(p, offset){

		var pos = 0;

		if (this.isHorizontal){
			pos = Math.round(this.children[p].usualX + offset);
			this.children[p].domNode.style.left = pos + 'px';
		}else{
			pos = Math.round(this.children[p].usualY + offset);
			this.children[p].domNode.style.top = pos + 'px';
		}
		this.positionLabel(this.children[p]);


		//
		// position before
		//

		var bpos = pos;

		for(var i=p-1; i>=0; i--){

			bpos -= this.children[i].sizeMain;

			if (this.isHorizontal){
				this.children[i].domNode.style.left = bpos + 'px';
			}else{
				this.children[i].domNode.style.top = bpos + 'px';
			}
			this.positionLabel(this.children[i]);
		}

		//
		// position after
		//

		var apos = pos;

		for(var i=p+1; i<this.itemCount; i++){

			apos += this.children[i-1].sizeMain;

			if (this.isHorizontal){
				this.children[i].domNode.style.left = apos + 'px';
			}else{
				this.children[i].domNode.style.top = apos + 'px';
			}
			this.positionLabel(this.children[i]);
		}

	},

	positionLabel: function(itm){

		var x = 0;
		var y = 0;
		
		var labelW = dojo.style.getOuterWidth(itm.lblNode);
		var labelH = dojo.style.getOuterHeight(itm.lblNode);

		if (this.labelEdge == this.EDGE.TOP){
			x = Math.round((itm.sizeW / 2) - (labelW / 2));
			y = -labelH;
		}

		if (this.labelEdge == this.EDGE.BOTTOM){
			x = Math.round((itm.sizeW / 2) - (labelW / 2));
			y = itm.sizeH;
		}

		if (this.labelEdge == this.EDGE.LEFT){
			x = -labelW;
			y = Math.round((itm.sizeH / 2) - (labelH / 2));
		}

		if (this.labelEdge == this.EDGE.RIGHT){
			x = itm.sizeW;
			y = Math.round((itm.sizeH / 2) - (labelH / 2));
		}

		itm.lblNode.style.left = x + 'px';
		itm.lblNode.style.top  = y + 'px';
	},

	calcHitGrid: function(){

		var pos = dojo.style.getAbsolutePosition(this.domNode, true);

		this.hitX1 = pos.x - this.proximityLeft;
		this.hitY1 = pos.y - this.proximityTop;
		this.hitX2 = this.hitX1 + this.totalWidth;
		this.hitY2 = this.hitY1 + this.totalHeight;

		//dojo.debug(this.hitX1+','+this.hitY1+' // '+this.hitX2+','+this.hitY2);
	},

	toEdge: function(inp, def){
		return this.EDGE[inp.toUpperCase()] || def;
	},
	
	// slowly expand the image to user specified max size
	expandSlowly: function(){
		if( !this.isOver ){ return; }
		this.timerScale += 0.2;
		this.paint();
		if ( this.timerScale<1.0 ) {
			dojo.lang.setTimeout(this, "expandSlowly", 10);
		}
	},

	destroy: function(){
		// need to disconnect when we destroy
		dojo.event.disconnect(document.documentElement, "onmouseout", this, "onBodyOut");
		dojo.event.disconnect(document.documentElement, "onmousemove", this, "mouseHandler");
		dojo.widget.html.FisheyeList.superclass.destroy.call(this);
	}
});

dojo.widget.html.FisheyeListItem = function(){
	dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.FisheyeListItem, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.FisheyeListItem, {
	widgetType: "FisheyeListItem",
	
	// Constructor arguments
	iconSrc: "",
	svgSrc: "",
	caption: "",

	blankImgPath: dojo.uri.dojoUri("src/widget/templates/images/blank.gif"),

	templateString:
		'<div class="dojoHtmlFisheyeListItem">' +
		'  <img class="dojoHtmlFisheyeListItemImage" dojoAttachPoint="imgNode" dojoAttachEvent="onMouseOver;onMouseOut;onClick">' +
		'  <div class="dojoHtmlFisheyeListItemLabel" dojoAttachPoint="lblNode"></div>' +
		'</div>',
	
	imgNode: null,

	fillInTemplate: function() {
		//
		// set image
		// TODO: turn on/off SVG support based on browser version.
		// this.parent.enableCrappySvgSupport is not available to this function
		//
		if (this.svgSrc != ""){
			this.svgNode = this.createSvgNode(this.svgSrc);
			this.domNode.appendChild(this.svgNode);
			this.imgNode.style.display = 'none';
		} else if((this.iconSrc.toLowerCase().substring(this.iconSrc.length-4)==".png")&&(dojo.render.html.ie)){
			this.imgNode.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.iconSrc+"', sizingMethod='scale')";
			this.imgNode.src = this.blankImgPath.toString();
		} else {
			this.imgNode.src = this.iconSrc;
		}

		//
		// Label
		//
		if ( this.lblNode ) {
			this.lblNode.appendChild(document.createTextNode(this.caption));
		}
		dojo.html.disableSelection(this.domNode);
	},
	
	createSvgNode: function(src){

		var elm = document.createElement('embed');
		elm.src = src;
		elm.type = 'image/svg+xml';
		//elm.style.border = '1px solid black';
		elm.style.width = '1px';
		elm.style.height = '1px';
		elm.loaded = 0;
		elm.setSizeOnLoad = false;

		elm.onload = function(){
			this.svgRoot = this.getSVGDocument().rootElement;
			this.svgDoc = this.getSVGDocument().documentElement;
			this.zeroWidth = this.svgRoot.width.baseVal.value;
			this.zeroHeight = this.svgRoot.height.baseVal.value;
			this.loaded = true;

			if (this.setSizeOnLoad){
				this.setSize(this.setWidth, this.setHeight);
			}
		}

		elm.setSize = function(w, h){
			if (!this.loaded){
				this.setWidth = w;
				this.setHeight = h;
				this.setSizeOnLoad = true;
				return;
			}

			this.style.width = w+'px';
			this.style.height = h+'px';
			this.svgRoot.width.baseVal.value = w;
			this.svgRoot.height.baseVal.value = h;

			var scale_x = w / this.zeroWidth;
			var scale_y = h / this.zeroHeight;

			for(var i=0; i<this.svgDoc.childNodes.length; i++){
				if (this.svgDoc.childNodes[i].setAttribute){
					this.svgDoc.childNodes[i].setAttribute( "transform", "scale("+scale_x+","+scale_y+")" );
				}
			}
		}

		return elm;
	},

	onMouseOver: function(e) {
		// in conservative mode, don't activate the menu until user mouses over an icon
		if( !this.parent.isOver ){
			this.parent.setActive(e);
		}
		if ( this.caption != "" ) {
			dojo.html.addClass(this.lblNode, "selected");
			this.parent.positionLabel(this);
		}
	},
	
	onMouseOut: function() {
		dojo.html.removeClass(this.lblNode, "selected");
	},

	onClick: function() {
	}
});


__CPAN_FILE__ src/widget/TreeControllerExtension.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/**
 * Additional tree utils
 *
 */
dojo.provide("dojo.widget.TreeControllerExtension");


dojo.widget.TreeControllerExtension = function() { }

dojo.lang.extend(dojo.widget.TreeControllerExtension, {

	saveExpandedIndices: function(node, field) {
		var obj = {};

		for(var i=0; i<node.children.length; i++) {
			if (node.children[i].isExpanded) {
				var key = dojo.lang.isUndefined(field) ? i : node.children[i][field];
				obj[key] = this.saveExpandedIndices(node.children[i], field);
			}
		}

		return obj;
	},


	restoreExpandedIndices: function(node, savedIndices, field) {
		var _this = this;

		var handler = function(node, savedIndices) {
			this.node = node; //.children[i];
			this.savedIndices = savedIndices; //[i];
			// recursively read next savedIndices level and apply to opened node
			this.process = function() {
				//dojo.debug("Callback applied for "+this.node);
				_this.restoreExpandedIndices(this.node, this.savedIndices, field);
			};
		}


		for(var i=0; i<node.children.length; i++) {
			var child = node.children[i];

			var found = false;
			var key = -1;

			//dojo.debug("Check "+child)
			// process field set case
			if (dojo.lang.isUndefined(field) && savedIndices[i]) {
				found = true;
				key = i;
			}

			// process case when field is not set
			if (field) {
				for(var key in savedIndices) {
					//dojo.debug("Compare "+key+" "+child[field])
					if (key == child[field]) {
						found = true;
						break;
					}
				}
			}

			// if we found anything - expand it
			if (found) {
				//dojo.debug("Found at "+key)
				var h = new handler(child, savedIndices[key]);
				_this.expand(child, false, h, h.process);
			} else if (child.isExpanded) { // not found, so collapse
				//dojo.debug("Collapsing all descendants "+node.children[i])
				dojo.lang.forEach(child.getDescendants(), function(elem) { _this.collapse(elem); });
				//this.collapse(node.children[i]);
			}

		}


	}

});






__CPAN_FILE__ src/widget/ComboBox.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.ComboBox");

dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");

dojo.widget.incrementalComboBoxDataProvider = function(url, limit, timeout){
	this.searchUrl = url;
	this.inFlight = false;
	this.activeRequest = null;
	this.allowCache = false;

	this.cache = {};

	this.init = function(cbox){
		this.searchUrl = cbox.dataUrl;
	}

	this.addToCache = function(keyword, data){
		if(this.allowCache){
			this.cache[keyword] = data;
		}
	}

	this.startSearch = function(searchStr, type, ignoreLimit){
		if(this.inFlight){
			// FIXME: implement backoff!
		}
		var tss = encodeURIComponent(searchStr);
		var realUrl = dojo.string.paramString(this.searchUrl, {"searchString": tss});
		var _this = this;
		var request = dojo.io.bind({
			url: realUrl,
			method: "get",
			mimetype: "text/json",
			load: function(type, data, evt){
				_this.inFlight = false;
				if(!dojo.lang.isArray(data)){
					var arrData = [];
					for(var key in data){
						arrData.push([data[key], key]);
					}
					data = arrData;
				}
				_this.addToCache(searchStr, data);
				_this.provideSearchResults(data);
			}
		});
		this.inFlight = true;
	}
}

dojo.widget.ComboBoxDataProvider = function(dataPairs, limit, timeout){
	// NOTE: this data provider is designed as a naive reference
	// implementation, and as such it is written more for readability than
	// speed. A deployable data provider would implement lookups, search
	// caching (and invalidation), and a significantly less naive data
	// structure for storage of items.

	this.data = [];
	this.searchTimeout = 500;
	this.searchLimit = 30;
	this.searchType = "STARTSTRING"; // may also be "STARTWORD" or "SUBSTRING"
	this.caseSensitive = false;
	// for caching optimizations
	this._lastSearch = "";
	this._lastSearchResults = null;

	this.init = function(cbox, node){
		if(!dojo.string.isBlank(cbox.dataUrl)){
			this.getData(cbox.dataUrl);
		}else{
			// check to see if we can populate the list from <option> elements
			if((node)&&(node.nodeName.toLowerCase() == "select")){
				// NOTE: we're not handling <optgroup> here yet
				var opts = node.getElementsByTagName("option");
				var ol = opts.length;
				var data = [];
				for(var x=0; x<ol; x++){
					var keyValArr = [new String(opts[x].innerHTML), new String(opts[x].value)];
					data.push(keyValArr);
					if(opts[x].selected){ 
						cbox.setAllValues(keyValArr[0], keyValArr[1]);
					}
				}
				this.setData(data);
			}
		}
	}

	this.getData = function(url){
		dojo.io.bind({
			url: url,
			load: dojo.lang.hitch(this, function(type, data, evt){ 
				if(!dojo.lang.isArray(data)){
					var arrData = [];
					for(var key in data){
						arrData.push([data[key], key]);
					}
					data = arrData;
				}
				this.setData(data);
			}),
			mimetype: "text/json"
		});
	}

	this.startSearch = function(searchStr, type, ignoreLimit){
		// FIXME: need to add timeout handling here!!
		this._preformSearch(searchStr, type, ignoreLimit);
	}

	this._preformSearch = function(searchStr, type, ignoreLimit){
		//
		//	NOTE: this search is LINEAR, which means that it exhibits perhaps
		//	the worst possible speed characteristics of any search type. It's
		//	written this way to outline the responsibilities and interfaces for
		//	a search.
		//
		var st = type||this.searchType;
		// FIXME: this is just an example search, which means that we implement
		// only a linear search without any of the attendant (useful!) optimizations
		var ret = [];
		if(!this.caseSensitive){
			searchStr = searchStr.toLowerCase();
		}
		for(var x=0; x<this.data.length; x++){
			if((!ignoreLimit)&&(ret.length >= this.searchLimit)){
				break;
			}
			// FIXME: we should avoid copies if possible!
			var dataLabel = new String((!this.caseSensitive) ? this.data[x][0].toLowerCase() : this.data[x][0]);
			if(dataLabel.length < searchStr.length){
				// this won't ever be a good search, will it? What if we start
				// to support regex search?
				continue;
			}

			if(st == "STARTSTRING"){
				// jum.debug(dataLabel.substr(0, searchStr.length))
				// jum.debug(searchStr);
				if(searchStr == dataLabel.substr(0, searchStr.length)){
					ret.push(this.data[x]);
				}
			}else if(st == "SUBSTRING"){
				// this one is a gimmie
				if(dataLabel.indexOf(searchStr) >= 0){
					ret.push(this.data[x]);
				}
			}else if(st == "STARTWORD"){
				// do a substring search and then attempt to determine if the
				// preceeding char was the beginning of the string or a
				// whitespace char.
				var idx = dataLabel.indexOf(searchStr);
				if(idx == 0){
					// implicit match
					ret.push(this.data[x]);
				}
				if(idx <= 0){
					// if we didn't match or implicily matched, march onward
					continue;
				}
				// otherwise, we have to go figure out if the match was at the
				// start of a word...
				// this code is taken almost directy from nWidgets
				var matches = false;
				while(idx!=-1){
					// make sure the match either starts whole string, or
					// follows a space, or follows some punctuation
					if(" ,/(".indexOf(dataLabel.charAt(idx-1)) != -1){
						// FIXME: what about tab chars?
						matches = true; break;
					}
					idx = dataLabel.indexOf(searchStr, idx+1);
				}
				if(!matches){
					continue;
				}else{
					ret.push(this.data[x]);
				}
			}
		}
		this.provideSearchResults(ret);
	}

	this.provideSearchResults = function(resultsDataPairs){
	}

	this.addData = function(pairs){
		// FIXME: incredibly naive and slow!
		this.data = this.data.concat(pairs);
	}

	this.setData = function(pdata){
		// populate this.data and initialize lookup structures
		this.data = pdata;
	}
	
	if(dataPairs){
		this.setData(dataPairs);
	}
}

dojo.declare(
	"dojo.widget.ComboBox",
	null,
	{
		widgetType: "ComboBox",
		isContainer: false,
	
		forceValidOption: false,
		searchType: "stringstart",
		dataProvider: null,
	
		startSearch: function(searchString){},
		openResultList: function(results){},
		clearResultList: function(){},
		hideResultList: function(){},
		selectNextResult: function(){},
		selectPrevResult: function(){},
		setSelectedResult: function(){}
	}
);

// render-specific includes
dojo.requireAfterIf("html", "dojo.widget.html.ComboBox");


__CPAN_FILE__ src/widget/SplitContainer.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.SplitContainer");
dojo.provide("dojo.widget.SplitContainerPanel");
dojo.provide("dojo.widget.html.SplitContainer");
dojo.provide("dojo.widget.html.SplitContainerPanel");

//
// TODO
// make it prettier
// active dragging upwards doesn't always shift other bars (direction calculation is wrong in this case)
//

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.LayoutContainer");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.html");
dojo.require("dojo.style");
dojo.require("dojo.dom");
dojo.require("dojo.io");	// workaround dojo bug. dojo.io.cookie requires dojo.io but it still doesn't get pulled in
dojo.require("dojo.io.cookie");

dojo.widget.html.SplitContainer = function(){

	dojo.widget.HtmlWidget.call(this);

	this.sizers = [];
}

dojo.inherits(dojo.widget.html.SplitContainer, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.SplitContainer, {
	widgetType: "SplitContainer",
	isContainer: true,

	virtualSizer: null,
	isHorizontal: 0,
	paneBefore: null,
	paneAfter: null,
	isSizing: false,
	dragOffset: null,
	startPoint: null,
	lastPoint: null,
	sizingSplitter: null,
	isActiveResize: 0,
	offsetX: 0,
	offsetY: 0,
	isDraggingLeft: 0,
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlSplitContainer.css"),
	originPos: null,
	persist: true,		// save splitter positions in a cookie

	activeSizing: '',
	sizerWidth: 15,
	orientation: 'horizontal',

	debugName: '',

	fillInTemplate: function(){

		dojo.style.insertCssFile(this.templateCssPath, null, true);
		dojo.html.addClass(this.domNode, "dojoSplitContainer");
		this.domNode.style.overflow='hidden';	// workaround firefox bug

		this.paneWidth = dojo.style.getContentWidth(this.domNode);
		this.paneHeight = dojo.style.getContentHeight(this.domNode);

		this.isHorizontal = (this.orientation == 'horizontal') ? 1 : 0;
		this.isActiveResize = (this.activeSizing == '1') ? 1 : 0;

		//dojo.debug("fillInTemplate for "+this.debugName);
	},

	onResized: function(e){
		this.paneWidth = dojo.style.getContentWidth(this.domNode);
		this.paneHeight = dojo.style.getContentHeight(this.domNode);
		this.layoutPanels();
	},

	postCreate: function(args, fragment, parentComp){

		// dojo.debug("post create for "+this.debugName);

		// attach the children and create the draggers
		for(var i=0; i<this.children.length; i++){
            with(this.children[i].domNode.style){
                position = "absolute";
            }
            dojo.html.addClass(this.children[i].domNode,
                "dojoSplitPane");

            if(i == this.children.length-1){
                break;
            }

            this._addSizer();
		}

		// create the fake dragger
		this.virtualSizer = document.createElement('div');
		this.virtualSizer.style.position = 'absolute';
		this.virtualSizer.style.display = 'none';
		//this.virtualSizer.style.backgroundColor = 'lime';
		this.virtualSizer.style.zIndex = 10;
		this.virtualSizer.className = this.isHorizontal ? 'dojoSplitContainerVirtualSizerH' : 'dojoSplitContainerVirtualSizerV';
		this.domNode.appendChild(this.virtualSizer);

		dojo.html.disableSelection(this.virtualSizer);

		if(this.persist){
			this.restoreState();
		}

		// size the panels once the browser has caught up
		this.resizeSoon();
	},

    _injectChild: function(child) {
        with(child.domNode.style){
            position = "absolute";
        }
        dojo.html.addClass(child.domNode,
            "dojoSplitPane");
    },

    _addSizer: function() {
        var i = this.sizers.length;

        this.sizers[i] = document.createElement('div');
        this.sizers[i].style.position = 'absolute';
        this.sizers[i].className = this.isHorizontal ? 'dojoSplitContainerSizerH' : 'dojoSplitContainerSizerV';

        var self = this;
        var handler = (function(){ var sizer_i = i; return function(e){ self.beginSizing(e, sizer_i); } })();
        dojo.event.connect(this.sizers[i], "onmousedown", handler);

        this.domNode.appendChild(this.sizers[i]);
        dojo.html.disableSelection(this.sizers[i]);
    },

    removeChild: function(widget){
        // Remove sizer, but only if widget is really our child and
        // we have at least one sizer to throw away
        if (this.sizers.length > 0) {
            for(var x=0; x<this.children.length; x++){
                if(this.children[x] === widget){
                    var i = this.sizers.length - 1;
                    this.domNode.removeChild(this.sizers[i]);
                    this.sizers.length = i;
                    break;
                }
            }
        }

        // Remove widget and repaint
        dojo.widget.html.SplitContainer.superclass.removeChild.call(this, widget, arguments);
        this.onResized();
    },

    addChild: function(widget, overrideContainerNode, pos, ref, insertIndex){
        dojo.widget.html.SplitContainer.superclass.addChild.call(this, widget, overrideContainerNode, pos, ref, insertIndex);
        this._injectChild(widget);

        if (this.children.length > 1) {
            this._addSizer();
        }

        this.layoutPanels();
    },

    layoutPanels: function(){
        if (this.children.length == 0){ return; }

		//
		// calculate space
		//

		var space = this.isHorizontal ? this.paneWidth : this.paneHeight;

		if (this.children.length > 1){

			space -= this.sizerWidth * (this.children.length - 1);
		}


		//
		// calculate total of SizeShare values
		//

		var out_of = 0;

		for(var i=0; i<this.children.length; i++){

			out_of += this.children[i].sizeShare;
		}


		//
		// work out actual pixels per sizeshare unit
		//

		var pix_per_unit = space / out_of;


		//
		// set the SizeActual member of each pane
		//

		var total_size = 0;

		for(var i=0; i<this.children.length-1; i++){

			var size = Math.round(pix_per_unit * this.children[i].sizeShare);
			this.children[i].sizeActual = size;
			total_size += size;
		}
		this.children[this.children.length-1].sizeActual = space - total_size;

		//
		// make sure the sizes are ok
		//

		this.checkSizes();


		//
		// now loop, positioning each pane and letting children resize themselves
		//

		var pos = 0;
		var size = this.children[0].sizeActual;
		this.movePanel(this.children[0].domNode, pos, size);
		this.children[0].position = pos;
        this.children[0].checkSize();
		pos += size;

		for(var i=1; i<this.children.length; i++){

			// first we position the sizing handle before this pane
			this.movePanel(this.sizers[i-1], pos, this.sizerWidth);
			this.sizers[i-1].position = pos;
			pos += this.sizerWidth;

			size = this.children[i].sizeActual;
			this.movePanel(this.children[i].domNode, pos, size);
			this.children[i].position = pos;
            this.children[i].checkSize();
			pos += size;
		}
	},

	movePanel: function(panel, pos, size){
		if (this.isHorizontal){
			panel.style.left = pos + 'px';
			panel.style.top = 0;

			dojo.style.setOuterWidth(panel, size);
			dojo.style.setOuterHeight(panel, this.paneHeight);
		}else{
			panel.style.left = 0;
			panel.style.top = pos + 'px';

			dojo.style.setOuterWidth(panel, this.paneWidth);
			dojo.style.setOuterHeight(panel, size);
		}
	},

	growPane: function(growth, pane){

		if (growth > 0){
			if (pane.sizeActual > pane.sizeMin){
				if ((pane.sizeActual - pane.sizeMin) > growth){

					// stick all the growth in this pane
					pane.sizeActual = pane.sizeActual - growth;
					growth = 0;
				}else{
					// put as much growth in here as we can
					growth -= pane.sizeActual - pane.sizeMin;
					pane.sizeActual = pane.sizeMin;
				}
			}
		}
		return growth;
	},

	checkSizes: function(){

		var total_min_size = 0;
		var total_size = 0;

		for(var i=0; i<this.children.length; i++){

			total_size += this.children[i].sizeActual;
			total_min_size += this.children[i].sizeMin;
		}

		// only make adjustments if we have enough space for all the minimums

		if (total_min_size <= total_size){

			var growth = 0;

			for(var i=0; i<this.children.length; i++){

				if (this.children[i].sizeActual < this.children[i].sizeMin){

					growth += this.children[i].sizeMin - this.children[i].sizeActual;
					this.children[i].sizeActual = this.children[i].sizeMin;
				}
			}

			if (growth > 0){
				if (this.isDraggingLeft){
					for(var i=this.children.length-1; i>=0; i--){
						growth = this.growPane(growth, this.children[i]);
					}
				}else{
					for(var i=0; i<this.children.length; i++){
						growth = this.growPane(growth, this.children[i]);
					}
				}
			}
		}else{

			for(var i=0; i<this.children.length; i++){
				this.children[i].sizeActual = Math.round(total_size * (this.children[i].sizeMin / total_min_size));
			}
		}
	},

	beginSizing: function(e, i){
		var clientX = e.layerX;
		var clientY = e.layerY;
		var screenX = e.pageX;
		var screenY = e.pageY;

		this.paneBefore = this.children[i];
		this.paneAfter = this.children[i+1];

		this.isSizing = true;
		this.sizingSplitter = this.sizers[i];
		this.originPos = dojo.style.getAbsolutePosition(this.domNode, true);
		this.dragOffset = {'x':clientX, 'y':clientY};
		this.startPoint  = {'x':screenX, 'y':screenY};
		this.lastPoint  = {'x':screenX, 'y':screenY};

		this.offsetX = screenX - clientX;
		this.offsetY = screenY - clientY;

		if (!this.isActiveResize){
			this.showSizingLine();
		}

		//
		// attach mouse events
		//

		dojo.event.connect(document.documentElement, "onmousemove", this, "changeSizing");
		dojo.event.connect(document.documentElement, "onmouseup", this, "endSizing");
	},

	changeSizing: function(e){
		var screenX = e.pageX;
		var screenY = e.pageY;

		if (this.isActiveResize){
			this.lastPoint = {'x':screenX, 'y':screenY};
			this.movePoint();
			this.updateSize();
		}else{
			this.lastPoint = {'x':screenX, 'y':screenY};
			this.movePoint();
			this.moveSizingLine();
		}
	},

	endSizing: function(e){

		if (!this.isActiveResize){
			this.hideSizingLine();
		}

		this.updateSize();

		this.isSizing = false;

		dojo.event.disconnect(document.documentElement, "onmousemove", this, "changeSizing");
		dojo.event.disconnect(document.documentElement, "onmouseup", this, "endSizing");
		
		if(this.persist){
			this.saveState(this);
		}
	},

	movePoint: function(){

		// make sure FLastPoint is a legal point to drag to
		var p = this.screenToMainClient(this.lastPoint);

		if (this.isHorizontal){

			var a = p.x - this.dragOffset.x;
			a = this.legaliseSplitPoint(a);
			p.x = a + this.dragOffset.x;
		}else{
			var a = p.y - this.dragOffset.y;
			a = this.legaliseSplitPoint(a);
			p.y = a + this.dragOffset.y;
		}

		this.lastPoint = this.mainClientToScreen(p);
	},

	screenToClient: function(pt){

		pt.x -= (this.offsetX + this.sizingSplitter.position);
		pt.y -= (this.offsetY + this.sizingSplitter.position);

		return pt;
	},

	clientToScreen: function(pt){

		pt.x += (this.offsetX + this.sizingSplitter.position);
		pt.y += (this.offsetY + this.sizingSplitter.position);

		return pt;
	},

	screenToMainClient: function(pt){

		pt.x -= this.offsetX;
		pt.y -= this.offsetY;

		return pt;
	},

	mainClientToScreen: function(pt){

		pt.x += this.offsetX;
		pt.y += this.offsetY;

		return pt;
	},

	legaliseSplitPoint: function(a){

		a += this.sizingSplitter.position;

		this.isDraggingLeft = (a > 0) ? 1 : 0;

		if (!this.isActiveResize){

			if (a < this.paneBefore.position + this.paneBefore.sizeMin){

				a = this.paneBefore.position + this.paneBefore.sizeMin;
			}

			if (a > this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin))){

				a = this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin));
			}
		}

		a -= this.sizingSplitter.position;

		this.checkSizes();

		return a;
	},

	updateSize: function(){

		var p = this.clientToScreen(this.lastPoint);
		var p = this.screenToClient(this.lastPoint);

		var pos = this.isHorizontal ? p.x - (this.dragOffset.x + this.originPos.x) : p.y - (this.dragOffset.y + this.originPos.y);

		var start_region = this.paneBefore.position;
		var end_region   = this.paneAfter.position + this.paneAfter.sizeActual;

		this.paneBefore.sizeActual = pos - start_region;
		this.paneAfter.position    = pos + this.sizerWidth;
		this.paneAfter.sizeActual  = end_region - this.paneAfter.position;

		for(var i=0; i<this.children.length; i++){

			this.children[i].sizeShare = this.children[i].sizeActual;
		}

		this.layoutPanels();
	},

	showSizingLine: function(){

		this.moveSizingLine();

		if (this.isHorizontal){
			dojo.style.setOuterWidth(this.virtualSizer, this.sizerWidth);
			dojo.style.setOuterHeight(this.virtualSizer, this.paneHeight);
		}else{
			dojo.style.setOuterWidth(this.virtualSizer, this.paneWidth);
			dojo.style.setOuterHeight(this.virtualSizer, this.sizerWidth);
		}

		this.virtualSizer.style.display = 'block';
	},

	hideSizingLine: function(){

		this.virtualSizer.style.display = 'none';
	},

	moveSizingLine: function(){

		var origin = {'x':0, 'y':0};

		if (this.isHorizontal){
			origin.x += (this.lastPoint.x - this.startPoint.x) + this.sizingSplitter.position;
		}else{
			origin.y += (this.lastPoint.y - this.startPoint.y) + this.sizingSplitter.position;
		}

		this.virtualSizer.style.left = origin.x + 'px';
		this.virtualSizer.style.top = origin.y + 'px';
	},
	
	_getCookieName: function(i) {
		return this.widgetId + "_" + i;
	},

	restoreState: function () {
		for(var i=0; i<this.children.length; i++) {
			var cookieName = this._getCookieName(i);
			var cookieValue = dojo.io.cookie.getCookie(cookieName);
			if (cookieValue != null) {
				var pos = parseInt(cookieValue);
				this.children[i].sizeShare=pos;
			}
		}
	},

	saveState: function (){
		for(var i=0; i<this.children.length; i++) {
			var cookieName = this._getCookieName(i);
			dojo.io.cookie.setCookie(cookieName, this.children[i].sizeShare, null, null, null, null);
		}
	}
});

// These arguments can be specified for the children of a SplitContainer.
// Since any widget can be specified as a SplitContainer child, mix them
// into the base widget class.  (This is a hack, but it's effective.)
dojo.lang.extend(dojo.widget.Widget, {
	sizeMin: 10,
	sizeShare: 10
});

// Deprecated class for split pane children.
// Actually any widget can be the child of a split pane
dojo.widget.html.SplitContainerPanel = function(){
	dojo.widget.html.LayoutContainer.call(this);
}
dojo.inherits(dojo.widget.html.SplitContainerPanel, dojo.widget.html.LayoutContainer);
dojo.lang.extend(dojo.widget.html.SplitContainerPanel, {
	widgetType: "SplitContainerPanel"
});

dojo.widget.tags.addParseTreeHandler("dojo:SplitContainer");
dojo.widget.tags.addParseTreeHandler("dojo:SplitContainerPanel");

__CPAN_FILE__ src/widget/PopUpButton.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.PopUpButton");
dojo.provide("dojo.widget.DomPopUpButton");
dojo.provide("dojo.widget.HtmlPopUpButton");

dojo.deprecated("dojo.widget.PopUpButton, dojo.widget.DomPopUpButton, dojo.widget.HtmlPopUpButton",  "use dojo.widget.DropDownButton", "0.4");

//dojo.require("dojo.widget.Button");
//dojo.require("dojo.widget.HtmlButton");

dojo.require("dojo.widget.Menu");
dojo.require("dojo.widget.MenuItem");

dojo.require("dojo.html");

dojo.widget.tags.addParseTreeHandler("dojo:PopUpButton");

/* PopUpButton
 **************/
 
dojo.widget.PopUpButton = function () {
	dojo.widget.PopUpButton.superclass.constructor.call(this);
}
dojo.inherits(dojo.widget.PopUpButton, dojo.widget.Widget);

dojo.lang.extend(dojo.widget.PopUpButton, {
	widgetType: "PopUpButton",
	
	label: ""
});


/* DomPopUpButton
 *****************/
dojo.widget.DomPopUpButton = function(){
	dojo.widget.DomPopUpButton.superclass.constructor.call(this);
}
dojo.inherits(dojo.widget.DomPopUpButton, dojo.widget.DomWidget);

dojo.lang.extend(dojo.widget.DomPopUpButton, {
	widgetType: dojo.widget.PopUpButton.prototype.widgetType
});


/* HtmlPopUpButton
 ******************/

dojo.widget.HtmlPopUpButton = function () {
	dojo.widget.HtmlPopUpButton.superclass.constructor.call(this);
}
dojo.inherits(dojo.widget.HtmlPopUpButton, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.HtmlPopUpButton, {
	widgetType: dojo.widget.PopUpButton.prototype.widgetType,
	templateString: null,
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/PopUpButton.css"),
	
	buildRendering: function (args, frag) {
		dojo.style.insertCssFile(this.templateCssPath, null, true);
	
		this.domNode = document.createElement("a");
		this.domNode.className = "PopUpButton";
		dojo.event.connect(this.domNode, "onmousedown", this, "onMouseDown");
		
		// draw the arrow
		var arrow = document.createElement("img");
		arrow.src = dojo.uri.dojoUri("src/widget/templates/images/dropdownButtonsArrow.gif");
		dojo.html.setClass(arrow, "downArrow");
		this.domNode.appendChild(arrow);

		this.menu = dojo.widget.fromScript("Menu");
		dojo.html.addClass(this.menu.domNode, "PopUpButtonMenu");
		dojo.event.connect(this.menu, "onSelect", this, "onSelect");
		
		if (frag["dojo:" + this.widgetType.toLowerCase()].nodeRef) {
			var node = frag["dojo:" + this.widgetType.toLowerCase()].nodeRef;
			var options = node.getElementsByTagName("option");
			for (var i = 0; i < options.length; i++) {
				var properties = {
					title: dojo.dom.textContent(options[i]),
					value: options[i].value
				}
				this.addItem(dojo.widget.fromScript("MenuItem", properties));
			}
		}
	},

	addItem: function (item) {
		// TODO: should be dojo.widget.MenuItem
		if (item instanceof dojo.widget.html.MenuItem) {
			this.menu.push(item);
		} else {
			// TODO: create one
			var menuItem = dojo.widget.fromScript("MenuItem", {title: item});
			this.menu.push(menuItem);
		}
	},
	
	
/* Enabled utility methods
 **************************/
	
	_enabled: true,
	
	isEnabled: function() { return this._enabled; },
	
	setEnabled: function(enabled, force, preventEvent) {
		enabled = Boolean(enabled);
		if (force || this._enabled != enabled) {
			this._enabled = enabled;
			if (!preventEvent) {
				this._fireEvent(this._enabled ? "onEnable" : "onDisable");
				this._fireEvent("onChangeEnabled");
			}
		}
		
		dojo.html[(this._enabled ? "add" : "remove")
			+ "Class"](this.domNode, "disabled");
		
		return this._enabled;
	},
	
	enable: function(force, preventEvent) {
		return this.setEnabled(true, force, preventEvent);
	},
	
	disable: function(force, preventEvent) {
		return this.setEnabled(false, force, preventEvent);
	},
	
	toggleEnabled: function(force, preventEvent) {
		return this.setEnabled(!this._enabled, force, preventEvent);
	},


/* Select utility methods
 **************************/

	onSelect: function (item, e) {
		this.domNode.firstChild.nodeValue = item.title;
	},
	
	onMouseDown: function (e) {
		if (!this._menuVisible) {
			this._showMenu(e);
			dojo.lang.setTimeout(dojo.event.connect, 1, document, "onmousedown", this, "_hideMenu");
		}
	},
	
	
	_fireEvent: function(evt) {
		if(typeof this[evt] == "function") {
			var args = [this];
			for(var i = 1; i < arguments.length; i++) {
				args.push(arguments[i]);
			}
			this[evt].apply(this, args);
		}
	},

	
	_showMenu: function (e) {
		if (!this._enabled) { return; }
		this._menuVisible = true;
		with (dojo.html) {
			var y = getAbsoluteY(this.domNode) + getInnerHeight(this.domNode);
			var x = getAbsoluteX(this.domNode);
		}
	
		document.body.appendChild(this.menu.domNode);
		with (this.menu.domNode.style) {
			top = y + "px";
			left = x + "px";
		}
	},
	
	_hideMenu: function (e) {
		this.menu.domNode.parentNode.removeChild(this.menu.domNode);
		dojo.event.disconnect(document, "onmousedown", this, "_hideMenu");
		this._menuVisible = false;
	}

});

__CPAN_FILE__ src/widget/FloatingPane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.FloatingPane");
dojo.provide("dojo.widget.html.FloatingPane");

//
// this widget provides a window-like floating pane
//

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.Manager");
dojo.require("dojo.html");
dojo.require("dojo.html.shadow");
dojo.require("dojo.style");
dojo.require("dojo.dom");
dojo.require("dojo.html.layout");
dojo.require("dojo.widget.ContentPane");
dojo.require("dojo.dnd.HtmlDragMove");
dojo.require("dojo.dnd.HtmlDragMoveSource");
dojo.require("dojo.dnd.HtmlDragMoveObject");
dojo.require("dojo.widget.ResizeHandle");

dojo.widget.html.FloatingPane = function(){
	dojo.widget.html.ContentPane.call(this);
}

dojo.inherits(dojo.widget.html.FloatingPane, dojo.widget.html.ContentPane);

dojo.lang.extend(dojo.widget.html.FloatingPane, {
	widgetType: "FloatingPane",

	// Constructor arguments
	title: '',
	iconSrc: '',
	hasShadow: false,
	constrainToContainer: false,
	taskBarId: "",
	resizable: true,
	titleBarDisplay: "fancy",

	windowState: "normal",
	displayCloseAction: false,
	displayMinimizeAction: false,
	displayMaximizeAction: false,

	maxTaskBarConnectAttempts: 5,
	taskBarConnectAttempts: 0,

	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlFloatingPane.html"),
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlFloatingPane.css"),

	drag: null,

	fillInTemplate: function(args, frag){
		// Copy style info from input node to output node
		var source = this.getFragNodeRef(frag);
		dojo.html.copyStyle(this.domNode, source);

		// necessary for safari, khtml (for computing width/height)
		document.body.appendChild(this.domNode);

		// if display:none then state=minimized, otherwise state=normal
		if(!this.isShowing()){
			this.windowState="minimized";
		}

		// <img src=""> can hang IE!  better get rid of it
		if(this.iconSrc==""){
			dojo.dom.removeNode(this.titleBarIcon);
		}else{
			this.titleBarIcon.src = this.iconSrc.toString();// dojo.uri.Uri obj req. toString()
		}

		if(this.titleBarDisplay!="none"){	
			this.titleBar.style.display="";
			dojo.html.disableSelection(this.titleBar);

			this.titleBarIcon.style.display = (this.iconSrc=="" ? "none" : "");

			this.minimizeAction.style.display = (this.displayMinimizeAction ? "" : "none");
			this.maximizeAction.style.display= 
				(this.displayMaximizeAction && this.windowState!="maximized" ? "" : "none");
			this.restoreAction.style.display= 
				(this.displayMaximizeAction && this.windowState=="maximized" ? "" : "none");
			this.closeAction.style.display= (this.displayCloseAction ? "" : "none");

			this.drag = new dojo.dnd.HtmlDragMoveSource(this.domNode);	
			if (this.constrainToContainer) {
				this.drag.constrainTo();
			}
			this.drag.setDragHandle(this.titleBar);

			var self = this;

			dojo.event.topic.subscribe("dragMove",
				function (info){
					if (info.source.domNode == self.domNode){
						dojo.event.topic.publish('floatingPaneMove', { source: self } );
					}
				}
			);

		}

		if(this.resizable){
			this.resizeBar.style.display="";
			var rh = dojo.widget.createWidget("ResizeHandle", {targetElmId: this.widgetId, id:this.widgetId+"_resize"});
			this.resizeBar.appendChild(rh.domNode);
		}

		// add a drop shadow
		if(this.hasShadow){
			this.shadow=new dojo.html.shadow(this.domNode);
		}

		// Prevent IE bleed-through problem
		this.bgIframe = new dojo.html.BackgroundIframe(this.domNode);

		if( this.taskBarId ){
			this.taskBarSetup();
		}

		if (dojo.hostenv.post_load_) {
			this.setInitialWindowState();
		} else {
			dojo.addOnLoad(this, "setInitialWindowState");
		}

		// counteract body.appendChild above
		document.body.removeChild(this.domNode);

		dojo.widget.html.FloatingPane.superclass.fillInTemplate.call(this, args, frag);
	},

	postCreate: function(){
		if(this.isShowing()){
			this.width=-1;	// force resize
			this.resizeTo(dojo.style.getOuterWidth(this.domNode), dojo.style.getOuterHeight(this.domNode));
		}
	},

	maximizeWindow: function(evt) {
		this.previous={
			width: dojo.style.getOuterWidth(this.domNode) || this.width,
			height: dojo.style.getOuterHeight(this.domNode) || this.height,
			left: this.domNode.style.left,
			top: this.domNode.style.top,
			bottom: this.domNode.style.bottom,
			right: this.domNode.style.right
		};
		this.domNode.style.left =
			dojo.style.getPixelValue(this.domNode.parentNode, "padding-left", true) + "px";
		this.domNode.style.top =
			dojo.style.getPixelValue(this.domNode.parentNode, "padding-top", true) + "px";

		if ((this.domNode.parentNode.nodeName.toLowerCase() == 'body')) {
			this.resizeTo(
				dojo.html.getViewportWidth()-dojo.style.getPaddingWidth(document.body),
				dojo.html.getViewportHeight()-dojo.style.getPaddingHeight(document.body)
			);
		} else {
			this.resizeTo(
				dojo.style.getContentWidth(this.domNode.parentNode),
				dojo.style.getContentHeight(this.domNode.parentNode)
			);
		}
		this.maximizeAction.style.display="none";
		this.restoreAction.style.display="";
		this.windowState="maximized";
	},

	minimizeWindow: function(evt) {
		this.hide();
		this.windowState = "minimized";
	},

	restoreWindow: function(evt) {
		if (this.windowState=="minimized") {
			this.show() 
		} else {
			for(var attr in this.previous){
				this.domNode.style[attr] = this.previous[attr];
			}
			this.resizeTo(this.previous.width, this.previous.height);
			this.previous=null;

			this.restoreAction.style.display="none";
			this.maximizeAction.style.display=this.displayMaximizeAction ? "" : "none";
		}

		this.windowState="normal";
	},

	closeWindow: function(evt) {
		dojo.dom.removeNode(this.domNode);
		this.destroy();
	},

	onMouseDown: function(evt) {
		this.bringToTop();
	},

	bringToTop: function() {
		var floatingPanes= dojo.widget.manager.getWidgetsByType(this.widgetType);
		var windows = [];
		for (var x=0; x<floatingPanes.length; x++) {
			if (this.widgetId != floatingPanes[x].widgetId) {
					windows.push(floatingPanes[x]);
			}
		}

		windows.sort(function(a,b) {
			return a.domNode.style.zIndex - b.domNode.style.zIndex;
		});
		
		windows.push(this);

		var floatingPaneStartingZ = 100;
		for (x=0; x<windows.length;x++) {
			windows[x].domNode.style.zIndex = floatingPaneStartingZ + x;
		}
	},

	setInitialWindowState: function() {
		if (this.windowState == "maximized") {
			this.maximizeWindow();
			this.show();
			return;
		}

		if (this.windowState=="normal") {
			this.show();
			return;
		}

		if (this.windowState=="minimized") {
			this.hide();
			return;
		}

		this.windowState="minimized";
	},

	// add icon to task bar, connected to me
	taskBarSetup: function() {
		var taskbar = dojo.widget.getWidgetById(this.taskBarId);
		if (!taskbar){
			if (this.taskBarConnectAttempts <  this.maxTaskBarConnectAttempts) {
				dojo.lang.setTimeout(this, this.taskBarSetup, 50);
				this.taskBarConnectAttempts++;
			} else {
				dojo.debug("Unable to connect to the taskBar");
			}
			return;
		}
		taskbar.addChild(this);
	},

	show: function(){
		dojo.widget.html.FloatingPane.superclass.show.apply(this, arguments);
		this.bringToTop();
	},

	onShow: function(){
		dojo.widget.html.FloatingPane.superclass.onShow.call(this);
		this.resizeTo(dojo.style.getOuterWidth(this.domNode), dojo.style.getOuterHeight(this.domNode));
	},

	// This is called when the user adjusts the size of the floating pane
	resizeTo: function(w, h){
		dojo.style.setOuterWidth(this.domNode, w);
		dojo.style.setOuterHeight(this.domNode, h);

		dojo.html.layout(this.domNode,
			[
			  {domNode: this.titleBar, layoutAlign: "top"},
			  {domNode: this.resizeBar, layoutAlign: "bottom"},
			  {domNode: this.containerNode, layoutAlign: "client"}
			] );

		// If any of the children have layoutAlign specified, obey it
		dojo.html.layout(this.containerNode, this.children, "top-bottom");
		
		this.bgIframe.onResized();
		if(this.shadow){ this.shadow.size(w, h); }
		this.onResized();
	},

	checkSize: function() {
		// checkSize() is called when the user has resized the browser window,
		// but that doesn't affect this widget (or this widget's children)
		// so it can be safely ignored...
		// TODO: unless we are maximized.  then we should resize ourself.
	}
});

dojo.widget.tags.addParseTreeHandler("dojo:FloatingPane");

__CPAN_FILE__ src/widget/YahooMap.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.YahooMap");
dojo.provide("dojo.widget.YahooMap.Controls");
dojo.require("dojo.widget.*");

dojo.widget.defineWidget(
	"dojo.widget.YahooMap",
	dojo.widget.Widget,
	{ isContainer: false }
);

dojo.widget.YahooMap.Controls={
	MapType:"maptype",
	Pan:"pan",
	ZoomLong:"zoomlong",
	ZoomShort:"zoomshort"
};
dojo.requireAfterIf("html", "dojo.widget.html.YahooMap");

__CPAN_FILE__ src/widget/SvgWidget.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.widget.DomWidget");
dojo.provide("dojo.widget.SvgWidget");
dojo.provide("dojo.widget.SVGWidget"); // back compat

dojo.require("dojo.dom");

// SVGWidget is a mixin ONLY
dojo.widget.SvgWidget = function(args){
	// mix in the parent type
	// dojo.widget.DomWidget.call(this);
}
dojo.inherits(dojo.widget.SvgWidget, dojo.widget.DomWidget);

dojo.lang.extend(dojo.widget.SvgWidget, {
	getContainerHeight: function(){
		// NOTE: container height must be returned as the INNER height
		dojo.unimplemented("dojo.widget.SvgWidget.getContainerHeight");
	},

	getContainerWidth: function(){
		// return this.parent.domNode.offsetWidth;
		dojo.unimplemented("dojo.widget.SvgWidget.getContainerWidth");
	},

	setNativeHeight: function(height){
		// var ch = this.getContainerHeight();
		dojo.unimplemented("dojo.widget.SVGWidget.setNativeHeight");
	},

	createNodesFromText: function(txt, wrap){
		return dojo.dom.createNodesFromText(txt, wrap);
	}
});

dojo.widget.SVGWidget = dojo.widget.SvgWidget;

try{
(function(){
	var tf = function(){
		// FIXME: fill this in!!!
		var rw = new function(){
			dojo.widget.SvgWidget.call(this);
			this.buildRendering = function(){ return; }
			this.destroyRendering = function(){ return; }
			this.postInitialize = function(){ return; }
			this.cleanUp = function(){ return; }
			this.widgetType = "SVGRootWidget";
			this.domNode = document.documentElement;
		}
		var wm = dojo.widget.manager;
		wm.root = rw;
		wm.add(rw);

		// extend the widgetManager with a getWidgetFromNode method
		wm.getWidgetFromNode = function(node){
			var filter = function(x){
				if(x.domNode == node){
					return true;
				}
			}
			var widgets = [];
			while((node)&&(widgets.length < 1)){
				widgets = this.getWidgetsByFilter(filter);
				node = node.parentNode;
			}
			if(widgets.length > 0){
				return widgets[0];
			}else{
				return null;
			}
		}

		wm.getWidgetFromEvent = function(domEvt){
			return this.getWidgetFromNode(domEvt.target);
		}

		wm.getWidgetFromPrimitive = wm.getWidgetFromNode;
	}
	// make sure we get called when the time is right
	dojo.event.connect(dojo.hostenv, "loaded", tf);
})();
}catch(e){ alert(e); }

__CPAN_FILE__ src/widget/SortableTable.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.SortableTable");
dojo.require("dojo.widget.*");
dojo.requireAfterIf("html", "dojo.widget.html.SortableTable");
dojo.widget.tags.addParseTreeHandler("dojo:sortableTable");

//	set up the general widget
dojo.widget.SortableTable=function(){
	//	summary
	//	base class for the SortableTable
	dojo.widget.Widget.call(this);
	this.widgetType="SortableTable";
	this.isContainer=false;

	//	custom properties
	this.enableMultipleSelect=false;
	this.maximumNumberOfSelections=0;	//	0 for unlimited, is the default.
	this.enableAlternateRows=false;
	this.minRows=0;	//	0 means ignore.
	this.defaultDateFormat="%D";
	this.data=[];
	this.selected=[];		//	always an array to handle multiple selections.
	this.columns=[];
	this.sortIndex=0;		//	index of the column sorted on, first is the default.
	this.sortDirection=0;	//	0==asc, 1==desc
	this.valueField="Id";	//	if a JSON structure is parsed and there is a field of this name,
							//	a value attribute will be added to the row (tr value="{Id}")
};
dojo.inherits(dojo.widget.SortableTable, dojo.widget.Widget);

__CPAN_FILE__ src/widget/AccordionContainer.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.AccordionContainer");

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.AccordionPane");

dojo.widget.defineWidget(
	"dojo.widget.AccordionContainer",
	dojo.widget.HtmlWidget,
	{
		widgetType: "AccordionContainer",
		isContainer: true,
		labelNodeClass: "",
		containerNodeClass: "",
		allowCollapse: false,

		addChild: function(widget, overrideContainerNode, pos, ref, insertIndex){
			if (widget.widgetType != "AccordionPane") {
				var wrapper=dojo.widget.createWidget("AccordionPane",{label: widget.label, open: widget.open, labelNodeClass: this.labelNodeClass, containerNodeClass: this.containerNodeClass, allowCollapse: this.allowCollapse });
				wrapper.addChild(widget);
				this.addWidgetAsDirectChild(wrapper);
				this.registerChild(wrapper);
				wrapper.setSizes();
				return wrapper;
			} else {
				dojo.html.addClass(widget.containerNode, this.containerNodeClass);
				dojo.html.addClass(widget.labelNode, this.labelNodeClass);
				this.addWidgetAsDirectChild(widget);
				this.registerChild(widget);	
				widget.setSizes();
				return widget;
			}
	        },
	
		postCreate: function() {
			var tmpChildren = this.children;
			this.children=[];
			dojo.html.removeChildren(this.domNode);
			dojo.lang.forEach(tmpChildren, dojo.lang.hitch(this,"addChild"));
		},
	
		removeChild: function(widget) {
			dojo.widget.AccordionContainer.superclass.removeChild.call(this, widget);
			if(this.children[0]){
				this.children[0].setSizes();
			}
		},
		
		onResized: function(){
			this.children[0].setSizes();
		}
	}
);

// These arguments can be specified for the children of a Accordion
// Since any widget can be specified as a child, mix them
// into the base widget class.  (This is a hack, but it's effective.)
dojo.lang.extend(dojo.widget.Widget, {
	label: "",
	open: false
});


__CPAN_FILE__ src/widget/TreeNode.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/


dojo.provide("dojo.widget.TreeNode");

dojo.require("dojo.event.*");
dojo.require("dojo.io.*");

// make it a tag
dojo.widget.tags.addParseTreeHandler("dojo:TreeNode");


// # //////////

dojo.widget.TreeNode = function() {
	dojo.widget.HtmlWidget.call(this);

	this.actionsDisabled = [];
}

dojo.inherits(dojo.widget.TreeNode, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.TreeNode, {
	widgetType: "TreeNode",

	loadStates: {
		UNCHECKED: "UNCHECKED",
    	LOADING: "LOADING",
    	LOADED: "LOADED"
	},


	actions: {
		MOVE: "MOVE",
    	REMOVE: "REMOVE",
    	EDIT: "EDIT",
    	ADDCHILD: "ADDCHILD"
	},

	isContainer: true,

	lockLevel: 0, // lock ++ unlock --, so nested locking works fine


	templateString: ('<div class="dojoTreeNode"> '
		+ '<span treeNode="${this.widgetId}" class="dojoTreeNodeLabel" dojoAttachPoint="labelNode"> '
		+ '		<span dojoAttachPoint="titleNode" dojoAttachEvent="onClick: onTitleClick" class="dojoTreeNodeLabelTitle">${this.title}</span> '
		+ '</span> '
		+ '<span class="dojoTreeNodeAfterLabel" dojoAttachPoint="afterLabelNode">${this.afterLabel}</span> '
		+ '<div dojoAttachPoint="containerNode" style="display:none"></div> '
		+ '</div>').replace(/(>|<)\s+/g, '$1'), // strip whitespaces between nodes


	childIconSrc: "",
	childIconFolderSrc: dojo.uri.dojoUri("src/widget/templates/images/Tree/closed.gif"), // for under root parent item child icon,
	childIconDocumentSrc: dojo.uri.dojoUri("src/widget/templates/images/Tree/document.gif"), // for under root parent item child icon,

	childIcon: null,
	isTreeNode: true,

	objectId: "", // the widget represents an object

	afterLabel: "",
	afterLabelNode: null, // node to the left of labelNode

	// an icon left from childIcon: imgs[-2].
	// if +/- for folders, blank for leaves
	expandIcon: null,

	title: "",
	object: "", // node may have object attached, settable from HTML
	isFolder: false,

	labelNode: null, // the item label
	titleNode: null, // the item title
	imgs: null, // an array of icons imgs

	expandLevel: "", // expand to level

	tree: null,

	depth: 0,

	isExpanded: false,

	state: null,  // after creation will change to loadStates: "loaded/loading/unchecked"
	domNodeInitialized: false,  // domnode is initialized with icons etc


	isFirstNode: function() {
		return this.getParentIndex() == 0 ? true: false;
	},

	isLastNode: function() {
		return this.getParentIndex() == this.parent.children.length-1 ? true : false;
	},

	lock: function(){ return this.tree.lock.apply(this, arguments) },
	unlock: function(){ return this.tree.unlock.apply(this, arguments) },
	isLocked: function(){ return this.tree.isLocked.apply(this, arguments) },
	cleanLock: function(){ return this.tree.cleanLock.apply(this, arguments) },

	actionIsDisabled: function(action) {
		var _this = this;

		var disabled = false;

		if (this.tree.strictFolders && action == this.actions.ADDCHILD && !this.isFolder) {
			disabled = true;
		}

		if (dojo.lang.inArray(_this.actionsDisabled, action)) {
			disabled = true;
		}

		if (this.isLocked()) {
			disabled = true;
		}

		return disabled;
	},

	getInfo: function() {
		// No title here (title may be widget)
		var info = {
			widgetId: this.widgetId,
			objectId: this.objectId,
			index: this.getParentIndex(),
			isFolder: this.isFolder
		}

		return info;
	},

	initialize: function(args, frag){

		//dojo.debug(this.title)

		this.state = this.loadStates.UNCHECKED;

		for(var i=0; i<this.actionsDisabled.length; i++) {
			this.actionsDisabled[i] = this.actionsDisabled[i].toUpperCase();
		}

		this.expandLevel = parseInt(this.expandLevel);

	},


	/**
	 * Change visible node depth by appending/prepending with blankImgs
	 * @param depthDiff Integer positive => move right, negative => move left
	*/
	adjustDepth: function(depthDiff) {

		for(var i=0; i<this.children.length; i++) {
			this.children[i].adjustDepth(depthDiff);
		}

		this.depth += depthDiff;

		if (depthDiff>0) {
			for(var i=0; i<depthDiff; i++) {
				var img = this.tree.makeBlankImg();
				this.imgs.unshift(img);
				//dojo.debugShallow(this.domNode);
				dojo.dom.insertBefore(this.imgs[0], this.domNode.firstChild);

			}
		}
		if (depthDiff<0) {
			for(var i=0; i<-depthDiff;i++) {
				this.imgs.shift();
				dojo.dom.removeNode(this.domNode.firstChild);
			}
		}

	},


	markLoading: function() {
		this._markLoadingSavedIcon = this.expandIcon.src;
		this.expandIcon.src = this.tree.expandIconSrcLoading;
	},

	// if icon is "Loading" then
	unMarkLoading: function() {
		if (!this._markLoadingSavedIcon) return;

		var im = new Image();
		im.src = this.tree.expandIconSrcLoading;

		//dojo.debug("Unmark "+this.expandIcon.src+" : "+im.src);
		if (this.expandIcon.src == im.src) {
			this.expandIcon.src = this._markLoadingSavedIcon;
		}
		this._markLoadingSavedIcon = null;
	},


	setFolder: function() {
		dojo.event.connect(this.expandIcon, 'onclick', this, 'onTreeClick');
		this.expandIcon.src = this.isExpanded ? this.tree.expandIconSrcMinus : this.tree.expandIconSrcPlus;
		this.isFolder = true;
	},


	createDOMNode: function(tree, depth){

		this.tree = tree;
		this.depth = depth;


		//
		// add the tree icons
		//

		this.imgs = [];

		for(var i=0; i<this.depth+1; i++){

			var img = this.tree.makeBlankImg();

			this.domNode.insertBefore(img, this.labelNode);

			this.imgs.push(img);
		}


		this.expandIcon = this.imgs[this.imgs.length-1];


		this.childIcon = this.tree.makeBlankImg();

		// add to images before the title
		this.imgs.push(this.childIcon);

		dojo.dom.insertBefore(this.childIcon, this.titleNode);

		// node with children(from source html) becomes folder on build stage.
		if (this.children.length || this.isFolder) {
			this.setFolder();
		}
		else {
			// leaves are always loaded
			//dojo.debug("Set "+this+" state to loaded");
			this.state = this.loadStates.LOADED;
		}

		dojo.event.connect(this.childIcon, 'onclick', this, 'onIconClick');


		//
		// create the child rows
		//


		for(var i=0; i<this.children.length; i++){
			this.children[i].parent = this;

			var node = this.children[i].createDOMNode(this.tree, this.depth+1);

			this.containerNode.appendChild(node);
		}


		if (this.children.length) {
			this.state = this.loadStates.LOADED;
		}

		this.updateIcons();

		this.domNodeInitialized = true;

		dojo.event.topic.publish(this.tree.eventNames.createDOMNode, { source: this } );

		return this.domNode;
	},

	onTreeClick: function(e){
		dojo.event.topic.publish(this.tree.eventNames.treeClick, { source: this, event: e });
	},

	onIconClick: function(e){
		dojo.event.topic.publish(this.tree.eventNames.iconClick, { source: this, event: e });
	},

	onTitleClick: function(e){
		dojo.event.topic.publish(this.tree.eventNames.titleClick, { source: this, event: e });
	},

	markSelected: function() {
		dojo.html.addClass(this.titleNode, 'dojoTreeNodeLabelSelected');
	},


	unMarkSelected: function() {
		//dojo.debug('unmark')
		dojo.html.removeClass(this.titleNode, 'dojoTreeNodeLabelSelected');
	},

	updateExpandIcon: function() {
		if (this.isFolder){
			this.expandIcon.src = this.isExpanded ? this.tree.expandIconSrcMinus : this.tree.expandIconSrcPlus;
		} else {
			this.expandIcon.src = this.tree.blankIconSrc;
		}
	},

	/* set the grid under the expand icon */
	updateExpandGrid: function() {

		if (this.tree.showGrid){
			if (this.depth){
				this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcL : this.tree.gridIconSrcT);
			}else{
				if (this.isFirstNode()){
					this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcX : this.tree.gridIconSrcY);
				}else{
					this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcL : this.tree.gridIconSrcT);
				}
			}
		}else{
			this.setGridImage(-2, this.tree.blankIconSrc);
		}

	},

	/* set the grid under the child icon */
	updateChildGrid: function() {

		if ((this.depth || this.tree.showRootGrid) && this.tree.showGrid){
			this.setGridImage(-1, (this.children.length && this.isExpanded) ? this.tree.gridIconSrcP : this.tree.gridIconSrcC);
		}else{
			if (this.tree.showGrid && !this.tree.showRootGrid){
				this.setGridImage(-1, (this.children.length && this.isExpanded) ? this.tree.gridIconSrcZ : this.tree.blankIconSrc);
			}else{
				this.setGridImage(-1, this.tree.blankIconSrc);
			}
		}


	},

	updateParentGrid: function() {
		var parent = this.parent;

		//dojo.debug("updateParentGrid "+this);

		for(var i=0; i<this.depth; i++){

			//dojo.debug("Parent "+parent);

			var idx = this.imgs.length-(3+i);
			var img = (this.tree.showGrid && !parent.isLastNode()) ? this.tree.gridIconSrcV : this.tree.blankIconSrc;

			//dojo.debug("Image "+img+" for "+idx);

			this.setGridImage(idx, img);

			parent = parent.parent;
		}
	},

	updateExpandGridColumn: function() {
		if (!this.tree.showGrid) return;

		var _this = this;

		var icon = this.isLastNode() ? this.tree.blankIconSrc : this.tree.gridIconSrcV;

		dojo.lang.forEach(_this.getDescendants(),
			function(node) { node.setGridImage(_this.depth, icon); }
		);

		this.updateExpandGrid();
	},

	updateIcons: function(){


		//dojo.profile.start("updateIcons")

		//dojo.debug("Update icons for "+this)
		//dojo.debug(this.isFolder)

		this.imgs[0].style.display = this.tree.showRootGrid ? 'inline' : 'none';


		//
		// set the expand icon
		//


		//
		// set the child icon
		//
		this.buildChildIcon();

		this.updateExpandGrid();
		this.updateChildGrid();
		this.updateParentGrid();



		dojo.profile.stop("updateIcons")

	},

	buildChildIcon: function() {
		// IE (others?) tries to download whatever is on src attribute so setting "url()" like before isnt a good idea
		// Only results in a 404
		if(this.childIconSrc){
			this.childIcon.src = this.childIconSrc;
		}
		this.childIcon.style.display = this.childIconSrc ? 'inline' : 'none';
	},

	setGridImage: function(idx, src){

		if (idx < 0){
			idx = this.imgs.length + idx;
		}

		//if (idx >= this.imgs.length-2) return;
		this.imgs[idx].style.backgroundImage = 'url(' + src + ')';
	},


	updateIconTree: function(){
		this.tree.updateIconTree.call(this);
	},




	expand: function(){
		if (this.isExpanded) return;

		if (this.children.length) {
			this.showChildren();
		}

		this.isExpanded = true;

		this.updateExpandIcon();

		dojo.event.topic.publish(this.tree.eventNames.expand, {source: this} );
	},

	collapse: function(){
		if (!this.isExpanded) return;

		this.hideChildren();
		this.isExpanded = false;

		this.updateExpandIcon();

		dojo.event.topic.publish(this.tree.eventNames.collapse, {source: this} );
	},

	hideChildren: function(){
		this.tree.toggleObj.hide(
			this.containerNode, this.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onHide")
		);

		/* if dnd is in action, recalculate changed coordinates */
		if(dojo.exists(dojo, 'dnd.dragManager.dragObjects') && dojo.dnd.dragManager.dragObjects.length) {
			dojo.dnd.dragManager.cacheTargetLocations();
		}
	},

	showChildren: function(){
		this.tree.toggleObj.show(
			this.containerNode, this.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onShow")
		);

		/* if dnd is in action, recalculate changed coordinates */
		if(dojo.exists(dojo, 'dnd.dragManager.dragObjects') && dojo.dnd.dragManager.dragObjects.length) {
			dojo.dnd.dragManager.cacheTargetLocations();
		}
	},

	addChild: function(){
		return this.tree.addChild.apply(this, arguments);
	},

	doAddChild: function(){
		return this.tree.doAddChild.apply(this, arguments);
	},



	/* Edit current node : change properties and update contents */
	edit: function(props) {
		dojo.lang.mixin(this, props);
		if (props.title) {
			this.titleNode.innerHTML = this.title;
		}

		if (props.afterLabel) {
			this.afterLabelNode.innerHTML = this.afterLabel;
		}

		if (props.childIconSrc) {
			this.buildChildIcon();
		}


	},


	removeNode: function(){ return this.tree.removeNode.apply(this, arguments) },
	doRemoveNode: function(){ return this.tree.doRemoveNode.apply(this, arguments) },


	toString: function() {
		return "["+this.widgetType+" Tree:"+this.tree+" ID:"+this.widgetId+" Title:"+this.title+"]";

	}

});





__CPAN_FILE__ src/widget/DebugConsole.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.DebugConsole");
dojo.require("dojo.widget.Widget");

dojo.widget.DebugConsole= function(){
	dojo.widget.Widget.call(this);

	this.widgetType = "DebugConsole";
	this.isContainer = true;
}
dojo.inherits(dojo.widget.DebugConsole, dojo.widget.Widget);
dojo.widget.tags.addParseTreeHandler("dojo:debugconsole");
dojo.requireAfterIf("html", "dojo.widget.html.DebugConsole");

__CPAN_FILE__ src/widget/HtmlWidget.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.DomWidget");
dojo.require("dojo.html");
dojo.require("dojo.html.extras");
dojo.require("dojo.lang.extras");
dojo.require("dojo.lang.func");
dojo.require("dojo.lfx.toggle");

dojo.declare("dojo.widget.HtmlWidget", dojo.widget.DomWidget, {								 
	widgetType: "HtmlWidget",

	templateCssPath: null,
	templatePath: null,

	// for displaying/hiding widget
	toggle: "plain",
	toggleDuration: 150,

	animationInProgress: false,

	initialize: function(args, frag){
	},

	postMixInProperties: function(args, frag){
		// now that we know the setting for toggle, get toggle object
		// (default to plain toggler if user specified toggler not present)
		this.toggleObj =
			dojo.lfx.toggle[this.toggle.toLowerCase()] || dojo.lfx.toggle.plain;
	},

	getContainerHeight: function(){
		// NOTE: container height must be returned as the INNER height
		dojo.unimplemented("dojo.widget.HtmlWidget.getContainerHeight");
	},

	getContainerWidth: function(){
		return this.parent.domNode.offsetWidth;
	},

	setNativeHeight: function(height){
		var ch = this.getContainerHeight();
	},

	createNodesFromText: function(txt, wrap){
		return dojo.html.createNodesFromText(txt, wrap);
	},

	destroyRendering: function(finalize){
		try{
			if(!finalize){
				dojo.event.browser.clean(this.domNode);
			}
			this.domNode.parentNode.removeChild(this.domNode);
			delete this.domNode;
		}catch(e){ /* squelch! */ }
	},

	/////////////////////////////////////////////////////////
	// Displaying/hiding the widget
	/////////////////////////////////////////////////////////
	isShowing: function(){
		return dojo.style.isShowing(this.domNode);
	},

	toggleShowing: function(){
		// dojo.style.toggleShowing(this.domNode);
		if(this.isHidden){
			this.show();
		}else{
			this.hide();
		}
	},

	show: function(){
		this.animationInProgress=true;
		this.isHidden = false;
		this.toggleObj.show(this.domNode, this.toggleDuration, null,
			dojo.lang.hitch(this, this.onShow), this.explodeSrc);
	},

	// called after the show() animation has completed
	onShow: function(){
		this.animationInProgress=false;
		this.checkSize();
	},

	hide: function(){
		this.animationInProgress = true;
		this.isHidden = true;
		this.toggleObj.hide(this.domNode, this.toggleDuration, null,
			dojo.lang.hitch(this, this.onHide), this.explodeSrc);
	},

	// called after the hide() animation has completed
	onHide: function(){
		this.animationInProgress=false;
	},

	//////////////////////////////////////////////////////////////////////////////
	// Sizing related methods
	//  If the parent changes size then for each child it should call either
	//   - resizeTo(): size the child explicitly
	//   - or checkSize(): notify the child the the parent has changed size
	//////////////////////////////////////////////////////////////////////////////

	// Test if my size has changed.
	// If width & height are specified then that's my new size; otherwise,
	// query outerWidth/outerHeight of my domNode
	_isResized: function(w, h){
		// If I'm not being displayed then disregard (show() must
		// check if the size has changed)
		if(!this.isShowing()){ return false; }

		// If my parent has been resized and I have style="height: 100%"
		// or something similar then my size has changed too.
		w=w||dojo.style.getOuterWidth(this.domNode);
		h=h||dojo.style.getOuterHeight(this.domNode);
		if(this.width == w && this.height == h){ return false; }

		this.width=w;
		this.height=h;
		return true;
	},

	// Called when my parent has changed size, but my parent won't call resizeTo().
	// This is useful if my size is height:100% or something similar.
	// Also called whenever I am shown, because the first time I am shown I may need
	// to do size calculations.
	checkSize: function(){
		if(!this._isResized()){ return; }
		this.onResized();
	},

	// Explicitly set this widget's size (in pixels).
	resizeTo: function(w, h){
		if(!this._isResized(w,h)){ return; }
		dojo.style.setOuterWidth(this.domNode, w);
		dojo.style.setOuterHeight(this.domNode, h);
		this.onResized();
	},

	resizeSoon: function(){
		if(this.isShowing()){
			dojo.lang.setTimeout(this, this.onResized, 0);
		}
	},

	// Called when my size has changed.
	// Must notify children if their size has (possibly) changed
	onResized: function(){
		dojo.lang.forEach(this.children, function(child){ child.checkSize(); });
	}
});

__CPAN_FILE__ src/widget/ShowAction.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.ShowAction");

dojo.require("dojo.widget.*");
dojo.require("dojo.lang.common");

dojo.widget.ShowAction = function(){}
dojo.lang.extend(dojo.widget.ShowAction, {
	on: "",
	action: "",
	duration: 0,
	from: "",
	to: "",
	auto: "false"
});

dojo.requireAfterIf("html", "dojo.widget.html.ShowAction");
__CPAN_FILE__ src/widget/AccordionPane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.AccordionPane");
dojo.requireAfterIf("html", "dojo.widget.html.AccordionPane");

__CPAN_FILE__ src/widget/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: ["dojo.xml.Parse", 
			 "dojo.widget.Widget", 
			 "dojo.widget.Parse", 
			 "dojo.widget.Manager"],
	browser: ["dojo.widget.DomWidget",
			  "dojo.widget.HtmlWidget"],
	dashboard: ["dojo.widget.DomWidget",
			  "dojo.widget.HtmlWidget"],
	svg: 	 ["dojo.widget.SvgWidget"],
	rhino: 	 ["dojo.widget.SwtWidget"]
});
dojo.provide("dojo.widget.*");

__CPAN_FILE__ src/widget/Menu2.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Menu2");
dojo.provide("dojo.widget.html.Menu2");
dojo.provide("dojo.widget.PopupMenu2");
dojo.provide("dojo.widget.MenuItem2");
dojo.provide("dojo.widget.MenuBar2");

dojo.require("dojo.html");
dojo.require("dojo.style");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");


dojo.widget.PopupMenu2 = function(){
	dojo.widget.HtmlWidget.call(this);
	this.items = [];	// unused???
	this.targetNodeIds = []; // fill this with nodeIds upon widget creation and it becomes context menu for those nodes
	this.queueOnAnimationFinish = [];

	this.eventNames =  {
		open: ""
	};

}

dojo.inherits(dojo.widget.PopupMenu2, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.PopupMenu2, {
	widgetType: "PopupMenu2",
	isContainer: true,

	snarfChildDomOutput: true,

	currentSubmenu: null,
	currentSubmenuTrigger: null,
	parentMenu: null,
	parentMenuBar: null,
	isShowingNow: false,
	menuX: 0,
	menuY: 0,
	menuWidth: 0,
	menuHeight: 0,
	menuIndex: 0,

	domNode: null,
	containerNode: null,

	eventNaming: "default",


	templateString: '<div class="dojoPopupMenu2" style="left:-9999px; top:-9999px; display: none;"><div dojoAttachPoint="containerNode" class="dojoPopupMenu2Client"></div></div>',
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlMenu2.css"),

	itemHeight: 18,
	iconGap: 1,
	accelGap: 10,
	submenuGap: 2,
	finalGap: 5,
	submenuIconSize: 4,
	separatorHeight: 9,
	submenuDelay: 500,
	submenuOverlap: 5,
	contextMenuForWindow: false,
	openEvent: null,

	submenuIconSrc: dojo.uri.dojoUri("src/widget/templates/images/submenu_off.gif").toString(),
	submenuIconOnSrc: dojo.uri.dojoUri("src/widget/templates/images/submenu_on.gif").toString(),

	initialize: function(args, frag) {

		if (this.eventNaming == "default") {
			for (var eventName in this.eventNames) {
				this.eventNames[eventName] = this.widgetId+"/"+eventName;
			}
		}

	},

	postCreate: function(){
		if (this.domNode.style.display=="none"){
			this.domNode.style.display = "";
		}
		this.domNode.style.left = '-9999px'
		this.domNode.style.top = '-9999px'

		// attach menu to document body if it's not already there
		if (this.domNode.parentNode != document.body){
			document.body.appendChild(this.domNode);
		}


		if (this.contextMenuForWindow){
			var doc = document.documentElement  || document.body;
			dojo.widget.Menu2.OperaAndKonqFixer.fixNode(doc);
			dojo.event.connect(doc, "oncontextmenu", this, "onOpen");
		} else if ( this.targetNodeIds.length > 0 ){
			for(var i=0; i<this.targetNodeIds.length; i++){
				this.bindDomNode(this.targetNodeIds[i]);
			}
		}

		this.subscribeSubitemsOnOpen();

		this.layoutMenuSoon();
	},

	subscribeSubitemsOnOpen: function() {
		var subItems = this.getChildrenOfType(dojo.widget.MenuItem2);

		//dojo.debug(subItems)

		for(var i=0; i<subItems.length; i++) {
			//dojo.debug(subItems[i]);
			dojo.event.topic.subscribe(this.eventNames.open, subItems[i], "menuOpen")
		}
	},

	// get open event for current menu
	getTopOpenEvent: function() {
		var menu = this;
		while (menu.parent){ menu = menu.parent; }
		return menu.openEvent;
	},

	// attach menu to given node
	bindDomNode: function(nodeName){
		var node = dojo.byId(nodeName);

		// fixes node so that it supports oncontextmenu if not natively supported, Konqueror, Opera more?
		dojo.widget.Menu2.OperaAndKonqFixer.fixNode(node);

		dojo.event.kwConnect({
			srcObj:     node,
			srcFunc:    "oncontextmenu",
			targetObj:  this,
			targetFunc: "onOpen",
			once:       true
		});
	},

	// detach menu from given node
	unBindDomNode: function(nodeName){
		var node = dojo.byId(nodeName);
		dojo.event.kwDisconnect({
			srcObj:     node,
			srcFunc:    "oncontextmenu",
			targetObj:  this,
			targetFunc: "onOpen",
			once:       true
		});

		// cleans a fixed node, konqueror and opera
		dojo.widget.Menu2.OperaAndKonqFixer.cleanNode(node);
	},

	layoutMenuSoon: function(){
		dojo.lang.setTimeout(this, "layoutMenu", 0);
	},

	layoutMenu: function(){

        // menu must be attached to DOM for size calculations to work
		// even though we attached to document.body in postCreate(), here
		// we seem to be attached to a #document-fragment.  Don't understand why.
        document.body.appendChild(this.domNode);

        // determine menu width
		var max_label_w = 0;
		var max_accel_w = 0;

		for(var i=0; i<this.children.length; i++){
			if (this.children[i].getLabelWidth){
				max_label_w = Math.max(max_label_w, this.children[i].getLabelWidth());
			}

			if (dojo.lang.isFunction(this.children[i].getAccelWidth)){
				max_accel_w = Math.max(max_accel_w, this.children[i].getAccelWidth());
			}
		}

		if( isNaN(max_label_w) || isNaN(max_accel_w) ){
			// Browser needs some more time to calculate sizes
			this.layoutMenuSoon();
			return;
		}

		var clientLeft = dojo.style.getPixelValue(this.domNode, "padding-left", true) + dojo.style.getPixelValue(this.containerNode, "padding-left", true);
		var clientTop  = dojo.style.getPixelValue(this.domNode, "padding-top", true)  + dojo.style.getPixelValue(this.containerNode, "padding-top", true);

		if( isNaN(clientLeft) || isNaN(clientTop) ){
			// Browser needs some more time to calculate sizes
			this.layoutMenuSoon();
			return;
		}

		var y = clientTop;
		var max_item_width = 0;

		for(var i=0; i<this.children.length; i++){

			var ch = this.children[i];

			ch.layoutItem(max_label_w, max_accel_w);

			ch.topPosition = y;

			y += dojo.style.getOuterHeight(ch.domNode);
			max_item_width = Math.max(max_item_width, dojo.style.getOuterWidth(ch.domNode));
		}

		dojo.style.setContentWidth(this.containerNode, max_item_width);
		dojo.style.setContentHeight(this.containerNode, y-clientTop);

		dojo.style.setContentWidth(this.domNode, dojo.style.getOuterWidth(this.containerNode));
		dojo.style.setContentHeight(this.domNode, dojo.style.getOuterHeight(this.containerNode));

		this.menuWidth = dojo.style.getOuterWidth(this.domNode);
		this.menuHeight = dojo.style.getOuterHeight(this.domNode);
	},

	/**
	 * Open the menu at position (x,y), relative to the viewport
	 * (usually positions are relative to the document; why is this different??)
	 */
	open: function(x, y, parent, explodeSrc){

		// if explodeSrc isn't specified then explode from my parent widget
		explodeSrc = explodeSrc || parent["domNode"] || [];

		if (this.isShowingNow){ return; }

		var parentMenu = (parent && parent.widgetType=="PopupMenu2") ? parent : null;

		if ( !parentMenu ) {
			// record whenever a top level menu is opened
			// explodeSrc may or may not be a node - it may also be an [x,y] position array
			var button = explodeSrc instanceof Array ? null : explodeSrc;
			dojo.widget.html.Menu2Manager.opened(this, button);
		}

		//dojo.debug("open called for animation "+this.animationInProgress)

		// if I click  right button and menu is opened, then it gets 2 commands: close -> open
		// so close enables animation and next "open" is put to queue to occur at new location
		if(this.animationInProgress){
			this.queueOnAnimationFinish.push(this.open, arguments);
			return;
		}

		var viewport = dojo.html.getViewportSize();
		var scrolloffset = dojo.html.getScrollOffset();

		var clientRect = {
			'left'  : scrolloffset[0],
			'right' : scrolloffset[0] + viewport[0],
			'top'   : scrolloffset[1],
			'bottom': scrolloffset[1] + viewport[1]
		};

		if (parentMenu){
			// submenu is opening

			if (x + this.menuWidth > clientRect.right){ x = x - (this.menuWidth + parentMenu.menuWidth - (2 * this.submenuOverlap)); }

			if (y + this.menuHeight > clientRect.bottom){ y = y -
			(this.menuHeight - (this.itemHeight + 5)); } // TODO: why 5?

		}else{
			// top level menu is opening
			x+=scrolloffset[0];
			y+=scrolloffset[1];
			explodeSrc[0] += scrolloffset[0];
			explodeSrc[1] += scrolloffset[1];

			if (x < clientRect.left){ x = clientRect.left; }
			if (x + this.menuWidth > clientRect.right){ x = x - this.menuWidth; }

			if (y < clientRect.top){ y = clientRect.top; }
			if (y + this.menuHeight > clientRect.bottom){ y = y - this.menuHeight; }
		}

		this.parentMenu = parentMenu;
		this.explodeSrc = explodeSrc;
		this.menuIndex = parentMenu ? parentMenu.menuIndex + 1 : 1;

		this.menuX = x;
		this.menuY = y;

		// move the menu into position but make it invisible
		// (because when menus are initially constructed they are visible but off-screen)
		this.domNode.style.zIndex = 200 + this.menuIndex;
		this.domNode.style.left = x + 'px';
		this.domNode.style.top = y + 'px';
		this.domNode.style.display='none';
		this.domNode.style.position='absolute';

		// then use the user defined method to display it
		this.show();

		this.isShowingNow = true;
	},

	close: function(){
		// If we are in the process of opening the menu and we are asked to close it,
		// we should really cancel the current animation, but for simplicity we will
		// just ignore the request
		if(this.animationInProgress){
			this.queueOnAnimationFinish.push(this.close, []);
			return;
		}

		this.closeSubmenu();
		this.hide();
		this.isShowingNow = false;
		dojo.widget.html.Menu2Manager.closed(this);

		if (this.parentMenuBar){
			this.parentMenuBar.closedMenu(this);
		}
	},

	onShow: function() {
		dojo.widget.HtmlWidget.prototype.onShow.call(this);
		this.processQueue();
	},

	// do events from queue
	processQueue: function() {
		if (!this.queueOnAnimationFinish.length) return;

		var func = this.queueOnAnimationFinish.shift();
		var args = this.queueOnAnimationFinish.shift();

		func.apply(this, args);
	},

	onHide: function() {
		dojo.widget.HtmlWidget.prototype.onHide.call(this);

		this.processQueue();
	},


	closeAll: function(){
		if (this.parentMenu){
			this.parentMenu.closeAll();
		}else{
			this.close();
		}
	},

	closeSubmenu: function(){
		if (this.currentSubmenu == null){ return; }

		this.currentSubmenu.close();
		this.currentSubmenu = null;

		this.currentSubmenuTrigger.is_open = false;
		this.currentSubmenuTrigger.closedSubmenu();
		this.currentSubmenuTrigger = null;
	},

	openSubmenu: function(submenu, from_item){

		var our_x = dojo.style.getPixelValue(this.domNode, 'left');
		var our_y = dojo.style.getPixelValue(this.domNode, 'top');
		var our_w = dojo.style.getOuterWidth(this.domNode);
		var item_y = from_item.topPosition;

		var x = our_x + our_w - this.submenuOverlap;
		var y = our_y + item_y;

		this.currentSubmenu = submenu;
		this.currentSubmenu.open(x, y, this, from_item.domNode);

		this.currentSubmenuTrigger = from_item;
		this.currentSubmenuTrigger.is_open = true;
	},

	onOpen: function(e){
		this.openEvent = e;

		//dojo.debugShallow(e);
		this.open(e.clientX, e.clientY, null, [e.clientX, e.clientY]);

		if(e["preventDefault"]){
			e.preventDefault();
		}
	},

	isPointInMenu: function(x, y){

		if (x < this.menuX){ return false; }
		if (x > this.menuX + this.menuWidth){ return false; }

		if (y < this.menuY){ return false; }
		if (y > this.menuY + this.menuHeight){ return false; }

		return true;
	}
});


dojo.widget.MenuItem2 = function(){
	dojo.widget.HtmlWidget.call(this);

	this.eventNames = {
		engage: ""
	};
}

dojo.inherits(dojo.widget.MenuItem2, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.MenuItem2, {
	widgetType: "MenuItem2",
	templateString:
			 '<div class="dojoMenuItem2">'
			+'<div dojoAttachPoint="iconNode" class="dojoMenuItem2Icon"></div>'
			+'<span dojoAttachPoint="labelNode" class="dojoMenuItem2Label"><span><span></span></span></span>'
			+'<span dojoAttachPoint="accelNode" class="dojoMenuItem2Accel"><span><span></span></span></span>'
			+'<div dojoAttachPoint="submenuNode" class="dojoMenuItem2Submenu"></div>'
			+'<div dojoAttachPoint="targetNode" class="dojoMenuItem2Target" dojoAttachEvent="onMouseOver: onHover; onMouseOut: onUnhover; onClick: _onClick;">&nbsp;</div>'
			+'</div>',

	//
	// nodes
	//

	domNode: null,
	iconNode: null,
	labelNode: null,
	accelNode: null,
	submenuNode: null,
	targetNode: null,

	//
	// internal settings
	//

	is_hovering: false,
	hover_timer: null,
	is_open: false,
	topPosition: 0,

	//
	// options
	//

	caption: 'Untitled',
	accelKey: '',
	iconSrc: '',
	submenuId: '',
	disabled: false,
	eventNaming: "default",


	postCreate: function(){

		dojo.html.disableSelection(this.domNode);

		if (this.disabled){
			this.setDisabled(true);
		}

		this.labelNode.childNodes[0].appendChild(document.createTextNode(this.caption));
		this.accelNode.childNodes[0].appendChild(document.createTextNode(this.accelKey));

		this.labelShadowNode = this.labelNode.childNodes[0].childNodes[0];
		this.accelShadowNode = this.accelNode.childNodes[0].childNodes[0];

		this.labelShadowNode.appendChild(document.createTextNode(this.caption));
		this.accelShadowNode.appendChild(document.createTextNode(this.accelKey));

		if (this.eventNaming == "default") {
			for (var eventName in this.eventNames) {
				this.eventNames[eventName] = this.widgetId+"/"+eventName;
			}
		}
	},

	layoutItem: function(label_w, accel_w){

		var x_label = this.parent.itemHeight + this.parent.iconGap;
		var x_accel = x_label + label_w + this.parent.accelGap;
		var x_submu = x_accel + accel_w + this.parent.submenuGap;
		var total_w = x_submu + this.parent.submenuIconSize + this.parent.finalGap;


		this.iconNode.style.left = '0px';
		this.iconNode.style.top = '0px';


		if (this.iconSrc){

			if ((this.iconSrc.toLowerCase().substring(this.iconSrc.length-4) == ".png") && (dojo.render.html.ie)){

				this.iconNode.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.iconSrc+"', sizingMethod='image')";
				this.iconNode.style.backgroundImage = '';
			}else{
				this.iconNode.style.backgroundImage = 'url('+this.iconSrc+')';
			}
		}else{
			this.iconNode.style.backgroundImage = '';
		}

		dojo.style.setOuterWidth(this.iconNode, this.parent.itemHeight);
		dojo.style.setOuterHeight(this.iconNode, this.parent.itemHeight);

		dojo.style.setOuterHeight(this.labelNode, this.parent.itemHeight);
		dojo.style.setOuterHeight(this.accelNode, this.parent.itemHeight);

		dojo.style.setContentWidth(this.domNode, total_w);
		dojo.style.setContentHeight(this.domNode, this.parent.itemHeight);

		this.labelNode.style.left = x_label + 'px';
		this.accelNode.style.left = x_accel + 'px';
		this.submenuNode.style.left = x_submu + 'px';

		dojo.style.setOuterWidth(this.submenuNode, this.parent.submenuIconSize);
		dojo.style.setOuterHeight(this.submenuNode, this.parent.itemHeight);

		this.submenuNode.style.display = this.submenuId ? 'block' : 'none';
		this.submenuNode.style.backgroundImage = 'url('+this.parent.submenuIconSrc+')';

		dojo.style.setOuterWidth(this.targetNode, total_w);
		dojo.style.setOuterHeight(this.targetNode, this.parent.itemHeight);
	},

	onHover: function(){

		if (this.is_hovering){ return; }
		if (this.is_open){ return; }

		this.parent.closeSubmenu();
		this.highlightItem();

		if (this.is_hovering){ this.stopSubmenuTimer(); }
		this.is_hovering = true;
		this.startSubmenuTimer();
	},

	onUnhover: function(){
		if (!this.is_open){ this.unhighlightItem(); }

		this.is_hovering = false;
		this.stopSubmenuTimer();
	},

	// Internal function for clicks
	_onClick: function(){
		if (this.disabled){ return; }

		if (this.submenuId){
			if (!this.is_open){
				this.stopSubmenuTimer();
				this.openSubmenu();
			}
		}else{
			this.parent.closeAll();
		}

		// for some browsers the onMouseOut doesn't get called (?), so call it manually
		this.onUnhover();

		// user defined handler for click
		this.onClick();

		dojo.event.topic.publish(this.eventNames.engage, this);
	},

	// User defined function to handle clicks
	onClick: function() { },

	highlightItem: function(){
		dojo.html.addClass(this.domNode, 'dojoMenuItem2Hover');
		this.submenuNode.style.backgroundImage = 'url('+this.parent.submenuIconOnSrc+')';
	},

	unhighlightItem: function(){
		dojo.html.removeClass(this.domNode, 'dojoMenuItem2Hover');
		this.submenuNode.style.backgroundImage = 'url('+this.parent.submenuIconSrc+')';
	},

	startSubmenuTimer: function(){
		this.stopSubmenuTimer();

		if (this.disabled){ return; }

		var self = this;
		var closure = function(){ return function(){ self.openSubmenu(); } }();

		this.hover_timer = window.setTimeout(closure, this.parent.submenuDelay);
	},

	stopSubmenuTimer: function(){
		if (this.hover_timer){
			window.clearTimeout(this.hover_timer);
			this.hover_timer = null;
		}
	},

	openSubmenu: function(){
		// first close any other open submenu
		this.parent.closeSubmenu();

		var submenu = dojo.widget.getWidgetById(this.submenuId);
		if (submenu){

			this.parent.openSubmenu(submenu, this);
		}

		//dojo.debug('open submenu for item '+this.widgetId);
	},

	closedSubmenu: function(){

		this.onUnhover();
	},

	setDisabled: function(value){
		this.disabled = value;

		if (this.disabled){
			dojo.html.addClass(this.domNode, 'dojoMenuItem2Disabled');
		}else{
			dojo.html.removeClass(this.domNode, 'dojoMenuItem2Disabled');
		}
	},

	getLabelWidth: function(){

		var node = this.labelNode.childNodes[0];

		return dojo.style.getOuterWidth(node);
	},

	getAccelWidth: function(){

		var node = this.accelNode.childNodes[0];

		return dojo.style.getOuterWidth(node);
	},

	menuOpen: function(message) {
	}

});


dojo.widget.MenuSeparator2 = function(){
	dojo.widget.HtmlWidget.call(this);
}

dojo.inherits(dojo.widget.MenuSeparator2, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.MenuSeparator2, {
	widgetType: "MenuSeparator2",

	domNode: null,
	topNode: null,
	bottomNode: null,

	templateString: '<div class="dojoMenuSeparator2">'
			+'<div dojoAttachPoint="topNode" class="dojoMenuSeparator2Top"></div>'
			+'<div dojoAttachPoint="bottomNode" class="dojoMenuSeparator2Bottom"></div>'
			+'</div>',

	postCreate: function(){
		dojo.html.disableSelection(this.domNode);
		this.layoutItem();
	},

	layoutItem: function(label_w, accel_w){

		var full_width = this.parent.itemHeight
				+ this.parent.iconGap
				+ label_w
				+ this.parent.accelGap
				+ accel_w
				+ this.parent.submenuGap
				+ this.parent.submenuIconSize
				+ this.parent.finalGap;

		if (isNaN(full_width)){ return; }

		dojo.style.setContentHeight(this.domNode, this.parent.separatorHeight);
		dojo.style.setContentWidth(this.domNode, full_width);
	}
});

//
// the menu manager makes sure we don't have several menus
// open at once. the root menu in an opening sequence calls
// opened(). when a root menu closes it calls closed(). then
// everything works. lovely.
//

dojo.widget.html.Menu2Manager = new function(){

	this.currentMenu = null;
	this.currentButton = null;		// button that opened current menu (if any)
	this.focusNode = null;

	dojo.event.connect(document, 'onmousedown', this, 'onClick');
	dojo.event.connect(window, "onscroll", this, "onClick");

	this.closed = function(menu){
		if (this.currentMenu == menu){
			this.currentMenu = null;
			this.currentButton = null;
		}
	};

	this.opened = function(menu, button){
		if (menu == this.currentMenu){ return; }

		if (this.currentMenu){
			this.currentMenu.close();
		}

		this.currentMenu = menu;
		this.currentButton = button;
	};

	this.onClick = function(e){

		if (!this.currentMenu){ return; }

		var scrolloffset = dojo.html.getScrollOffset();

		var x = e.clientX + scrolloffset[0];
		var y = e.clientY + scrolloffset[1];

		var m = this.currentMenu;

		// starting from the base menu, perform a hit test
		// and exit when one succeeds

		while (m){

			if (m.isPointInMenu(x, y)){

				return;
			}

			m = m.currentSubmenu;
		}

		// Also, if user clicked the button that opened this menu, then
		// that button will send the menu a close() command, so this code
		// shouldn't try to close the menu.  Closing twice messes up animation.
		if (this.currentButton && dojo.html.overElement(this.currentButton, e)){
			return;
		}

		// the click didn't fall within the open menu tree
		// so close it

		this.currentMenu.close();
	};
}

// ************************** make contextmenu work in konqueror and opera *********************
dojo.widget.Menu2.OperaAndKonqFixer = new function(){
 	var implement = true;
 	var delfunc = false;

 	/** 	dom event check
 	*
 	*	make a event and dispatch it and se if it calls function below,
 	*	if it does its supported and we dont need to implement our own
 	*/

 	// gets called if we have support for oncontextmenu
 	if (!dojo.lang.isFunction(document.oncontextmenu)){
 		document.oncontextmenu = function(){
 			implement = false;
 			delfunc = true;
 		}
 	}

 	if (document.createEvent){ // moz, safari has contextmenu event, need to do livecheck on this env.
 		try {
 			var e = document.createEvent("MouseEvents");
 			e.initMouseEvent("contextmenu", 1, 1, window, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, null);
 			document.dispatchEvent(e);
 		} catch (e) {/* assume not supported */}
 	} else {
 		// IE no need to implement custom contextmenu
 		implement = false;
 	}

 	// clear this one if it wasn't there before
 	if (delfunc){
 		delete document.oncontextmenu;
 	}
 	/***** end dom event check *****/


 	/**
 	*	this fixes a dom node by attaching a custom oncontextmenu function that gets called when apropriate
 	*	@param	node	a dom node
 	*
 	*	no returns
 	*/
 	this.fixNode = function(node){
 		if (implement){
 			// attach stub oncontextmenu function
 			if (!dojo.lang.isFunction(node.oncontextmenu)){
 				node.oncontextmenu = function(e){/*stub*/}
 			}

 			// attach control function for oncontextmenu
 			if (window.opera){
 				// opera
 				// listen to ctrl-click events
 				node._menufixer_opera = function(e){
 					if (e.ctrlKey){
 						this.oncontextmenu(e);
 					}
 				};

 				dojo.event.connect(node, "onclick", node, "_menufixer_opera");

 			} else {
 				// konqueror
 				// rightclick, listen to mousedown events
 				node._menufixer_konq = function(e){
 					if (e.button==2 ){
 						e.preventDefault(); // need to prevent browsers menu
 						this.oncontextmenu(e);
 					}
 				};

 				dojo.event.connect(node, "onmousedown", node, "_menufixer_konq");
 			}
 		}
 	}

 	/**
 	*	this cleans up a fixed node, prevent memoryleak?
 	*	@param node	node to clean
 	*
 	*	no returns
 	*/
 	this.cleanNode = function(node){
 		if (implement){
 			// checks needed if we gets a non fixed node
 			if (node._menufixer_opera){
 				dojo.event.disconnect(node, "onclick", node, "_menufixer_opera");
 				delete node._menufixer_opera;
 			} else if(node._menufixer_konq){
 				dojo.event.disconnect(node, "onmousedown", node, "_menufixer_konq");
 				delete node._menufixer_konq;
 			}
 			if (node.oncontextmenu){
 				delete node.oncontextmenu;
 			}
 		}
 	}
};


dojo.widget.MenuBar2 = function(){
	dojo.widget.HtmlWidget.call(this);
}

dojo.inherits(dojo.widget.MenuBar2, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.MenuBar2, {
	widgetType: "MenuBar2",
	isContainer: true,

	snarfChildDomOutput: true,

	currentItem: null,
	isExpanded: false,

	currentSubmenu: null,
	currentSubmenuTrigger: null,

	domNode: null,
	containerNode: null,

	templateString: '<div class="dojoMenuBar2"><div dojoAttachPoint="containerNode" class="dojoMenuBar2Client"></div></div>',
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlMenu2.css"),

	itemHeight: 18,
	openEvent: null,


	postCreate: function(){

		// do something here

		this.layoutMenuSoon();
	},

	layoutMenuSoon: function(){
		dojo.lang.setTimeout(this, "layoutMenu", 0);
	},

	layoutMenu: function(){

		// menu must be attached to DOM for size calculations to work

		var parent = this.domNode.parentNode;
		if (! parent || parent == undefined) {
			document.body.appendChild(this.domNode);
		}


		// determine menu height

		var max_label_h = 0;

		for(var i=0; i<this.children.length; i++){

			if (this.children[i].getLabelHeight){

				max_label_h = Math.max(max_label_h, this.children[i].getLabelHeight());
			}
		}

		if (isNaN(max_label_h)){
			// Browser needs some more time to calculate sizes
			this.layoutMenuSoon();
			return;
		}

		var clientLeft = dojo.style.getPixelValue(this.domNode, "padding-left", true)
				+ dojo.style.getPixelValue(this.containerNode, "margin-left", true)
				+ dojo.style.getPixelValue(this.containerNode, "padding-left", true);
		var clientTop  = dojo.style.getPixelValue(this.domNode, "padding-top", true)
				+ dojo.style.getPixelValue(this.containerNode, "padding-top", true);

		if (isNaN(clientLeft) || isNaN(clientTop)){
			// Browser needs some more time to calculate sizes
			this.layoutMenuSoon();
			return;
		}

		var max_item_height = 0;
		var x = clientLeft;

		for (var i=0; i<this.children.length; i++){

			var ch = this.children[i];

			ch.layoutItem(max_label_h);

			ch.leftPosition = x;
			ch.domNode.style.left = x + 'px';

			x += dojo.style.getOuterWidth(ch.domNode);
			max_item_height = Math.max(max_item_height, dojo.style.getOuterHeight(ch.domNode));
		}

		dojo.style.setContentHeight(this.containerNode, max_item_height);
		dojo.style.setContentHeight(this.domNode, dojo.style.getOuterHeight(this.containerNode));
	},

	openSubmenu: function(submenu, from_item){

		var our_pos = dojo.style.getAbsolutePosition(this.domNode, false);

		var our_h = dojo.style.getOuterHeight(this.domNode);
		var item_x = from_item.leftPosition;

		var x = our_pos.x + item_x;
		var y = our_pos.y + our_h;

		this.currentSubmenu = submenu;
		this.currentSubmenu.open(x, y, this, from_item.domNode);
		this.currentSubmenu.parentMenuBar = this;
	},

	closeSubmenu: function(){

		if (this.currentSubmenu == null){ return; }

		var menu = this.currentSubmenu;
		this.currentSubmenu = null;
		menu.close();
	},

	itemHover: function(item){

		if (item == this.currentItem) return;

		if (this.currentItem){
			this.currentItem.unhighlightItem();

			if (this.isExpanded){
				this.closeSubmenu();
			}
		}

		this.currentItem = item;
		this.currentItem.highlightItem();

		if (this.isExpanded){
			this.currentItem.expandMenu();
		}
	},

	itemUnhover: function(item){

		if (item != this.currentItem) return;

		if (this.currentItem && !this.isExpanded){
			this.currentItem.unhighlightItem();
			this.currentItem = null;
		}
	},

	itemClick: function(item){

		if (item != this.currentItem){

			this.itemHover(item);
		}

		if (this.isExpanded){

			this.isExpanded = false;
			this.closeSubmenu();

		}else{

			this.isExpanded = true;
			this.currentItem.expandMenu();
		}
	},

	closedMenu: function(menu){

		if (this.currentSubmenu == menu){

			this.isExpanded = false;
			this.itemUnhover(this.currentItem);
		}
	}
});


dojo.widget.MenuBarItem2 = function(){
	dojo.widget.HtmlWidget.call(this);
}

dojo.inherits(dojo.widget.MenuBarItem2, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.MenuBarItem2, {

	widgetType: "MenuBarItem2",
	templateString:
			 '<div class="dojoMenuBarItem2">'
			+'<span dojoAttachPoint="labelNode" class="dojoMenuBarItem2Label"><span><span></span></span></span>'
			+'<div dojoAttachPoint="targetNode" class="dojoMenuBarItem2Target" dojoAttachEvent="onMouseOver: onHover; onMouseOut: onUnhover; onClick: _onClick;">&nbsp;</div>'
			+'</div>',

	//
	// nodes
	//

	domNode: null,
	labelNode: null,
	targetNode: null,

	//
	// internal settings
	//

	is_hovering: false,
	hover_timer: null,
	is_open: false,

	//
	// options
	//

	caption: 'Untitled',
	accelKey: '',
	iconSrc: '',
	submenuId: '',
	disabled: false,
	eventNaming: "default",


	postCreate: function(){

		dojo.html.disableSelection(this.domNode);

		if (this.disabled){
			this.setDisabled(true);
		}

		this.labelNode.childNodes[0].appendChild(document.createTextNode(this.caption));

		this.labelShadowNode = this.labelNode.childNodes[0].childNodes[0];
		this.labelShadowNode.appendChild(document.createTextNode(this.caption));

		if (this.eventNaming == "default") {
			for (var eventName in this.eventNames) {
				this.eventNames[eventName] = this.widgetId+"/"+eventName;
			}
		}
	},

	layoutItem: function(item_h){

		var label_w = dojo.style.getOuterWidth(this.labelNode);

		var clientLeft = dojo.style.getPixelValue(this.domNode, "padding-left", true);
		var clientTop  = dojo.style.getPixelValue(this.domNode, "padding-top", true);

		this.labelNode.style.left = clientLeft + 'px';

		dojo.style.setOuterHeight(this.labelNode, item_h);
		dojo.style.setContentWidth(this.domNode, label_w);
		dojo.style.setContentHeight(this.domNode, item_h);

		this.labelNode.style.left = '0px';

		dojo.style.setOuterWidth(this.targetNode, label_w);
		dojo.style.setOuterHeight(this.targetNode, item_h);
	},

	getLabelHeight: function(){

		return dojo.style.getOuterHeight(this.labelNode);
	},

	onHover: function(){
		this.parent.itemHover(this);
	},

	onUnhover: function(){
		this.parent.itemUnhover(this);
	},

	_onClick: function(){
		this.parent.itemClick(this);
	},

	highlightItem: function(){
		dojo.html.addClass(this.domNode, 'dojoMenuBarItem2Hover');
	},

	unhighlightItem: function(){
		dojo.html.removeClass(this.domNode, 'dojoMenuBarItem2Hover');
	},

	expandMenu: function(){

		var submenu = dojo.widget.getWidgetById(this.submenuId);
		if (submenu){

			this.parent.openSubmenu(submenu, this);
		}
	},

	setDisabled: function(value){
		this.disabled = value;

		if (this.disabled){
			dojo.html.addClass(this.domNode, 'dojoMenuBarItem2Disabled');
		}else{
			dojo.html.removeClass(this.domNode, 'dojoMenuBarItem2Disabled');
		}
	}
});

// make it a tag
dojo.widget.tags.addParseTreeHandler("dojo:MenuBar2");
dojo.widget.tags.addParseTreeHandler("dojo:MenuBarItem2");
dojo.widget.tags.addParseTreeHandler("dojo:PopupMenu2");
dojo.widget.tags.addParseTreeHandler("dojo:MenuItem2");
dojo.widget.tags.addParseTreeHandler("dojo:MenuSeparator2");


__CPAN_FILE__ src/widget/ContextMenu.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.ContextMenu");

dojo.deprecated("dojo.widget.ContextMenu",  "use dojo.widget.Menu2", "0.4");

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.DomWidget");

dojo.widget.ContextMenu = function(){
	dojo.widget.Widget.call(this);
	this.widgetType = "ContextMenu";
	this.isContainer = true;
	this.isOpened = false;
	
	// copy children widgets output directly to parent (this node), to avoid
	// errors trying to insert an <li> under a <div>
	this.snarfChildDomOutput = true;

}

dojo.inherits(dojo.widget.ContextMenu, dojo.widget.Widget);
dojo.widget.tags.addParseTreeHandler("dojo:contextmenu");

dojo.requireAfterIf("html", "dojo.widget.html.ContextMenu");

__CPAN_FILE__ src/widget/Manager.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Manager");
dojo.require("dojo.lang.array");
dojo.require("dojo.lang.func");
dojo.require("dojo.event.*");

// Manager class
dojo.widget.manager = new function(){
	this.widgets = [];
	this.widgetIds = [];
	
	// map of widgetId-->widget for widgets without parents (top level widgets)
	this.topWidgets = {};

	var widgetTypeCtr = {};
	var renderPrefixCache = [];

	this.getUniqueId = function (widgetType) {
		return widgetType + "_" + (widgetTypeCtr[widgetType] != undefined ?
			++widgetTypeCtr[widgetType] : widgetTypeCtr[widgetType] = 0);
	}

	this.add = function(widget){
		dojo.profile.start("dojo.widget.manager.add");
		this.widgets.push(widget);
		// Opera9 uses ID (caps)
		if(!widget.extraArgs["id"]){
			widget.extraArgs["id"] = widget.extraArgs["ID"];
		}
		// FIXME: the rest of this method is very slow!
		if(widget.widgetId == ""){
			if(widget["id"]){
				widget.widgetId = widget["id"];
			}else if(widget.extraArgs["id"]){
				widget.widgetId = widget.extraArgs["id"];
			}else{
				widget.widgetId = this.getUniqueId(widget.widgetType);
			}
		}
		if(this.widgetIds[widget.widgetId]){
			dojo.debug("widget ID collision on ID: "+widget.widgetId);
		}
		this.widgetIds[widget.widgetId] = widget;
		// Widget.destroy already calls removeById(), so we don't need to
		// connect() it here
		dojo.profile.end("dojo.widget.manager.add");
	}

	this.destroyAll = function(){
		for(var x=this.widgets.length-1; x>=0; x--){
			try{
				// this.widgets[x].destroyChildren();
				this.widgets[x].destroy(true);
				delete this.widgets[x];
			}catch(e){ }
		}
	}

	// FIXME: we should never allow removal of the root widget until all others
	// are removed!
	this.remove = function(widgetIndex){
		var tw = this.widgets[widgetIndex].widgetId;
		delete this.widgetIds[tw];
		this.widgets.splice(widgetIndex, 1);
	}
	
	// FIXME: suboptimal performance
	this.removeById = function(id) {
		for (var i=0; i<this.widgets.length; i++){
			if(this.widgets[i].widgetId == id){
				this.remove(i);
				break;
			}
		}
	}

	this.getWidgetById = function(id){
		return this.widgetIds[id];
	}

	this.getWidgetsByType = function(type){
		var lt = type.toLowerCase();
		var ret = [];
		dojo.lang.forEach(this.widgets, function(x){
			if(x.widgetType.toLowerCase() == lt){
				ret.push(x);
			}
		});
		return ret;
	}

	this.getWidgetsOfType = function (id) {
		dojo.deprecated("getWidgetsOfType", "use getWidgetsByType", "0.4");
		return dojo.widget.manager.getWidgetsByType(id);
	}

	this.getWidgetsByFilter = function(unaryFunc, onlyOne){
		var ret = [];
		dojo.lang.every(this.widgets, function(x){
			if(unaryFunc(x)){
				ret.push(x);
				if(onlyOne){return false;}
			}
			return true;
		});
		return (onlyOne ? ret[0] : ret);
	}

	this.getAllWidgets = function() {
		return this.widgets.concat();
	}

	//	added, trt 2006-01-20
	this.getWidgetByNode = function(/* DOMNode */ node){
		var w=this.getAllWidgets();
		for (var i=0; i<w.length; i++){
			if (w[i].domNode==node){
				return w[i];
			}
		}
		return null;
	}

	// shortcuts, baby
	this.byId = this.getWidgetById;
	this.byType = this.getWidgetsByType;
	this.byFilter = this.getWidgetsByFilter;
	this.byNode = this.getWidgetByNode;

	// map of previousally discovered implementation names to constructors
	var knownWidgetImplementations = {};

	// support manually registered widget packages
	var widgetPackages = ["dojo.widget"];
	for (var i=0; i<widgetPackages.length; i++) {
		// convenience for checking if a package exists (reverse lookup)
		widgetPackages[widgetPackages[i]] = true;
	}

	this.registerWidgetPackage = function(pname) {
		if(!widgetPackages[pname]){
			widgetPackages[pname] = true;
			widgetPackages.push(pname);
		}
	}
	
	this.getWidgetPackageList = function() {
		return dojo.lang.map(widgetPackages, function(elt) { return(elt!==true ? elt : undefined); });
	}
	
	this.getImplementation = function(widgetName, ctorObject, mixins){
		// try and find a name for the widget
		var impl = this.getImplementationName(widgetName);
		if(impl){ 
			// var tic = new Date();
			var ret = new impl(ctorObject);
			// dojo.debug(new Date() - tic);
			return ret;
		}
	}

	this.getImplementationName = function(widgetName){
		/*
		 * This is the overly-simplistic implemention of getImplementation (har
		 * har). In the future, we are going to want something that allows more
		 * freedom of expression WRT to specifying different specializations of
		 * a widget.
		 *
		 * Additionally, this implementation treats widget names as case
		 * insensitive, which does not necessarialy mesh with the markup which
		 * can construct a widget.
		 */

		var lowerCaseWidgetName = widgetName.toLowerCase();

		var impl = knownWidgetImplementations[lowerCaseWidgetName];
		if(impl){
			return impl;
		}

		// first store a list of the render prefixes we are capable of rendering
		if(!renderPrefixCache.length){
			for(var renderer in dojo.render){
				if(dojo.render[renderer]["capable"] === true){
					var prefixes = dojo.render[renderer].prefixes;
					for(var i = 0; i < prefixes.length; i++){
						renderPrefixCache.push(prefixes[i].toLowerCase());
					}
				}
			}
			// make sure we don't HAVE to prefix widget implementation names
			// with anything to get them to render
			renderPrefixCache.push("");
		}

		// look for a rendering-context specific version of our widget name
		for(var i = 0; i < widgetPackages.length; i++){
			var widgetPackage = dojo.evalObjPath(widgetPackages[i]);
			if(!widgetPackage) { continue; }

			for (var j = 0; j < renderPrefixCache.length; j++) {
				if (!widgetPackage[renderPrefixCache[j]]) { continue; }
				for (var widgetClass in widgetPackage[renderPrefixCache[j]]) {
					if (widgetClass.toLowerCase() != lowerCaseWidgetName) { continue; }
					knownWidgetImplementations[lowerCaseWidgetName] =
						widgetPackage[renderPrefixCache[j]][widgetClass];
					return knownWidgetImplementations[lowerCaseWidgetName];
				}
			}

			for (var j = 0; j < renderPrefixCache.length; j++) {
				for (var widgetClass in widgetPackage) {
					if (widgetClass.toLowerCase() !=
						(renderPrefixCache[j] + lowerCaseWidgetName)) { continue; }
	
					knownWidgetImplementations[lowerCaseWidgetName] =
						widgetPackage[widgetClass];
					return knownWidgetImplementations[lowerCaseWidgetName];
				}
			}
		}
		
		throw new Error('Could not locate "' + widgetName + '" class');
	}

	// FIXME: does it even belong in this name space?
	// NOTE: this method is implemented by DomWidget.js since not all
	// hostenv's would have an implementation.
	/*this.getWidgetFromPrimitive = function(baseRenderType){
		dojo.unimplemented("dojo.widget.manager.getWidgetFromPrimitive");
	}

	this.getWidgetFromEvent = function(nativeEvt){
		dojo.unimplemented("dojo.widget.manager.getWidgetFromEvent");
	}*/

	// Catch window resize events and notify top level widgets
	this.resizing=false;
	this.onWindowResized = function(){
		if(this.resizing){
			return;	// duplicate event
		}
		try{
			this.resizing=true;
			for(var id in this.topWidgets){
				var child = this.topWidgets[id];
				if(child.checkSize ){
					child.checkSize();
				}
			};
		}catch(e){
		}finally{
			this.resizing=false;
		}
	}
	if(typeof window != "undefined") {
		dojo.addOnLoad(this, 'onWindowResized');							// initial sizing
		dojo.event.connect(window, 'onresize', this, 'onWindowResized');	// window resize
	}

	// FIXME: what else?
};

(function(){
	var dw = dojo.widget;
	var dwm = dw.manager;
	var h = dojo.lang.curry(dojo.lang, "hitch", dwm);
	var g = function(oldName, newName){
		dw[(newName||oldName)] = h(oldName);
	}
	// copy the methods from the default manager (this) to the widget namespace
	g("add", "addWidget");
	g("destroyAll", "destroyAllWidgets");
	g("remove", "removeWidget");
	g("removeById", "removeWidgetById");
	g("getWidgetById");
	g("getWidgetById", "byId");
	g("getWidgetsByType");
	g("getWidgetsByFilter");
	g("getWidgetsByType", "byType");
	g("getWidgetsByFilter", "byFilter");
	g("getWidgetByNode", "byNode");
	dw.all = function(n){
		var widgets = dwm.getAllWidgets.apply(dwm, arguments);
		if(arguments.length > 0) {
			return widgets[n];
		}
		return widgets;
	}
	g("registerWidgetPackage");
	g("getImplementation", "getWidgetImplementation");
	g("getImplementationName", "getWidgetImplementationName");

	dw.widgets = dwm.widgets;
	dw.widgetIds = dwm.widgetIds;
	dw.root = dwm.root;
})();

__CPAN_FILE__ src/widget/DatePicker.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.DatePicker");
dojo.provide("dojo.widget.DatePicker.util");
dojo.require("dojo.widget.DomWidget");
dojo.require("dojo.date");

// NOTE: this function is only used as mixin (never as a constructor)
dojo.widget.DatePicker = function() {
	// the following aliases prevent breaking people using 0.2.x
	this.months = dojo.date.months,
	this.weekdays = dojo.date.days,
	this.toRfcDate = dojo.widget.DatePicker.util.toRfcDate,
	this.fromRfcDate = dojo.widget.DatePicker.util.fromRfcDate,
	this.initFirstSaturday = dojo.widget.DatePicker.util.initFirstSaturday
};

dojo.requireAfterIf("html", "dojo.widget.html.DatePicker");

dojo.widget.DatePicker.util = new function() {
	this.months = dojo.date.months;
	this.weekdays = dojo.date.days;
	
	this.toRfcDate = function(jsDate) {
		if(!jsDate) {
			var jsDate = new Date();
		}
		// because this is a date picker and not a time picker, we don't return a time
		return dojo.date.format(jsDate, "%Y-%m-%d");
	}
	
	this.fromRfcDate = function(rfcDate) {
		// backwards compatible support for use of "any" instead of just not 
		// including the time
		if(rfcDate.indexOf("Tany")!=-1) {
			rfcDate = rfcDate.replace("Tany","");
		}
		var jsDate = new Date();
		dojo.date.setIso8601(jsDate, rfcDate);
		return jsDate;
	}
	
	this.initFirstSaturday = function(month, year) {
		if(!month) {
			month = this.date.getMonth();
		}
		if(!year) {
			year = this.date.getFullYear();
		}
		var firstOfMonth = new Date(year, month, 1);
		return {year: year, month: month, date: 7 - firstOfMonth.getDay()};
	}
}

__CPAN_FILE__ src/widget/RichText.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

 /* -*- tab-width: 4 -*- */
dojo.provide("dojo.widget.RichText");
dojo.provide("dojo.widget.html.RichText");

dojo.require("dojo.widget.*");
dojo.require("dojo.dom");
dojo.require("dojo.html");
dojo.require("dojo.event.*");
dojo.require("dojo.style");
dojo.require("dojo.string");

// used to save content
try {
	document.write('<textarea id="dojo.widget.RichText.savedContent" ' +
		'style="display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;"></textarea>');
}catch(e){ }

dojo.widget.defineWidget(
	"dojo.widget.html.RichText",
	dojo.widget.HtmlWidget,
	{
		/** whether to inherit the parent's width or simply use 100% */
		inheritWidth: false,
		focusOnLoad: true,
		
		/**
		 * If a save name is specified the content is saved and restored if the
		 * editor is not properly closed after editing has started.
		 */
		saveName: "",
		_content: "",
		
		/* set height to fix the editor at a specific height, with scrolling */
		height: null,

		/** The minimum height that the editor should have */
		minHeight: "1em",
		
		isClosed: true,
		isLoaded: false,
		
		/** whether to use the active-x object in IE */
		useActiveX: false,

		/* whether to use relative URLs for images - if this is enabled
       	images will be given absolute URLs when inside the editor but
       	will be changed to use relative URLs (to the current page) on save
		*/
		relativeImageUrls: false,
		
		_SEPARATOR: "@@**%%__RICHTEXTBOUNDRY__%%**@@",

		// contentFilters: [],

		/*
		defaultContentCleaner: function(content){
			if(!dojo.render.html.ie){
				return content;
			}

			content = content.replace(/\x20/g, " ");
			// alert(content);
			return content;
		},
		*/

	/* Init
	 *******/

		fillInTemplate: function(){
			this.open();

			// add the formatting functions
			var funcs = ["queryCommandEnabled", "queryCommandState",
				"queryCommandValue", "execCommand"];
			for(var i = 0; i < funcs.length; i++){
				dojo.event.connect("around", this, funcs[i], this, "_normalizeCommand");
			}
			
			// backwards compatibility, needs to be removed
			dojo.event.connect(this, "onKeyPressed", this, "afterKeyPress");
			dojo.event.connect(this, "onKeyPress", this, "keyPress");
			dojo.event.connect(this, "onKeyDown", this, "keyDown");
			dojo.event.connect(this, "onKeyUp", this, "keyUp");

			// add default some key handlers		
			var ctrl = this.KEY_CTRL;
			var exec = function (cmd, arg) {
				return arguments.length == 1 ? function () { this.execCommand(cmd); } :
					function () { this.execCommand(cmd, arg); }
			}
				
			this.addKeyHandler("b", ctrl, exec("bold"));
			this.addKeyHandler("i", ctrl, exec("italic"));
			this.addKeyHandler("u", ctrl, exec("underline"));
			this.addKeyHandler("a", ctrl, exec("selectall"));
			//this.addKeyHandler("k", ctrl, exec("createlink", ""));
			//this.addKeyHandler("K", ctrl, exec("unlink"));
			this.addKeyHandler("s", ctrl, function () { this.save(true); });
			
			this.addKeyHandler("1", ctrl, exec("formatblock", "h1"));
			this.addKeyHandler("2", ctrl, exec("formatblock", "h2"));
			this.addKeyHandler("3", ctrl, exec("formatblock", "h3"));
			this.addKeyHandler("4", ctrl, exec("formatblock", "h4"));
					
			this.addKeyHandler("\\", ctrl, exec("insertunorderedlist"));
			if(!dojo.render.html.ie){
				this.addKeyHandler("Z", ctrl, exec("redo"));
			}
		},


		events: ["onBlur", "onFocus", "onKeyPress", "onKeyDown", "onKeyUp", "onClick"],

		/**
		 * Transforms the node referenced in this.domNode into a rich text editing
		 * node. This can result in the creation and replacement with an <iframe> if
		 * designMode is used, an <object> and active-x component if inside of IE or
		 * a reguler element if contentEditable is available.
		 */
		open: function (element) {
			dojo.event.topic.publish("dojo.widget.RichText::open", this);

			if (!this.isClosed) { this.close(); }
			this._content = "";
			if((arguments.length == 1)&&(element["nodeName"])){ this.domNode = element; } // else unchanged

			if(	(this.domNode["nodeName"])&&
				(this.domNode.nodeName.toLowerCase() == "textarea")){
				this.textarea = this.domNode;
				var html = dojo.string.trim(this.textarea.value);
				if(html == ""){ html = "&nbsp;"; }
				this.domNode = document.createElement("div");
				with(this.textarea.style){
					display = "block";
					position = "absolute";
					width = "1px";
					height = "1px";
					border = margin = padding = "0px";
					visiblity = "hidden";
					if(dojo.render.html.ie){
						overflow = "hidden";
					}
				}
				dojo.dom.insertBefore(this.domNode, this.textarea);
				this.domNode.innerHTML = html;
				
				if(this.textarea.form){
					dojo.event.connect(this.textarea.form, "onsubmit", 
						// FIXME: should we be calling close() here instead?
						dojo.lang.hitch(this, function(){
							this.textarea.value = this.getEditorContent();
						})
					);
				}
				
				// dojo plucks our original domNode from the document so we need
				// to go back and put ourselves back in
				var editor = this;
				dojo.event.connect(this, "postCreate", function (){
					dojo.dom.insertAfter(editor.textarea, editor.domNode);
				});
			}else{
				var html = dojo.string.trim(this.domNode.innerHTML);
				if(html == ""){ html = "&nbsp;"; }
			}
					
			this._oldHeight = dojo.style.getContentHeight(this.domNode);
			this._oldWidth = dojo.style.getContentWidth(this.domNode);

			this._firstChildContributingMargin = this._getContributingMargin(this.domNode, "top");
			this._lastChildContributingMargin = this._getContributingMargin(this.domNode, "bottom");

			this.savedContent = document.createElement("div");
			while (this.domNode.hasChildNodes()) {
				this.savedContent.appendChild(this.domNode.firstChild);
			}
			
			// If we're a list item we have to put in a blank line to force the
			// bullet to nicely align at the top of text
			if(	(this.domNode["nodeName"])&&
				(this.domNode.nodeName == "LI")){
				this.domNode.innerHTML = " <br>";
			}
					
			if(this.saveName != ""){
				var saveTextarea = document.getElementById("dojo.widget.RichText.savedContent");
				if (saveTextarea.value != "") {
					var datas = saveTextarea.value.split(this._SEPARATOR);
					for (var i = 0; i < datas.length; i++) {
						var data = datas[i].split(":");
						if (data[0] == this.saveName) {
							html = data[1];
							datas.splice(i, 1);
							break;
						}
					}				
				}
				dojo.event.connect("before", window, "onunload", this, "_saveContent");
				// dojo.event.connect(window, "onunload", this, "_saveContent");
			}

			// Safari's selections go all out of whack if we do it inline,
			// so for now IE is our only hero
			//if (typeof document.body.contentEditable != "undefined") {
			if (this.useActiveX && dojo.render.html.ie) { // active-x
				this._drawObject(html);
				// dojo.debug(this.object.document);
			} else if (dojo.render.html.ie) { // contentEditable, easy
				this.editNode = document.createElement("div");
				with (this.editNode) {
					innerHTML = html;
					contentEditable = true;
					style.height = this.height ? this.height : this.minHeight;
				}

				if(this.height){ this.editNode.style.overflowY="scroll"; }
				// FIXME: setting contentEditable on switches this element to
				// IE's hasLayout mode, triggering weird margin collapsing
				// behavior. It's particularly bad if the element you're editing
				// contains childnodes that don't have margin: defined in local
				// css rules. It would be nice if it was possible to hack around
				// this. Sadly _firstChildContributingMargin and 
				// _lastChildContributingMargin don't work on IE unless all
				// elements have margins set in CSS :-(

				this.domNode.appendChild(this.editNode);

				dojo.lang.forEach(this.events, function(e){
					dojo.event.connect(this.editNode, e.toLowerCase(), this, e);
				}, this);
			
				this.window = window;
				this.document = document;
				
				this.onLoad();
			} else { // designMode in iframe
				this._drawIframe(html);
			}

			// TODO: this is a guess at the default line-height, kinda works
			if (this.domNode.nodeName == "LI") { this.domNode.lastChild.style.marginTop = "-1.2em"; }
			dojo.html.addClass(this.domNode, "RichTextEditable");
			
			this.isClosed = false;
		},

		_hasCollapseableMargin: function(element, side) {
			// check if an element has padding or borders on the given side
			// which would prevent it from collapsing margins
			if (dojo.style.getPixelValue(element, 
										 'border-'+side+'-width', 
										 false)) {
				return false;
			} else if (dojo.style.getPixelValue(element, 
												'padding-'+side,
												false)) {
				return false;
			} else {
				return true;
			}
		},

		_getContributingMargin:	function(element, topOrBottom) {
			// calculate how much margin this element and its first or last
			// child are contributing to the total margin between this element
			// and the adjacent node. CSS border collapsing makes this
			// necessary.

			if (topOrBottom == "top") {
				var siblingAttr = "previousSibling";
				var childSiblingAttr = "nextSibling";
				var childAttr = "firstChild";
				var marginProp = "margin-top";
				var siblingMarginProp = "margin-bottom";
			} else {
				var siblingAttr = "nextSibling";
				var childSiblingAttr = "previousSibling";
				var childAttr = "lastChild";
				var marginProp = "margin-bottom";
				var siblingMarginProp = "margin-top";
			}

			var elementMargin = dojo.style.getPixelValue(element, marginProp, false);

			function isSignificantNode(element) {
				// see if an node is significant in the current context
				// for calulating margins
				return !(element.nodeType==3 && dojo.string.isBlank(element.data)) 
					&& dojo.style.getStyle(element, "display") != "none" 
					&& !dojo.style.isPositionAbsolute(element);
			}

			// walk throuh first/last children to find total collapsed margin size
			var childMargin = 0;
			var child = element[childAttr];
			while (child) {
				// skip over insignificant elements (whitespace, etc)
				while ((!isSignificantNode(child)) && child[childSiblingAttr]) {
					child = child[childSiblingAttr];
				}
						  
				childMargin = Math.max(childMargin, dojo.style.getPixelValue(child, marginProp, false));
				// stop if we hit a bordered/padded element
				if (!this._hasCollapseableMargin(child, topOrBottom)) break;
				child = child[childAttr];								   
			}

			// if this element has a border, return full child margin immediately
			// as there won't be any margin collapsing
			if (!this._hasCollapseableMargin(element, topOrBottom)){ return parseInt(childMargin); }

			// find margin supplied by nearest sibling
			var contextMargin = 0;
			var sibling = element[siblingAttr];
			while (sibling) {
				if (isSignificantNode(sibling)) {
					contextMargin = dojo.style.getPixelValue(sibling, 
															 siblingMarginProp, 
															 false);
					break;
				}
				sibling = sibling[siblingAttr];
			}
			if (!sibling) { // no sibling, look at parent's margin instead
				contextMargin = dojo.style.getPixelValue(element.parentNode, 
												marginProp, false);
			}

			if (childMargin > elementMargin) {
				return parseInt(Math.max((childMargin-elementMargin)-contextMargin, 0));
			} else {
				return 0;
			}
			
		},
		
		/** Draws an iFrame using the existing one if one exists. 
			Used by Mozilla, Safari, and Opera */
		_drawIframe: function (html) {

			// detect firefox < 1.5, which has some iframe loading issues
			var oldMoz = Boolean(dojo.render.html.moz && (
									typeof window.XML == 'undefined'))

			if (!this.iframe) {
				var currentDomain = (new dojo.uri.Uri(document.location)).host;
				this.iframe = document.createElement("iframe");
				with (this.iframe) {
					scrolling = this.height ? "auto" : "no";
					style.border = "none";
					style.lineHeight = "0"; // squash line height
					style.verticalAlign = "bottom";
				}
			}
			// opera likes this to be outside the with block
			this.iframe.src = dojo.uri.dojoUri("src/widget/templates/richtextframe.html") + "#" + ((document.domain != currentDomain) ? document.domain : "");
			this.iframe.width = this.inheritWidth ? this._oldWidth : "100%";
			if (this.height) {
				this.iframe.style.height = this.height;
			} else {
				var height = this._oldHeight;
				if (this._hasCollapseableMargin(this.domNode, 'top')) {
					height += this._firstChildContributingMargin;
				}
				if (this._hasCollapseableMargin(this.domNode, 'bottom')) {
					height += this._lastChildContributingMargin;
				}
				this.iframe.height = height;
			}

			var tmpContent = document.createElement('div');
			tmpContent.innerHTML = html;

			// make relative image urls absolute
			if (this.relativeImageUrls) {
				var imgs = tmpContent.getElementsByTagName('img');
				for (var i=0; i<imgs.length; i++) {
					imgs[i].src = (new dojo.uri.Uri(window.location, imgs[i].src)).toString();
				}
				html = tmpContent.innerHTML;
			}

			// fix margins on tmpContent
			var firstChild = dojo.dom.firstElement(tmpContent);
			var lastChild = dojo.dom.lastElement(tmpContent);
			if(firstChild){
				firstChild.style.marginTop = this._firstChildContributingMargin+"px";
			}
			if(lastChild){
				lastChild.style.marginBottom = this._lastChildContributingMargin+"px";
			}

			// show existing content behind iframe for now
			tmpContent.style.position = "absolute";
			this.domNode.appendChild(tmpContent);
			this.domNode.appendChild(this.iframe);

			var _iframeInitialized = false;

			// now we wait for onload. Janky hack!
			var ifrFunc = dojo.lang.hitch(this, function(){
				if(!_iframeInitialized){
					_iframeInitialized = true;
				}else{ return; }
				if(!this.editNode){
					if(this.iframe.contentWindow){
						this.window = this.iframe.contentWindow;
					}else{
						// for opera
						this.window = this.iframe.contentDocument.window;
					}
					if(dojo.render.html.moz){
						this.document = this.iframe.contentWindow.document
					}else{
						this.document = this.iframe.contentDocument;
					}

					// curry the getStyle function
					var getStyle = (function (domNode) { return function (style) {
						return dojo.style.getStyle(domNode, style);
					}; })(this.domNode);

					var font =
						getStyle('font-weight') + " " +
						getStyle('font-size') + " " +
						getStyle('font-family');
					
					// line height is tricky - applying a units value will mess things up.
					// if we can't get a non-units value, bail out.
					var lineHeight = "1.0";
					var lineHeightStyle = dojo.style.getUnitValue(this.domNode, 'line-height');
					if (lineHeightStyle.value && lineHeightStyle.units=="") {
						lineHeight = lineHeightStyle.value;
					}

					dojo.style.insertCssText(
						'    body,html { background: transparent; padding: 0; margin: 0; }\n' +
						// TODO: left positioning will case contents to disappear out of view
						//       if it gets too wide for the visible area
						'    body { top: 0; left: 0; right: 0;' +
						(this.height ? '' : ' position: fixed; ') + 
						'        font: ' + font + ';\n' + 
						'        min-height: ' + this.minHeight + '; \n' +
						'        line-height: ' + lineHeight + '} \n' +
						'    p { margin: 1em 0 !important; }\n' +
						'    body > *:first-child { padding-top: 0 !important; margin-top: ' + this._firstChildContributingMargin + 'px !important; }\n' + // FIXME: test firstChild nodeType
						'    body > *:last-child { padding-bottom: 0 !important; margin-bottom: ' + this._lastChildContributingMargin + 'px !important; }\n' +
						'    li > ul:-moz-first-node, li > ol:-moz-first-node { padding-top: 1.2em; }\n' +
						'    li { min-height: 1.2em; }\n' +
						//'    p,ul,li { padding-top: 0; padding-bottom: 0; margin-top:0; margin-bottom: 0; }\n' + 
						'', this.document);

					tmpContent.parentNode.removeChild(tmpContent);
					this.document.body.innerHTML = html;
					if(oldMoz){
						this.document.designMode = "on";
					}
					this.onLoad();
				}else{
					tmpContent.parentNode.removeChild(tmpContent);
					this.editNode.innerHTML = html;
					this.onDisplayChanged();
				}
			});

			if(this.editNode){
				ifrFunc(); // iframe already exists, just set content
			}else if(dojo.render.html.moz){
				// FIXME: if we put this on a delay, we get a height of 20px.
				// Otherwise we get the correctly specified minHeight value.
				this.iframe.onload = function(){
					setTimeout(ifrFunc, 250);
				}
			}else{ // new mozillas, opera, safari
				this.iframe.onload = ifrFunc;
			}
		},
		
		/** Draws an active x object, used by IE */
		_drawObject: function (html) {
			this.object = document.createElement("object");

			with (this.object) {
				classid = "clsid:2D360201-FFF5-11D1-8D03-00A0C959BC0A";
				width = this.inheritWidth ? this._oldWidth : "100%";
				style.height = this.height ? this.height : (this._oldHeight+"px");
				Scrollbars = this.height ? true : false;
				Appearance = this._activeX.appearance.flat;
			}
			this.domNode.appendChild(this.object);

			this.object.attachEvent("DocumentComplete", dojo.lang.hitch(this, "onLoad"));
			this.object.attachEvent("DisplayChanged", dojo.lang.hitch(this, "_updateHeight"));
			this.object.attachEvent("DisplayChanged", dojo.lang.hitch(this, "onDisplayChanged"));

			dojo.lang.forEach(this.events, function(e){
				this.object.attachEvent(e.toLowerCase(), dojo.lang.hitch(this, e));
			}, this);

			this.object.DocumentHTML = '<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' +
				'<title></title>' +
				'<style type="text/css">' +
				'    body,html { padding: 0; margin: 0; }' + //font: ' + font + '; }' +
				(this.height ? '' : '    body { overflow: hidden; }') +
				//'    #bodywrapper {  }' +
				'</style>' +
				//'<base href="' + window.location + '">' +
				'<body><div id="bodywrapper">' + html + '</div></body>';
		},

	/* Event handlers
	 *****************/

	 	_isResized: function(){ return false; },

		onLoad: function(e){
			this.isLoaded = true;
			if (this.object){
				this.document = this.object.DOM;
				this.window = this.document.parentWindow;
				this.editNode = this.document.body.firstChild;
				this.domNode.style.height = this.height ? this.height : this.minHeight;
				this.connect(this, "onDisplayChanged", "_updateHeight");
			}else if (this.iframe){
				this.editNode = this.document.body;
				this.connect(this, "onDisplayChanged", "_updateHeight");
		
				try { // sanity check for Mozilla
					this.document.execCommand("useCSS", false, true); // old moz call
					this.document.execCommand("styleWithCSS", false, false); // new moz call
					//this.document.execCommand("insertBrOnReturn", false, false); // new moz call
				}catch(e2){ }
				
				if (dojo.render.html.safari) {
					/*
					this.iframe.style.visiblity = "visible";
					this.iframe.style.border = "1px solid black";
					this.editNode.style.visiblity = "visible";
					this.editNode.style.border = "1px solid black";
					*/
					// this.onDisplayChanged();
					this.connect(this.editNode, "onblur", "onBlur");
					this.connect(this.editNode, "onfocus", "onFocus");
				
					this.interval = setInterval(dojo.lang.hitch(this, "onDisplayChanged"), 750);
					// dojo.raise("onload");
					// dojo.debug(this.editNode.parentNode.parentNode.parentNode.nodeName);
				} else if (dojo.render.html.mozilla || dojo.render.html.opera) {

					// We need to unhook the blur event listener on close as we
					// can encounter a garunteed crash in FF if another event is
					// also fired
					var doc = this.document;
					var blurfp = dojo.event.browser.addListener(this.document, "blur", dojo.lang.hitch(this, "onBlur"));
					var unBlur = { unBlur: function(e){
							dojo.event.browser.removeListener(doc, "blur", blurfp);
					} };
					dojo.event.connect("before", this, "close", unBlur, "unBlur");
					dojo.event.browser.addListener(this.document, "focus", dojo.lang.hitch(this, "onFocus"));
				
					// safari can't handle key listeners, it kills the speed
					var addListener = dojo.event.browser.addListener;
					addListener(this.document, "keypress", dojo.lang.hitch(this, "onKeyPress"));
					addListener(this.document, "keydown", dojo.lang.hitch(this, "onKeyDown"));
					addListener(this.document, "keyup", dojo.lang.hitch(this, "onKeyUp"));
					addListener(this.document, "click", dojo.lang.hitch(this, "onClick"));
				}

				// FIXME: when scrollbars appear/disappear this needs to be fired						
			}else if(dojo.render.html.ie){
				// IE contentEditable
				this.editNode.style.zoom = 1.0;
			}
			
			if(this.focusOnLoad){
				this.focus();
			}
			this.onDisplayChanged(e);
		},

		/** Fired on keydown */
		onKeyDown: function(e){
			if((!e)&&(this.object)){
				e = dojo.event.browser.fixEvent(this.window.event);
			}
			dojo.debug("onkeydown:", e.keyCode);
			// we need this event at the moment to get the events from control keys
			// such as the backspace. It might be possible to add this to Dojo, so that
			// keyPress events can be emulated by the keyDown and keyUp detection.
			if((dojo.render.html.ie)&&(e.keyCode == e.KEY_TAB)){
				e.preventDefault();
				e.stopPropagation();
				// FIXME: this is a poor-man's indent/outdent. It would be
				// better if it added 4 "&nbsp;" chars in an undoable way.
				// Unfortuantly pasteHTML does not prove to be undoable 
				this.execCommand((e.shiftKey ? "outdent" : "indent"));
			}else if(dojo.render.html.ie){
				if((65 <= e.keyCode)&&(e.keyCode <= 90)){
					e.charCode = e.keyCode;
					this.onKeyPress(e);
				}
				// dojo.debug(e.ctrlKey);
				// dojo.debug(e.keyCode);
				// dojo.debug(e.charCode);
				// this.onKeyPress(e);
			}
		},
		
		/** Fired on keyup */
		onKeyUp: function(e){
			return;
		},
		
		KEY_CTRL: 1,
		
		/** Fired on keypress. */
		onKeyPress: function(e){
			if((!e)&&(this.object)){
				e = dojo.event.browser.fixEvent(this.window.event);
			}
			// handle the various key events

			var character = e.charCode > 0 ? String.fromCharCode(e.charCode) : null;
			var code = e.keyCode;

			var modifiers = e.ctrlKey ? this.KEY_CTRL : 0;

			if (this._keyHandlers[character]) {
				dojo.debug("char:", character);
				var handlers = this._keyHandlers[character], i = 0, handler;
				while (handler = handlers[i++]) {
					if (modifiers == handler.modifiers) {
						handler.handler.call(this);
						e.preventDefault();
						break;
					}
				}
			}
			
			/*
			// define some key combos
			if (e.ctrlKey || e.metaKey) { // modifier pressed
				switch (character) {
					case "b": this.execCommand("bold"); break;
					case "i": this.execCommand("italic"); break;
					case "u": this.execCommand("underline"); break;
					//case "a": this.execCommand("selectall"); break;
					//case "k": this.execCommand("createlink", ""); break;
					//case "K": this.execCommand("unlink"); break;
					case "Z": this.execCommand("redo"); break;
					case "s": this.close(true); break; // saves
					
					case "1": this.execCommand("formatblock", "h1"); break;
					case "2": this.execCommand("formatblock", "h2"); break;
					case "3": this.execCommand("formatblock", "h3"); break;
					case "4": this.execCommand("formatblock", "h4"); break;
					
					case "\\": this.execCommand("insertunorderedlist"); break;
					
					default: switch (code) {
						case e.KEY_LEFT_ARROW:
						case e.KEY_RIGHT_ARROW:
							//break; // preventDefault stops the browser
								   // going through its history
						default:
							preventDefault = false; break; // didn't handle here
					}
				}
			} else {
				switch (code) {
					case e.KEY_TAB:
					  // commenting out bcs it's crashing FF
						// this.execCommand(e.shiftKey ? "unindent" : "indent");
						// break;
					default:
						preventDefault = false; break; // didn't handle here
				}
			}
			
			if (preventDefault) { e.preventDefault(); }
			*/

			// function call after the character has been inserted
			dojo.lang.setTimeout(this, this.onKeyPressed, 1, e);
		},
		
		addKeyHandler: function (key, modifiers, handler) {
			if (!(this._keyHandlers[key] instanceof Array)) { this._keyHandlers[key] = []; }
			this._keyHandlers[key].push({
				modifiers: modifiers || 0,
				handler: handler
			});
		},
		
		
		
		/**
		 * Fired after a keypress event has occured and it's action taken. This
		 * is useful if action needs to be taken after text operations have
		 * finished
		 */
		onKeyPressed: function (e) {
			// Mozilla adds a single <p> with an embedded <br> when you hit enter once:
			//   <p><br>\n</p>
			// when you hit enter again it adds another <br> inside your enter
			//   <p><br>\n<br>\n</p>
			// and if you hit enter again it splits the <br>s over 2 <p>s
			//   <p><br>\n</p>\n<p><br>\n</p>
			// now this assumes that <p>s have double the line-height of <br>s to work
			// and so we need to remove the <p>s to ensure the position of the cursor
			// changes from the users perspective when they hit enter, as the second two
			// html snippets render the same when margins are set to 0.
			
			// TODO: doesn't really work; is this really needed?
			//if (dojo.render.html.moz) {
			//	for (var i = 0; i < this.document.getElementsByTagName("p").length; i++) {
			//		var p = this.document.getElementsByTagName("p")[i];
			//		if (p.innerHTML.match(/^<br>\s$/m)) {
			//			while (p.hasChildNodes()) { p.parentNode.insertBefore(p.firstChild, p); }
			//			p.parentNode.removeChild(p);
			//		}
			//	}
			//}
			this.onDisplayChanged(/*e*/); // can't pass in e
		},
		
		onClick: function(e){ this.onDisplayChanged(e); },
		onBlur: function(e){ },
		_initialFocus: true,
		onFocus: function(e){ 
			if( (dojo.render.html.mozilla)&&(this._initialFocus) ){
				this._initialFocus = false;
				if(dojo.string.trim(this.editNode.innerHTML) == "&nbsp;"){
					this.execCommand("selectall");
					this.window.getSelection().collapseToStart();
				}
			}
		},

		blur: function () {
			if (this.iframe) { this.window.blur(); }
			else if (this.editNode) { this.editNode.blur(); }
		},
		
		focus: function () {
			if(this.iframe){
				this.window.focus();
			}else if(this.editNode){
				this.editNode.focus();
			}
		},
		
		/** this event will be fired everytime the display context changes and the
		 result needs to be reflected in the UI */
		onDisplayChanged: function (e){ },
		

	/* Formatting commands
	 **********************/
		
		/** IE's Active X codes */
		_activeX: {
			command: {
				bold: 5000,
				italic: 5023,
				underline: 5048,

				justifycenter: 5024,
				justifyleft: 5025,
				justifyright: 5026,

				cut: 5003,
				copy: 5002,
				paste: 5032,
				"delete": 5004,

				undo: 5049,
				redo: 5033,

				removeformat: 5034,
				selectall: 5035,
				unlink: 5050,

				indent: 5018,
				outdent: 5031,

				insertorderedlist: 5030,
				insertunorderedlist: 5051,

				// table commands
				inserttable: 5022,
				insertcell: 5019,
				insertcol: 5020,
				insertrow: 5021,
				deletecells: 5005,
				deletecols: 5006,
				deleterows: 5007,
				mergecells: 5029,
				splitcell: 5047,
				
				// the command need mapping, they don't translate directly
				// to the contentEditable commands
				setblockformat: 5043,
				getblockformat: 5011,
				getblockformatnames: 5012,
				setfontname: 5044,
				getfontname: 5013,
				setfontsize: 5045,
				getfontsize: 5014,
				setbackcolor: 5042,
				getbackcolor: 5010,
				setforecolor: 5046,
				getforecolor: 5015,
				
				findtext: 5008,
				font: 5009,
				hyperlink: 5016,
				image: 5017,
				
				lockelement: 5027,
				makeabsolute: 5028,
				sendbackward: 5036,
				bringforward: 5037,
				sendbelowtext: 5038,
				bringabovetext: 5039,
				sendtoback: 5040,
				bringtofront: 5041,
				
				properties: 5052
			},
			
			ui: {
				"default": 0,
				prompt: 1,
				noprompt: 2
			},
			
			status: {
				notsupported: 0,
				disabled: 1,
				enabled: 3,
				latched: 7,
				ninched: 11
			},
			
			appearance: {
				flat: 0,
				inset: 1
			},
			
			state: {
				unchecked: 0,
				checked: 1,
				gray: 2
			}
		},
		
		/**
		 * Used as the advice function by dojo.event.connect to map our
		 * normalized set of commands to those supported by the target
		 * browser
		 *
		 * @param arugments The arguments Array, containing at least one
		 *                  item, the command and an optional second item,
		 *                  an argument.
		 */
		_normalizeCommand: function (joinObject){
			var drh = dojo.render.html;
			
			var command = joinObject.args[0].toLowerCase();
			if(command == "formatblock"){
				if(drh.safari){ command = "heading"; }
				if(drh.ie){ joinObject.args[1] = "<"+joinObject.args[1]+">"; }
			}
			if (command == "hilitecolor" && !drh.mozilla) { command = "backcolor"; }
			joinObject.args[0] = command;
			
			if (joinObject.args.length > 1) { // a command was specified
				var argument = joinObject.args[1];
				if (command == "heading") { throw new Error("unimplemented"); }
				joinObject.args[1] = argument;
			}
			
			return joinObject.proceed();
		},
		
		/**
		 * Tests whether a command is supported by the host. Clients SHOULD check
		 * whether a command is supported before attempting to use it, behaviour
		 * for unsupported commands is undefined.
		 *
		 * @param command The command to test for
		 * @return true if the command is supported, false otherwise
		 */
		queryCommandAvailable: function (command) {
			var ie = 1;
			var mozilla = 1 << 1;
			var safari = 1 << 2;
			var opera = 1 << 3;
			function isSupportedBy (browsers) {
				return {
					ie: Boolean(browsers & ie),
					mozilla: Boolean(browsers & mozilla),
					safari: Boolean(browsers & safari),
					opera: Boolean(browsers & opera)
				}
			}

			var supportedBy = null;
			
			switch (command.toLowerCase()) {
				case "bold": case "italic": case "underline":
				case "subscript": case "superscript":
				case "fontname": case "fontsize":
				case "forecolor": case "hilitecolor":
				case "justifycenter": case "justifyfull": case "justifyleft": 
				case "justifyright": case "delete": case "undo": case "redo":
					supportedBy = isSupportedBy(mozilla | ie | safari | opera);
					break;
					
				case "createlink": case "unlink": case "removeformat":
				case "inserthorizontalrule": case "insertimage":
				case "insertorderedlist": case "insertunorderedlist":
				case "indent": case "outdent": case "formatblock": 
				case "inserthtml":
					supportedBy = isSupportedBy(mozilla | ie | opera);
					break;
					
				case "strikethrough": 
					supportedBy = isSupportedBy(mozilla |  opera | (this.object ? 0 : ie));
					break;

				case "blockdirltr": case "blockdirrtl":
				case "dirltr": case "dirrtl":
				case "inlinedirltr": case "inlinedirrtl":
				case "cut": case "copy": case "paste": 
					supportedBy = isSupportedBy(ie);
					break;
				
				case "inserttable":
					supportedBy = isSupportedBy(mozilla | (this.object ? ie : 0));
					break;
				
				case "insertcell": case "insertcol": case "insertrow":
				case "deletecells": case "deletecols": case "deleterows":
				case "mergecells": case "splitcell":
					supportedBy = isSupportedBy(this.object ? ie : 0);
					break;
				
				default: return false;
			}
			
			return (dojo.render.html.ie && supportedBy.ie) ||
				(dojo.render.html.mozilla && supportedBy.mozilla) ||
				(dojo.render.html.safari && supportedBy.safari) ||
				(dojo.render.html.opera && supportedBy.opera);
		},

		/**
		 * Executes a command in the Rich Text area
		 *
		 * @param command The command to execute
		 * @param argument An optional argument to the command
		 */
		execCommand: function (command, argument){
			var returnValue;
			if(this.object){
				if(command == "forecolor"){
					command = "setforecolor";
				}else if(command == "backcolor"){
					command = "setbackcolor";
				}
			
				//if (typeof this._activeX.command[command] == "undefined") { return null; }
			
				if(command == "inserttable"){
					var tableInfo = this.constructor._tableInfo;
					if(!tableInfo){
						tableInfo = document.createElement("object");
						tableInfo.classid = "clsid:47B0DFC7-B7A3-11D1-ADC5-006008A5848C";
						document.body.appendChild(tableInfo);
						this.constructor._table = tableInfo;
					}
					
					tableInfo.NumRows = argument["rows"];
					tableInfo.NumCols = argument["cols"];
					tableInfo.TableAttrs = argument["TableAttrs"];
					tableInfo.CellAttrs = argument["CellAttrs"];
					tableInfo.Caption = argument["Caption"];
				}
			
				if(command == "inserthtml"){
					var insertRange = this.document.selection.createRange();
					insertRange.select();
					insertRange.pasteHTML(argument);
					insertRange.collapse(true);
					return true;
				}else if(arguments.length == 1){
					return this.object.ExecCommand(this._activeX.command[command],
						this._activeX.ui.noprompt);
				}else{
					return this.object.ExecCommand(this._activeX.command[command],
						this._activeX.ui.noprompt, argument);
				}
		
			/* */
			}else if(command == "inserthtml"){
				// on IE, we can use the pasteHTML method of the textRange object
				// to get an undo-able innerHTML modification
				if(dojo.render.html.ie){
					dojo.debug("inserthtml breaks the undo stack when not using the ActiveX version of the control!");
					var insertRange = this.document.selection.createRange();
					insertRange.select();
					insertRange.pasteHTML(argument);
					insertRange.collapse(true);
					return true;
				}else{
					return this.document.execCommand(command, false, argument);			
				}
			/* */
			// fix up unlink in Mozilla to unlink the link and not just the selection
			}else if((command == "unlink")&&
				(this.queryCommandEnabled("unlink"))&&
				(dojo.render.html.mozilla)){
				// grab selection
				// Mozilla gets upset if we just store the range so we have to
				// get the basic properties and recreate to save the selection
				var selection = this.window.getSelection();
				var selectionRange = selection.getRangeAt(0);
				var selectionStartContainer = selectionRange.startContainer;
				var selectionStartOffset = selectionRange.startOffset;
				var selectionEndContainer = selectionRange.endContainer;
				var selectionEndOffset = selectionRange.endOffset;
				
				// select our link and unlink
				var range = document.createRange();
				var a = this.getSelectedNode();
				while(a.nodeName != "A"){ a = a.parentNode; }
				range.selectNode(a);
				selection.removeAllRanges();
				selection.addRange(range);
				
				returnValue = this.document.execCommand("unlink", false, null);
				
				// restore original selection
				var selectionRange = document.createRange();
				selectionRange.setStart(selectionStartContainer, selectionStartOffset);
				selectionRange.setEnd(selectionEndContainer, selectionEndOffset);
				selection.removeAllRanges();
				selection.addRange(selectionRange);
				
				return returnValue;
			}else if((command == "inserttable")&&(dojo.render.html.mozilla)){

				var cols = "<tr>";
				for (var i = 0; i < argument.cols; i++) { cols += "<td></td>"; }
				cols += "</tr>";
			
				var table = "<table><tbody>";
				for (var i = 0; i < argument.rows; i++) { table += cols; }
				table += "</tbody></table>";
				returnValue = this.document.execCommand("inserthtml", false, table);

			}else if((command == "hilitecolor")&&(dojo.render.html.mozilla)){
				// mozilla doesn't support hilitecolor properly when useCSS is
				// set to false (bugzilla #279330)
				
				this.document.execCommand("useCSS", false, false);
				returnValue = this.document.execCommand(command, false, argument);			
				this.document.execCommand("useCSS", false, true);
			
			}else if((dojo.render.html.ie)&&( (command == "backcolor")||(command == "forecolor") )){
				// IE weirdly collapses ranges when we exec these commands, so prevent it	
				var tr = this.document.selection.createRange();
				argument = arguments.length > 1 ? argument : null;
				returnValue = this.document.execCommand(command, false, argument);
				// timeout is workaround for weird IE behavior were the text
				// selection gets correctly re-created, but subsequent input
				// apparently isn't bound to it
				setTimeout(function(){tr.select();}, 1);
			}else{
				// dojo.debug("command:", command, "arg:", argument);

				argument = arguments.length > 1 ? argument : null;
				if(dojo.render.html.moz){
					this.document = this.iframe.contentWindow.document
				}
				returnValue = this.document.execCommand(command, false, argument);

				// try{
				// }catch(e){
				// 	dojo.debug(e);
				// }
			}
			
			this.onDisplayChanged();
			return returnValue;
		},

		queryCommandEnabled: function(command, argument){
			if(this.object){
				if(command == "forecolor"){
					command = "setforecolor";
				}else if(command == "backcolor"){
					command = "setbackcolor";
				}

				if(typeof this._activeX.command[command] == "undefined"){ return false; }
				var status = this.object.QueryStatus(this._activeX.command[command]);
				return ((status != this.activeX.status.notsupported)&& 
					(status != this.activeX.status.diabled));
			}else{
				// mozilla returns true always
				if(command == "unlink" && dojo.render.html.mozilla){
					var node = this.getSelectedNode();
					while (node.parentNode && node.nodeName != "A") { node = node.parentNode; }
					return node.nodeName == "A";
				} else if (command == "inserttable" && dojo.render.html.mozilla) {
					return true;
				}

				// return this.document.queryCommandEnabled(command);
				var elem = (dojo.render.html.ie) ? this.document.selection.createRange() : this.document;
				return elem.queryCommandEnabled(command);
			}
		},

		queryCommandState: function(command, argument){
			if(this.object){
				if(command == "forecolor"){
					command = "setforecolor";
				}else if(command == "backcolor"){
					command = "setbackcolor";
				}

				if(typeof this._activeX.command[command] == "undefined"){ return null; }
				var status = this.object.QueryStatus(this._activeX.command[command]);
				return ((status == this._activeX.status.enabled)||
					(status == this._activeX.status.ninched));
			}else{
				return this.document.queryCommandState(command);
			}
		},

		queryCommandValue: function (command, argument) {
			if (this.object) {
				switch (command) {
					case "forecolor":
					case "backcolor":
					case "fontsize":
					case "fontname":
					case "blockformat":
						command = "get" + command;
						return this.object.execCommand(
							this._activeX.command[command],
							this._activeX.ui.noprompt);
				}			
			
				//var status = this.object.QueryStatus(this._activeX.command[command]);
			} else {
				return this.document.queryCommandValue(command);
			}
		},
		
		
	/* Misc.
	 ********/

		getSelectedNode: function(){
			if(!this.isLoaded){ return; }
			if(this.document.selection){
				return this.document.selection.createRange().parentElement();
			}else if(dojo.render.html.mozilla){
				return this.window.getSelection().getRangeAt(0).commonAncestorContainer;
			}
			return this.editNode;
		},
		
		placeCursorAtStart: function(){
			if(!this.isLoaded){
				dojo.event.connect(this, "onLoad", this, "placeCursorAtEnd");
				return;
			}
			dojo.event.disconnect(this, "onLoad", this, "placeCursorAtEnd");
			if(this.window.getSelection){
				var selection = this.window.getSelection;
				if(selection.removeAllRanges){ // Mozilla
					var range = this.document.createRange();
					range.selectNode(this.editNode.firstChild);
					range.collapse(true);
					var selection = this.window.getSelection();
					selection.removeAllRanges();
					selection.addRange(range);
				}else{ // Safari
					// not a great deal we can do
				}
			}else if(this.document.selection){ // IE
				var range = this.document.body.createTextRange();
				range.moveToElementText(this.editNode);
				range.collapse(true);
				range.select();
			}
		},

		replaceEditorContent: function(html){
			if(this.window.getSelection){
				var selection = this.window.getSelection;
				// if(selection.removeAllRanges){ // Mozilla			
				if(dojo.render.html.moz){ // Mozilla			
					var range = this.document.createRange();
					range.selectNodeContents(this.editNode);
					var selection = this.window.getSelection();
					selection.removeAllRanges();
					selection.addRange(range);
					this.execCommand("inserthtml", html);
				}else{ // Safari
					// look ma! it's a totally f'd browser!
					this.editNode.innerHTML = html;
				}
			}else if(this.document.selection){ // IE
				var range = this.document.body.createTextRange();
				range.moveToElementText(this.editNode);
				range.select();
				this.execCommand("inserthtml", html);
			}
		},
		
		placeCursorAtEnd: function(){
			if(!this.isLoaded){
				dojo.event.connect(this, "onLoad", this, "placeCursorAtEnd");
				return;
			}
			dojo.event.disconnect(this, "onLoad", this, "placeCursorAtEnd");
			if(this.window.getSelection){
				var selection = this.window.getSelection;
				if(selection.removeAllRanges){ // Mozilla
					var range = this.document.createRange();
					range.selectNode(this.editNode.lastChild);
					range.collapse(false);
					var selection = this.window.getSelection();
					selection.removeAllRanges();
					selection.addRange(range);
				}else{ // Safari
					// not a great deal we can do
				}
			}else if(this.document.selection){ // IE
				var range = this.document.body.createTextRange();
				range.moveToElementText(this.editNode);
				range.collapse(true);
				range.select();
			}
		},

		_lastHeight: 0,

		/** Updates the height of the iframe to fit the contents. */
		_updateHeight: function(){
			if(!this.isLoaded){ return; }
			if(this.height){ return; }
			if(this.iframe){
				/*
				if(!this.document.body["offsetHeight"]){
					return;
				}
				*/
				// The height includes the padding, borders and margins so these
				// need to be added on
				var heights = ["margin-top", "margin-bottom",
					"padding-bottom", "padding-top",
					"border-width-bottom", "border-width-top"];
				for(var i = 0, chromeheight = 0; i < heights.length; i++){
					var height = dojo.style.getStyle(this.iframe, heights[i]);
					// Safari doesn't have all the heights so we have to test
					if(height){
						chromeheight += Number(height.replace(/[^0-9]/g, ""));
					}
				}

				if(this.document.body["offsetHeight"]){
					this._lastHeight = Math.max(this.document.body.scrollHeight, this.document.body.offsetHeight) + chromeheight;
					this.iframe.height = this._lastHeight + "px";
					this.window.scrollTo(0, 0);
				}
				// dojo.debug(this.iframe.height);
			}else if(this.object){
				this.object.style.height = dojo.style.getInnerHeight(this.editNode)+"px";
			}
		},
		
		/**
		 * Saves the content in an onunload event if the editor has not been closed
		 */
		_saveContent: function(e){
			var saveTextarea = document.getElementById("dojo.widget.RichText.savedContent");
			saveTextarea.value += this._SEPARATOR + this.saveName + ":" + this.getEditorContent();
		},

		getEditorContent: function(){
			var ec = "";
			try{
				ec = (this._content.length > 0) ? this._content : this.editNode.innerHTML;
				if(dojo.string.trim(ec) == "&nbsp;"){ ec = ""; }
			}catch(e){ /* squelch */ }

			dojo.lang.forEach(this.contentFilters, function(ef){
				ec = ef(ec);
			});

			if (this.relativeImageUrls) {
				// why use a regexp instead of dom? because IE is stupid 
				// and won't let us set img.src to a relative URL
				// this comes after contentFilters because once content
				// gets innerHTML'd img urls will be fully qualified
				var siteBase = window.location.protocol + "//" + window.location.host;
				var pathBase = window.location.pathname;
				if (pathBase.match(/\/$/)) {
					// ends with slash, match full path
				} else {
					// match parent path to find siblings
					var pathParts = pathBase.split("/");
					if (pathParts.length) {
						pathParts.pop();
					}
					pathBase = pathParts.join("/") + "/";

				}
				
				var sameSite = new RegExp("(<img[^>]*\ src=[\"'])("+siteBase+"("+pathBase+")?)", "ig");
				ec = ec.replace(sameSite, "$1");
			}
			return ec;
		},
		
		/**
		 * Kills the editor and optionally writes back the modified contents to the 
		 * element from which it originated.
		 *
		 * @param save Whether or not to save the changes. If false, the changes are
		 *             discarded.
		 * @return true if the contents has been modified, false otherwise
		 */
		close: function(save, force){
			if(this.isClosed){return false; }

			if (arguments.length == 0) { save = true; }
			this._content = this.editNode.innerHTML;
			var changed = (this.savedContent.innerHTML != this._content);
			
			// line height is squashed for iframes
			// FIXME: why was this here? if (this.iframe){ this.domNode.style.lineHeight = null; }

			if(this.interval){ clearInterval(this.interval); }
			
			if(dojo.render.html.ie && !this.object){
				dojo.event.browser.clean(this.editNode);
			}
			
			if (this.iframe) {
				// FIXME: should keep iframe around for later re-use
				delete this.iframe;
			}
			this.domNode.innerHTML = "";

			if(save){
				// kill listeners on the saved content
				dojo.event.browser.clean(this.savedContent);
				if(dojo.render.html.moz){
					var nc = document.createElement("span");
					this.domNode.appendChild(nc);
					nc.innerHTML = this.editNode.innerHTML;
				}else{
					this.domNode.innerHTML = this._content;
				}
			} else {
				while (this.savedContent.hasChildNodes()) {
					this.domNode.appendChild(this.savedContent.firstChild);
				}
			}
			delete this.savedContent;
			
			dojo.html.removeClass(this.domNode, "RichTextEditable");
			this.isClosed = true;
			this.isLoaded = false;
			// FIXME: is this always the right thing to do?
			delete this.editNode;

			return changed;
		},

		destroyRendering: function(){}, // stub!
		
		destroy: function (){
			this.destroyRendering();
			if(!this.isClosed){ this.close(false); }
		
			// disconnect those listeners.
			while(this._connected.length){
				this.disconnect(this._connected[0],
					this._connected[1], this._connected[2]);
			}
		},

		_connected: [],
		connect: function (targetObj, targetFunc, thisFunc) {
			dojo.event.connect(targetObj, targetFunc, this, thisFunc);
			// this._connected.push([targetObj, targetFunc, thisFunc]);	
		},
		
		// FIXME: below two functions do not work with the above line commented out
		disconnect: function (targetObj, targetFunc, thisFunc) {
			for (var i = 0; i < this._connected.length; i++) {
				if (this._connected[0] == targetObj &&
					this._connected[1] == targetFunc &&
					this._connected[2] == thisFunc) {
					dojo.event.disconnect(targetObj, targetFunc, this, thisFunc);
					this._connected.splice(i, 1);
					break;
				}
			}
		},
		
		disconnectAllWithRoot: function (targetObj) {
			for (var i = 0; i < this._connected.length; i++) {
				if (this._connected[0] == targetObj) {
					dojo.event.disconnect(targetObj,
						this._connected[1], this, this._connected[2]);
					this._connected.splice(i, 1);
				}
			}	
		}
		
	},
	"html",
	function(){
		this.contentFilters = [];
		// this.contentFilters.push(this.defaultContentCleaner);
		
		this._keyHandlers = {};
	}
);

__CPAN_FILE__ src/widget/TreeContextMenu.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/



dojo.provide("dojo.widget.TreeContextMenu");
dojo.provide("dojo.widget.TreeMenuItem");

dojo.require("dojo.event.*");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.Menu2");


dojo.widget.tags.addParseTreeHandler("dojo:TreeContextMenu");
dojo.widget.tags.addParseTreeHandler("dojo:TreeMenuItem");



dojo.widget.TreeContextMenu = function() {
	dojo.widget.PopupMenu2.call(this);

	this.listenedTrees = [];

}


dojo.inherits(dojo.widget.TreeContextMenu, dojo.widget.PopupMenu2);

dojo.lang.extend(dojo.widget.TreeContextMenu, {

	widgetType: "TreeContextMenu",

	open: function(x, y, parentMenu, explodeSrc){

		var result = dojo.widget.PopupMenu2.prototype.open.apply(this, arguments);

		/* publish many events here about structural changes */
		dojo.event.topic.publish(this.eventNames.open, { menu:this });

		return result;
	},

	listenTree: function(tree) {
		/* add context menu to all nodes that exist already */
		var nodes = tree.getDescendants();

		for(var i=0; i<nodes.length; i++) {
			if (!nodes[i].isTreeNode) continue;
			this.bindDomNode(nodes[i].labelNode);
		}


		/* bind context menu to all nodes that will be created in the future (e.g loaded from server)*/
		var _this = this;
		dojo.event.topic.subscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
		dojo.event.topic.subscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
		dojo.event.topic.subscribe(tree.eventNames.moveTo, this, "onMoveTo");
		dojo.event.topic.subscribe(tree.eventNames.removeNode, this, "onRemoveNode");
		dojo.event.topic.subscribe(tree.eventNames.addChild, this, "onAddChild");
		dojo.event.topic.subscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");

		this.listenedTrees.push(tree);

	},

	unlistenTree: function(tree) {
		/* clear event listeners */

		dojo.event.topic.unsubscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
		dojo.event.topic.unsubscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
		dojo.event.topic.unsubscribe(tree.eventNames.moveTo, this, "onMoveTo");
		dojo.event.topic.unsubscribe(tree.eventNames.removeNode, this, "onRemoveNode");
		dojo.event.topic.unsubscribe(tree.eventNames.addChild, this, "onAddChild");
		dojo.event.topic.unsubscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");

		for(var i=0; i<this.listenedTrees.length; i++){
           if(this.listenedTrees[i] === tree){
                   this.listenedTrees.splice(i, 1);
                   break;
           }
		}
	},

	onTreeDestroy: function(message) {
		this.unlistenTree(message.source);
	},

	bindTreeNode: function(node) {
		var _this = this;
		//dojo.debug("bind to "+node);
		dojo.lang.forEach(node.getDescendants(),
			function(e) {_this.bindDomNode(e.labelNode); }
		);
	},


	unBindTreeNode: function(node) {
		var _this = this;
		//dojo.debug("Unbind from "+node);
		dojo.lang.forEach(node.getDescendants(),
			function(e) {_this.unBindDomNode(e.labelNode); }
		);
	},

	onCreateDOMNode: function(message) {
		this.bindTreeNode(message.source);
	},


	onMoveFrom: function(message) {
		if (!dojo.lang.inArray(this.listenedTrees, message.newTree)) {
			this.unBindTreeNode(message.child);
		}
	},

	onMoveTo: function(message) {
		if (dojo.lang.inArray(this.listenedTrees, message.newTree)) {
			this.bindTreeNode(message.child);
		}
	},

	onRemoveNode: function(message) {
		this.unBindTreeNode(message.child);
	},

	onAddChild: function(message) {
		if (message.domNodeInitialized) {
			// dom node was there already => I did not process onNodeDomCreate
			this.bindTreeNode(message.child);
		}
	}


});






dojo.widget.TreeMenuItem = function() {
	dojo.widget.MenuItem2.call(this);

}


dojo.inherits(dojo.widget.TreeMenuItem, dojo.widget.MenuItem2);


dojo.lang.extend(dojo.widget.TreeMenuItem, {

	widgetType: "TreeMenuItem",

	// treeActions menu item performs following actions (to be checked for permissions)
	treeActions: "",

	initialize: function(args, frag) {

		this.treeActions = this.treeActions.split(",");
		for(var i=0; i<this.treeActions.length; i++) {
			this.treeActions[i] = this.treeActions[i].toUpperCase();
		}

	},

	getTreeNode: function() {
		var menu = this;

		while (! (menu instanceof dojo.widget.TreeContextMenu) ) {
			menu = menu.parent;
		}

		var source = menu.getTopOpenEvent().target;

		while (!source.getAttribute('treeNode') && source.tagName != 'body') {
			source = source.parentNode;
		}
		if (source.tagName == 'body') {
			dojo.raise("treeNode not detected");
		}
		var treeNode = dojo.widget.manager.getWidgetById(source.getAttribute('treeNode'));

		return treeNode;
	},


	menuOpen: function(message) {
		var treeNode = this.getTreeNode();

		this.setDisabled(false); // enable by default

		var _this = this;
		dojo.lang.forEach(_this.treeActions,
			function(action) {
				_this.setDisabled( treeNode.actionIsDisabled(action) );
			}
		);

	},

	toString: function() {
		return "["+this.widgetType+" node "+this.getTreeNode()+"]";
	}

});



__CPAN_FILE__ src/widget/Rounded.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Rounded");
dojo.widget.tags.addParseTreeHandler("dojo:rounded");

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.html.ContentPane");
dojo.require("dojo.html");
dojo.require("dojo.style");

/*
 *	The following script is derived (with permission) from curvyCorners,
 *	written by Cameron Cooke (CLA on file) and was adapted to Dojo by Brian
 *	Lucas (CLA on file)
 */

dojo.widget.Rounded = function() {
	dojo.widget.html.ContentPane.call(this);
}

dojo.inherits(dojo.widget.Rounded, dojo.widget.html.ContentPane);

dojo.lang.extend(dojo.widget.Rounded, {
	isSafari: dojo.render.html.safari,
	widgetType: "Rounded",
	boxMargin: "50px", // margin outside rounded corner box
	radius: 14, // radius of corners
	domNode: "",
	corners: "TR,TL,BR,BL", // corner string to render
	antiAlias: true, // false to disable anti-aliasing

	fillInTemplate: function(args, frag) {
		dojo.widget.Rounded.superclass.fillInTemplate.call(this, args, frag);

		dojo.style.insertCssFile(this.templateCssPath);

		// Magic to automatically calculate the box height/width if not supplied
		if (this.domNode.style.height<=0) {
			var minHeight = (this.radius*1)+this.domNode.clientHeight;
			this.domNode.style.height = minHeight+"px";
		}

		if (this.domNode.style.width<=0) {
			var minWidth = (this.radius*1)+this.domNode.clientWidth;
			this.domNode.style.width = minWidth+"px";
		}

		var cornersAvailable = ["TR", "TL", "BR", "BL"];
		var cornersPassed = this.corners.split(",");

		this.settings = {
			antiAlias: this.antiAlias
		};

		var setCorner = function(currentCorner) {
			var val = currentCorner.toLowerCase();
			if(dojo.lang.inArray(cornersPassed, currentCorner)) {
				this.settings[val] = { radius: this.radius, enabled: true };
			} else {
				this.settings[val] = { radius: 0 }
			}
		}
		dojo.lang.forEach(cornersAvailable, setCorner, this);

		this.domNode.style.margin = this.boxMargin;
		this.curvyCorners(this.settings);
		this.applyCorners();
	},

	// ------------- curvyCorners OBJECT

	curvyCorners: function(settings){	

		// Setup Globals
		this.box             = this.domNode;
		this.topContainer    = null;
		this.bottomContainer = null;
		this.masterCorners   = [];

		// Get box formatting details
		var boxHeight       = dojo.style.getStyle(this.box, "height");
		if(boxHeight=="") boxHeight="0px";
		var boxWidth        = dojo.style.getStyle(this.box, "width");
		var borderWidth     = dojo.style.getStyle(this.box, "borderTopWidth");
		if(borderWidth=="") borderWidth="0px";
		//alert(borderWidth);

		var borderColour    = dojo.style.getStyle(this.box, "borderTopColor");
		// Set to true if we have a border
		if(borderWidth>0) this.antiAlias=true;

		var boxColour       = dojo.style.getStyle(this.box, "backgroundColor");
		var backgroundImage = dojo.style.getStyle(this.box, "backgroundImage");
		var boxPosition     = dojo.style.getStyle(this.box, "position");

		// Set formatting propertes
		this.boxHeight       = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight));
		this.boxWidth        = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth));
		this.borderWidth     = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0));

		// DEBUG ME?

		//dojo.debug(this.rgb2Hex(boxColour));
		var test  = new dojo.graphics.color.Color(boxColour);
		//dojo.debug(test.toHex()); 

		this.boxColour       = ((boxColour != "" && boxColour != "transparent")? ((boxColour.substr(0, 3) == "rgb")? this.rgb2Hex(boxColour) : boxColour) : "#ffffff");
		this.borderColour    = ((borderColour != "" && borderColour != "transparent" && this.borderWidth > 0)? ((borderColour.substr(0, 3) == "rgb")? this.rgb2Hex(borderColour)  : borderColour) : this.boxColour);
		this.borderString    = this.borderWidth + "px" + " solid " + this.borderColour;
		this.backgroundImage = ((backgroundImage != "none")? backgroundImage : "");

		// Make box relative if not already absolute
		if(boxPosition != "absolute") this.box.style.position = "relative";

		//This method creates the corners and
		//applies them to the div element.

		this.applyCorners = function() {
			// Create top and bottom containers.
			// These will be used as a parent for the corners and bars.
			for(var t = 0; t < 2; t++) {
			    switch(t) {
			        // Top
			        case 0:
						// Only build top bar if a top corner is to be draw
						if(this.settings.tl.enabled || this.settings.tr.enabled ) {
							var newMainContainer = document.createElement("DIV");
			
							with(newMainContainer.style){
								width    = "100%";
								fontSize = "1px";
								overflow = "hidden";
								position = "absolute";
								//backgroundColor = "#FFFFC4";
								paddingLeft  = this.borderWidth + "px";
								paddingRight = this.borderWidth + "px";
								var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0);
								height = topMaxRadius + "px";
								top    = 0 - topMaxRadius + "px";
								left   = 0 - this.borderWidth + "px";
							}
							
							this.topContainer = this.box.appendChild(newMainContainer);
						}
			            break;
	
			        // Bottom
			        case 1:      
			            // Only build bottom bar if a top corner is to be draw
			            if(this.settings.bl.enabled || this.settings.br.enabled) {
							var newMainContainer = document.createElement("DIV");
							with(newMainContainer.style){
								width    = "100%";
								fontSize = "1px";
								overflow = "hidden";
								position = "absolute";
								//backgroundColor = "#FFFFC4";
								paddingLeft  = this.borderWidth + "px";
								paddingRight = this.borderWidth + "px";
								var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0);
								height  = botMaxRadius + "px";
								bottom  =  0 - botMaxRadius + "px";
								left    =  0 - this.borderWidth + "px";
							}
						this.bottomContainer = this.box.appendChild(newMainContainer);
			            }
		            break;
			    }
			}
	
			// Turn off current borders
			if(this.topContainer) this.box.style.borderTopWidth = "0px";
			if(this.bottomContainer) this.box.style.borderBottomWidth = "0px";
	
			// Create array of available corners
			var corners = ["tr", "tl", "br", "bl"];
		
			//Loop for each corner
	
			for(var i in corners) {
			    // Get current corner type from array
			    var cc = corners[i];

			    // Has the user requested the currentCorner be round?
			    if(!this.settings[cc]) {
			        // No
			        if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null)) {
						// We need to create a filler div to fill the space upto the next horzontal corner.
						var newCorner = document.createElement("DIV");
		
						// Setup corners properties
						newCorner.style.position = "relative";
						newCorner.style.fontSize = "1px";
						newCorner.style.overflow = "hidden";
		
						// Add background image?
						if(this.backgroundImage == "") {
							newCorner.style.backgroundColor = this.boxColour;
						} else {
							newCorner.style.backgroundImage = this.backgroundImage;
						}

			            switch(cc) {
							case "tl":
								with(newCorner.style){
									height      = topMaxRadius - this.borderWidth + "px";
									marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px";
									borderLeft  = this.borderString;
									borderTop   = this.borderString;
									left         = -this.borderWidth + "px";
								}
							break;
			
							case "tr":
								with(newCorner.style){
									height      = topMaxRadius - this.borderWidth + "px";
									marginLeft  = this.settings.tl.radius - (this.borderWidth*2) + "px";
									borderRight = this.borderString;
									borderTop   = this.borderString;
									backgroundPosition  = "-" + this.boxWidth + "px 0px";
									left         = this.borderWidth + "px";
								}
							break;
	
							case "bl":
								with(newCorner.style){
									height       = botMaxRadius - this.borderWidth + "px";
									marginRight  = this.settings.br.radius - (this.borderWidth*2) + "px";
									borderLeft   = this.borderString;
									borderBottom = this.borderString;
									left         = -this.borderWidth + "px";
								}
							break;
			
							case "br":
								with(newCorner.style){
									height       = botMaxRadius - this.borderWidth + "px";
									marginLeft   = this.settings.bl.radius - (this.borderWidth*2) + "px";
									borderRight  = this.borderString;
									borderBottom = this.borderString;
									left         = this.borderWidth + "px"
								}
							break;
			            }
			        }
			    } else {
			        /*
			        PERFORMANCE NOTE:

			        If more than one corner is requested and a corner has been already
			        created for the same radius then that corner will be used as a master and cloned.
			        The pixel bars will then be repositioned to form the new corner type.
			        All new corners start as a bottom right corner.
			        */
			        if(this.masterCorners[this.settings[cc].radius]) {
			            // Create clone of the master corner
			            var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);
			        } else {
			            // Yes, we need to create a new corner
			            var newCorner = document.createElement("DIV");
						with(newCorner.style){
							height = this.settings[cc].radius + "px";
							width  = this.settings[cc].radius + "px";
							position = "absolute";
							fontSize = "1px";
							overflow = "hidden";
						}
						// THE FOLLOWING BLOCK OF CODE CREATES A ROUNDED CORNER
						// ---------------------------------------------------- TOP
			
						// Get border radius
						var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth);
			
						// Cycle the x-axis
						for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++) {
							// Calculate the value of y1 which identifies the pixels inside the border
							if((intx +1) >= borderRadius) {
								var y1 = -1;
							} else {
								var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1);
							}
			
							// Only calculate y2 and y3 if there is a border defined
							if(borderRadius != j) {
								if((intx) >= borderRadius) {
									var y2 = -1;
								} else {
									var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2)));
								}
			
								if((intx+1) >= j) {
									var y3 = -1;
								} else {
									var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);
								}
							}

							// Calculate y4
							if((intx) >= j) {
								var y4 = -1;
							} else {
								var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2)));
							}

							// Draw bar on inside of the border with foreground colour
							if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius);
	
							// Only draw border/foreground antialiased pixels and border if there is a border defined
							if(borderRadius != j) {
								// Draw aa pixels?
								if(this.antiAlias) {
									// Cycle the y-axis
									for(var inty = (y1 + 1); inty < y2; inty++) {
										// For each of the pixels that need anti aliasing between the foreground and border colour draw single pixel divs
										if(this.backgroundImage != "") {					
											var borderFract = (this.pixelFraction(intx, inty, borderRadius) * 100);
					
											if (borderFract < 30) {
												this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);
											} else {
												this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);
											}
										} else {
											var pixelcolour = dojo.graphics.color.blend(this.boxColour, this.borderColour, this.pixelFraction(intx, inty, borderRadius));
											this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius);
										}
									}
								}

								// Draw bar for the border
								if(y3 >= y2) {
									if (y1 == -1) {
										y1 = 0;
									}
									this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, this.settings[cc].radius);
								}	
								// Set the colour for the outside curve
								var outsideColour = this.borderColour;
							} else {
								// Set the coour for the outside curve
								var outsideColour = this.boxColour;
								var y3 = y1;
							}
			
							// Draw aa pixels?
							if(this.antiAlias) {		
								// Cycle the y-axis and draw the anti aliased pixels on the
								// outside of the curve
								for(var inty = (y3 + 1); inty < y4; inty++) {
									// For each of the pixels that need anti aliasing between 
									//the foreground/border colour & background draw single pixel divs
									this.drawPixel(intx, inty, outsideColour, (this.pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);
								}
							}
			            }

			            // END OF CORNER CREATION
			            // ---------------------------------------------------- END

			            // We now need to store the current corner in the masterConers array
			            this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);
			        }
			
					//Now we have a new corner we need to reposition all the pixels unless
					//the current corner is the bottom right.
			        if(cc != "br") {	
						// Loop through all children (pixel bars)
						for(var t = 0, k = newCorner.childNodes.length; t < k; t++) {
							// Get current pixel bar
							var pixelBar = newCorner.childNodes[t];
	
							// Get current top and left properties
							var pixelBarTop    = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px")));
							var pixelBarLeft   = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px")));
							var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px")));
							
							// Reposition pixels
							if(cc == "tl" || cc == "bl") {
								pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px"; // Left
							}
							if(cc == "tr" || cc == "tl") {
								pixelBar.style.top =  this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px"; // Top
							}
							var value;
					
							switch(cc) {
								case "tr":
									value = (-1 *( Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) - (Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth))));
									pixelBar.style.backgroundPosition  = value + "px";
									
								break;
				
								case "tl":
									value = (-1 *( Math.abs((this.settings[cc].radius -pixelBarLeft -1)  - this.borderWidth) - (Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth))));
									pixelBar.style.backgroundPosition  = value + "px";

								break;
				
								case "bl":
									value = (-1 *( Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) - (Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth))));
									pixelBar.style.backgroundPosition  = value + "px";

								break;
							}
						}
					}
				}
				if(newCorner) {
					// Position the container
					switch(cc) {
						case "tl":
							if(newCorner.style.position == "absolute") newCorner.style.top  = "0px";
							if(newCorner.style.position == "absolute") newCorner.style.left = "0px";
							if(this.topContainer) this.topContainer.appendChild(newCorner);
						break;

						case "tr":
							if(newCorner.style.position == "absolute") newCorner.style.top  = "0px";
							if(newCorner.style.position == "absolute") newCorner.style.right = "0px";
							if(this.topContainer) this.topContainer.appendChild(newCorner);
						break;
		
						case "bl":
							if(newCorner.style.position == "absolute") newCorner.style.bottom  = "0px";
							if(newCorner.style.position == "absolute") newCorner.style.left = "0px";
							if(this.bottomContainer) this.bottomContainer.appendChild(newCorner);
						break;
						
						case "br":
							if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px";
							if(newCorner.style.position == "absolute") newCorner.style.right = "0px";
							if(this.bottomContainer) this.bottomContainer.appendChild(newCorner);
						break;
					}
				}
			}
			//The last thing to do is draw the rest of the filler DIVs.
			//We only need to create a filler DIVs when two corners have
			//diffrent radiuses in either the top or bottom container.
	
			// Find out which corner has the biiger radius and get the difference amount
			var radiusDiff = [];
			radiusDiff["t"] = this.settings.tl.enabled && this.settings.tr.enabled ? Math.abs(this.settings.tl.radius - this.settings.tr.radius) : 0;
			radiusDiff["b"] = this.settings.bl.enabled && this.settings.br.enabled ? Math.abs(this.settings.bl.radius - this.settings.br.radius) : 0;

			for(var z in radiusDiff) {
				if(radiusDiff[z]) {
					// Get the type of corner that is the smaller one
					var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r");

					// First we need to create a DIV for the space under the smaller corner
					var newFiller = document.createElement("DIV");
					with(newFiller.style) {
						height = radiusDiff[z] + "px";
						width  =  this.settings[smallerCornerType].radius+ "px"
						position = "absolute";
						fontSize = "1px";
						overflow = "hidden";
						backgroundColor = this.boxColour;
					}

					// Position filler
					switch(smallerCornerType) {
						case "tl":
							with(newFiller.style) {
								bottom = "0px";
								left   = "0px";
								borderLeft = this.borderString;
							}
							this.topContainer.appendChild(newFiller);
						break;
	
						case "tr":
							with(newFiller.style) {
								bottom = "0px";
								right  = "0px";
								borderRight = this.borderString;
							}
							this.topContainer.appendChild(newFiller);
						break;

						case "bl":
							with(newFiller.style) {
								top    = "0px";
								left   = "0px";
								borderLeft = this.borderString;
							}
							this.bottomContainer.appendChild(newFiller);
						break;

						case "br":
							with(newFiller.style) {
								top    = "0px";
								right  = "0px";
								borderRight = this.borderString;
							}
							this.bottomContainer.appendChild(newFiller);
						break;
					}
			    }

				// Create the bar to fill the gap between each corner horizontally
				var newFillerBar = document.createElement("DIV");
				with(newFillerBar.style) {
					position = "relative";
					fontSize = "1px";
					overflow = "hidden";
					backgroundColor = this.boxColour;
				}

				switch(z) {
					case "t":
						// Top Bar
						if(this.topContainer) {
							with(newFillerBar.style) {
								height      = topMaxRadius - this.borderWidth + "px";
								marginLeft  = this.settings.tl.radius - this.borderWidth + "px";
								marginRight = this.settings.tr.radius - this.borderWidth + "px";
								borderTop   = this.borderString;
							}
						this.topContainer.appendChild(newFillerBar);
						}
					break;

					case "b":
						if(this.bottomContainer) {
						// Bottom Bar
						with(newFillerBar.style) {
							height       = botMaxRadius - this.borderWidth + "px";
							marginLeft   = this.settings.bl.radius - this.borderWidth + "px";
							marginRight  = this.settings.br.radius - this.borderWidth + "px";
							borderBottom = this.borderString;
						}
						this.bottomContainer.appendChild(newFillerBar);
					}
					break;
				}
			}
		}

		// This function draws the pixles
		this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius) {
			// Create pixel
			var pixel = document.createElement("DIV");

			
			// Section doesn't like with (pixel.style) { DEBUG?
			pixel.style.height   = height + "px";
			pixel.style.width    = "1px";
			pixel.style.position = "absolute";
			pixel.style.fontSize = "1px";
			pixel.style.overflow = "hidden";
			
			// Dont apply background image to border pixels
			if(image == -1 && this.backgroundImage != "") {
				pixel.style.backgroundImage = this.backgroundImage;
				pixel.style.backgroundPosition  = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + cornerRadius + inty) -this.borderWidth) + "px";
			} else {
				pixel.style.backgroundColor = colour;
			}
			
			// Set opacity if the transparency is anything other than 100
			if (transAmount != 100) {
				dojo.style.setOpacity(pixel, transAmount);
			}
			// Set the pixels position
			pixel.style.top = inty + "px";
			pixel.style.left = intx + "px";
		
			newCorner.appendChild(pixel);
		}
	},

	//For a pixel cut by the line determines the fraction of the pixel on the 'inside' of the
	//line.  Returns a number between 0 and 1
	pixelFraction: function(x, y, r) {
		var pixelfraction = 0;
		
		//determine the co-ordinates of the two points on the perimeter of the pixel that the
		//circle crosses
		
		var xvalues = [];
		var yvalues = [];
		var point = 0;
		var whatsides = "";

		// x + 0 = Left
		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2)));

		if ((intersect >= y) && (intersect < (y+1))) {
			whatsides = "Left";
			xvalues[point] = 0;
			yvalues[point] = intersect - y;
			point =  point + 1;
		}

		// y + 1 = Top
		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2)));
		
		if ((intersect >= x) && (intersect < (x+1))) {
			whatsides = whatsides + "Top";
			xvalues[point] = intersect - x;
			yvalues[point] = 1;
			point = point + 1;
		}
		// x + 1 = Right
		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2)));

		if ((intersect >= y) && (intersect < (y+1))) {
			whatsides = whatsides + "Right";
			xvalues[point] = 1;
			yvalues[point] = intersect - y;
			point =  point + 1;
		}
		// y + 0 = Bottom
		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2)));

		if ((intersect >= x) && (intersect < (x+1))) {
			whatsides = whatsides + "Bottom";
			xvalues[point] = intersect - x;
			yvalues[point] = 0;
		}

	    //depending on which sides of the perimeter of the pixel the circle crosses calculate the
	    //fraction of the pixel inside the circle

		switch (whatsides) {
			case "LeftRight":
				pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2);
			break;
			
			case "TopRight":
				pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2);
			break;
			
			case "TopBottom":
				pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2);
			break;
			
			case "LeftBottom":
				pixelfraction = (yvalues[0]*xvalues[1])/2;
			break;
			
			default:
				pixelfraction = 1;
	    }
	    return pixelfraction;
	},

	// This function converts CSS rgb(x, x, x) to hexadecimal
	rgb2Hex: function (rgbColour) {
		try{	
			// Get array of RGB values
			var rgbArray = this.rgb2Array(rgbColour);
			
			// Get RGB values
			var red   = parseInt(rgbArray[0]);
			var green = parseInt(rgbArray[1]);
			var blue  = parseInt(rgbArray[2]);
			
			// Build hex colour code
			var hexColour = "#" + this.intToHex(red) + this.intToHex(green) + this.intToHex(blue);
		}
		catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");
		}
		return hexColour;
	},

	//Converts a number to hexadecimal format

	intToHex: function (strNum) {
		var base = strNum / 16;
		var rem = strNum % 16;
		var base = base - (rem / 16);
		var baseS = this.makeHex(base);
		var remS = this.makeHex(rem);
		return baseS + '' + remS;
	},
	//gets the hex bits of a number

	makeHex: function(x) {
		if((x >= 0) && (x <= 9)) {
			return x;
		} else {
			switch(x) {
				case 10: return "A";
				case 11: return "B";
				case 12: return "C";
				case 13: return "D";
				case 14: return "E";
				case 15: return "F";
			}
		}
	},

	// Returns an array of rbg values
	rgb2Array: function(rgbColour) {
		// Remove rgb()
		var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")"));
	
		// Split RGB into array
		var rgbArray = rgbValues.split(", ");
		return rgbArray;
	}
}); // end function

__CPAN_FILE__ src/widget/MenuItem.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.MenuItem");
dojo.provide("dojo.widget.DomMenuItem");

dojo.deprecated("dojo.widget.MenuItem, dojo.widget.DomMenuItem",  "use dojo.widget.Menu2", "0.4");

dojo.require("dojo.string");
dojo.require("dojo.widget.*");

dojo.widget.tags.addParseTreeHandler("dojo:MenuItem");

/* MenuItem
 ***********/
 
dojo.widget.MenuItem = function(){
	dojo.widget.MenuItem.superclass.constructor.call(this);
}
dojo.inherits(dojo.widget.MenuItem, dojo.widget.Widget);

dojo.lang.extend(dojo.widget.MenuItem, {
	widgetType: "MenuItem",
	isContainer: true
});


/* DomMenuItem
 **************/
dojo.widget.DomMenuItem = function(){
	dojo.widget.DomMenuItem.superclass.constructor.call(this);
}
dojo.inherits(dojo.widget.DomMenuItem, dojo.widget.DomWidget);

dojo.lang.extend(dojo.widget.DomMenuItem, {
	widgetType: "MenuItem"
});

dojo.requireAfterIf("html", "dojo.html");
dojo.requireAfterIf("html", "dojo.widget.html.MenuItem");

__CPAN_FILE__ src/widget/Checkbox.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Checkbox");

dojo.requireAfterIf("html", "dojo.widget.html.Checkbox");

__CPAN_FILE__ src/widget/Editor.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/* TODO:
 * - font selector
 * - test, bug fix, more features :)
*/
dojo.provide("dojo.widget.Editor");
dojo.provide("dojo.widget.html.Editor");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.Toolbar");
dojo.require("dojo.widget.RichText");
dojo.require("dojo.widget.ColorPalette");
dojo.require("dojo.string.extras");

dojo.widget.tags.addParseTreeHandler("dojo:Editor");

dojo.widget.html.Editor = function() {
	dojo.widget.HtmlWidget.call(this);
	this.contentFilters = [];
	this._toolbars = [];
}
dojo.inherits(dojo.widget.html.Editor, dojo.widget.HtmlWidget);

dojo.widget.html.Editor.itemGroups = {
	textGroup: ["bold", "italic", "underline", "strikethrough"],
	blockGroup: ["formatBlock", "fontName", "fontSize"],
	justifyGroup: ["justifyleft", "justifycenter", "justifyright"],
	commandGroup: ["save", "cancel"],
	colorGroup: ["forecolor", "hilitecolor"],
	listGroup: ["insertorderedlist", "insertunorderedlist"],
	indentGroup: ["outdent", "indent"],
	linkGroup: ["createlink", "insertimage", "inserthorizontalrule"]
};

dojo.widget.html.Editor.formatBlockValues = {
	"Normal": "p",
	"Main heading": "h2",
	"Sub heading": "h3",
	"Sub sub heading": "h4",
	"Preformatted": "pre"
};

dojo.widget.html.Editor.fontNameValues = {
	"Arial": "Arial, Helvetica, sans-serif",
	"Verdana": "Verdana, sans-serif",
	"Times New Roman": "Times New Roman, serif",
	"Courier": "Courier New, monospace"
};

dojo.widget.html.Editor.fontSizeValues = {
	"1 (8 pt)" : "1",
	"2 (10 pt)": "2",
	"3 (12 pt)": "3",
	"4 (14 pt)": "4",
	"5 (18 pt)": "5",
	"6 (24 pt)": "6",
	"7 (36 pt)": "7"
};

dojo.widget.html.Editor.defaultItems = [
	"commandGroup", "|", "blockGroup", "|", "textGroup", "|", "colorGroup", "|", "justifyGroup", "|", "listGroup", "indentGroup", "|", "linkGroup"
];

// ones we support by default without asking the RichText component
// NOTE: you shouldn't put buttons like bold, italic, etc in here
dojo.widget.html.Editor.supportedCommands = ["save", "cancel", "|", "-", "/", " "];

dojo.lang.extend(dojo.widget.html.Editor, {
	widgetType: "Editor",

	saveUrl: "",
	saveMethod: "post",
	saveArgName: "editorContent",
	closeOnSave: false,
	items: dojo.widget.html.Editor.defaultItems,
	formatBlockItems: dojo.lang.shallowCopy(dojo.widget.html.Editor.formatBlockValues),
	fontNameItems: dojo.lang.shallowCopy(dojo.widget.html.Editor.fontNameValues),
	fontSizeItems: dojo.lang.shallowCopy(dojo.widget.html.Editor.fontSizeValues),

	// used to get the properties of an item if it is given as a string
	getItemProperties: function(name) {
		var props = {};
		switch(name.toLowerCase()) {
			case "bold":
			case "italic":
			case "underline":
			case "strikethrough":
				props.toggleItem = true;
				break;

			case "justifygroup":
				props.defaultButton = "justifyleft";
				props.preventDeselect = true;
				props.buttonGroup = true;
				break;

			case "listgroup":
				props.buttonGroup = true;
				break;

			case "save":
			case "cancel":
				props.label = dojo.string.capitalize(name);
				break;

			case "forecolor":
			case "hilitecolor":
				props.name = name;
				props.toggleItem = true; // FIXME: they aren't exactly toggle items
				props.icon = this.getCommandImage(name);
				break;

			case "formatblock":
				props.name = "formatBlock";
				props.values = this.formatBlockItems;
				break;

			case "fontname":
				props.name = "fontName";
				props.values = this.fontNameItems;

			case "fontsize":
				props.name = "fontSize";
				props.values = this.fontSizeItems;
		}
		return props;
	},

	validateItems: true, // set to false to add items, regardless of support
	focusOnLoad: true,
	minHeight: "1em",

	_richText: null, // RichText widget
	_richTextType: "RichText",

	_toolbarContainer: null, // ToolbarContainer widget
	_toolbarContainerType: "ToolbarContainer",

	_toolbars: [],
	_toolbarType: "Toolbar",

	_toolbarItemType: "ToolbarItem",

	buildRendering: function(args, frag) {
		// get the node from args/frag
		var node = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];
		var trt = dojo.widget.createWidget(this._richTextType, {
			focusOnLoad: this.focusOnLoad,
			minHeight: this.minHeight
		}, node)
		var _this = this;
		// this appears to fix a weird timing bug on Safari
		setTimeout(function(){
			_this.setRichText(trt);

			_this.initToolbar();

			_this.fillInTemplate(args, frag);
		}, 0);
	},

	setRichText: function(richText) {
		if(this._richText && this._richText == richText) {
			dojo.debug("Already set the richText to this richText!");
			return;
		}

		if(this._richText && !this._richText.isClosed) {
			dojo.debug("You are switching richTexts yet you haven't closed the current one. Losing reference!");
		}
		this._richText = richText;
		dojo.event.connect(this._richText, "close", this, "onClose");
		dojo.event.connect(this._richText, "onLoad", this, "onLoad");
		dojo.event.connect(this._richText, "onDisplayChanged", this, "updateToolbar");
		if(this._toolbarContainer) {
			this._toolbarContainer.enable();
			this.updateToolbar(true);
		}
	},

	initToolbar: function() {
		// var tic = new Date();
		if(this._toolbarContainer) { return; } // only create it once
		this._toolbarContainer = dojo.widget.createWidget(this._toolbarContainerType);
		var tb = this.addToolbar();
		var last = true;
		for(var i = 0; i < this.items.length; i++) {
			if(this.items[i] == "\n") { // new row
				tb = this.addToolbar();
			} else {
				if((this.items[i] == "|")&&(!last)){
					last = true;
				}else{
					last = this.addItem(this.items[i], tb);
				}
			}
		}
		this.insertToolbar(this._toolbarContainer.domNode, this._richText.domNode);
		// alert(new Date - tic);
	},

	// allow people to override this so they can make their own placement logic
	insertToolbar: function(tbNode, richTextNode) {
		dojo.html.insertBefore(tbNode, richTextNode);
		//dojo.html.insertBefore(this._toolbarContainer.domNode, this._richText.domNode);
	},

	addToolbar: function(toolbar) {
		this.initToolbar();
		if(!(toolbar instanceof dojo.widget.html.Toolbar)) {
			toolbar = dojo.widget.createWidget(this._toolbarType);
		}
		this._toolbarContainer.addChild(toolbar);
		this._toolbars.push(toolbar);
		return toolbar;
	},

	addItem: function(item, tb, dontValidate) {
		if(!tb) { tb = this._toolbars[0]; }
		var cmd = ((item)&&(!dojo.lang.isUndefined(item["getValue"]))) ?  cmd = item["getValue"](): item;

		var groups = dojo.widget.html.Editor.itemGroups;
		if(item instanceof dojo.widget.ToolbarItem) {
			tb.addChild(item);
		} else if(groups[cmd]) {
			var group = groups[cmd];
			var worked = true;
			if(cmd == "justifyGroup" || cmd == "listGroup") {
				var btnGroup = [cmd];
				for(var i = 0 ; i < group.length; i++) {
					if(dontValidate || this.isSupportedCommand(group[i])) {
						btnGroup.push(this.getCommandImage(group[i]));
					}else{
						worked = false;
					}
				}
				if(btnGroup.length){
					/*
					// the addChild interface is assinine. Work around it.
					var tprops = this.getItemProperties(cmd);
					var tmpGroup = dojo.widget.createWidget("ToolbarButtonGroup", tprops);
					dojo.debug(btnGroup);
					dojo.event.connect(tmpGroup, "onClick", this, "_action");
					dojo.event.connect(tmpGroup, "onChangeSelect", this, "_action");
					*/
					var btn = tb.addChild(btnGroup, null, this.getItemProperties(cmd));
					dojo.event.connect(btn, "onClick", this, "_action");
					dojo.event.connect(btn, "onChangeSelect", this, "_action");
				}
				return worked;
			} else {
				for(var i = 0; i < group.length; i++) {
					if(!this.addItem(group[i], tb)){
						worked = false;
					}
				}
				return worked;
			}
		} else {
			if((!dontValidate)&&(!this.isSupportedCommand(cmd))){
				return false;
			}
			if(dontValidate || this.isSupportedCommand(cmd)) {
				cmd = cmd.toLowerCase();
				if(cmd == "formatblock") {
					var select = dojo.widget.createWidget("ToolbarSelect", {
						name: "formatBlock",
						values: this.formatBlockItems
					});
					tb.addChild(select);
					var _this = this;
					dojo.event.connect(select, "onSetValue", function(item, value) {
						_this.onAction("formatBlock", value);
					});
				} else if(cmd == "fontname") {
					var select = dojo.widget.createWidget("ToolbarSelect", {
						name: "fontName",
						values: this.fontNameItems
					});
					tb.addChild(select);
					dojo.event.connect(select, "onSetValue", dojo.lang.hitch(this, function(item, value) {
						this.onAction("fontName", value);
					}));
				} else if(cmd == "fontsize") {
					var select = dojo.widget.createWidget("ToolbarSelect", {
						name: "fontSize",
						values: this.fontSizeItems
					});
					tb.addChild(select);
					dojo.event.connect(select, "onSetValue", dojo.lang.hitch(this, function(item, value) {
						this.onAction("fontSize", value);
					}));
				} else if(dojo.lang.inArray(cmd, ["forecolor", "hilitecolor"])) {
					var btn = tb.addChild(dojo.widget.createWidget("ToolbarColorDialog", this.getItemProperties(cmd)));
					dojo.event.connect(btn, "onSetValue", this, "_setValue");
				} else {
					var btn = tb.addChild(this.getCommandImage(cmd), null, this.getItemProperties(cmd));
					if(cmd == "save"){
						dojo.event.connect(btn, "onClick", this, "_save");
					}else if(cmd == "cancel"){
						dojo.event.connect(btn, "onClick", this, "_close");
					} else {
						dojo.event.connect(btn, "onClick", this, "_action");
						dojo.event.connect(btn, "onChangeSelect", this, "_action");
					}
				}
			}
		}
		return true;
	},

	enableToolbar: function() {
		if(this._toolbarContainer) {
			this._toolbarContainer.domNode.style.display = "";
			this._toolbarContainer.enable();
		}
	},

	disableToolbar: function(hide){
		if(hide){
			if(this._toolbarContainer){
				this._toolbarContainer.domNode.style.display = "none";
			}
		}else{
			if(this._toolbarContainer){
				this._toolbarContainer.disable();
			}
		}
	},

	_updateToolbarLastRan: null,
	_updateToolbarTimer: null,
	_updateToolbarFrequency: 500,

	updateToolbar: function(force) {
		if(!this._toolbarContainer) { return; }

		// keeps the toolbar from updating too frequently
		// TODO: generalize this functionality?
		var diff = new Date() - this._updateToolbarLastRan;
		if(!force && this._updateToolbarLastRan && (diff < this._updateToolbarFrequency)) {
			clearTimeout(this._updateToolbarTimer);
			var _this = this;
			this._updateToolbarTimer = setTimeout(function() {
				_this.updateToolbar();
			}, this._updateToolbarFrequency/2);
			return;
		} else {
			this._updateToolbarLastRan = new Date();
		}
		// end frequency checker

		var items = this._toolbarContainer.getItems();
		for(var i = 0; i < items.length; i++) {
			var item = items[i];
			if(item instanceof dojo.widget.html.ToolbarSeparator) { continue; }
			var cmd = item._name;
			if (cmd == "save" || cmd == "cancel") { continue; }
			else if(cmd == "justifyGroup") {
				try {
					if(!this._richText.queryCommandEnabled("justifyleft")) {
						item.disable(false, true);
					} else {
						item.enable(false, true);
						var jitems = item.getItems();
						for(var j = 0; j < jitems.length; j++) {
							var name = jitems[j]._name;
							var value = this._richText.queryCommandValue(name);
							if(typeof value == "boolean" && value) {
								value = name;
								break;
							} else if(typeof value == "string") {
								value = "justify"+value;
							} else {
								value = null;
							}
						}
						if(!value) { value = "justifyleft"; } // TODO: query actual style
						item.setValue(value, false, true);
					}
				} catch(err) {}
			} else if(cmd == "listGroup") {
				var litems = item.getItems();
				for(var j = 0; j < litems.length; j++) {
					this.updateItem(litems[j]);
				}
			} else {
				this.updateItem(item);
			}
		}
	},

	updateItem: function(item) {
		try {
			var cmd = item._name;
			var enabled = this._richText.queryCommandEnabled(cmd);
			item.setEnabled(enabled, false, true);

			var active = this._richText.queryCommandState(cmd);
			if(active && cmd == "underline") {
				// don't activate underlining if we are on a link
				active = !this._richText.queryCommandEnabled("unlink");
			}
			item.setSelected(active, false, true);
			return true;
		} catch(err) {
			return false;
		}
	},

	supportedCommands: dojo.widget.html.Editor.supportedCommands.concat(),

	isSupportedCommand: function(cmd) {
		// FIXME: how do we check for ActiveX?
		var yes = dojo.lang.inArray(cmd, this.supportedCommands);
		if(!yes) {
			try {
				var richText = this._richText || dojo.widget.HtmlRichText.prototype;
				yes = richText.queryCommandAvailable(cmd);
			} catch(E) {}
		}
		return yes;
	},

	getCommandImage: function(cmd) {
		if(cmd == "|") {
			return cmd;
		} else {
			return dojo.uri.dojoUri("src/widget/templates/buttons/" + cmd + ".gif");
		}
	},

	_action: function(e) {
		this._fire("onAction", e.getValue());
	},

	_setValue: function(a, b) {
		this._fire("onAction", a.getValue(), b);
	},

	_save: function(e){
		// FIXME: how should this behave when there's a larger form in play?
		if(!this._richText.isClosed){
			if(this.saveUrl.length){
				var content = {};
				content[this.saveArgName] = this.getHtml();
				dojo.io.bind({
					method: this.saveMethod,
					url: this.saveUrl,
					content: content
				});
			}else{
				dojo.debug("please set a saveUrl for the editor");
			}
			if(this.closeOnSave){
				this._richText.close(e.getName().toLowerCase() == "save");
			}
		}
	},

	_close: function(e) {
		if(!this._richText.isClosed) {
			this._richText.close(e.getName().toLowerCase() == "save");
		}
	},

	onAction: function(cmd, value) {
		switch(cmd) {
			case "createlink":
				if(!(value = prompt("Please enter the URL of the link:", "http://"))) {
					return;
				}
				break;
			case "insertimage":
				if(!(value = prompt("Please enter the URL of the image:", "http://"))) {
					return;
				}
				break;
		}
		this._richText.execCommand(cmd, value);
	},

	fillInTemplate: function(args, frag) {
		// dojo.event.connect(this, "onResized", this._richText, "onResized");
	},

	_fire: function(eventName) {
		if(dojo.lang.isFunction(this[eventName])) {
			var args = [];
			if(arguments.length == 1) {
				args.push(this);
			} else {
				for(var i = 1; i < arguments.length; i++) {
					args.push(arguments[i]);
				}
			}
			this[eventName].apply(this, args);
		}
	},

	getHtml: function(){
		this._richText.contentFilters = this._richText.contentFilters.concat(this.contentFilters);
		return this._richText.getEditorContent();
	},

	getEditorContent: function(){
		return this.getHtml();
	},

	onClose: function(save, hide){
		this.disableToolbar(hide);
		if(save) {
			this._fire("onSave");
		} else {
			this._fire("onCancel");
		}
	},

	// events baby!
	onLoad: function(){},
	onSave: function(){},
	onCancel: function(){}
});


__CPAN_FILE__ src/widget/Dialog.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Dialog");
dojo.provide("dojo.widget.html.Dialog");

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.ContentPane");
dojo.require("dojo.event.*");
dojo.require("dojo.graphics.color");
dojo.require("dojo.html");

dojo.widget.defineWidget(
	"dojo.widget.html.Dialog",
	dojo.widget.html.ContentPane,
	{
		templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlDialog.html"),
		isContainer: true,
		_scrollConnected: false,
		
		// provide a focusable element or element id if you need to
		// work around FF's tendency to send focus into outer space on hide
		focusElement: "",

		bg: null,
		bgColor: "black",
		bgOpacity: 0.4,
		followScroll: true,
		_fromTrap: false,
		anim: null,
		blockDuration: 0,
		lifetime: 0,

		trapTabs: function(e){
			if(e.target == this.tabStart) {
				if(this._fromTrap) {
					this._fromTrap = false;
				} else {
					this._fromTrap = true;
					this.tabEnd.focus();
				}
			} else if(e.target == this.tabEnd) {
				if(this._fromTrap) {
					this._fromTrap = false;
				} else {
					this._fromTrap = true;
					this.tabStart.focus();
				}
			}
		},

		clearTrap: function(e) {
			var _this = this;
			setTimeout(function() {
				_this._fromTrap = false;
			}, 100);
		},

		postCreate: function(args, frag, parentComp) {
			with(this.domNode.style) {
				position = "absolute";
				zIndex = 999;
				display = "none";
				overflow = "visible";
			}
			var b = document.body;
			b.appendChild(this.domNode);

			this.bg = document.createElement("div");
			this.bg.className = "dialogUnderlay";
			with(this.bg.style) {
				position = "absolute";
				left = top = "0px";
				zIndex = 998;
				display = "none";
			}
			this.setBackgroundColor(this.bgColor);
			b.appendChild(this.bg);

			this.bgIframe = new dojo.html.BackgroundIframe(this.bg);
		},

		setBackgroundColor: function(color) {
			if(arguments.length >= 3) {
				color = new dojo.graphics.color.Color(arguments[0], arguments[1], arguments[2]);
			} else {
				color = new dojo.graphics.color.Color(color);
			}
			this.bg.style.backgroundColor = color.toString();
			return this.bgColor = color;
		},
		
		setBackgroundOpacity: function(op) {
			if(arguments.length == 0) { op = this.bgOpacity; }
			dojo.style.setOpacity(this.bg, op);
			try {
				this.bgOpacity = dojo.style.getOpacity(this.bg);
			} catch (e) {
				this.bgOpacity = op;
			}
			return this.bgOpacity;
		},

		sizeBackground: function() {
			if(this.bgOpacity > 0) {
				var h = Math.max(
					document.documentElement.scrollHeight || document.body.scrollHeight,
					dojo.html.getViewportHeight());
				var w = dojo.html.getViewportWidth();
				this.bg.style.width = w + "px";
				this.bg.style.height = h + "px";
			}
			this.bgIframe.onResized();
		},

		showBackground: function() {
			this.sizeBackground();
			if(this.bgOpacity > 0) {
				this.bg.style.display = "block";
			}
		},

		placeDialog: function() {
			var scroll_offset = dojo.html.getScrollOffset();
			var viewport_size = dojo.html.getViewportSize();

			// find the size of the dialog
			var w = dojo.style.getOuterWidth(this.containerNode);
			var h = dojo.style.getOuterHeight(this.containerNode);

			var x = scroll_offset[0] + (viewport_size[0] - w)/2;
			var y = scroll_offset[1] + (viewport_size[1] - h)/2;

			with(this.domNode.style) {
				left = x + "px";
				top = y + "px";
			}
		},

		show: function() {
			this.setBackgroundOpacity();
			this.showBackground();

			dojo.widget.html.Dialog.superclass.show.call(this);

			// FIXME: moz doesn't generate onscroll events for mouse or key scrolling (wtf)
			// we should create a fake event by polling the scrolltop/scrollleft every X ms.
			// this smells like it should be a dojo feature rather than just for this widget.

			if (this.followScroll && !this._scrollConnected){
				this._scrollConnected = true;
				dojo.event.connect(window, "onscroll", this, "onScroll");
			}
			
			if(this.lifetime){
				this.timeRemaining = this.lifetime;
				if(!this.blockDuration){
					dojo.event.connect(this.bg, "onclick", this, "hide");
				}else{
					dojo.event.disconnect(this.bg, "onclick", this, "hide");
				}
				if(this.timerNode){
					this.timerNode.innerHTML = Math.ceil(this.timeRemaining/1000);
				}
				if(this.blockDuration && this.closeNode){
					if(this.lifetime > this.blockDuration){
						this.closeNode.style.visibility = "hidden";
					}else{
						this.closeNode.style.display = "none";
					}
				}
				this.timer = setInterval(dojo.lang.hitch(this, "onTick"), 100);
			}

			this.checkSize();
		},

		onLoad: function(){
			// when href is specified we need to reposition
			// the dialog after the data is loaded
			this.placeDialog();
		},
		
		fillInTemplate: function(){
			// dojo.event.connect(this.domNode, "onclick", this, "killEvent");
		},

		hide: function(){
			// workaround for FF focus going into outer space
			if (this.focusElement) { 
				dojo.byId(this.focusElement).focus(); 
				dojo.byId(this.focusElement).blur();
			}
			
			if(this.timer){
				clearInterval(this.timer);
			}

			this.bg.style.display = "none";
			this.bg.style.width = this.bg.style.height = "1px";

			dojo.widget.html.Dialog.superclass.hide.call(this);

			if (this._scrollConnected){
				this._scrollConnected = false;
				dojo.event.disconnect(window, "onscroll", this, "onScroll");
			}
		},
		
		setTimerNode: function(node){
			this.timerNode = node;
		},

		setCloseControl: function(node) {
			this.closeNode = node;
			dojo.event.connect(node, "onclick", this, "hide");
		},

		setShowControl: function(node) {
			dojo.event.connect(node, "onclick", this, "show");
		},
		
		onTick: function(){
			if(this.timer){
				this.timeRemaining -= 100;
				if(this.lifetime - this.timeRemaining >= this.blockDuration){
					dojo.event.connect(this.bg, "onclick", this, "hide");
					if(this.closeNode){
						this.closeNode.style.visibility = "visible";
					}
				}
				if(!this.timeRemaining){
					clearInterval(this.timer);
					this.hide();
				}else if(this.timerNode){
					this.timerNode.innerHTML = Math.ceil(this.timeRemaining/1000);
				}
			}
		},

		onScroll: function(){
			this.placeDialog();
			this.domNode.style.display = "block";
		},

		// Called when the browser window's size is changed
		checkSize: function() {
			if(this.isShowing()){
				this.sizeBackground();
				this.placeDialog();
				this.domNode.style.display="block";
				this.onResized();
			}
		},
		
		killEvent: function(evt){
			evt.preventDefault();
			evt.stopPropagation();
		}

	}
);

__CPAN_FILE__ src/widget/Button2.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Button2");
dojo.require("dojo.widget.Button");
dojo.require("dojo.widget.*");

dojo.widget.tags.addParseTreeHandler("dojo:button2");
dojo.widget.tags.addParseTreeHandler("dojo:dropdownbutton2");
dojo.widget.tags.addParseTreeHandler("dojo:combobutton2");

dojo.deprecated("dojo.widget.Button2", "Use dojo.widget.Button instead", "0.4");

dojo.requireAfterIf("html", "dojo.widget.html.Button2");

dojo.widget.Button2 = function(){}
dojo.inherits(dojo.widget.Button2, dojo.widget.Button);
dojo.lang.extend(dojo.widget.Button2, { widgetType: "Button2" });

dojo.widget.DropDownButton2 = function(){}
dojo.inherits(dojo.widget.DropDownButton2, dojo.widget.DropDownButton);
dojo.lang.extend(dojo.widget.DropDownButton2, { widgetType: "DropDownButton2" });

dojo.widget.ComboButton2 = function(){}
dojo.inherits(dojo.widget.ComboButton2, dojo.widget.ComboButton);
dojo.lang.extend(dojo.widget.ComboButton2, { widgetType: "ComboButton2" });

__CPAN_FILE__ src/widget/ColorPalette.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.ColorPalette");
dojo.provide("dojo.widget.html.ColorPalette");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.Toolbar");
dojo.require("dojo.html");

dojo.widget.tags.addParseTreeHandler("dojo:ToolbarColorDialog");

dojo.widget.html.ToolbarColorDialog = function(){
	dojo.widget.html.ToolbarDialog.call(this);
	
	/*
	FIXME: 	why the fuck did anyone ever think this kind of expensive iteration
			was a good idea?

	for (var method in this.constructor.prototype) {
		this[method] = this.constructor.prototype[method];
	}
	*/
}

dojo.inherits(dojo.widget.html.ToolbarColorDialog, dojo.widget.html.ToolbarDialog);

dojo.lang.extend(dojo.widget.html.ToolbarColorDialog, {

	widgetType: "ToolbarColorDialog",

	palette: "7x10",

	fillInTemplate: function (args, frag) {
		dojo.widget.html.ToolbarColorDialog.superclass.fillInTemplate.call(this, args, frag);
		this.dialog = dojo.widget.createWidget("ColorPalette", {palette: this.palette});
		this.dialog.domNode.style.position = "absolute";

		dojo.event.connect(this.dialog, "onColorSelect", this, "_setValue");
	},

	_setValue: function(color) {
		this._value = color;
		this._fireEvent("onSetValue", color);
	},
	
	showDialog: function (e) {
		dojo.widget.html.ToolbarColorDialog.superclass.showDialog.call(this, e);
		var x = dojo.html.getAbsoluteX(this.domNode);
		var y = dojo.html.getAbsoluteY(this.domNode) + dojo.html.getInnerHeight(this.domNode);
		this.dialog.showAt(x, y);
	},
	
	hideDialog: function (e) {
		dojo.widget.html.ToolbarColorDialog.superclass.hideDialog.call(this, e);
		this.dialog.hide();
	}
});



dojo.widget.tags.addParseTreeHandler("dojo:colorpalette");

dojo.widget.html.ColorPalette = function () {
	dojo.widget.HtmlWidget.call(this);
}

dojo.inherits(dojo.widget.html.ColorPalette, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.ColorPalette, {

	widgetType: "colorpalette",
	
	palette: "7x10",

	bgIframe: null,
	
	palettes: {
		"7x10": [["fff", "fcc", "fc9", "ff9", "ffc", "9f9", "9ff", "cff", "ccf", "fcf"],
			["ccc", "f66", "f96", "ff6", "ff3", "6f9", "3ff", "6ff", "99f", "f9f"],
			["c0c0c0", "f00", "f90", "fc6", "ff0", "3f3", "6cc", "3cf", "66c", "c6c"],
			["999", "c00", "f60", "fc3", "fc0", "3c0", "0cc", "36f", "63f", "c3c"],
			["666", "900", "c60", "c93", "990", "090", "399", "33f", "60c", "939"],
			["333", "600", "930", "963", "660", "060", "366", "009", "339", "636"],
			["000", "300", "630", "633", "330", "030", "033", "006", "309", "303"]],
	
		"3x4": [["ffffff"/*white*/, "00ff00"/*lime*/, "008000"/*green*/, "0000ff"/*blue*/],
			["c0c0c0"/*silver*/, "ffff00"/*yellow*/, "ff00ff"/*fuchsia*/, "000080"/*navy*/],
			["808080"/*gray*/, "ff0000"/*red*/, "800080"/*purple*/, "000000"/*black*/]]
			//["00ffff"/*aqua*/, "808000"/*olive*/, "800000"/*maroon*/, "008080"/*teal*/]];
	},

	buildRendering: function () {
		
		this.domNode = document.createElement("table");
		dojo.html.disableSelection(this.domNode);
		dojo.event.connect(this.domNode, "onmousedown", function (e) {
			e.preventDefault();
		});
		with (this.domNode) { // set the table's properties
			cellPadding = "0"; cellSpacing = "1"; border = "1";
			style.backgroundColor = "white"; //style.position = "absolute";
		}
		var tbody = document.createElement("tbody");
		this.domNode.appendChild(tbody);
		var colors = this.palettes[this.palette];
		for (var i = 0; i < colors.length; i++) {
			var tr = document.createElement("tr");
			for (var j = 0; j < colors[i].length; j++) {
				if (colors[i][j].length == 3) {
					colors[i][j] = colors[i][j].replace(/(.)(.)(.)/, "$1$1$2$2$3$3");
				}
	
				var td = document.createElement("td");
				with (td.style) {
					backgroundColor = "#" + colors[i][j];
					border = "1px solid gray";
					width = height = "15px";
					fontSize = "1px";
				}
	
				td.color = "#" + colors[i][j];
	
				td.onmouseover = function (e) { this.style.borderColor = "white"; }
				td.onmouseout = function (e) { this.style.borderColor = "gray"; }
				dojo.event.connect(td, "onmousedown", this, "click");
	
				td.innerHTML = "&nbsp;";
				tr.appendChild(td);
			}
			tbody.appendChild(tr);
		}

		if(dojo.render.html.ie){
			this.bgIframe = document.createElement("<iframe frameborder='0' src='javascript:void(0);'>");
			with(this.bgIframe.style){
				position = "absolute";
				left = top = "0px";
				display = "none";
			}
			document.body.appendChild(this.bgIframe);
			dojo.style.setOpacity(this.bgIframe, 0);
		}
	},

	click: function (e) {
		this.onColorSelect(e.currentTarget.color);
		e.currentTarget.style.borderColor = "gray";
	},

	onColorSelect: function (color) { },

	hide: function (){
		this.domNode.parentNode.removeChild(this.domNode);
		if(this.bgIframe){
			this.bgIframe.style.display = "none";
		}
	},
	
	showAt: function (x, y) {
		with(this.domNode.style){
			top = y + "px";
			left = x + "px";
			zIndex = 999;
		}
		document.body.appendChild(this.domNode);
		if(this.bgIframe){
			with(this.bgIframe.style){
				display = "block";
				top = y + "px";
				left = x + "px";
				zIndex = 998;
				width = dojo.html.getOuterWidth(this.domNode) + "px";
				height = dojo.html.getOuterHeight(this.domNode) + "px";
			}

		}
	}

});

__CPAN_FILE__ src/widget/Wizard.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Wizard");

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.LayoutContainer");
dojo.require("dojo.widget.ContentPane");
dojo.require("dojo.event.*");
dojo.require("dojo.html");
dojo.require("dojo.style");

//////////////////////////////////////////
// WizardContainer -- a set of panels
//////////////////////////////////////////
dojo.widget.WizardContainer = function() {
	dojo.widget.html.LayoutContainer.call(this);
}
dojo.inherits(dojo.widget.WizardContainer, dojo.widget.html.LayoutContainer);

dojo.lang.extend(dojo.widget.WizardContainer, {

	widgetType: "WizardContainer",

	labelPosition: "top",

	templatePath: dojo.uri.dojoUri("src/widget/templates/Wizard.html"),
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/Wizard.css"),

	selected: null,		// currently selected panel
	wizardNode: null, // the outer wizard node
	wizardPanelContainerNode: null, // the container for the panels
	wizardControlContainerNode: null, // the container for the wizard controls
	previousButton: null, // the previous button
	nextButton: null, // the next button
	cancelButton: null, // the cancel button
	doneButton: null, // the done button
	nextButtonLabel: "next",
	previousButtonLabel: "previous",
	cancelButtonLabel: "cancel",
	doneButtonLabel: "done",
	cancelFunction : "",

	hideDisabledButtons: false,

	fillInTemplate: function(args, frag){
		dojo.event.connect(this.nextButton, "onclick", this, "nextPanel");
		dojo.event.connect(this.previousButton, "onclick", this, "previousPanel");
		if (this.cancelFunction){
			dojo.event.connect(this.cancelButton, "onclick", this.cancelFunction);
		}else{
			this.cancelButton.style.display = "none";
		}
		dojo.event.connect(this.doneButton, "onclick", this, "done");
		this.nextButton.value = this.nextButtonLabel;
		this.previousButton.value = this.previousButtonLabel;
		this.cancelButton.value = this.cancelButtonLabel;
		this.doneButton.value = this.doneButtonLabel;
	},

	checkButtons: function(){
		var lastStep = !this.hasNextPanel();
		this.nextButton.disabled = lastStep;
		this.setButtonClass(this.nextButton);
		if(this.selected.doneFunction){
			this.doneButton.style.display = "";
			// hide the next button if this is the last one and we have a done function
			if(lastStep){
				this.nextButton.style.display = "none";
			}
		}else{
			this.doneButton.style.display = "none";
		}
		this.previousButton.disabled = ((!this.hasPreviousPanel()) || (!this.selected.canGoBack));
		this.setButtonClass(this.previousButton);
	},

	setButtonClass: function(button){
		if(!this.hideDisabledButtons){
			button.style.display = "";
			dojo.html.setClass(button, button.disabled ? "WizardButtonDisabled" : "WizardButton");
		}else{
			button.style.display = button.disabled ? "none" : "";
		}
	},

	registerChild: function(panel, insertionIndex){
		dojo.widget.WizardContainer.superclass.registerChild.call(this, panel, insertionIndex);
		this.wizardPanelContainerNode.appendChild(panel.domNode);
		panel.hide();

		if(!this.selected){
			this.onSelected(panel);
		}
		this.checkButtons();
	},

	onSelected: function(panel){
		// Deselect old panel and select new one
		if(this.selected ){
			if (this.selected.checkPass()) {
				this.selected.hide();
			} else {
				return;
			}
		}
		panel.show();
		this.selected = panel;
	},

	getPanels: function() {
		return this.getChildrenOfType("WizardPane", false);
	},

	selectedIndex: function() {
		if (this.selected) {
			return dojo.lang.indexOf(this.getPanels(), this.selected);
		}
		return -1;
	},

	nextPanel: function() {
		var selectedIndex = this.selectedIndex();
		if ( selectedIndex > -1 ) {
			var childPanels = this.getPanels();
			if (childPanels[selectedIndex + 1]) {
				this.onSelected(childPanels[selectedIndex + 1]);
			}
		}
		this.checkButtons();
	},

	previousPanel: function() {
		var selectedIndex = this.selectedIndex();
		if ( selectedIndex > -1 ) {
			var childPanels = this.getPanels();
			if (childPanels[selectedIndex - 1]) {
				this.onSelected(childPanels[selectedIndex - 1]);
			}
		}
		this.checkButtons();
	},

	hasNextPanel: function() {
		var selectedIndex = this.selectedIndex();
		return (selectedIndex < (this.getPanels().length - 1));
	},

	hasPreviousPanel: function() {
		var selectedIndex = this.selectedIndex();
		return (selectedIndex > 0);
	},

	done: function() {
		this.selected.done();
	}
});
dojo.widget.tags.addParseTreeHandler("dojo:WizardContainer");

//////////////////////////////////////////
// WizardPane -- a panel in a wizard
//////////////////////////////////////////
dojo.widget.WizardPane = function() {
	dojo.widget.html.ContentPane.call(this);
}
dojo.inherits(dojo.widget.WizardPane, dojo.widget.html.ContentPane);

dojo.lang.extend(dojo.widget.WizardPane, {
	widgetType: "WizardPane",

	canGoBack: true,

	passFunction: "",
	doneFunction: "",

	fillInTemplate: function(args, frag) {
		if (this.passFunction) {
			this.passFunction = dj_global[this.passFunction];
		}
		if (this.doneFunction) {
			this.doneFunction = dj_global[this.doneFunction];
		}
	},

	checkPass: function() {
		if (this.passFunction && dojo.lang.isFunction(this.passFunction)) {
			var failMessage = this.passFunction();
			if (failMessage) {
				alert(failMessage);
				return false;
			}
		}
		return true;
	},

	done: function() {
		if (this.doneFunction && dojo.lang.isFunction(this.doneFunction)) {
			this.doneFunction();
		}
	}
});

dojo.widget.tags.addParseTreeHandler("dojo:WizardPane");

__CPAN_FILE__ src/widget/Editor2.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/* TODO:
 * - font selector
 * - test, bug fix, more features :)
*/
dojo.provide("dojo.widget.Editor2");
dojo.provide("dojo.widget.html.Editor2");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.RichText");
dojo.require("dojo.widget.Editor2Toolbar");
// dojo.require("dojo.widget.ColorPalette");
// dojo.require("dojo.string.extras");

dojo.widget.defineWidget(
	"dojo.widget.html.Editor2",
	dojo.widget.html.RichText,
	{
		saveUrl: "",
		saveMethod: "post",
		saveArgName: "editorContent",
		closeOnSave: false,
		shareToolbar: false,
		toolbarAlwaysVisible: false,
		htmlEditing: false,
		_inHtmlMode: false,
		_htmlEditNode: null,

		commandList: dojo.widget.html.Editor2Toolbar.prototype.commandList,
		toolbarWidget: null,
		scrollInterval: null,
		

		editorOnLoad: function(){
			var toolbars = dojo.widget.byType("Editor2Toolbar");
			if((!toolbars.length)||(!this.shareToolbar)){
				var tbOpts = {};
				tbOpts.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlEditorToolbarOneline.html");
				this.toolbarWidget = dojo.widget.createWidget("Editor2Toolbar", 
										tbOpts, this.domNode, "before");
				dojo.event.connect(this, "destroy", this.toolbarWidget, "destroy");
				this.toolbarWidget.hideUnusableButtons(this);

				if(this.object){
					this.tbBgIframe = new dojo.html.BackgroundIframe(this.toolbarWidget.domNode);
					this.tbBgIframe.iframe.style.height = "30px";
				}

				// need to set position fixed to wherever this thing has landed
				if(this.toolbarAlwaysVisible){
					var src = document["documentElement"]||window;
					this.scrollInterval = setInterval(dojo.lang.hitch(this, "globalOnScrollHandler"), 100);
					// dojo.event.connect(src, "onscroll", this, "globalOnScrollHandler");
					dojo.event.connect("before", this, "destroyRendering", this, "unhookScroller");
				}
			}else{
				// FIXME: 	should we try harder to explicitly manage focus in
				// 			order to prevent too many editors from all querying
				// 			for button status concurrently?
				// FIXME: 	selecting in one shared toolbar doesn't clobber
				// 			selection in the others. This is problematic.
				this.toolbarWidget = toolbars[0];
			}
			dojo.event.topic.registerPublisher("Editor2.clobberFocus", this.editNode, "onfocus");
			// dojo.event.topic.registerPublisher("Editor2.clobberFocus", this.editNode, "onclick");
			dojo.event.topic.subscribe("Editor2.clobberFocus", this, "setBlur");
			dojo.event.connect(this.editNode, "onfocus", this, "setFocus");
			dojo.event.connect(this.toolbarWidget.linkButton, "onclick", 
				dojo.lang.hitch(this, function(){
					var range;
					if(this.document.selection){
						range = this.document.selection.createRange().text;
					}else if(dojo.render.html.mozilla){
						range = this.window.getSelection().toString();
					}
					if(range.length){
						this.toolbarWidget.exec("createlink", 
							prompt("Please enter the URL of the link:", "http://"));
					}else{
						alert("Please select text to link");
					}
				})
			);

			var focusFunc = dojo.lang.hitch(this, function(){ 
				if(dojo.render.html.ie){
					this.editNode.focus();
				}else{
					this.window.focus(); 
				}
			});

			dojo.event.connect(this.toolbarWidget, "formatSelectClick", focusFunc);
			dojo.event.connect(this, "execCommand", focusFunc);

			if(this.htmlEditing){
				var tb = this.toolbarWidget.htmltoggleButton;
				if(tb){
					tb.style.display = "";
					dojo.event.connect(this.toolbarWidget, "htmltoggleClick",
										this, "toggleHtmlEditing");
				}
			}
		},

		toggleHtmlEditing: function(){
			if(!this._inHtmlMode){
				this._inHtmlMode = true;
				this.toolbarWidget.highlightButton("htmltoggle");
				if(!this._htmlEditNode){
					this._htmlEditNode = document.createElement("textarea");
					dojo.html.insertBefore(this._htmlEditNode, this.domNode);
				}
				this._htmlEditNode.style.display = "";
				this._htmlEditNode.style.width = "100%";
				this._htmlEditNode.style.height = dojo.style.getInnerHeight(this.editNode)+"px";
				this._htmlEditNode.value = this.editNode.innerHTML;
				this.domNode.style.display = "none";
			}else{
				this._inHtmlMode = false;
				this.domNode.style.display = "";
				this.toolbarWidget.unhighlightButton("htmltoggle");
				dojo.lang.setTimeout(this, "replaceEditorContent", 1, this._htmlEditNode.value);
				this._htmlEditNode.style.display = "none";
				this.editNode.focus();
			}
		},

		setFocus: function(){
			// dojo.debug("setFocus:", this);
			dojo.event.connect(this.toolbarWidget, "exec", this, "execCommand");
		},

		setBlur: function(){
			// dojo.debug("setBlur:", this);
			dojo.event.disconnect(this.toolbarWidget, "exec", this, "execCommand");
		},

		_scrollSetUp: false,
		_fixEnabled: false,
		_scrollThreshold: false,
		_handleScroll: true,
		globalOnScrollHandler: function(){
			var isIE = dojo.render.html.ie;
			if(!this._handleScroll){ return; }
			var ds = dojo.style;
			var tdn = this.toolbarWidget.domNode;
			var db = document["body"];
			var totalHeight = ds.getOuterHeight(tdn);
			if(!this._scrollSetUp){
				this._scrollSetUp = true;
				var editorWidth =  ds.getOuterWidth(this.domNode); 
				this._scrollThreshold = ds.abs(tdn, false).y;
				// dojo.debug("threshold:", this._scrollThreshold);
				if((isIE)&&(db)&&(ds.getStyle(db, "background-image")=="none")){
					with(db.style){
						backgroundImage = "url(" + dojo.uri.dojoUri("src/widget/templates/images/blank.gif") + ")";
						backgroundAttachment = "fixed";
					}
				}
			}

			var scrollPos = (window["pageYOffset"]) ? window["pageYOffset"] : (document["documentElement"]||document["body"]).scrollTop;

			// FIXME: need to have top and bottom thresholds so toolbar doesn't keep scrolling past the bottom
			if(scrollPos > this._scrollThreshold){
				// dojo.debug(scrollPos);
				if(!this._fixEnabled){
					this.domNode.style.marginTop = totalHeight+"px";
					if(isIE){
						// FIXME: should we just use setBehvior() here instead?
						var cl = dojo.style.abs(tdn).x;
						document.body.appendChild(tdn);
						tdn.style.left = cl+dojo.style.getPixelValue(document.body, "margin-left")+"px";
						dojo.html.addClass(tdn, "IEFixedToolbar");
						if(this.object){
							dojo.html.addClass(this.tbBgIframe, "IEFixedToolbar");
						}
						
					}else{
						with(tdn.style){
							position = "fixed";
							top = "0px";
						}
					}
					tdn.style.zIndex = 1000;
					this._fixEnabled = true;
				}
				// if we're showing the floating toolbar, make sure that if
				// we've scrolled past the bottom of the editor that we hide
				// the toolbar for this instance of the editor.

				// TODO: when we get multiple editor toolbar support working
				// correctly, ensure that we check this against the scroll
				// position of the bottom-most editor instance.
				if(!dojo.render.html.safari){
					// safari reports a bunch of things incorrectly here
					var eHeight = (this.height) ? parseInt(this.height) : ((this.object) ? dojo.style.getInnerHeight(this.editNode) : this._lastHeight);
					if(scrollPos > (this._scrollThreshold+eHeight)){
						tdn.style.display = "none";
					}else{
						tdn.style.display = "";
					}
				}

			}else if(this._fixEnabled){
				this.domNode.style.marginTop = null;
				with(tdn.style){
					position = "";
					top = "";
					zIndex = "";
					if(isIE){
						marginTop = "";
					}
				}
				if(isIE){
					dojo.html.removeClass(tdn, "IEFixedToolbar");
					dojo.html.insertBefore(tdn, this._htmlEditNode||this.domNode);
				}
				this._fixEnabled = false;
			}
		},

		unhookScroller: function(){
			this._handleScroll = false;
			clearInterval(this.scrollInterval);
			// var src = document["documentElement"]||window;
			// dojo.event.disconnect(src, "onscroll", this, "globalOnScrollHandler");
			if(dojo.render.html.ie){
				dojo.html.removeClass(this.toolbarWidget.domNode, "IEFixedToolbar");
			}
		},

		_updateToolbarLastRan: null,
		_updateToolbarTimer: null,
		_updateToolbarFrequency: 500,

		updateToolbar: function(force){
			if((!this.isLoaded)||(!this.toolbarWidget)){ return; }

			// keeps the toolbar from updating too frequently
			// TODO: generalize this functionality?
			var diff = new Date() - this._updateToolbarLastRan;
			if( (!force)&&(this._updateToolbarLastRan)&&
				((diff < this._updateToolbarFrequency)) ){

				clearTimeout(this._updateToolbarTimer);
				var _this = this;
				this._updateToolbarTimer = setTimeout(function() {
					_this.updateToolbar();
				}, this._updateToolbarFrequency/2);
				return;

			}else{
				this._updateToolbarLastRan = new Date();
			}
			// end frequency checker

			dojo.lang.forEach(this.commandList, function(cmd){
					if(cmd == "inserthtml"){ return; }
					try{
						if(this.queryCommandEnabled(cmd)){
							if(this.queryCommandState(cmd)){
								this.toolbarWidget.highlightButton(cmd);
							}else{
								this.toolbarWidget.unhighlightButton(cmd);
							}
						}
					}catch(e){
						// alert(cmd+":"+e);
					}
				}, this);

			var h = dojo.render.html;
			
			// safari f's us for selection primitives
			if(h.safari){ return; }

			var selectedNode = (h.ie) ? this.document.selection.createRange().parentElement() : this.window.getSelection().anchorNode;
			// make sure we actuall have an element
			while((selectedNode)&&(selectedNode.nodeType != 1)){
				selectedNode = selectedNode.parentNode;
			}
			if(!selectedNode){ return; }

			var formats = ["p", "pre", "h1", "h2", "h3", "h4"];
			// gotta run some specialized updates for the various
			// formatting options
			var type = formats[dojo.lang.find(formats, selectedNode.nodeName.toLowerCase())];
			while((selectedNode)&&(selectedNode!=this.editNode)&&(!type)){
				selectedNode = selectedNode.parentNode;
				type = formats[dojo.lang.find(formats, selectedNode.nodeName.toLowerCase())];
			}
			if(!type){
				type = "";
			}else{
				if(type.charAt(0)=="h"){
					this.toolbarWidget.unhighlightButton("bold");
				}
			}
			this.toolbarWidget.selectFormat(type);
		},

		updateItem: function(item) {
			try {
				var cmd = item._name;
				var enabled = this._richText.queryCommandEnabled(cmd);
				item.setEnabled(enabled, false, true);

				var active = this._richText.queryCommandState(cmd);
				if(active && cmd == "underline") {
					// don't activate underlining if we are on a link
					active = !this._richText.queryCommandEnabled("unlink");
				}
				item.setSelected(active, false, true);
				return true;
			} catch(err) {
				return false;
			}
		},


		_save: function(e){
			// FIXME: how should this behave when there's a larger form in play?
			if(!this.isClosed){
				if(this.saveUrl.length){
					var content = {};
					content[this.saveArgName] = this.getHtml();
					dojo.io.bind({
						method: this.saveMethod,
						url: this.saveUrl,
						content: content
					});
				}else{
					dojo.debug("please set a saveUrl for the editor");
				}
				if(this.closeOnSave){
					this.close(e.getName().toLowerCase() == "save");
				}
			}
		},

		wireUpOnLoad: function(){
			if(!dojo.render.html.ie){
				/*
				dojo.event.kwConnect({
					srcObj:		this.document,
					srcFunc:	"click", 
					targetObj:	this.toolbarWidget,
					targetFunc:	"hideAllDropDowns",
					once:		true
				});
				*/
			}
		}
	},
	"html",
	function(){
		var cp = dojo.widget.html.Editor2.prototype;
		if(!cp._wrappersSet){
			cp._wrappersSet = true;
			cp.fillInTemplate = (function(fit){
				return function(){
					fit.call(this);
					this.editorOnLoad();
				};
			})(cp.fillInTemplate);
		
			cp.onDisplayChanged = (function(odc){
				return function(){
					try{
						odc.call(this);
						this.updateToolbar();
					}catch(e){}
				};
			})(cp.onDisplayChanged);

			cp.onLoad = (function(ol){
				return function(){
					ol.call(this);
					this.wireUpOnLoad();
				};
			})(cp.onLoad);
		}
	}
);

__CPAN_FILE__ src/widget/TreeSelector.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/


dojo.provide("dojo.widget.TreeSelector");

dojo.require("dojo.widget.HtmlWidget");


dojo.widget.tags.addParseTreeHandler("dojo:TreeSelector");


dojo.widget.TreeSelector = function() {
	dojo.widget.HtmlWidget.call(this);


	this.eventNames = {};

	this.listenedTrees = [];

}

dojo.inherits(dojo.widget.TreeSelector, dojo.widget.HtmlWidget);


dojo.lang.extend(dojo.widget.TreeSelector, {
	widgetType: "TreeSelector",
	selectedNode: null,

	dieWithTree: false,

	eventNamesDefault: {
		select : "select",
		destroy : "destroy",
		deselect : "deselect",
		dblselect: "dblselect" // select already selected node.. Edit or whatever
	},

	initialize: function() {

		for(name in this.eventNamesDefault) {
			if (dojo.lang.isUndefined(this.eventNames[name])) {
				this.eventNames[name] = this.widgetId+"/"+this.eventNamesDefault[name];
			}
		}

	},


	destroy: function() {
		dojo.event.topic.publish(this.eventNames.destroy, { source: this } );

		return dojo.widget.HtmlWidget.prototype.destroy.apply(this, arguments);
	},


	listenTree: function(tree) {
		dojo.event.topic.subscribe(tree.eventNames.titleClick, this, "select");
		dojo.event.topic.subscribe(tree.eventNames.iconClick, this, "select");
		dojo.event.topic.subscribe(tree.eventNames.collapse, this, "onCollapse");
		dojo.event.topic.subscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
		dojo.event.topic.subscribe(tree.eventNames.removeNode, this, "onRemoveNode");
		dojo.event.topic.subscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");

		/* remember all my trees to deselect when element is movedFrom them */
		this.listenedTrees.push(tree);
	},


	unlistenTree: function(tree) {

		dojo.event.topic.unsubscribe(tree.eventNames.titleClick, this, "select");
		dojo.event.topic.unsubscribe(tree.eventNames.iconClick, this, "select");
		dojo.event.topic.unsubscribe(tree.eventNames.collapse, this, "onCollapse");
		dojo.event.topic.unsubscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
		dojo.event.topic.unsubscribe(tree.eventNames.removeNode, this, "onRemoveNode");
		dojo.event.topic.unsubscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");


		for(var i=0; i<this.listenedTrees.length; i++){
           if(this.listenedTrees[i] === tree){
                   this.listenedTrees.splice(i, 1);
                   break;
           }
		}
	},


	onTreeDestroy: function(message) {

		this.unlistenTree(message.source);

		if (this.dieWithTree) {
			//dojo.debug("Killing myself "+this.widgetId);
			this.destroy();
			//dojo.debug("done");
		}
	},


	// deselect node if parent is collapsed
	onCollapse: function(message) {
		if (!this.selectedNode) return;

		var node = message.source;
		var parent = this.selectedNode.parent;
		while (parent !== node && parent.isTreeNode) {
			parent = parent.parent;
		}
		if (parent.isTreeNode) {
			this.deselect();
		}
	},



	select: function(message) {
		var node = message.source;
		var e = message.event;

		if (this.selectedNode === node) {
			dojo.event.topic.publish(this.eventNames.dblselect, { node: node });
			return;
		}

		if (this.selectedNode) {
			this.deselect();
		}

		this.doSelect(node);

		dojo.event.topic.publish(this.eventNames.select, {node: node} );
	},

	/**
	 * Deselect node if target tree is out of our concern
	 */
	onMoveFrom: function(message) {
		if (message.child !== this.selectedNode) {
			return;
		}

		if (!dojo.lang.inArray(this.listenedTrees, message.newTree)) {
			this.deselect();
		}
	},

	onRemoveNode: function(message) {
		if (message.child !== this.selectedNode) {
			return;
		}

		this.deselect();
	},

	doSelect: function(node){

		node.markSelected();

		this.selectedNode = node;
	},

	deselect: function(){

		var node = this.selectedNode;

		this.selectedNode = null;
		node.unMarkSelected();
		dojo.event.topic.publish(this.eventNames.deselect, {node: node} );

	}

});




__CPAN_FILE__ src/widget/InlineEditBox.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.InlineEditBox");
dojo.provide("dojo.widget.html.InlineEditBox");

dojo.require("dojo.widget.*");
dojo.require("dojo.lfx.*");
dojo.require("dojo.graphics.color");
dojo.require("dojo.string");
dojo.require("dojo.style");
dojo.require("dojo.html");

dojo.widget.tags.addParseTreeHandler("dojo:inlineeditbox");

dojo.widget.html.InlineEditBox = function(){
	dojo.widget.HtmlWidget.call(this);
	// mutable objects need to be in constructor to give each instance its own copy
	this.history = [];
}

dojo.inherits(dojo.widget.html.InlineEditBox, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.InlineEditBox, {
	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlInlineEditBox.html"),
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlInlineEditBox.css"),
	widgetType: "InlineEditBox",

	form: null,
	editBox: null,
	edit: null,
	text: null,
	textarea: null,
	submitButton: null,
	cancelButton: null,
	mode: "text",

	minWidth: 100, //px. minimum width of edit box
	minHeight: 200, //px. minimum width of edit box, if it's a TA

	editing: false,
	textValue: "",
	defaultText: "",
	doFade: false,
	
	onSave: function(newValue, oldValue){},
	onUndo: function(value){},

	postCreate: function(args, frag){
		// put original node back in the document, and attach handlers
		// which hide it and display the editor
		this.editable = this.getFragNodeRef(frag);
		dojo.dom.insertAfter(this.editable, this.form);
		dojo.event.connect(this.editable, "onmouseover", this, "mouseover");
		dojo.event.connect(this.editable, "onmouseout", this, "mouseout");
		dojo.event.connect(this.editable, "onclick", this, "beginEdit");

		this.textValue = dojo.string.trim(this.editable.innerHTML);
		if(dojo.string.trim(this.textValue).length == 0){
			this.editable.innerHTML = this.defaultText;
		}		
	},

	mouseover: function(e){
		if(!this.editing){
			dojo.html.addClass(this.editable, "editableRegion");
			if(this.mode == "textarea"){
				dojo.html.addClass(this.editable, "editableTextareaRegion");
			}
		}
	},

	mouseout: function(e){
		if(!this.editing){
			dojo.html.removeClass(this.editable, "editableRegion");
			dojo.html.removeClass(this.editable, "editableTextareaRegion");
		}
	},

	// When user clicks the text, then start editing.
	// Hide the text and display the form instead.
	beginEdit: function(e){
		if(this.editing){ return; }
		this.mouseout();
		this.editing = true;

		// setup the form's <input> or <textarea> field, as specified by mode
		var ee = this[this.mode.toLowerCase()];
		ee.value = dojo.string.trim(this.textValue);
		ee.style.fontSize = dojo.style.getStyle(this.editable, "font-size");
		ee.style.fontWeight = dojo.style.getStyle(this.editable, "font-weight");
		ee.style.fontStyle = dojo.style.getStyle(this.editable, "font-style");
		ee.style.width = Math.max(dojo.html.getInnerWidth(this.editable), this.minWidth) + "px";
		if(this.mode.toLowerCase()=="textarea"){
			ee.style.display = "block";
			ee.style.height = Math.max(dojo.html.getInnerHeight(this.editable), this.minHeight) + "px";
		} else {
			ee.style.display = "";
		}

		// show the edit form and hide the read only version of the text
		this.form.style.display = "";
		this.editable.style.display = "none";

		ee.select();
		this.submitButton.disabled = true;
	},

	saveEdit: function(e){
		e.preventDefault();
		e.stopPropagation();
		var ee = this[this.mode.toLowerCase()];
		if((this.textValue != ee.value)&&
			(dojo.string.trim(ee.value) != "")){
			this.doFade = true;
			this.history.push(this.textValue);
			this.onSave(ee.value, this.textValue);
			this.textValue = ee.value;
			this.editable.innerHTML = this.textValue;
		}else{
			this.doFade = false;
		}
		this.finishEdit(e);
	},

	cancelEdit: function(e){
		if(!this.editing){ return false; }
		this.editing = false;
		this.form.style.display="none";
		this.editable.style.display = "";
		return true;
	},

	finishEdit: function(e){
		if(!this.cancelEdit(e)){ return; }
		if(this.doFade) {
			dojo.lfx.highlight(this.editable, dojo.graphics.color.hex2rgb("#ffc"), 700).play(300);
		}
		this.doFade = false;
	},

	setText: function(txt){
		// sets the text without informing the server
		var tt = dojo.string.trim(txt);
		this.textValue = tt
		this.editable.innerHTML = tt;
	},

	undo: function(){
		if(this.history.length > 0){
			var value = this.history.pop();
			this.editable.innerHTML = value;
			this.textValue = value;
			this.onUndo(value);
		}
	},

	checkForValueChange: function(){
		var ee = this[this.mode.toLowerCase()];
		if((this.textValue != ee.value)&&
			(dojo.string.trim(ee.value) != "")){
			this.submitButton.disabled = false;
		}
	}
});

__CPAN_FILE__ src/widget/ResizeHandle.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.ResizeHandle");
dojo.provide("dojo.widget.html.ResizeHandle");

dojo.require("dojo.widget.*");
dojo.require("dojo.html");
dojo.require("dojo.style");
dojo.require("dojo.dom");
dojo.require("dojo.event");

dojo.widget.html.ResizeHandle = function(){
	dojo.widget.HtmlWidget.call(this);
}

dojo.inherits(dojo.widget.html.ResizeHandle, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.ResizeHandle, {
	widgetType: "ResizeHandle",

	isSizing: false,
	startPoint: null,
	startSize: null,
	minSize: null,

	targetElmId: '',

	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlResizeHandle.css"),
	templateString: '<div class="dojoHtmlResizeHandle"><div></div></div>',

	postCreate: function(){
		dojo.event.connect(this.domNode, "onmousedown", this, "beginSizing");
	},

	beginSizing: function(e){
		if (this.isSizing){ return false; }

		// get the target dom node to adjust.  targetElmId can refer to either a widget or a simple node
		this.targetWidget = dojo.widget.byId(this.targetElmId);
		this.targetDomNode = this.targetWidget ? this.targetWidget.domNode : dojo.byId(this.targetElmId);
		if (!this.targetDomNode){ return; }

		this.isSizing = true;
		this.startPoint  = {'x':e.clientX, 'y':e.clientY};
		this.startSize  = {'w':dojo.style.getOuterWidth(this.targetDomNode), 'h':dojo.style.getOuterHeight(this.targetDomNode)};

		dojo.event.kwConnect({
			srcObj: document.body, 
			srcFunc: "onmousemove",
			targetObj: this,
			targetFunc: "changeSizing",
			rate: 25
		});
		dojo.event.connect(document.body, "onmouseup", this, "endSizing");

		e.preventDefault();
	},

	changeSizing: function(e){
		// On IE, if you move the mouse above/to the left of the object being resized,
		// sometimes clientX/Y aren't set, apparently.  Just ignore the event.
		try{
			if(!e.clientX  || !e.clientY){ return; }
		}catch(e){
			// sometimes you get an exception accessing above fields...
			return;
		}
		var dx = this.startPoint.x - e.clientX;
		var dy = this.startPoint.y - e.clientY;
		
		var newW = this.startSize.w - dx;
		var newH = this.startSize.h - dy;

		// minimum size check
		if (this.minSize) {
			if (newW < this.minSize.w) {
				newW = dojo.style.getOuterWidth(this.targetDomNode);
			}
			if (newH < this.minSize.h) {
				newH = dojo.style.getOuterHeight(this.targetDomNode);
			}
		}
		
		if(this.targetWidget){
			this.targetWidget.resizeTo(newW, newH);
		}else{
			dojo.style.setOuterWidth(this.targetDomNode, newW);
			dojo.style.setOuterHeight(this.targetDomNode, newH);
		}
		
		e.preventDefault();
	},

	endSizing: function(e){
		dojo.event.disconnect(document.body, "onmousemove", this, "changeSizing");
		dojo.event.disconnect(document.body, "onmouseup", this, "endSizing");

		this.isSizing = false;
	}


});

dojo.widget.tags.addParseTreeHandler("dojo:ResizeHandle");

__CPAN_FILE__ src/widget/Show.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Show");

dojo.require("dojo.widget.*");
dojo.require("dojo.lang.common");

dojo.widget.Show = function(){}
dojo.lang.extend(dojo.widget.Show, {
	isContainer: true,
	_slide: -1,
	_slides: [],
	gotoSlide: function(/*int*/ slide){
		this._slide = slide;
		// summary: Placeholder
	},
	nextSlide: function(/*Event?*/ event){
		if(!this._slides[this._slide].nextAction(event)){
			if((this._slide + 1) != this._slides.length){
				this.gotoSlide(this._slide + 1);
				return true; // boolean
			}
			return false; // boolean
		}
	},
	previousSlide: function(/*Event?*/ event){
		if(!this._slides[this._slide].previousAction(event)){
			if((this._slide - 1) != -1){
				this.gotoSlide(this._slide - 1);
				return true; // boolean
			}
			return false; // boolean
		}
	}
});

dojo.requireAfterIf("html", "dojo.widget.html.Show");
__CPAN_FILE__ src/widget/LayoutContainer.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

//
// this widget provides Delphi-style panel layout semantics
//

dojo.provide("dojo.widget.LayoutContainer");
dojo.provide("dojo.widget.html.LayoutContainer");

dojo.require("dojo.widget.*");
dojo.require("dojo.html.layout");

dojo.widget.html.LayoutContainer = function(){
	dojo.widget.HtmlWidget.call(this);
}

dojo.inherits(dojo.widget.html.LayoutContainer, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.LayoutContainer, {
	widgetType: "LayoutContainer",
	isContainer: true,

	layoutChildPriority: 'top-bottom',

	postCreate: function(){
		dojo.html.layout(this.domNode, this.children, this.layoutChildPriority);
	},

	addChild: function(child, overrideContainerNode, pos, ref, insertIndex){
		dojo.widget.html.LayoutContainer.superclass.addChild.call(this, child, overrideContainerNode, pos, ref, insertIndex);
		dojo.html.layout(this.domNode, this.children, this.layoutChildPriority);
	},

	removeChild: function(pane){
		dojo.widget.html.LayoutContainer.superclass.removeChild.call(this,pane);
		dojo.html.layout(this.domNode, this.children, this.layoutChildPriority);
	},

	onResized: function(){
		dojo.html.layout(this.domNode, this.children, this.layoutChildPriority);
	},

	show: function(){
		// If this node was created while display=="none" then it
		// hasn't been laid out yet.  Do that now.
		this.domNode.style.display="";
		this.checkSize();
		this.domNode.style.display="none";
		this.domNode.style.visibility="";

		dojo.widget.html.LayoutContainer.superclass.show.call(this);
	}
});

// This argument can be specified for the children of a LayoutContainer.
// Since any widget can be specified as a LayoutContainer child, mix it
// into the base widget class.  (This is a hack, but it's effective.)
dojo.lang.extend(dojo.widget.Widget, {
	layoutAlign: 'none'
});

dojo.widget.tags.addParseTreeHandler("dojo:LayoutContainer");

__CPAN_FILE__ src/widget/ShowSlide.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.ShowSlide");

dojo.require("dojo.widget.*");
dojo.require("dojo.lang.common");

dojo.widget.ShowSlide = function(){
}
dojo.lang.extend(dojo.widget.ShowSlide, {
	title: "",
	_action: -1,
	isContainer: true,
	_components: {},
	_actions: [],
	gotoAction: function(/*int*/ action){
		this._action = action;
	},
	nextAction: function(/*Event?*/ event){
		if((this._action + 1) != this._actions.length){
			++this._action;
			return true; // boolean
		}
		return false; // boolean
	},
	previousAction: function(/*Event?*/ event){
		if((this._action - 1) != -1){
			--this._action;
			return true; // boolean
		}
		return false; // boolean
	}
});

dojo.requireAfterIf("html", "dojo.widget.html.ShowSlide");
__CPAN_FILE__ src/widget/TreeBasicController.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/


dojo.provide("dojo.widget.TreeBasicController");

dojo.require("dojo.event.*");
dojo.require("dojo.json")
dojo.require("dojo.io.*");


dojo.widget.tags.addParseTreeHandler("dojo:TreeBasicController");


dojo.widget.TreeBasicController = function() {
	dojo.widget.HtmlWidget.call(this);
}

dojo.inherits(dojo.widget.TreeBasicController, dojo.widget.HtmlWidget);


dojo.lang.extend(dojo.widget.TreeBasicController, {
	widgetType: "TreeBasicController",

	DNDController: "",

	dieWithTree: false,

	initialize: function(args, frag){

		/* no DND by default for compatibility */
		if (this.DNDController == "create") {
			dojo.require("dojo.dnd.TreeDragAndDrop");
			this.DNDController = new dojo.dnd.TreeDNDController(this);
		}



	},


	/**
	 * Binds controller to all tree events
	*/
	listenTree: function(tree) {
		//dojo.debug("Event "+tree.eventNames.treeClick);
		dojo.event.topic.subscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
		dojo.event.topic.subscribe(tree.eventNames.treeClick, this, "onTreeClick");
		dojo.event.topic.subscribe(tree.eventNames.treeCreate, this, "onTreeCreate");
		dojo.event.topic.subscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");

		if (this.DNDController) {
			this.DNDController.listenTree(tree);
		}
	},

	unlistenTree: function(tree) {
		dojo.event.topic.unsubscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
		dojo.event.topic.unsubscribe(tree.eventNames.treeClick, this, "onTreeClick");
		dojo.event.topic.unsubscribe(tree.eventNames.treeCreate, this, "onTreeCreate");
		dojo.event.topic.unsubscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");
	},

	onTreeDestroy: function(message) {
		var tree = message.source;

		this.unlistenTree(tree);

		if (this.dieWithTree) {
			//alert("Killing myself "+this.widgetId);
			this.destroy();
			//dojo.debug("done");
		}
	},

	onCreateDOMNode: function(message) {

		var node = message.source;


		if (node.expandLevel > 0) {
			this.expandToLevel(node, node.expandLevel);
		}
	},

	// perform actions-initializers for tree
	onTreeCreate: function(message) {
		var tree = message.source;
		var _this = this;
		if (tree.expandLevel) {
			dojo.lang.forEach(tree.children,
				function(child) {
					_this.expandToLevel(child, tree.expandLevel-1)
				}
			);
		}
	},

	expandToLevel: function(node, level) {
		if (level == 0) return;

		var children = node.children;
		var _this = this;

		var handler = function(node, expandLevel) {
			this.node = node;
			this.expandLevel = expandLevel;
			// recursively expand opened node
			this.process = function() {
				//dojo.debug("Process "+node+" level "+level);
				for(var i=0; i<this.node.children.length; i++) {
					var child = node.children[i];

					_this.expandToLevel(child, this.expandLevel);
				}
			};
		}

		var h = new handler(node, level-1);


		this.expand(node, false, h, h.process);

	},




	onTreeClick: function(message){
		var node = message.source;

		if(node.isLocked()) {
			return false;
		}

		if (node.isExpanded){
			this.collapse(node);
		} else {
			this.expand(node);
		}
	},

	expand: function(node, sync, callObj, callFunc) {
		node.expand();
		if (callFunc) callFunc.apply(callObj, [node]);
	},

	collapse: function(node) {

		node.collapse();
	},

// =============================== move ============================

	/**
	 * Checks whether it is ok to change parent of child to newParent
	 * May incur type checks etc
	 *
	 * It should check only hierarchical possibility w/o index, etc
	 * because in onDragOver event for Between DND mode we can't calculate index at once on onDragOVer.
	 * index changes as client moves mouse up-down over the node
	 */
	canMove: function(child, newParent){

		if (child.actionIsDisabled(child.actions.MOVE)) {
			return false;
		}

		// if we move under same parent then no matter if ADDCHILD disabled for him
		// but if we move to NEW parent then check if action is disabled for him
		// also covers case for newParent being a non-folder in strict mode etc
		if (child.parent !== newParent && newParent.actionIsDisabled(newParent.actions.ADDCHILD)) {
			return false;
		}

		// Can't move parent under child. check whether new parent is child of "child".
		var node = newParent;
		while(node.isTreeNode) {
			//dojo.debugShallow(node.title)
			if (node === child) {
				// parent of newParent is child
				return false;
			}
			node = node.parent;
		}

		return true;
	},


	move: function(child, newParent, index) {

		/* move sourceTreeNode to new parent */
		if (!this.canMove(child, newParent)) {
			return false;
		}

		var result = this.doMove(child, newParent, index);

		if (!result) return result;

		if (newParent.isTreeNode) {
			this.expand(newParent);
		}

		return result;
	},

	doMove: function(child, newParent, index) {
		child.tree.move(child, newParent, index);

		return true;
	},

// =============================== removeNode ============================


	canRemoveNode: function(child) {
		if (child.actionIsDisabled(child.actions.REMOVE)) {
			return false;
		}

		return true;
	},


	removeNode: function(node, callObj, callFunc) {
		if (!this.canRemoveNode(node)) {
			return false;
		}

		return this.doRemoveNode(node, callObj, callFunc);
	},


	doRemoveNode: function(node, callObj, callFunc) {
		node.tree.removeNode(node);

		if (callFunc) {
			callFunc.apply(dojo.lang.isUndefined(callObj) ? this : callObj, [node]);
		}
	},


	// -----------------------------------------------------------------------------
	//                             Create node stuff
	// -----------------------------------------------------------------------------


	canCreateChild: function(parent, index, data) {
		if (parent.actionIsDisabled(parent.actions.ADDCHILD)) return false;

		return true;
	},


	/* send data to server and add child from server */
	/* data may contain an almost ready child, or anything else, suggested to server */
	/*in RPC controllers server responds with child data to be inserted */
	createChild: function(parent, index, data, callObj, callFunc) {
		if (!this.canCreateChild(parent, index, data)) {
			return false;
		}

		return this.doCreateChild.apply(this, arguments);
	},

	doCreateChild: function(parent, index, data, callObj, callFunc) {

		var widgetType = data.widgetType ? data.widgetType : "TreeNode";

		var newChild = dojo.widget.createWidget(widgetType, data);

		parent.addChild(newChild, index);

		this.expand(parent);

		if (callFunc) {
			callFunc.apply(callObj, [newChild]);
		}

		return newChild;
	}



});

__CPAN_FILE__ src/widget/Spinner.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Spinner");
dojo.provide("dojo.widget.AdjustableIntegerTextbox");

dojo.require("dojo.widget.validate.IntegerTextbox");
dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");

/*
  ****** AdjustableIntegerTextbox ******

  A subclass of IntegerTextbox.
*/
dojo.widget.AdjustableIntegerTextbox = function(node) {
        // this property isn't a primitive and needs to be created on a per-item basis.
        this.flags = {};
}
dojo.inherits(dojo.widget.AdjustableIntegerTextbox, dojo.widget.validate.IntegerTextbox);
dojo.lang.extend(dojo.widget.AdjustableIntegerTextbox, {
        // new subclass properties
        widgetType: "AdjustableIntegerTextbox",
		delta: "1",

        adjustValue: function(direction, x){
			var val = this.getValue().replace(/[^\-+\d]/g, "");
			if(val.length == 0){ return; }

			num = Math.min(Math.max((parseInt(val)+(parseInt(this.delta) * direction)), this.flags.min), this.flags.max);
			val = (new Number(num)).toString();

			if(num >= 0){
				val = ((this.flags.signed == true)?'+':' ')+val; // make sure first char is a nondigit
			}

			if(this.flags.separator.length > 0){
				for (var i=val.length-3; i > 1; i-=3){
					val = val.substr(0,i)+this.flags.separator+val.substr(i);
				}
			}

			if(val.substr(0,1) == ' '){ val = val.substr(1); } // remove space

			this.setValue(val);

			return val.length;
	}
});
dojo.widget.tags.addParseTreeHandler("dojo:AdjustableIntegerTextbox");

/*
  ****** AdjustableRealNumberTextbox ******

  A subclass of RealNumberTextbox.
  @attr places    The exact number of decimal places.  If omitted, it's unlimited and optional.
  @attr exponent  Can be true or false.  If omitted the exponential part is optional.
  @attr eSigned   Is the exponent signed?  Can be true or false, if omitted the sign is optional.
*/
dojo.widget.AdjustableRealNumberTextbox = function(node) {
        // this property isn't a primitive and needs to be created on a per-item basis.
        this.flags = {};
}
dojo.inherits(dojo.widget.AdjustableRealNumberTextbox, dojo.widget.validate.RealNumberTextbox);
dojo.lang.extend(dojo.widget.AdjustableRealNumberTextbox, {
        // new subclass properties
        widgetType: "AdjustableRealNumberTextbox",
		delta: "1e1",

        adjustValue: function(direction, x){
			var val = this.getValue().replace(/[^\-+\.eE\d]/g, "");
			if(!val.length){ return; }

			var num = parseFloat(val);
			if(isNaN(num)){ return; }
			var delta = this.delta.split(/[eE]/);
			if(!delta.length){
				delta = [1, 1];
			}else{
				delta[0] = parseFloat(delta[0].replace(/[^\-+\.\d]/g, ""));
				if(isNaN(delta[0])){ delta[0] = 1; }
				if(delta.length > 1){
					delta[1] = parseInt(delta[1]);
				}
				if(isNaN(delta[1])){ delta[1] = 1; }
			}
			val = this.getValue().split(/[eE]/);
			if(!val.length){ return; }
			var numBase = parseFloat(val[0].replace(/[^\-+\.\d]/g, ""));
			if(val.length == 1){
				var numExp = 0;
			}else{
				var numExp = parseInt(val[1].replace(/[^\-+\d]/g, ""));
			}
			if(x <= val[0].length){
				x = 0;
				numBase += delta[0] * direction;
			}else{
				x = Number.MAX_VALUE;
				numExp += delta[1] * direction;
				if(this.flags.eSigned == false && numExp < 0){
					numExp = 0;
				}
			}
			num = Math.min(Math.max((numBase * Math.pow(10,numExp)), this.flags.min), this.flags.max);
			if((this.flags.exponent == true || (this.flags.exponent != false && x != 0)) && num.toExponential){
				if (isNaN(this.flags.places) || this.flags.places == Infinity){
					val = num.toExponential();
				}else{
					val = num.toExponential(this.flags.places);
				}
			}else if(num.toFixed && num.toPrecision){
				if(isNaN(this.flags.places)){
					val = num.toPrecision((1/3).toString().length-1);
				}else{
					val = num.toFixed(this.flags.places);
				}
			}else{
				val = num.toString();
			}

			if(num >= 0){
				if(this.flags.signed == true){
					val = '+' + val;
				}
			}
			val = val.split(/[eE]/);
			if(this.flags.separator.length > 0){
				if(num >= 0 && val[0].substr(0,1) != '+'){
					val[0] = ' ' + val[0]; // make sure first char is nondigit for easy algorithm
				}
				var i = val[0].lastIndexOf('.');
				if(i >= 0){
					i -= 3;
				}else{
					i = val[0].length-3;
				}
				for (; i > 1; i-=3){
					val[0] = val[0].substr(0,i)+this.flags.separator+val[0].substr(i);
				}
				if(val[0].substr(0,1) == ' '){ val[0] = val[0].substr(1); } // remove space
			}
			if(val.length > 1){
				if((this.flags.eSigned == true)&&(val[1].substr(0,1) != '+')){
					val[1] = '+' + val[1];
				}else if((!this.flags.eSigned)&&(val[1].substr(0,1) == '+')){
					val[1] = val[1].substr(1);
				}else if((!this.flags.eSigned)&&(val[1].substr(0,1) == '-')&&(num.toFixed && num.toPrecision)){
					if(isNaN(this.flags.places)){
						val[0] = num.toPrecision((1/3).toString().length-1);
					}else{
						val[0] = num.toFixed(this.flags.places).toString();
					}
					val[1] = "0";
				}
				val[0] += 'e' + val[1];
			}
			this.setValue(val[0]);
			if(x > val[0].length){ x = val[0].length; }
			return x;
	}
});
dojo.widget.tags.addParseTreeHandler("dojo:AdjustableRealNumberTextbox");

dojo.widget.Spinner = function(){
	dojo.widget.Widget.call(this);
}

dojo.inherits(dojo.widget.Spinner, dojo.widget.Widget);

dojo.widget.Spinner.defaults = {
	widgetType: "Spinner",
	isContainer: false
};

dojo.lang.extend(dojo.widget.Spinner, dojo.widget.Spinner.defaults);

dojo.widget.DomSpinner = function(){
	dojo.widget.Spinner.call(this);
	dojo.widget.DomWidget.call(this, true);
}

dojo.inherits(dojo.widget.DomSpinner, dojo.widget.DomWidget);
dojo.widget.tags.addParseTreeHandler("dojo:Spinner");

// render-specific includes
dojo.requireAfterIf("html", "dojo.widget.html.Spinner");

__CPAN_FILE__ src/widget/Parse.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Parse");

dojo.require("dojo.widget.Manager");
dojo.require("dojo.dom");

dojo.widget.Parse = function(fragment) {
	this.propertySetsList = [];
	this.fragment = fragment;
	
	this.createComponents = function(frag, parentComp){
		var comps = [ ];
		var built = false;
		// if we have items to parse/create at this level, do it!
		try{
			if((frag)&&(frag["tagName"])&&(frag!=frag["nodeRef"])){
				var djTags = dojo.widget.tags;
				// we split so that you can declare multiple
				// non-destructive widgets from the same ctor node
				var tna = String(frag["tagName"]).split(";");
				for(var x=0; x<tna.length; x++){
					var ltn = (tna[x].replace(/^\s+|\s+$/g, "")).toLowerCase();
					if(djTags[ltn]){
						built = true;
						frag.tagName = ltn;
						var ret = djTags[ltn](frag, this, parentComp, frag["index"]);
						comps.push(ret);
					}else{
						if((dojo.lang.isString(ltn))&&(ltn.substr(0, 5)=="dojo:")){
							dojo.debug("no tag handler registed for type: ", ltn);
						}
					}
				}
			}
		}catch(e){
			dojo.debug("dojo.widget.Parse: error:", e);
			// throw(e);
			// IE is such a bitch sometimes
		}
		// if there's a sub-frag, build widgets from that too
		if(!built){
			comps = comps.concat(this.createSubComponents(frag, parentComp));
		}
		return comps;
	}

	/*	createSubComponents recurses over a raw JavaScript object structure,
			and calls the corresponding handler for its normalized tagName if it exists
	*/
	this.createSubComponents = function(fragment, parentComp){
		var frag, comps = [];
		for(var item in fragment){
			frag = fragment[item];
			if ((frag)&&(typeof frag == "object")&&(frag!=fragment.nodeRef)&&(frag!=fragment["tagName"])){
				comps = comps.concat(this.createComponents(frag, parentComp));
			}
		}
		return comps;
	}

	/*  parsePropertySets checks the top level of a raw JavaScript object
			structure for any propertySets.  It stores an array of references to 
			propertySets that it finds.
	*/
	this.parsePropertySets = function(fragment) {
		return [];
		var propertySets = [];
		for(var item in fragment){
			if(	(fragment[item]["tagName"] == "dojo:propertyset") ) {
				propertySets.push(fragment[item]);
			}
		}
		// FIXME: should we store these propertySets somewhere for later retrieval
		this.propertySetsList.push(propertySets);
		return propertySets;
	}
	
	/*  parseProperties checks a raw JavaScript object structure for
			properties, and returns an array of properties that it finds.
	*/
	this.parseProperties = function(fragment) {
		var properties = {};
		for(var item in fragment){
			// FIXME: need to check for undefined?
			// case: its a tagName or nodeRef
			if((fragment[item] == fragment["tagName"])||
				(fragment[item] == fragment.nodeRef)){
				// do nothing
			}else{
				if((fragment[item]["tagName"])&&
					(dojo.widget.tags[fragment[item].tagName.toLowerCase()])){
					// TODO: it isn't a property or property set, it's a fragment, 
					// so do something else
					// FIXME: needs to be a better/stricter check
					// TODO: handle xlink:href for external property sets
				}else if((fragment[item][0])&&(fragment[item][0].value!="")&&(fragment[item][0].value!=null)){
					try{
						// FIXME: need to allow more than one provider
						if(item.toLowerCase() == "dataprovider") {
							var _this = this;
							this.getDataProvider(_this, fragment[item][0].value);
							properties.dataProvider = this.dataProvider;
						}
						properties[item] = fragment[item][0].value;
						var nestedProperties = this.parseProperties(fragment[item]);
						// FIXME: this kind of copying is expensive and inefficient!
						for(var property in nestedProperties){
							properties[property] = nestedProperties[property];
						}
					}catch(e){ dojo.debug(e); }
				}
			}
		}
		return properties;
	}

	/* getPropertySetById returns the propertySet that matches the provided id
	*/
	
	this.getDataProvider = function(objRef, dataUrl) {
		// FIXME: this is currently sync.  To make this async, we made need to move 
		//this step into the widget ctor, so that it is loaded when it is needed 
		// to populate the widget
		dojo.io.bind({
			url: dataUrl,
			load: function(type, evaldObj){
				if(type=="load"){
					objRef.dataProvider = evaldObj;
				}
			},
			mimetype: "text/javascript",
			sync: true
		});
	}

	
	this.getPropertySetById = function(propertySetId){
		for(var x = 0; x < this.propertySetsList.length; x++){
			if(propertySetId == this.propertySetsList[x]["id"][0].value){
				return this.propertySetsList[x];
			}
		}
		return "";
	}
	
	/* getPropertySetsByType returns the propertySet(s) that match(es) the
	 * provided componentClass
	 */
	this.getPropertySetsByType = function(componentType){
		var propertySets = [];
		for(var x=0; x < this.propertySetsList.length; x++){
			var cpl = this.propertySetsList[x];
			var cpcc = cpl["componentClass"]||cpl["componentType"]||null;
			// FIXME: propertySetId is not in scope here
			if((cpcc)&&(propertySetId == cpcc[0].value)){
				propertySets.push(cpl);
			}
		}
		return propertySets;
	}
	
	/* getPropertySets returns the propertySet for a given component fragment
	*/
	this.getPropertySets = function(fragment){
		var ppl = "dojo:propertyproviderlist";
		var propertySets = [];
		var tagname = fragment["tagName"];
		if(fragment[ppl]){ 
			var propertyProviderIds = fragment[ppl].value.split(" ");
			// FIXME: should the propertyProviderList attribute contain #
			// 		  syntax for reference to ids or not?
			// FIXME: need a better test to see if this is local or external
			// FIXME: doesn't handle nested propertySets, or propertySets that
			// 		  just contain information about css documents, etc.
			for(var propertySetId in propertyProviderIds){
				if((propertySetId.indexOf("..")==-1)&&(propertySetId.indexOf("://")==-1)){
					// get a reference to a propertySet within the current parsed structure
					var propertySet = this.getPropertySetById(propertySetId);
					if(propertySet != ""){
						propertySets.push(propertySet);
					}
				}else{
					// FIXME: add code to parse and return a propertySet from
					// another document
					// alex: is this even necessaray? Do we care? If so, why?
				}
			}
		}
		// we put the typed ones first so that the parsed ones override when
		// iteration happens.
		return (this.getPropertySetsByType(tagname)).concat(propertySets);
	}
	
	/* 
		nodeRef is the node to be replaced... in the future, we might want to add 
		an alternative way to specify an insertion point

		componentName is the expected dojo widget name, i.e. Button of ContextMenu

		properties is an object of name value pairs
	*/
	this.createComponentFromScript = function(nodeRef, componentName, properties){
		var ltn = "dojo:" + componentName.toLowerCase();
		if(dojo.widget.tags[ltn]){
			properties.fastMixIn = true;
			return [dojo.widget.tags[ltn](properties, this, null, null, properties)];
		}else{
			if(ltn.substr(0, 5)=="dojo:"){
				dojo.debug("no tag handler registed for type: ", ltn);
			}
		}
	}
}


dojo.widget._parser_collection = {"dojo": new dojo.widget.Parse() };
dojo.widget.getParser = function(name){
	if(!name){ name = "dojo"; }
	if(!this._parser_collection[name]){
		this._parser_collection[name] = new dojo.widget.Parse();
	}
	return this._parser_collection[name];
}

/**
 * Creates widget.
 *
 * @param name     The name of the widget to create
 * @param props    Key-Value pairs of properties of the widget
 * @param refNode  If the last argument is specified this node is used as
 *                 a reference for inserting this node into a DOM tree else
 *                 it beomces the domNode
 * @param position The position to insert this widget's node relative to the
 *                 refNode argument
 * @return The new Widget object
 */
 
dojo.widget.createWidget = function(name, props, refNode, position){
	var lowerCaseName = name.toLowerCase();
	var namespacedName = "dojo:" + lowerCaseName;
	var isNode = ( dojo.byId(name) && (!dojo.widget.tags[namespacedName]) );

	// if we got a node or an unambiguious ID, build a widget out of it
	if(	(arguments.length==1) && ((typeof name != "string")||(isNode)) ){
		// we got a DOM node
		var xp = new dojo.xml.Parse();
		// FIXME: we should try to find the parent!
		var tn = (isNode) ? dojo.byId(name) : name;
		return dojo.widget.getParser().createComponents(xp.parseElement(tn, null, true))[0];
	}

	function fromScript (placeKeeperNode, name, props) {
		props[namespacedName] = { 
			dojotype: [{value: lowerCaseName}],
			nodeRef: placeKeeperNode,
			fastMixIn: true
		};
		return dojo.widget.getParser().createComponentFromScript(
			placeKeeperNode, name, props, true);
	}

	if (typeof name != "string" && typeof props == "string") {
		dojo.deprecated("dojo.widget.createWidget", 
			"argument order is now of the form " +
			"dojo.widget.createWidget(NAME, [PROPERTIES, [REFERENCENODE, [POSITION]]])", "0.4");
		return fromScript(name, props, refNode);
	}
	
	props = props||{};
	var notRef = false;
	var tn = null;
	var h = dojo.render.html.capable;
	if(h){
		tn = document.createElement("span");
	}
	if(!refNode){
		notRef = true;
		refNode = tn;
		if(h){
			document.body.appendChild(refNode);
		}
	}else if(position){
		dojo.dom.insertAtPosition(tn, refNode, position);
	}else{ // otherwise don't replace, but build in-place
		tn = refNode;
	}
	var widgetArray = fromScript(tn, name, props);
	if (!widgetArray || !widgetArray[0] || typeof widgetArray[0].widgetType == "undefined") {
		throw new Error("createWidget: Creation of \"" + name + "\" widget failed.");
	}
	if (notRef) {
		if (widgetArray[0].domNode.parentNode) {
			widgetArray[0].domNode.parentNode.removeChild(widgetArray[0].domNode);
		}
	}
	return widgetArray[0]; // just return the widget
}
 
dojo.widget.fromScript = function(name, props, refNode, position){
	dojo.deprecated("dojo.widget.fromScript", " use " +
		"dojo.widget.createWidget instead", "0.4");
	return dojo.widget.createWidget(name, props, refNode, position);
}

__CPAN_FILE__ src/widget/Toolbar.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.ToolbarContainer");
dojo.provide("dojo.widget.html.ToolbarContainer");
dojo.provide("dojo.widget.Toolbar");
dojo.provide("dojo.widget.html.Toolbar");
dojo.provide("dojo.widget.ToolbarItem");
dojo.provide("dojo.widget.html.ToolbarButtonGroup");
dojo.provide("dojo.widget.html.ToolbarButton");
dojo.provide("dojo.widget.html.ToolbarDialog");
dojo.provide("dojo.widget.html.ToolbarMenu");
dojo.provide("dojo.widget.html.ToolbarSeparator");
dojo.provide("dojo.widget.html.ToolbarSpace");
dojo.provide("dojo.widget.Icon");

dojo.require("dojo.widget.*");
dojo.require("dojo.html");

/* ToolbarContainer
 *******************/
dojo.widget.tags.addParseTreeHandler("dojo:toolbarContainer");
dojo.widget.html.ToolbarContainer = function() {
	dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.ToolbarContainer, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.ToolbarContainer, {
	widgetType: "ToolbarContainer",
	isContainer: true,

	templateString: '<div class="toolbarContainer" dojoAttachPoint="containerNode"></div>',
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlToolbar.css"),

	getItem: function(name) {
		if(name instanceof dojo.widget.ToolbarItem) { return name; }
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.html.Toolbar) {
				var item = child.getItem(name);
				if(item) { return item; }
			}
		}
		return null;
	},

	getItems: function() {
		var items = [];
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.html.Toolbar) {
				items = items.concat(child.getItems());
			}
		}
		return items;
	},

	enable: function() {
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.html.Toolbar) {
				child.enable.apply(child, arguments);
			}
		}
	},

	disable: function() {
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.html.Toolbar) {
				child.disable.apply(child, arguments);
			}
		}
	},

	select: function(name) {
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.html.Toolbar) {
				child.select(arguments);
			}
		}
	},

	deselect: function(name) {
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.html.Toolbar) {
				child.deselect(arguments);
			}
		}
	},

	getItemsState: function() {
		var values = {};
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.html.Toolbar) {
				dojo.lang.mixin(values, child.getItemsState());
			}
		}
		return values;
	},

	getItemsActiveState: function() {
		var values = {};
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.html.Toolbar) {
				dojo.lang.mixin(values, child.getItemsActiveState());
			}
		}
		return values;
	},

	getItemsSelectedState: function() {
		var values = {};
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.html.Toolbar) {
				dojo.lang.mixin(values, child.getItemsSelectedState());
			}
		}
		return values;
	}
});

/* Toolbar
 **********/
dojo.widget.tags.addParseTreeHandler("dojo:toolbar");
dojo.widget.html.Toolbar = function() {
	dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.Toolbar, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.html.Toolbar, {
	widgetType: "Toolbar",
	isContainer: true,

	templateString: '<div class="toolbar" dojoAttachPoint="containerNode" unselectable="on" dojoOnMouseover="_onmouseover" dojoOnMouseout="_onmouseout" dojoOnClick="_onclick" dojoOnMousedown="_onmousedown" dojoOnMouseup="_onmouseup"></div>',
	//templateString: '<div class="toolbar" dojoAttachPoint="containerNode" unselectable="on"></div>',

	// given a node, tries to find it's toolbar item
	_getItem: function(node) {
		var start = new Date();
		var widget = null;
		while(node && node != this.domNode) {
			if(dojo.html.hasClass(node, "toolbarItem")) {
				var widgets = dojo.widget.manager.getWidgetsByFilter(function(w) { return w.domNode == node; });
				if(widgets.length == 1) {
					widget = widgets[0];
					break;
				} else if(widgets.length > 1) {
					dojo.raise("Toolbar._getItem: More than one widget matches the node");
				}
			}
			node = node.parentNode;
		}
		return widget;
	},

	_onmouseover: function(e) {
		var widget = this._getItem(e.target);
		if(widget && widget._onmouseover) { widget._onmouseover(e); }
	},

	_onmouseout: function(e) {
		var widget = this._getItem(e.target);
		if(widget && widget._onmouseout) { widget._onmouseout(e); }
	},

	_onclick: function(e) {
		var widget = this._getItem(e.target);
		if(widget && widget._onclick){ 
			widget._onclick(e);
		}
	},

	_onmousedown: function(e) {
		var widget = this._getItem(e.target);
		if(widget && widget._onmousedown) { widget._onmousedown(e); }
	},

	_onmouseup: function(e) {
		var widget = this._getItem(e.target);
		if(widget && widget._onmouseup) { widget._onmouseup(e); }
	},

	addChild: function(item, pos, props) {
		var widget = dojo.widget.ToolbarItem.make(item, null, props);
		var ret = dojo.widget.html.Toolbar.superclass.addChild.call(this, widget, null, pos, null);
		return ret;
	},

	push: function() {
		for(var i = 0; i < arguments.length; i++) {
			this.addChild(arguments[i]);
		}
	},

	getItem: function(name) {
		if(name instanceof dojo.widget.ToolbarItem) { return name; }
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.ToolbarItem
				&& child._name == name) { return child; }
		}
		return null;
	},

	getItems: function() {
		var items = [];
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.ToolbarItem) {
				items.push(child);
			}
		}
		return items;
	},

	getItemsState: function() {
		var values = {};
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.ToolbarItem) {
				values[child._name] = {
					selected: child._selected,
					enabled: child._enabled
				};
			}
		}
		return values;
	},

	getItemsActiveState: function() {
		var values = this.getItemsState();
		for(var item in values) {
			values[item] = values[item].enabled;
		}
		return values;
	},

	getItemsSelectedState: function() {
		var values = this.getItemsState();
		for(var item in values) {
			values[item] = values[item].selected;
		}
		return values;
	},

	enable: function() {
		var items = arguments.length ? arguments : this.children;
		for(var i = 0; i < items.length; i++) {
			var child = this.getItem(items[i]);
			if(child instanceof dojo.widget.ToolbarItem) {
				child.enable(false, true);
			}
		}
	},

	disable: function() {
		var items = arguments.length ? arguments : this.children;
		for(var i = 0; i < items.length; i++) {
			var child = this.getItem(items[i]);
			if(child instanceof dojo.widget.ToolbarItem) {
				child.disable();
			}
		}
	},

	select: function() {
		for(var i = 0; i < arguments.length; i++) {
			var name = arguments[i];
			var item = this.getItem(name);
			if(item) { item.select(); }
		}
	},

	deselect: function() {
		for(var i = 0; i < arguments.length; i++) {
			var name = arguments[i];
			var item = this.getItem(name);
			if(item) { item.disable(); }
		}
	},

	setValue: function() {
		for(var i = 0; i < arguments.length; i += 2) {
			var name = arguments[i], value = arguments[i+1];
			var item = this.getItem(name);
			if(item) {
				if(item instanceof dojo.widget.ToolbarItem) {
					item.setValue(value);
				}
			}
		}
	}
});

/* ToolbarItem hierarchy:
	- ToolbarItem
		- ToolbarButton
		- ToolbarDialog
			- ToolbarMenu
		- ToolbarSeparator
			- ToolbarSpace
				- ToolbarFlexibleSpace
*/


/* ToolbarItem
 **************/
dojo.widget.ToolbarItem = function() {
	dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.ToolbarItem, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.ToolbarItem, {
	templateString: '<span unselectable="on" class="toolbarItem"></span>',

	_name: null,
	getName: function() { return this._name; },
	setName: function(value) { return this._name = value; },
	getValue: function() { return this.getName(); },
	setValue: function(value) { return this.setName(value); },

	_selected: false,
	isSelected: function() { return this._selected; },
	setSelected: function(is, force, preventEvent) {
		if(!this._toggleItem && !force) { return; }
		is = Boolean(is);
		if(force || this._enabled && this._selected != is) {
			this._selected = is;
			this.update();
			if(!preventEvent) {
				this._fireEvent(is ? "onSelect" : "onDeselect");
				this._fireEvent("onChangeSelect");
			}
		}
	},
	select: function(force, preventEvent) {
		return this.setSelected(true, force, preventEvent);
	},
	deselect: function(force, preventEvent) {
		return this.setSelected(false, force, preventEvent);
	},

	_toggleItem: false,
	isToggleItem: function() { return this._toggleItem; },
	setToggleItem: function(value) { this._toggleItem = Boolean(value); },

	toggleSelected: function(force) {
		return this.setSelected(!this._selected, force);
	},

	_enabled: true,
	isEnabled: function() { return this._enabled; },
	setEnabled: function(is, force, preventEvent) {
		is = Boolean(is);
		if(force || this._enabled != is) {
			this._enabled = is;
			this.update();
			if(!preventEvent) {
				this._fireEvent(this._enabled ? "onEnable" : "onDisable");
				this._fireEvent("onChangeEnabled");
			}
		}
		return this._enabled;
	},
	enable: function(force, preventEvent) {
		return this.setEnabled(true, force, preventEvent);
	},
	disable: function(force, preventEvent) {
		return this.setEnabled(false, force, preventEvent);
	},
	toggleEnabled: function(force, preventEvent) {
		return this.setEnabled(!this._enabled, force, preventEvent);
	},

	_icon: null,
	getIcon: function() { return this._icon; },
	setIcon: function(value) {
		var icon = dojo.widget.Icon.make(value);
		if(this._icon) {
			this._icon.setIcon(icon);
		} else {
			this._icon = icon;
		}
		var iconNode = this._icon.getNode();
		if(iconNode.parentNode != this.domNode) {
			if(this.domNode.hasChildNodes()) {
				this.domNode.insertBefore(iconNode, this.domNode.firstChild);
			} else {
				this.domNode.appendChild(iconNode);
			}
		}
		return this._icon;
	},

	// TODO: update the label node (this.labelNode?)
	_label: "",
	getLabel: function() { return this._label; },
	setLabel: function(value) {
		var ret = this._label = value;
		if(!this.labelNode) {
			this.labelNode = document.createElement("span");
			this.domNode.appendChild(this.labelNode);
		}
		this.labelNode.innerHTML = "";
		this.labelNode.appendChild(document.createTextNode(this._label));
		this.update();
		return ret;
	},

	// fired from: setSelected, setEnabled, setLabel
	update: function() {
		if(this._enabled) {
			dojo.html.removeClass(this.domNode, "disabled");
			if(this._selected) {
				dojo.html.addClass(this.domNode, "selected");
			} else {
				dojo.html.removeClass(this.domNode, "selected");
			}
		} else {
			this._selected = false;
			dojo.html.addClass(this.domNode, "disabled");
			dojo.html.removeClass(this.domNode, "down");
			dojo.html.removeClass(this.domNode, "hover");
		}
		this._updateIcon();
	},

	_updateIcon: function() {
		if(this._icon) {
			if(this._enabled) {
				if(this._cssHover) {
					this._icon.hover();
				} else if(this._selected) {
					this._icon.select();
				} else {
					this._icon.enable();
				}
			} else {
				this._icon.disable();
			}
		}
	},

	_fireEvent: function(evt) {
		if(typeof this[evt] == "function") {
			var args = [this];
			for(var i = 1; i < arguments.length; i++) {
				args.push(arguments[i]);
			}
			this[evt].apply(this, args);
		}
	},

	_onmouseover: function(e) {
		if(!this._enabled) { return };
		dojo.html.addClass(this.domNode, "hover");
	},

	_onmouseout: function(e) {
		dojo.html.removeClass(this.domNode, "hover");
		dojo.html.removeClass(this.domNode, "down");
		if(!this._selected) {
			dojo.html.removeClass(this.domNode, "selected");
		}
	},

	_onclick: function(e) {
		// FIXME: buttons never seem to have this._enabled set to true on Opera 9
		// dojo.debug("widget:", this.widgetType, ":", this.getName(), ", enabled:", this._enabled);
		if(this._enabled && !this._toggleItem) {
			this._fireEvent("onClick");
		}
	},

	_onmousedown: function(e) {
		if(e.preventDefault) { e.preventDefault(); }
		if(!this._enabled) { return };
		dojo.html.addClass(this.domNode, "down");
		if(this._toggleItem) {
			if(this.parent.preventDeselect && this._selected) {
				return;
			}
			this.toggleSelected();
		}
	},

	_onmouseup: function(e) {
		dojo.html.removeClass(this.domNode, "down");
	},

	fillInTemplate: function(args, frag) {
		if(args.name) { this._name = args.name; }
		if(args.selected) { this.select(); }
		if(args.disabled) { this.disable(); }
		if(args.label) { this.setLabel(args.label); }
		if(args.icon) { this.setIcon(args.icon); }
		if(args.toggleitem||args.toggleItem) { this.setToggleItem(true); }
	}
});

dojo.widget.ToolbarItem.make = function(wh, whIsType, props) {
	var item = null;

	if(wh instanceof Array) {
		item = dojo.widget.createWidget("ToolbarButtonGroup", props);
		item.setName(wh[0]);
		for(var i = 1; i < wh.length; i++) {
			item.addChild(wh[i]);
		}
	} else if(wh instanceof dojo.widget.ToolbarItem) {
		item = wh;
	} else if(wh instanceof dojo.uri.Uri) {
		item = dojo.widget.createWidget("ToolbarButton",
			dojo.lang.mixin(props||{}, {icon: new dojo.widget.Icon(wh.toString())}));
	} else if(whIsType) {
		item = dojo.widget.createWidget(wh, props)
	} else if(typeof wh == "string" || wh instanceof String) {
		switch(wh.charAt(0)) {
			case "|":
			case "-":
			case "/":
				item = dojo.widget.createWidget("ToolbarSeparator", props);
				break;
			case " ":
				if(wh.length == 1) {
					item = dojo.widget.createWidget("ToolbarSpace", props);
				} else {
					item = dojo.widget.createWidget("ToolbarFlexibleSpace", props);
				}
				break;
			default:
				if(/\.(gif|jpg|jpeg|png)$/i.test(wh)) {
					item = dojo.widget.createWidget("ToolbarButton",
						dojo.lang.mixin(props||{}, {icon: new dojo.widget.Icon(wh.toString())}));
				} else {
					item = dojo.widget.createWidget("ToolbarButton",
						dojo.lang.mixin(props||{}, {label: wh.toString()}));
				}
		}
	} else if(wh && wh.tagName && /^img$/i.test(wh.tagName)) {
		item = dojo.widget.createWidget("ToolbarButton",
			dojo.lang.mixin(props||{}, {icon: wh}));
	} else {
		item = dojo.widget.createWidget("ToolbarButton",
			dojo.lang.mixin(props||{}, {label: wh.toString()}));
	}
	return item;
}

/* ToolbarButtonGroup
 *********************/
dojo.widget.tags.addParseTreeHandler("dojo:toolbarButtonGroup");
dojo.widget.html.ToolbarButtonGroup = function() {
	dojo.widget.ToolbarItem.call(this);
}
dojo.inherits(dojo.widget.html.ToolbarButtonGroup, dojo.widget.ToolbarItem);
dojo.lang.extend(dojo.widget.html.ToolbarButtonGroup, {
	widgetType: "ToolbarButtonGroup",
	isContainer: true,

	templateString: '<span unselectable="on" class="toolbarButtonGroup" dojoAttachPoint="containerNode"></span>',

	// if a button has the same name, it will be selected
	// if this is set to a number, the button at that index will be selected
	defaultButton: "",

    postCreate: function() {
        for (var i = 0; i < this.children.length; i++) {
            this._injectChild(this.children[i]);
        }
    },

	addChild: function(item, pos, props) {
		var widget = dojo.widget.ToolbarItem.make(item, null, dojo.lang.mixin(props||{}, {toggleItem:true}));
		var ret = dojo.widget.html.ToolbarButtonGroup.superclass.addChild.call(this, widget, null, pos, null);
        this._injectChild(widget);
        return ret;
    },

    _injectChild: function(widget) {
        dojo.event.connect(widget, "onSelect", this, "onChildSelected");
        dojo.event.connect(widget, "onDeselect", this, "onChildDeSelected");
        if(widget._name == this.defaultButton
			|| (typeof this.defaultButton == "number"
			&& this.children.length-1 == this.defaultButton)) {
			widget.select(false, true);
		}
	},

	getItem: function(name) {
		if(name instanceof dojo.widget.ToolbarItem) { return name; }
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.ToolbarItem
				&& child._name == name) { return child; }
		}
		return null;
	},

	getItems: function() {
		var items = [];
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.ToolbarItem) {
				items.push(child);
			}
		}
		return items;
	},

	onChildSelected: function(e) {
		this.select(e._name);
	},

	onChildDeSelected: function(e) {
		this._fireEvent("onChangeSelect", this._value);
	},

	enable: function(force, preventEvent) {
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.ToolbarItem) {
				child.enable(force, preventEvent);
				if(child._name == this._value) {
					child.select(force, preventEvent);
				}
			}
		}
	},

	disable: function(force, preventEvent) {
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.ToolbarItem) {
				child.disable(force, preventEvent);
			}
		}
	},

	_value: "",
	getValue: function() { return this._value; },

	select: function(name, force, preventEvent) {
		for(var i = 0; i < this.children.length; i++) {
			var child = this.children[i];
			if(child instanceof dojo.widget.ToolbarItem) {
				if(child._name == name) {
					child.select(force, preventEvent);
					this._value = name;
				} else {
					child.deselect(true, true);
				}
			}
		}
		if(!preventEvent) {
			this._fireEvent("onSelect", this._value);
			this._fireEvent("onChangeSelect", this._value);
		}
	},
	setValue: this.select,

	preventDeselect: false // if true, once you select one, you can't have none selected
});

/* ToolbarButton
 ***********************/
dojo.widget.tags.addParseTreeHandler("dojo:toolbarButton");
dojo.widget.html.ToolbarButton = function() {
	dojo.widget.ToolbarItem.call(this);
}
dojo.inherits(dojo.widget.html.ToolbarButton, dojo.widget.ToolbarItem);
dojo.lang.extend(dojo.widget.html.ToolbarButton, {
	widgetType: "ToolbarButton",

	fillInTemplate: function(args, frag) {
		dojo.widget.html.ToolbarButton.superclass.fillInTemplate.call(this, args, frag);
		dojo.html.addClass(this.domNode, "toolbarButton");
		if(this._icon) {
			this.setIcon(this._icon);
		}
		if(this._label) {
			this.setLabel(this._label);
		}

		if(!this._name) {
			if(this._label) {
				this.setName(this._label);
			} else if(this._icon) {
				var src = this._icon.getSrc("enabled").match(/[\/^]([^\.\/]+)\.(gif|jpg|jpeg|png)$/i);
				if(src) { this.setName(src[1]); }
			} else {
				this._name = this._widgetId;
			}
		}
	}
});

/* ToolbarDialog
 **********************/
dojo.widget.tags.addParseTreeHandler("dojo:toolbarDialog");
dojo.widget.html.ToolbarDialog = function() {
	dojo.widget.html.ToolbarButton.call(this);
}
dojo.inherits(dojo.widget.html.ToolbarDialog, dojo.widget.html.ToolbarButton);
dojo.lang.extend(dojo.widget.html.ToolbarDialog, {
	widgetType: "ToolbarDialog",
	
	fillInTemplate: function (args, frag) {
		dojo.widget.html.ToolbarDialog.superclass.fillInTemplate.call(this, args, frag);
		dojo.event.connect(this, "onSelect", this, "showDialog");
		dojo.event.connect(this, "onDeselect", this, "hideDialog");
	},
	
	showDialog: function (e) {
		dojo.lang.setTimeout(dojo.event.connect, 1, document, "onmousedown", this, "deselect");
	},
	
	hideDialog: function (e) {
		dojo.event.disconnect(document, "onmousedown", this, "deselect");
	}

});

/* ToolbarMenu
 **********************/
dojo.widget.tags.addParseTreeHandler("dojo:toolbarMenu");
dojo.widget.html.ToolbarMenu = function() {
	dojo.widget.html.ToolbarDialog.call(this);

	this.widgetType = "ToolbarMenu";
}
dojo.inherits(dojo.widget.html.ToolbarMenu, dojo.widget.html.ToolbarDialog);

/* ToolbarMenuItem
 ******************/
dojo.widget.ToolbarMenuItem = function() {
}

/* ToolbarSeparator
 **********************/
dojo.widget.tags.addParseTreeHandler("dojo:toolbarSeparator");
dojo.widget.html.ToolbarSeparator = function() {
    dojo.widget.ToolbarItem.call(this);
}
dojo.inherits(dojo.widget.html.ToolbarSeparator, dojo.widget.ToolbarItem);
dojo.lang.extend(dojo.widget.html.ToolbarSeparator, {
	widgetType: "ToolbarSeparator",
	templateString: '<span unselectable="on" class="toolbarItem toolbarSeparator"></span>',

	defaultIconPath: new dojo.uri.dojoUri("src/widget/templates/buttons/-.gif"),

	fillInTemplate: function(args, frag, skip) {
		dojo.widget.html.ToolbarSeparator.superclass.fillInTemplate.call(this, args, frag);
		this._name = this.widgetId;
		if(!skip) {
			if(!this._icon) {
				this.setIcon(this.defaultIconPath);
			}
			this.domNode.appendChild(this._icon.getNode());
		}
	},

	// don't want events!
	_onmouseover: null, 
    _onmouseout: null, 
    _onclick: null, 
    _onmousedown: null, 
    _onmouseup: null 
});

/* ToolbarSpace
 **********************/
dojo.widget.tags.addParseTreeHandler("dojo:toolbarSpace");
dojo.widget.html.ToolbarSpace = function() {
	dojo.widget.html.ToolbarSeparator.call(this);
}
dojo.inherits(dojo.widget.html.ToolbarSpace, dojo.widget.html.ToolbarSeparator);
dojo.lang.extend(dojo.widget.html.ToolbarSpace, {
    widgetType: "ToolbarSpace",

	fillInTemplate: function(args, frag, skip) {
		dojo.widget.html.ToolbarSpace.superclass.fillInTemplate.call(this, args, frag, true);
		if(!skip) {
			dojo.html.addClass(this.domNode, "toolbarSpace");
		}
	}
});

/* ToolbarSelect
 ******************/ 

dojo.widget.tags.addParseTreeHandler("dojo:toolbarSelect");
dojo.widget.html.ToolbarSelect = function() {
	dojo.widget.ToolbarItem.call(this);
}
dojo.inherits(dojo.widget.html.ToolbarSelect, dojo.widget.ToolbarItem);
dojo.lang.extend(dojo.widget.html.ToolbarSelect, {
    widgetType: "ToolbarSelect",
	templateString: '<span class="toolbarItem toolbarSelect" unselectable="on"><select dojoAttachPoint="selectBox" dojoOnChange="changed"></select></span>',

	fillInTemplate: function(args, frag) {
		dojo.widget.html.ToolbarSelect.superclass.fillInTemplate.call(this, args, frag, true);
		var keys = args.values;
		var i = 0;
		for(var val in keys) {
			var opt = document.createElement("option");
			opt.setAttribute("value", keys[val]);
			opt.innerHTML = val;
			this.selectBox.appendChild(opt);
		}
	},

	changed: function(e) {
		this._fireEvent("onSetValue", this.selectBox.value);
	},

	setEnabled: function(is, force, preventEvent) {
		var ret = dojo.widget.html.ToolbarSelect.superclass.setEnabled.call(this, is, force, preventEvent);
		this.selectBox.disabled = !this._enabled;
		return ret;
	},

	// don't want events!
	_onmouseover: null,
    _onmouseout: null,
    _onclick: null,
    _onmousedown: null,
    _onmouseup: null
});

/* Icon
 *********/
// arguments can be IMG nodes, Image() instances or URLs -- enabled is the only one required
dojo.widget.Icon = function(enabled, disabled, hover, selected){
	if(!arguments.length){
		// FIXME: should this be dojo.raise?
		throw new Error("Icon must have at least an enabled state");
	}
	var states = ["enabled", "disabled", "hover", "selected"];
	var currentState = "enabled";
	var domNode = document.createElement("img");

	this.getState = function(){ return currentState; }
	this.setState = function(value){
		if(dojo.lang.inArray(value, states)){
			if(this[value]){
				currentState = value;
				domNode.setAttribute("src", this[currentState].src);
			}
		}else{
			throw new Error("Invalid state set on Icon (state: " + value + ")");
		}
	}

	this.setSrc = function(state, value){
		if(/^img$/i.test(value.tagName)){
			this[state] = value;
		}else if(typeof value == "string" || value instanceof String
			|| value instanceof dojo.uri.Uri){
			this[state] = new Image();
			this[state].src = value.toString();
		}
		return this[state];
	}

	this.setIcon = function(icon){
		for(var i = 0; i < states.length; i++){
			if(icon[states[i]]){
				this.setSrc(states[i], icon[states[i]]);
			}
		}
		this.update();
	}

	this.enable = function(){ this.setState("enabled"); }
	this.disable = function(){ this.setState("disabled"); }
	this.hover = function(){ this.setState("hover"); }
	this.select = function(){ this.setState("selected"); }

	this.getSize = function(){
		return {
			width: domNode.width||domNode.offsetWidth,
			height: domNode.height||domNode.offsetHeight
		};
	}

	this.setSize = function(w, h){
		domNode.width = w;
		domNode.height = h;
		return { width: w, height: h };
	}

	this.getNode = function(){
		return domNode;
	}

	this.getSrc = function(state){
		if(state){ return this[state].src; }
		return domNode.src||"";
	}

	this.update = function(){
		this.setState(currentState);
	}

	for(var i = 0; i < states.length; i++){
		var arg = arguments[i];
		var state = states[i];
		this[state] = null;
		if(!arg){ continue; }
		this.setSrc(state, arg);
	}

	this.enable();
}

dojo.widget.Icon.make = function(a,b,c,d){
	for(var i = 0; i < arguments.length; i++){
		if(arguments[i] instanceof dojo.widget.Icon){
			return arguments[i];
		}
	}

	return new dojo.widget.Icon(a,b,c,d);
}

__CPAN_FILE__ src/widget/Menu.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.Menu");
dojo.provide("dojo.widget.DomMenu");

dojo.deprecated("dojo.widget.Menu, dojo.widget.DomMenu",  "use dojo.widget.Menu2", "0.4");

dojo.require("dojo.widget.*");

dojo.widget.tags.addParseTreeHandler("dojo:menu");

/* Menu
 *******/

dojo.widget.Menu = function () {
	dojo.widget.Menu.superclass.constructor.call(this);
}
dojo.inherits(dojo.widget.Menu, dojo.widget.Widget);

dojo.lang.extend(dojo.widget.Menu, {
	widgetType: "Menu",
	isContainer: true,
	
	items: [],
	push: function(item){
		dojo.connect.event(item, "onSelect", this, "onSelect");
		this.items.push(item);
	},
	onSelect: function(){}
});


/* DomMenu
 **********/

dojo.widget.DomMenu = function(){
	dojo.widget.DomMenu.superclass.constructor.call(this);
}
dojo.inherits(dojo.widget.DomMenu, dojo.widget.DomWidget);

dojo.lang.extend(dojo.widget.DomMenu, {
	widgetType: "Menu",
	isContainer: true,

	push: function (item) {
		dojo.widget.Menu.call(this, item);
		this.domNode.appendChild(item.domNode);
	}
});

dojo.requireAfterIf("html", "dojo.widget.html.Menu");

__CPAN_FILE__ src/widget/DropdownButton.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.DropdownButton");

dojo.deprecated("dojo.widget.DropdownButton",  "use dojo.widget.ComboButton", "0.4");

// Draws a button with a down arrow;
// when you press the down arrow something appears (usually a menu)

dojo.require("dojo.widget.*");

dojo.widget.tags.addParseTreeHandler("dojo:dropdownbutton");

dojo.widget.DropdownButton = function(){
	dojo.widget.Widget.call(this);

	this.widgetType = "DropdownButton";
}
dojo.inherits(dojo.widget.DropdownButton, dojo.widget.Widget);

dojo.requireAfterIf("html", "dojo.widget.html.DropdownButton");

__CPAN_FILE__ src/widget/SvgButton.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

// FIXME: not yet functional

dojo.provide("dojo.widget.SvgButton");

dojo.require("dojo.widget.Button");

dojo.widget.SvgButton = function(){
	// FIXME: this is incomplete and doesn't work yet
	// if DOMButton turns into a mixin, we should subclass Button instead and
	// just mix in the DOMButton properties.

	dojo.widget.DomButton.call(this);
	dojo.widget.SvgWidget.call(this);

	// FIXME: freaking implement this already!
	this.onFoo = function(){ alert("bar"); }

	this.label = "huzzah!";

	this.setLabel = function(x, y, textSize, label, shape){
		//var labelNode = this.domNode.ownerDocument.createTextNode(this.label);
		//var textNode = this.domNode.ownerDocument.createElement("text");
		var coords = dojo.widget.SvgButton.prototype.coordinates(x, y, textSize, label, shape);
		var textString = "";
		switch(shape) {
			case "ellipse":
				textString = "<text x='"+ coords[6] + "' y='"+ coords[7] + "'>"+ label + "</text>";
				//textNode.setAttribute("x", coords[6]);
				//textNode.setAttribute("y", coords[7]);
				break;
			case "rectangle":
				//FIXME: implement
				textString = "";
				//textNode.setAttribute("x", coords[6]);
				//textNode.setAttribute("y", coords[7]);
				break;
			case "circle":
				//FIXME: implement
				textString = "";
				//textNode.setAttribute("x", coords[6]);
				//textNode.setAttribute("y", coords[7]);
				break;
		}
		//textNode.appendChild(labelNode);
		//this.domNode.appendChild(textNode);
		return textString;
		//alert(textNode.getComputedTextLength());
	}

	this.fillInTemplate = function(x, y, textSize, label, shape){
		// the idea is to set the text to the appropriate place given its length
		// and the template shape
		
		// FIXME: For now, assuming text sizes are integers in SVG units
		this.textSize = textSize || 12;
		this.label = label;
		// FIXEME: for now, I'm going to fake this... need to come up with a real way to 
		// determine the actual width of the text, such as computedStyle
		var textWidth = this.label.length*this.textSize ;
		//this.setLabel();
	}
}

dojo.inherits(dojo.widget.SvgButton, dojo.widget.DomButton);

// FIXME
dojo.widget.SvgButton.prototype.shapeString = function(x, y, textSize, label, shape) {
	switch(shape) {
		case "ellipse":
			var coords = dojo.widget.SvgButton.prototype.coordinates(x, y, textSize, label, shape)
			return "<ellipse cx='"+ coords[4]+"' cy='"+ coords[5]+"' rx='"+ coords[2]+"' ry='"+ coords[3]+"'/>";
			break;
		case "rect":
			//FIXME: implement
			return "";
			//return "<rect x='110' y='45' width='70' height='30'/>";
			break;
		case "circle":
			//FIXME: implement
			return "";
			//return "<circle cx='210' cy='60' r='23'/>";
			break;
	}
}

dojo.widget.SvgButton.prototype.coordinates = function(x, y, textSize, label, shape) {
	switch(shape) {
		case "ellipse":
			var buttonWidth = label.length*textSize;
			var buttonHeight = textSize*2.5
			var rx = buttonWidth/2;
			var ry = buttonHeight/2;
			var cx = rx + x;
			var cy = ry + y;
			var textX = cx - rx*textSize/25;
			var textY = cy*1.1;
			return [buttonWidth, buttonHeight, rx, ry, cx, cy, textX, textY];
			break;
		case "rectangle":
			//FIXME: implement
			return "";
			break;
		case "circle":
			//FIXME: implement
			return "";
			break;
	}
}

dojo.widget.SvgButton.prototype.labelString = function(x, y, textSize, label, shape){
	var textString = "";
	var coords = dojo.widget.SvgButton.prototype.coordinates(x, y, textSize, label, shape);
	switch(shape) {
		case "ellipse":
			textString = "<text x='"+ coords[6] + "' y='"+ coords[7] + "'>"+ label + "</text>";
			break;
		case "rectangle":
			//FIXME: implement
			textString = "";
			break;
		case "circle":
			//FIXME: implement
			textString = "";
			break;
	}
	return textString;
}

dojo.widget.SvgButton.prototype.templateString = function(x, y, textSize, label, shape) {
	return "<g class='dojoButton' dojoAttachEvent='onClick; onMouseMove: onFoo;' dojoAttachPoint='labelNode'>"+ dojo.widgets.SVGButton.prototype.shapeString(x, y, textSize, label, shape) + dojo.widget.SVGButton.prototype.labelString(x, y, textSize, label, shape) + "</g>";
}

__CPAN_FILE__ src/widget/TimePicker.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.TimePicker");
dojo.provide("dojo.widget.TimePicker.util");
dojo.require("dojo.widget.DomWidget");
dojo.require("dojo.date");

dojo.widget.TimePicker = function(){
	dojo.widget.Widget.call(this);
	this.widgetType = "TimePicker";
	this.isContainer = false;
	// the following aliases prevent breaking people using 0.2.x
	this.toRfcDateTime = dojo.widget.TimePicker.util.toRfcDateTime;
	this.fromRfcDateTime = dojo.widget.TimePicker.util.fromRfcDateTime;
	this.toAmPmHour = dojo.widget.TimePicker.util.toAmPmHour;
	this.fromAmPmHour = dojo.widget.TimePicker.util.fromAmPmHour;
}

dojo.inherits(dojo.widget.TimePicker, dojo.widget.Widget);
dojo.widget.tags.addParseTreeHandler("dojo:timepicker");

dojo.requireAfterIf("html", "dojo.widget.html.TimePicker");

dojo.widget.TimePicker.util = new function() {
	// utility functions
	this.toRfcDateTime = function(jsDate) {
		if(!jsDate) {
			jsDate = new Date();
		}
		return dojo.date.format(jsDate, "%Y-%m-%dT%H:%M:00%z");
	}

	this.fromRfcDateTime = function(rfcDate, useDefaultMinutes, isAnyTime) {
		var tempDate = new Date();
		if(!rfcDate || rfcDate.indexOf("T")==-1) {
			if(useDefaultMinutes) {
				tempDate.setMinutes(Math.floor(tempDate.getMinutes()/5)*5);
			} else {
				tempDate.setMinutes(0);
			}
		} else {
			var tempTime = rfcDate.split("T")[1].split(":");
			// fullYear, month, date
			var tempDate = new Date();
			tempDate.setHours(tempTime[0]);
			tempDate.setMinutes(tempTime[1]);
		}
		return tempDate;
	}

	this.toAmPmHour = function(hour) {
		var amPmHour = hour;
		var isAm = true;
		if (amPmHour == 0) {
			amPmHour = 12;
		} else if (amPmHour>12) {
			amPmHour = amPmHour - 12;
			isAm = false;
		} else if (amPmHour == 12) {
			isAm = false;
		}
		return [amPmHour, isAm];
	}

	this.fromAmPmHour = function(amPmHour, isAm) {
		var hour = parseInt(amPmHour, 10);
		if(isAm && hour == 12) {
			hour = 0;
		} else if (!isAm && hour<12) {
			hour = hour + 12;
		}
		return hour;
	}
}

__CPAN_FILE__ src/widget/SlideShow.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.SlideShow");
dojo.provide("dojo.widget.html.SlideShow");

dojo.require("dojo.event");
dojo.require("dojo.widget.*");
dojo.require("dojo.lfx.*");
dojo.require("dojo.style");

dojo.widget.defineWidget(
	"dojo.widget.html.SlideShow",
	dojo.widget.HtmlWidget,
	{
		templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlSlideShow.html"),
		templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlSlideShow.css"),

		// over-ride some defaults
		isContainer: false,
		widgetType: "SlideShow",

		// useful properties
		imgUrls: [],		// the images we'll go through
		imgUrlBase: "",
		urlsIdx: 0,		// where in the images we are
		delay: 4000, 		// give it 4 seconds
		transitionInterval: 2000, // 2 seconds
		imgWidth: 800,	// img width
		imgHeight: 600,	// img height
		background: "img2", // what's in the bg
		foreground: "img1", // what's in the fg
		stopped: false,	// should I stay or should I go?
		fadeAnim: null, // references our animation

		// our DOM nodes:
		imagesContainer: null,
		startStopButton: null,
		controlsContainer: null,
		img1: null,
		img2: null,

		fillInTemplate: function(){
			dojo.style.setOpacity(this.img1, 0.9999);
			dojo.style.setOpacity(this.img2, 0.9999);
			with(this.imagesContainer.style){
				width = this.imgWidth+"px";
				height = this.imgHeight+"px";
			}
			with(this.img1.style){
				width = this.imgWidth+"px";
				height = this.imgHeight+"px";
			}
			with(this.img2.style){
				width = this.imgWidth+"px";
				height = this.imgHeight+"px";
			}
			if(this.imgUrls.length>1){
				this.img2.src = this.imgUrlBase+this.imgUrls[this.urlsIdx++];
				this.endTransition();
			}else{
				this.img1.src = this.imgUrlBase+this.imgUrls[this.urlsIdx++];
			}
		},

		togglePaused: function(){
			if(this.stopped){
				this.stopped = false;
				this.backgroundImageLoaded();
				this.startStopButton.value= "pause";
			}else{
				this.stopped = true;
				this.startStopButton.value= "play";
			}
		},

		backgroundImageLoaded: function(){
			// start fading out the foreground image
			if(this.stopped){ return; }

			// actually start the fadeOut effect
			// NOTE: if we wanted to use other transition types, we'd set them up
			// 		 here as well
			if(this.fadeAnim) {
				this.fadeAnim.stop();
			}
			this.fadeAnim = dojo.lfx.fadeOut(this[this.foreground], 
				this.transitionInterval, null);
			dojo.event.connect(this.fadeAnim,"onEnd",this,"endTransition");
			this.fadeAnim.play();
		},

		endTransition: function(){
			// move the foreground image to the background 
			with(this[this.background].style){ zIndex = parseInt(zIndex)+1; }
			with(this[this.foreground].style){ zIndex = parseInt(zIndex)-1; }

			// fg/bg book-keeping
			var tmp = this.foreground;
			this.foreground = this.background;
			this.background = tmp;

			// keep on truckin
			this.loadNextImage();
		},

		loadNextImage: function(){
			// load a new image in that container, and make sure it informs
			// us when it finishes loading
			dojo.event.kwConnect({
				srcObj: this[this.background],
				srcFunc: "onload",
				adviceObj: this,
				adviceFunc: "backgroundImageLoaded",
				once: true, // make sure we only ever hear about it once
				delay: this.delay
			});
			dojo.style.setOpacity(this[this.background], 1.0);
			this[this.background].src = this.imgUrlBase+this.imgUrls[this.urlsIdx++];
			if(this.urlsIdx>(this.imgUrls.length-1)){
				this.urlsIdx = 0;
			}
		}
	}
);

__CPAN_FILE__ src/widget/SwtWidget.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.SwtWidget");

dojo.require("dojo.event.*");
dojo.require("dojo.widget.Widget");
dojo.require("dojo.uri.*");
dojo.require("dojo.lang.func");
dojo.require("dojo.lang.extras");

try{
	importPackage(Packages.org.eclipse.swt.widgets);

	dojo.declare("dojo.widget.SwtWidget", dojo.widget.Widget, {
		initializer: function() {
			if((arguments.length>0)&&(typeof arguments[0] == "object")){
				this.create(arguments[0]);
			}
		},

		display: null,
		shell: null,

		show: function(){ },
		hide: function(){ },

		addChild: function(){ },
		registerChild: function(){ },
		addWidgetAsDirectChild: function(){ },
		removeChild: function(){ },
		cleanUp: function(){ },
		destroyRendering: function(){ },
		postInitialize: function(){ },
	});

	// initialize SWT runtime

	dojo.widget.SwtWidget.prototype.display = new Display();
	dojo.widget.SwtWidget.prototype.shell = new Shell(dojo.widget.SwtWidget.prototype.display);

	dojo.widget.manager.startShell = function(){
		var sh = dojo.widget.SwtWidget.prototype.shell;
		var d = dojo.widget.SwtWidget.prototype.display;
		sh.open();
		while(!sh.isDisposed()){
			dojo.widget.manager.doNext();
			if(!d.readAndDispatch()){
				d.sleep();
			}
		}
		d.dispose();
	};
}catch(e){
	// seems we didn't have the SWT classes in the environment. Log it.
	dojo.debug("dojo.widget.SwtWidget not loaded. SWT classes not available");
}

__CPAN_DIR__ src/widget/html
__CPAN_FILE__ src/widget/html/Tooltip.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.Tooltip");
dojo.require("dojo.widget.html.ContentPane");
dojo.require("dojo.widget.Tooltip");
dojo.require("dojo.uri");
dojo.require("dojo.widget.*");
dojo.require("dojo.event");
dojo.require("dojo.style");
dojo.require("dojo.html");

dojo.widget.defineWidget(
	"dojo.widget.html.Tooltip",
	dojo.widget.html.ContentPane,
	{
		widgetType: "Tooltip",
		isContainer: true,
	
		// Constructor arguments
		caption: "",
		showDelay: 500,
		hideDelay: 100,
		connectId: "",
	
		templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlTooltipTemplate.html"),
		templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlTooltipTemplate.css"),
	
		connectNode: null,
	
		// Tooltip has the following possible states:
		//   erased - nothing on screen
		//   displaying - currently being faded in (partially displayed)
		//   displayed - fully displayed
		//   erasing - currently being faded out (partially erased)
		state: "erased",
	
		fillInTemplate: function(args, frag){
			if(this.caption != ""){
				this.domNode.appendChild(document.createTextNode(this.caption));
			}
			this.connectNode = dojo.byId(this.connectId);		
			dojo.widget.html.Tooltip.superclass.fillInTemplate.call(this, args, frag);
		},
		
		postCreate: function(args, frag){
			// The domnode was appended to my parent widget's domnode, but the positioning
			// only works if the domnode is a child of document.body
			document.body.appendChild(this.domNode);
	
			dojo.event.connect(this.connectNode, "onmouseover", this, "onMouseOver");
			dojo.widget.html.Tooltip.superclass.postCreate.call(this, args, frag);
		},
		
		onMouseOver: function(e) {
			this.mouse = {x: e.pageX, y: e.pageY};
	
			if(!this.showTimer){
				this.showTimer = setTimeout(dojo.lang.hitch(this, "show"), this.showDelay);
				dojo.event.connect(document.documentElement, "onmousemove", this, "onMouseMove");
			}
		},
	
		onMouseMove: function(e) {
			this.mouse = {x: e.pageX, y: e.pageY};
	
			if(dojo.html.overElement(this.connectNode, e) || dojo.html.overElement(this.domNode, e)) {
				// If the tooltip has been scheduled to be erased, cancel that timer
				// since we are hovering over element/tooltip again
				if(this.hideTimer) {
					clearTimeout(this.hideTimer);
					delete this.hideTimer;
				}
			} else {
				// mouse has been moved off the element/tooltip
				// note: can't use onMouseOut to detect this because the "explode" effect causes
				// spurious onMouseOut/onMouseOver events (due to interference from outline)
				if(this.showTimer){
					clearTimeout(this.showTimer);
					delete this.showTimer;
				}
				if((this.state=="displaying"||this.state=="displayed") && !this.hideTimer){
					this.hideTimer = setTimeout(dojo.lang.hitch(this, "hide"), this.hideDelay);
				}
			}
		},
	
		show: function() {
			if(this.state=="erasing"){
				// we are in the process of erasing; when that is finished, display it.
				this.displayScheduled=true;
				return;
			}
			if ( this.state=="displaying" || this.state=="displayed" ) { return; }
	
			// prevent IE bleed through (iframe creation is deferred until first show()
			// call because apparently it takes a long time)
			if(!this.bgIframe){
				this.bgIframe = new dojo.html.BackgroundIframe(this.domNode);
			}
	
			this.position();
	
			// if rendering using explosion effect, need to set explosion source
			this.explodeSrc = [this.mouse.x, this.mouse.y];
	
			this.state="displaying";
	
			dojo.widget.html.Tooltip.superclass.show.call(this);
		},
	
		onShow: function() {
			dojo.widget.html.Tooltip.superclass.onShow.call(this);
			
			this.state="displayed";
			
			// in the corner case where the user has moved his mouse away
			// while the tip was fading in
			if(this.eraseScheduled){
				this.hide();
				this.eraseScheduled=false;
			}
		},
	
		hide: function() {
			if(this.state=="displaying"){
				// in the process of fading in.  wait until that is finished and then fade out
				this.eraseScheduled=true;
				return;
			}
			if ( this.state=="displayed" ) {
				this.state="erasing";
				if ( this.showTimer ) {
					clearTimeout(this.showTimer);
					delete this.showTimer;
				}
				if ( this.hideTimer ) {
					clearTimeout(this.hideTimer);
					delete this.hideTimer;
				}
				dojo.event.disconnect(document.documentElement, "onmousemove", this, "onMouseMove");
				dojo.widget.html.Tooltip.superclass.hide.call(this);
			}
		},
	
		onHide: function(){
			this.state="erased";
	
			// in the corner case where the user has moved his mouse back
			// while the tip was fading out
			if(this.displayScheduled){
				this.display();
				this.displayScheduled=false;
			}
		},
	
		position: function(){
			dojo.html.placeOnScreenPoint(this.domNode, this.mouse.x, this.mouse.y, [10,15], true);
			this.bgIframe.onResized();
		},
	
		onLoad: function(){
			if(this.isShowing()){
				// the tooltip has changed size due to downloaded contents, so reposition it
				dojo.lang.setTimeout(this, this.position, 50);
				dojo.widget.html.Tooltip.superclass.onLoad.apply(this, arguments);
			}
		},
	
		checkSize: function() {
			// checkSize() is called when the user has resized the browser window,
			// but that doesn't affect this widget (or this widget's children)
			// so it can be safely ignored
		}
	}
);

__CPAN_FILE__ src/widget/html/ContentPane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.ContentPane");

dojo.require("dojo.widget.*");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.ContentPane");
dojo.require("dojo.string");
dojo.require("dojo.string.extras");
dojo.require("dojo.style");

dojo.widget.html.ContentPane = function(){
	this._onLoadStack = [];
	this._onUnLoadStack = [];
	dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.ContentPane, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.ContentPane, {
	widgetType: "ContentPane",
	isContainer: true,

	// remote loading options
	adjustPaths: true,
	href: "",
	extractContent: true,
	parseContent: true,
	cacheContent: true,
	preload: false,			// force load of data even if pane is hidden
	refreshOnShow: false,
	handler: "",			// generate pane content from a java function
	executeScripts: false,	// if true scripts in content will be evaled after content is set and parsed
	scriptScope: null,		// scopeContainer for downloaded scripts

		// If the user want a global in the remote script he/she just omitts the var
		// examples:
		//--------------------------
		// these gets collected by scriptScope and is reached by dojo.widget.byId('..').scriptScope.myCustomproperty
		//	this.myString = "dojo is a great javascript toolkit!";
		//
		//	this.alertMyString = function(){
		//		alert(myString);
		//	}
		// -------------------------
		// these go into the global namespace (window) notice lack of var, equiv to window.myString
		//	myString = "dojo is a javascript toolkit!";
		//
		//	alertMyString = function(){
		//		alert(myString);
		// }


	// private
	_remoteStyles: null,	// array of stylenodes inserted to document head
							// by remote content, used when we clean up for new content

	_callOnUnLoad: false,		// used by setContent and _handleDefults, makes sure onUnLoad is only called once

	postCreate: function(args, frag, parentComp){
		if ( this.handler != "" ){
			this.setHandler(this.handler);
		}
		if(this.isShowing()||this.preload){ this.loadContents(); }
	},

	show: function(){
		// if refreshOnShow is true, reload the contents every time; otherwise, load only the first time
		if(this.refreshOnShow){
			this.refresh();
		}else{
			this.loadContents();
		}
		dojo.widget.html.ContentPane.superclass.show.call(this);
	},

	refresh: function(){
		this.isLoaded=false;
		this.loadContents();
	},

	loadContents: function() {
		if ( this.isLoaded ){
			return;
		}
		this.isLoaded=true;
		if ( dojo.lang.isFunction(this.handler)) {
			this._runHandler();
		} else if ( this.href != "" ) {
			this._downloadExternalContent(this.href, this.cacheContent);
		}
	},

	
	setUrl: function(/*String*/ url) {
		// summary:
		// 	Reset the (external defined) content of this pane and replace with new url
		this.href = url;
		this.isLoaded = false;
		if ( this.preload || this.isShowing() ){
			this.loadContents();
		}
	},

	_downloadExternalContent: function(url, useCache) {
		this._handleDefaults("Loading...", "onDownloadStart");
		var self = this;
		dojo.io.bind({
			url: url,
			useCache: useCache,
			preventCache: !useCache,
			mimetype: "text/html",
			handler: function(type, data, e) {
				if(type == "load") {
					self.onDownloadEnd.call(self, url, data);
				} else {
					// works best when from a live server instead of from file system 
					self._handleDefaults.call(self, "Error loading '" + url + "' (" + e.status + " "+  e.statusText + ")", "onDownloadError");
					self.onLoad();
				}
			}
		});
	},

	// called when setContent is finished
	onLoad: function(e){
		this._runStack("_onLoadStack");
	},

	// called before old content is cleared
	onUnLoad: function(e){
		this._runStack("_onUnLoadStack");
		this.scriptScope = null;
	},

	_runStack: function(stName){
		var st = this[stName]; var err = "";
		for(var i = 0;i < st.length; i++){
			try{
				st[i].call(this.scriptScope);
			}catch(e){ 
				err += "\n"+st[i]+" failed: "+e.description;
			}
		}
		this[stName] = [];

		if(err.length){
			var name = (stName== "_onLoadStack") ? "addOnLoad" : "addOnUnLoad";
			this._handleDefaults(name+" failure\n "+err, "onExecError", true);
		}
	},

	addOnLoad: function(obj, func){
		// summary
		// 	same as to dojo.addOnLoad but does not take "function_name" as a string
		this._pushOnStack(this._onLoadStack, obj, func);
	},

	addOnUnLoad: function(obj, func){
		// summary
		// 	same as to dojo.addUnOnLoad but does not take "function_name" as a string
		this._pushOnStack(this._onUnLoadStack, obj, func);
	},

	_pushOnStack: function(stack, obj, func){
		if(typeof func == 'undefined') {
			stack.push(obj);
		}else{
			stack.push(function(){ obj[func](); });
		}
	},

	destroy: function(){
		// make sure we call onUnLoad
		this.onUnLoad();
		dojo.widget.html.ContentPane.superclass.destroy.call(this);
	},

	// called when content script eval error or Java error occurs, preventDefault-able
	onExecError: function(e){ /*stub*/ },

	// called on DOM faults, require fault etc in content, preventDefault-able
	onContentError: function(e){ /*stub*/ },

	// called when download error occurs, preventDefault-able
	onDownloadError: function(e){ /*stub*/ },

	// called before download starts, preventDefault-able
	onDownloadStart: function(e){ /*stub*/ },

	// called when download is finished
	onDownloadEnd: function(url, data){
		data = this.splitAndFixPaths(data, url);
		this.setContent(data);
	},

	// usefull if user wants to prevent default behaviour ie: _setContent("Error...")
	_handleDefaults: function(e, handler, useAlert){
		if(!handler){ handler = "onContentError"; }
		if(dojo.lang.isString(e)){
			e = {
				"text": e,
				"toString": function(){ return this.text; }
			}
		}
		if(typeof e.returnValue != "boolean"){
			e.returnValue = true; 
		}
		if(typeof e.preventDefault != "function"){
			e.preventDefault = function(){
				this.returnValue = false;
			}
		}
		// call our handler
		this[handler](e);
		if(e.returnValue){
			if(useAlert){
				alert(e.toString());
			}else{
				if(this._callOnUnLoad){
					this.onUnLoad(); // makes sure scripts can clean up after themselves, before we setContent
				}
				this._callOnUnLoad = false; // makes sure we dont try to call onUnLoad again on this event,
											// ie onUnLoad before 'Loading...' but not before clearing 'Loading...'
				this._setContent(e.toString());
			}
		}
	},

	
	splitAndFixPaths: function(/*String*/s, /*dojo.uri.Uri?*/url){
		// summary:
		// 	fixes all remote paths in (hopefully) all cases for example images, remote scripts, links etc.
		// 	splits up content in different pieces, scripts, title, style, link and whats left becomes .xml

		if(!url) { url = "./"; } // point to this page if not set
		if(!s) { return ""; }

		// fix up paths in data
		var titles = []; var scripts = []; var linkStyles = [];
		var styles = []; var remoteScripts = []; var requires = [];

		// khtml is much more picky about dom faults, you can't for example attach a style node under body of document
		// must go into head, as does a title node, so we need to cut out those tags
		// cut out title tags
		var match = [];
		while(match){
			match = s.match(/<title[^>]*>([\s\S]*?)<\/title>/i); // can't match with dot as that 
			if(!match){ break;}					//doesnt match newline in js
			titles.push(match[1]);
			s = s.replace(/<title[^>]*>[\s\S]*?<\/title>/i, "");
		}

		// cut out <style> url(...) </style>, as that bails out in khtml
		var match = [];
		while(match){
			match = s.match(/<style[^>]*>([\s\S]*?)<\/style>/i);
			if(!match){ break; }
			styles.push(dojo.style.fixPathsInCssText(match[1], url));
			s = s.replace(/<style[^>]*?>[\s\S]*?<\/style>/i, "");
		}

		// attributepaths one tag can have multiple paths example:
		// <input src="..." style="url(..)"/> or <a style="url(..)" href="..">
		// strip out the tag and run fix on that.
		// this guarantees that we won't run replace another tag's attribute + it was easier do
		var pos = 0; var pos2 = 0; var stop = 0 ;var str = ""; var fixedPath = "";
		var attr = []; var fix = ""; var tagFix = ""; var tag = ""; var regex = ""; 
		while(pos>-1){
			pos = s.search(/<[a-z][a-z0-9]*[^>]*\s(?:(?:src|href|style)=[^>])+[^>]*>/i);
			if(pos==-1){ break; }
			str += s.substring(0, pos);
			s = s.substring(pos, s.length);
			tag = s.match(/^<[a-z][a-z0-9]*[^>]*>/i)[0];
			s = s.substring(tag.length, s.length);

			// loop through attributes
			pos2 = 0; tagFix = ""; fix = ""; regex = ""; var regexlen = 0;
			while(pos2!=-1){
				// slices up before next attribute check, values from previous loop
				tagFix += tag.substring(0, pos2) + fix;
				tag = tag.substring(pos2+regexlen, tag.length);

				// fix next attribute or bail out when done
				// hopefully this charclass covers most urls
				attr = tag.match(/ (src|href|style)=(['"]?)([\w()\[\]\/.,\\'"-:;#=&?\s@]+?)\2/i);
				if(!attr){ break; }

				switch(attr[1].toLowerCase()){
					case "src":// falltrough
					case "href":
						// this hopefully covers most common protocols
						if(attr[3].search(/^(?:[#]|(?:(?:https?|ftps?|file|javascript|mailto|news):))/)==-1){
							fixedPath = (new dojo.uri.Uri(url, attr[3]).toString());
						} else {
							pos2 = pos2 + attr[3].length;
							continue;
						}
						break;
					case "style":// style
						fixedPath = dojo.style.fixPathsInCssText(attr[3], url);
						break;
					default:
						pos2 = pos2 + attr[3].length;
						continue;
				}

				regex = " " + attr[1] + "=" + attr[2] + attr[3] + attr[2];
				regexlen = regex.length;
				fix = " " + attr[1] + "=" + attr[2] + fixedPath + attr[2];
				pos2 = tag.search(new RegExp(dojo.string.escapeRegExp(regex)));
			}
			str += tagFix + tag;
			pos = 0; // reset for next mainloop
		}
		s = str+s;

		// cut out all script tags, push them into scripts array
		match = []; var tmp = [];
		while(match){
			match = s.match(/<script([^>]*)>([\s\S]*?)<\/script>/i);
			if(!match){ break; }
			if(match[1]){
				attr = match[1].match(/src=(['"]?)([^"']*)\1/i);
				if(attr){
					// remove a dojo.js or dojo.js.uncompressed.js from remoteScripts
					// we declare all files with dojo.js as bad, regardless of folder
					var tmp = attr[2].search(/.*(\bdojo\b(?:\.uncompressed)?\.js)$/);
					if(tmp > -1){
						dojo.debug("Security note! inhibit:"+attr[2]+" from  beeing loaded again.");
					}else{
						remoteScripts.push(attr[2]);
					}
				}
			}
			if(match[2]){
				// strip out all djConfig variables from script tags nodeValue
				// this is ABSOLUTLY needed as reinitialize djConfig after dojo is initialised
				// makes a dissaster greater than Titanic, update remove writeIncludes() to
				var sc = match[2].replace(/(?:var )?\bdjConfig\b(?:[\s]*=[\s]*\{[^}]+\}|\.[\w]*[\s]*=[\s]*[^;\n]*)?;?|dojo\.hostenv\.writeIncludes\(\s*\);?/g, "");
				if(!sc){ continue; }

				// cut out all dojo.require (...) calls, if we have execute 
				// scripts false widgets dont get there require calls
				// does suck out possible widgetpackage registration as well
				tmp = [];
				while(tmp && requires.length<100){
					tmp = sc.match(/dojo\.(?:(?:require(?:After)?(?:If)?)|(?:widget\.(?:manager\.)?registerWidgetPackage)|(?:(?:hostenv\.)?setModulePrefix))\((['"]).*?\1\)\s*;?/);
					if(!tmp){ break;}
					requires.push(tmp[0]);
					sc = sc.replace(tmp[0], "");
				}
				scripts.push(sc);
			}
			s = s.replace(/<script[^>]*>[\s\S]*?<\/script>/i, "");
		}

		// scan for scriptScope in html eventHandlers and replace with link to this pane
		if(this.executeScripts){
			var regex = /(<[a-zA-Z][a-zA-Z0-9]*\s[^>]*\S=(['"])[^>]*[^\.\]])scriptScope([^>]*>)/;
			var pos = 0;var str = "";match = [];var cit = "";
			while(pos > -1){
				pos = s.search(regex);
				if(pos > -1){
					cit = ((RegExp.$2=="'") ? '"': "'");
					str += s.substring(0, pos);
					s = s.substr(pos).replace(regex, "$1dojo.widget.byId("+ cit + this.widgetId + cit + ").scriptScope$3");
				}
			}
			s = str + s;
		}

		// cut out all <link rel="stylesheet" href="..">
		match = [];
		while(match){
			match = s.match(/<link ([^>]*rel=['"]?stylesheet['"]?[^>]*)>/i);
			if(!match){ break; }
			attr = match[1].match(/href=(['"]?)([^'">]*)\1/i);
			if(attr){
				linkStyles.push(attr[2]);
			}
			s = s.replace(new RegExp(match[0]), "");
		}

		return {"xml": s, // Object
			"styles": styles,
			"linkStyles": linkStyles,
			"titles": titles,
			"requires": 	requires,
			"scripts": scripts,
			"remoteScripts": remoteScripts,
			"url": url};
	},

	
	_setContent: function(/*String*/ xml){
		// summary: 
		//		private internal function without path regExpCheck and no onLoad calls aftervards

		// remove old children from current content
		this.destroyChildren();

		// remove old stylenodes from HEAD
		if(this._remoteStyles){
			for(var i = 0; i < this._remoteStyles.length; i++){
				if(this._remoteStyles[i] && this._remoteStyles.parentNode){
					this._remoteStyles[i].parentNode.removeChild(this._remoteStyles[i]);
				}
			}
			this._remoteStyles = null;
		}

		var node = this.containerNode || this.domNode;
		try{
			if(typeof xml != "string"){
				node.innerHTML = "";
				node.appendChild(xml);
			}else{
				node.innerHTML = xml;
			}
		} catch(e){
			e = "Could'nt load content:"+e;
			this._handleDefaults(e, "onContentError");
		}
	},

	setContent: function(/*String*/ data){
		// summary:
		// 	Destroys old content and setting new content, and possibly initialize any widgets within 'data'

		if(this._callOnUnLoad){ // this tells a remote script clean up after itself
			this.onUnLoad();
		}
		this._callOnUnLoad = true;

		if(!data || dojo.dom.isNode(data)){
			// if we do a clean using setContent(""); or setContent(#node) bypass all parseing, extractContent etc
			this._setContent(data);
			this.onResized();
			this.onLoad();
		}else{
			// need to run splitAndFixPaths? ie. manually setting content
			 if((!data.xml)&&(this.adjustPaths)){
				data = this.splitAndFixPaths(data);
			}
			if(this.extractContent) {
				var matches = data.xml.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
				if(matches) { data.xml = matches[1]; }
			}
			// insert styleNodes, from <style>....
			for(var i = 0; i < data.styles.length; i++){
				if(i==0){ 
					this._remoteStyles = []; 
				}
				this._remoteStyles.push(dojo.style.insertCssText(data.styles[i]));
			}
			// insert styleNodes, from <link href="...">
			for(var i = 0; i < data.linkStyles.length; i++){
				if(i==0){ 
					this._remoteStyles = []; 
				}
				this._remoteStyles.push(dojo.style.insertCssFile(data.linkStyles[i]));
			}
			this._setContent(data.xml);

			if(this.parseContent){
				for(var i = 0; i < data.requires.length; i++){
					try{ 
						eval(data.requires[i]);
					} catch(e){
						this._handleDefaults(e, "onContentError", true);
					}
				}
			}
			// need to allow async load, Xdomain uses it
			// is inline function because we cant send args to addOnLoad function
			var _self = this;
			function asyncParse(){
				if(_self.executeScripts){
					_self._executeScripts(data);
				}

				if(_self.parseContent){
					var node = _self.containerNode || _self.domNode;
					var parser = new dojo.xml.Parse();
					var frag = parser.parseElement(node, null, true);
					// createSubComponents not createComponents because frag has already been created
					dojo.widget.getParser().createSubComponents(frag, _self);
				}

				_self.onResized();
				_self.onLoad();
			}
			// try as long as possible to make setContent sync call
			if(dojo.hostenv.isXDomain && data.requires.length){
				dojo.addOnLoad(asyncParse);
			}else{
				asyncParse();
			}
		}
	},

	// Generate pane content from given java function
	setHandler: function(handler) {
		var fcn = dojo.lang.isFunction(handler) ? handler : window[handler];
		if(!dojo.lang.isFunction(fcn)) {
			// FIXME: needs testing! somebody with java knowledge needs to try this
			this._handleDefaults("Unable to set handler, '" + handler + "' not a function.", "onExecError", true);
			return;
		}
		this.handler = function() {
			return fcn.apply(this, arguments);
		}
	},

	_runHandler: function() {
		if(dojo.lang.isFunction(this.handler)) {
			this.handler(this, this.domNode);
			return false;
		}
		return true;
	},

	_executeScripts: function(data) {
		// do remoteScripts first
		var self = this;
		for(var i = 0; i < data.remoteScripts.length; i++){
			dojo.io.bind({
				"url": data.remoteScripts[i],
				"useCash":	this.cacheContent,
				"load":     function(type, scriptStr){
						dojo.lang.hitch(self, data.scripts.push(scriptStr));
				},
				"error":    function(type, error){
						self._handleDefaults.call(self, type + " downloading remote script", "onExecError", true);
				},
				"mimetype": "text/plain",
				"sync":     true
			});
		}

		var scripts = "";
		for(var i = 0; i < data.scripts.length; i++){
			scripts += data.scripts[i];
		}

		try{
			// initialize a new anonymous container for our script, dont make it part of this widgets scope chain
			// instead send in a variable that points to this widget, usefull to connect events to onLoad, onUnLoad etc..
			this.scriptScope = null;
			this.scriptScope = new (new Function('_container_', scripts+'; return this;'))(self);
		}catch(e){
			this._handleDefaults("Error running scripts from content:\n"+e, "onExecError", true);
		}
	}
});

dojo.widget.tags.addParseTreeHandler("dojo:ContentPane");

__CPAN_FILE__ src/widget/html/DocPane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.DocPane");

dojo.require("dojo.widget.*");
dojo.require("dojo.io.*");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.HtmlWidget");

dojo.widget.html.DocPane = function(){
	dojo.widget.HtmlWidget.call(this);

	this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlDocPane.html");
	this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlDocPane.css");
	this.widgetType = "DocPane";
	this.isContainer = true;

	this.select;
	this.result;
	this.fn;
	this.fnLink;
	this.count;
	this.row;
	this.summary;
	this.description;
	this.variables;
	this.vRow;
	this.vLink;
	this.vDesc;
	this.parameters;
	this.pRow;
	this.pLink;
	this.pDesc;
	this.pOpt;
	this.pType;
	this.source;
	this.sType;
	this.sName;
	this.sParams;
	this.sPType;
	this.sPTypeSave;
	this.sPName;
	this.sPNameSave;

	dojo.event.topic.subscribe("/doc/results", this, "onDocResults");
	dojo.event.topic.subscribe("/doc/functionDetail", this, "onDocSelectFunction");
}

dojo.inherits(dojo.widget.html.DocPane, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.DocPane, {
	fillInTemplate: function(){
		this.homeSave = this.containerNode.cloneNode(true);
		this.selectSave = dojo.dom.removeNode(this.select);
		this.resultSave = dojo.dom.removeNode(this.result);
		this.rowParent = this.row.parentNode;
		this.rowSave = dojo.dom.removeNode(this.row);
		this.vParent = this.vRow.parentNode;
		this.vSave = dojo.dom.removeNode(this.vRow);
		this.pParent = this.pRow.parentNode;
		this.pSave = dojo.dom.removeNode(this.pRow);
		this.sPTypeSave = dojo.dom.removeNode(this.sPType);
		this.sPNameSave = dojo.dom.removeNode(this.sPName);
	},

	onDocSelectFunction: function(message){
		var meta = message.meta;
		if(meta){
			var variables = meta.variables;
			var this_variables = meta.this_variables;
			var child_variables = meta.child_variables;
			var parameters = meta.parameters;
		}
		var doc = message.doc;

		var appends = [];
		dojo.dom.removeChildren(this.domNode);
		this.fn.innerHTML = message.name;
		this.description.innerHTML = doc.description;

		this.variables.style.display = "block";
		var all = [];
		if(variables){
			all = variables;
		}
		if(this_variables){
			all = all.concat(this_variables);
		}
		if(child_variables){
			all = all.concat(child_variables);
		}
		if(!all.length){
			this.variables.style.display = "none";
		}else{
			for(var i = 0, one; one = all[i]; i++){
				this.vLink.innerHTML = one;
				this.vDesc.parentNode.style.display = "none";
				appends.push(this.vParent.appendChild(this.vSave.cloneNode(true)));
			}
		}
		
		this.sParams.innerHTML = "";
		for(var param in parameters){
			var paramType = parameters[param][0];
			var paramName = parameters[param][1];
			this.parameters.style.display = "block";		
			this.pLink.innerHTML = paramName;
			this.pOpt.style.display = "none";
			if(parameters[param].opt){
				this.pOpt.style.display = "inline";				
			}
			this.pType.parentNode.style.display = "none";
			if(parameters[param][0]){
				this.pType.parentNode.style.display = "inline";
				this.pType.innerHTML = paramType;
			}
			this.pDesc.parentNode.style.display = "none";
			if(doc.parameters[paramName] && doc.parameters[paramName].description){
				this.pDesc.parentNode.style.display = "inline";
				this.pDesc.innerHTML = doc.parameters[paramName].description;
			}
			appends.push(this.pParent.appendChild(this.pSave.cloneNode(true)));
			
			if(param > 0) {
				this.sParams.appendChild(document.createTextNode(", "));
			}
			if(paramType){
				dojo.debug(this.sPTypeSave);
				this.sPTypeSave.innerHTML = paramType;
				this.sParams.appendChild(this.sPTypeSave.cloneNode(true));
				this.sParams.appendChild(document.createTextNode(" "));
			}
			dojo.debug(this.sPNameSave);
			this.sPNameSave.innerHTML = paramName;
			this.sParams.appendChild(this.sPNameSave.cloneNode(true))
		}

		if(message.returns){
			this.sType.innerHTML = message.returns;
		}else{
			this.sType.innerHTML = "void";
		}
		
		this.sName.innerHTML = message.name;
		
		dojo.dom.removeChildren(this.source);
                this.source.appendChild(document.createTextNode("\n\r"));
		this.source.appendChild(document.createTextNode(message.src.replace(/\n/g, "\r\n\t")));
                this.source.appendChild(document.createTextNode("\n\r"));
		
		this.domNode.appendChild(this.selectSave.cloneNode(true));

		for(var i = 0, append; append = appends[i]; i++){
			dojo.dom.removeNode(append);
		}
	},

	onDocResults: function(message){
		var results = message.docResults;
		
		if(results.length == 1){
			dojo.event.topic.publish("/doc/selectFunction", results[0]);
			return;
		}

		dojo.dom.removeChildren(this.domNode);

		this.count.innerHTML = results.length;
		var appends = [];
		for(var i = 0, row; row = results[i]; i++){
			this.fnLink.innerHTML = row.name;
			this.fnLink.href = "#" + row.name;
			if(row.id){
				this.fnLink.href = this.fnLink.href + "," + row.id;	
			}
			this.summary.parentNode.style.display = "none";
			if(row.summary){
				this.summary.parentNode.style.display = "inline";				
				this.summary.innerHTML = row.summary;
			}
			appends.push(this.rowParent.appendChild(this.rowSave.cloneNode(true)));
		}
		
		function makeSelect(x){
			return function(e) {
				dojo.event.topic.publish("/doc/selectFunction", x);
			}
		}

		this.domNode.appendChild(this.resultSave.cloneNode(true));
		var as = this.domNode.getElementsByTagName("a");
		for(var i = 0, a; a = as[i]; i++){
			dojo.event.connect(a, "onclick", makeSelect(results[i]));
		}
		
		for(var i = 0, append; append = appends[i]; i++){
			this.rowParent.removeChild(append);
		}
	}
});

dojo.widget.tags.addParseTreeHandler("dojo:DocPane");

__CPAN_FILE__ src/widget/html/Slider.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/**
 * Slider Widget.
 * 
 * The slider widget comes in three forms:
 *  1. Base Slider widget which supports movement in x and y dimensions
 *  2. Vertical Slider (SliderVertical) widget which supports movement
 *     only in the y dimension.
 *  3. Horizontal Slider (SliderHorizontal) widget which supports movement
 *     only in the x dimension.
 *
 * The key objects in the widget are:
 *  - a container div which displays a bar in the background (Slider object)
 *  - a handle inside the container div, which represents the value
 *    (sliderHandle DOM node)
 *  - the object which moves the handle (handleMove is of type 
 *    SliderDragMoveSource)
 *
 * The values for the slider are calculated by grouping pixels together, 
 * based on the number of values to be represented by the slider.
 * The number of pixels in a group is called the valueSize
 *  e.g. if slider is 150 pixels long, and is representing the values
 *       0,1,...10 then pixels are grouped into lots of 15 (valueSize), where:
 *         value 0 maps to pixels  0 -  7
 *               1                 8 - 22
 *               2                23 - 37 etc.
 * The accuracy of the slider is limited to the number of pixels
 * (i.e tiles > pixels will result in the slider not being able to
 *  represent some values).
 *
 * Technical Notes:
 *  - 3 widgets exist because the framework caches the template in
 *    dojo.widget.fillFromTemplateCache (which ignores the changed URI)
 *
 * Todo:
 *  - Setting of initial value currently doesn't work, because the one or
 *    more of the offsets, constraints or containing block are not set and
 *    are required to set the valueSize is not set before fillInTemplate
 *    is called.
 *  - Issues with dragging handle when page has been scrolled
 *  - 
 *
 * References (aka sources of inspiration):
 *  - http://dojotoolkit.org/docs/fast_widget_authoring.html
 *  - http://dojotoolkit.org/docs/dojo_event_system.html
 * 
 * @author Marcel Linnenfelser (m.linnen@synflag.de)
 * @author Mathew Pole (mathew.pole@ebor.com)
 *
 * $Id: $
 */

// tell the package system what functionality is provided in this module (file)
// (note that the package system works on modules, not the classes)
dojo.provide("dojo.widget.html.Slider");

// load dependencies
dojo.require("dojo.event.*");
dojo.require("dojo.dnd.*");
// dojo.dnd.* doesn't include this package, because it's not in __package__.js
dojo.require("dojo.dnd.HtmlDragMove");
dojo.require("dojo.widget.*");
dojo.require("dojo.style");


/**
 * Define the two dimensional slider widget class.
 */
dojo.widget.defineWidget (
	"dojo.widget.html.Slider",
	dojo.widget.HtmlWidget,
	{
		// over-ride some defaults
		isContainer: false,
		widgetType: "Slider",

		// useful properties (specified as attributes in the html tag)
		// number of values to be represented by slider in the horizontal direction
		valuesX: 10,
		// number of values to be represented by slider in the vertical direction
		valuesY: 10,
		// can values be changed on the x (horizontal) axis?
		isEnableX: true,
		// can values be changed on the y (vertical) axis?
		isEnableY: true,
		// value size (pixels) in the x dimension
		valueSizeX: 0.0,
		// value size (pixels) in the y dimension
		valueSizeY: 0.0,
		// initial value in the x dimension
		initialValueX: 0,
		// initial value in the y dimension
		initialValueY: 0,

		// do we allow the user to click on the slider to set the position?
		// (note: dojo's infrastructor will convert attribute to a boolean)
		clickSelect: true,
		// should the handle snap to the grid or remain where it was dragged to?
		// (note: dojo's infrastructor will convert attribute to a boolean)
		snapToGrid: false,
		// should the value change while you are dragging, or just after drag finishes?
		activeDrag: false,

		templateCssPath: dojo.uri.dojoUri ("src/widget/templates/HtmlSlider.css"),
		templatePath: dojo.uri.dojoUri ("src/widget/templates/HtmlSlider.html"),

		// our DOM nodes
		sliderHandle: null,

		// private attributes
		// This is set to true when a drag is started, so that it is not confused
		// with a click
		isDragInProgress: false,


		// This function is called when the template is loaded
		fillInTemplate: function () 
		{
			// dojo.debug ("fillInTemplate - className = " + this.domNode.className);

			// setup drag-n-drop for the sliderHandle
			this.handleMove = new dojo.widget.html.SliderDragMoveSource (this.sliderHandle);
			this.handleMove.setParent (this);
			dojo.event.connect(this.handleMove, "onDragMove", this, "onDragMove");
			dojo.event.connect(this.handleMove, "onDragEnd", this, "onDragEnd");
			dojo.event.connect(this.handleMove, "onClick", this, "onClick");

			// keep the slider handle inside it's parent container
			this.handleMove.constrainToContainer = true;
		
			if (this.clickSelect) {
				dojo.event.connect (this.domNode, "onclick", this, "setPosition");
			} 

			if (this.isEnableX && this.initialValueX > 0) {
				alert("setting x to " + this.initialValueX);
				this.setValueX (this.initialValueX);
			}
			if (this.isEnableY && this.initialValueY > 0) {
				this.setValueY (this.initialValueY);
			}
		},


		// Move the handle (in the x dimension) to the specified value
		setValueX: function (value) {
			if (0.0 == this.valueSizeX) {
				this.valueSizeX = this.handleMove.calcValueSizeX ();
			}
			if (value > this.valuesX) {
				value = this.valuesX;
			}
			else if (value < 0) {
				value = 0;
			}
			//dojo.debug ("value = " + value, ", valueSizeX = " + this.valueSizeX);
			this.handleMove.domNode.style.left = (value * this.valueSizeX) + "px";
		},


		// Get the number of the value that matches the position of the handle
		getValueX: function () {
			if (0.0 == this.valueSizeX) {
				this.valueSizeX = this.handleMove.calcValueSizeX ();
			}
			return Math.round (dojo.style.getPixelValue (this.handleMove.domNode, "left") / this.valueSizeX);
		},


		// set the slider to a particular value
		setValueY: function (value) {
			if (0.0 == this.valueSizeY) {
				this.valueSizeY = this.handleMove.calcValueSizeY ();
			}
			if (value > this.valuesY) {
				value = this.valuesY;
			}
			else if (value < 0) {
				value = 0;
			}

			this.handleMove.domNode.style.top = (value * this.valueSizeY) + "px";
		},


		// Get the number of the value that the matches the position of the handle
		getValueY: function () {
			if (0.0 == this.valueSizeY) {
				this.valueSizeY = this.handleMove.calcValueSizeY ();
			}
			return Math.round (dojo.style.getPixelValue (this.handleMove.domNode, "top") / this.valueSizeY);
		},


		// set the position of the handle
		setPosition: function (e) {
			//dojo.debug ("Slider#setPosition - e.clientX = " + e.clientX
			//            + ", e.clientY = " + e.clientY);
			if (this.isDragInProgress) {
				this.isDragInProgress = false;
			}

			var offset = dojo.html.getScrollOffset();
			var parent = dojo.style.getAbsolutePosition(this.domNode, true);
			
			if (this.isEnableX) {
				var x = offset.x + e.clientX - parent.x;
				if (x > this.domNode.offsetWidth) {
					x = this.domNode.offsetWidth;
				}
				if (this.snapToGrid && x > 0) {
					if (0.0 == this.valueSizeX) {
						this.valueSizeX = this.handleMove.calcValueSizeX ();
					}
					x = this.valueSizeX * (Math.round (x / this.valueSizeX));
				}
				this.handleMove.domNode.style.left = x + "px";
			}
			if (this.isEnableY) {
				var y = offset.y + e.clientY - parent.y;
				if (y > this.domNode.offsetHeight) {
					y = this.domNode.offsetHeight;
				}
				if (this.snapToGrid && y > 0) {
					if (0.0 == this.valueSizeY) {
						this.valueSizeY = this.handleMove.calcValueSizeY ();
					}
					y = this.valueSizeY * (Math.round (y / this.valueSizeY));
				}
				this.handleMove.domNode.style.top = y + "px";
			}
		},

		onDragMove: function(){
			this.onValueChanged(this.getValueX(), this.getValueY());
		},
	
		onClick: function(){
			this.onValueChanged(this.getValueX(), this.getValueY());
		},
		
		onValueChanged: function(x, y){
		}
	}
);


/* ------------------------------------------------------------------------- */


/**
 * Define the horizontal slider widget class.
 */
dojo.widget.defineWidget (
	"dojo.widget.html.SliderHorizontal",
	dojo.widget.html.Slider,
	{
		widgetType: "SliderHorizontal",

		value: 0,

		isEnableY: false,
		templatePath: dojo.uri.dojoUri ("src/widget/templates/HtmlSliderHorizontal.html"),

		postMixInProperties: function(){
			this.initialValue = this.value;
		},

		// wrapper for getValueX
		getValue: function () {
			return this.getValueX ();
		},

		// wrapper for setValueX
		setValue: function (value) {
			this.setValueX (value);
			this.onValueChanged(value);
		},

		onDragMove: function(){
			if(this.activeDrag){
				this.onValueChanged(this.getValue());
			}
		},
	
		onDragEnd: function(){
			if(!this.activeDrag){
				this.onValueChanged(this.getValue());
			}
		},
	
		onClick: function(){
			this.onValueChanged(this.getValue());
		},
		
		onValueChanged: function(value){
			this.value=value;
		}
	}
);


/* ------------------------------------------------------------------------- */


/**
 * Define the vertical slider widget class.
 */
dojo.widget.defineWidget (
	"dojo.widget.html.SliderVertical",
	dojo.widget.html.Slider,
	{
		widgetType: "SliderVertical",

		value: 0,

		isEnableX: false,
		templatePath: dojo.uri.dojoUri ("src/widget/templates/HtmlSliderVertical.html"),

		postMixInProperties: function(){
			this.initialValueY = this.value;
		},

		// wrapper for getValueY
		getValue: function () {
			return this.getValueY ();
		},

		// wrapper for setValueY
		setValue: function (value) {
			this.setValueY (value);
		},

		onDragMove: function(){
			if(this.activeDrag){
				this.onValueChanged(this.getValue());
			}
		},
	
		onDragEnd: function(){
			if(!this.activeDrag){
				this.onValueChanged(this.getValue());
			}
		},
	
		onClick: function(){
			this.onValueChanged(this.getValue());
		},
		
		onValueChanged: function(value){
			this.value=value;
		}
	}
);


/* ------------------------------------------------------------------------- */


/**
 * This class extends the HtmlDragMoveSource class to provide
 * features for the slider handle.
 */
dojo.declare (
	"dojo.widget.html.SliderDragMoveSource",
	dojo.dnd.HtmlDragMoveSource,
{
	isDragInProgress: false,
	slider: null,


	/** Setup the handle for drag
	 *  Extends dojo.dnd.HtmlDragMoveSource by creating a SliderDragMoveSource */
	onDragStart: function (e) {
		this.isDragInProgress = true;
		this.constrainToContainer = true;

		var dragObj = this.createDragMoveObject ();
		var constraints = null;


		dojo.event.connect (dragObj, "onDragMove", this, "onDragMove");

		return dragObj;
	},


	onDragMove: function (e) {
		// placeholder to enable event connection
	},


	createDragMoveObject: function () {
		//dojo.debug ("SliderDragMoveSource#createDragMoveObject - " + this.slider);
		var dragObj = new dojo.widget.html.SliderDragMoveObject (this.dragObject, this.type);
		dragObj.slider = this.slider;

		// this code copied from dojo.dnd.HtmlDragSource#onDragStart
		if (this.dragClass) { 
			dragObj.dragClass = this.dragClass; 
		}
		if (this.constrainToContainer) {
			dragObj.constrainTo(this.constrainingContainer || this.domNode.parentNode);
		}
		return dragObj;
	},


	setParent: function (slider) {
		this.slider = slider;
	},

	
	calcValueSizeX: function () {
		var dragObj = this.createDragMoveObject ();
		dragObj.containingBlockPosition = dragObj.domNode.offsetParent ? 
		dojo.style.getAbsolutePosition(dragObj.domNode.offsetParent) : {x:0, y:0};
		
		var constraints = dragObj.getConstraints ();
		return (constraints.maxX - constraints.minX) / this.slider.valuesX;
	},

	
	calcValueSizeY: function () {
		var dragObj = this.createDragMoveObject ();
		dragObj.containingBlockPosition = dragObj.domNode.offsetParent ? 
		dojo.style.getAbsolutePosition(dragObj.domNode.offsetParent) : {x:0, y:0};
		var constraints = dragObj.getConstraints ();
		return (constraints.maxY - constraints.minY) / this.slider.valuesY;
	}
});


/* ------------------------------------------------------------------------- */


/**
 * This class extends the HtmlDragMoveObject class to provide
 * features for the slider handle.
 */
dojo.declare (
	"dojo.widget.html.SliderDragMoveObject",
	dojo.dnd.HtmlDragMoveObject,
{
	// reference to dojo.widget.html.Slider
	slider: null,

	/** Moves the node to follow the mouse.
	 *  Extends functon HtmlDragObject by adding functionality to snap handle
	 *  to a discrete value */
	onDragMove: function (e) {
		if (this.slider.isEnableX && 0.0 == this.slider.valueSizeX) {
			this.slider.valueSizeX = (this.constraints.maxX - this.constraints.minX) / this.slider.valuesX;
		}
		if (this.slider.isEnableY && 0.0 == this.slider.valueSizeY) {
			this.slider.valueSizeY = (this.constraints.maxY - this.constraints.minY) / this.slider.valuesY;
		}

		this.updateDragOffset ();

		var x = this.dragOffset.x + e.pageX;
		var y = this.dragOffset.y + e.pageY;

		if (this.constrainToContainer) {
			if (x < this.constraints.minX) { x = this.constraints.minX; }
			if (y < this.constraints.minY) { y = this.constraints.minY; }
			if (x > this.constraints.maxX) { x = this.constraints.maxX; }
			if (y > this.constraints.maxY) { y = this.constraints.maxY; }
		}

		if (this.slider.isEnableX) {
			var selectedValue = 0;
			if (x > 0) {
				selectedValue = Math.round (x / this.slider.valueSizeX);
			}
			// dojo.debug ("x = " + x + ", valueSize = " + valueSize 
			//             + ", selectedValue = " + selectedValue);
			x = (selectedValue * this.slider.valueSizeX);
		}

		if (this.slider.isEnableY) {
			var selectedValue = 0;
			if (y > 0) {
				selectedValue = Math.round (y / this.slider.valueSizeY);
			}
			y = (selectedValue * this.slider.valueSizeY);
		}

		this.setAbsolutePosition (x, y);
	}
});

__CPAN_FILE__ src/widget/html/TaskBar.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.TaskBar");
dojo.provide("dojo.widget.html.TaskBarItem");

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.FloatingPane");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.event");

// Icon associated w/a floating pane
dojo.widget.html.TaskBarItem = function(){
	dojo.widget.TaskBarItem.call(this);
	dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.TaskBarItem, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.TaskBarItem, {
	// constructor arguments
	iconSrc: '',
	caption: 'Untitled',
	window: null,
	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlTaskBarItemTemplate.html"),
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlTaskBar.css"),

	fillInTemplate: function() {
		if ( this.iconSrc != '' ) {
			var img = document.createElement("img");
			img.src = this.iconSrc;
			this.domNode.appendChild(img);
		}
		this.domNode.appendChild(document.createTextNode(this.caption));
		dojo.html.disableSelection(this.domNode);
	},

	postCreate: function() {
		this.window=dojo.widget.getWidgetById(this.windowId);
		this.window.explodeSrc = this.domNode;
		dojo.event.connect(this.window, "destroy", this, "destroy")
	},

	onClick: function() {
		this.window.show();
	}
});

// Collection of widgets in a bar, like Windows task bar
dojo.widget.html.TaskBar = function(){

	dojo.widget.html.FloatingPane.call(this);
	dojo.widget.TaskBar.call(this);
	this._addChildStack = [];
}

dojo.inherits(dojo.widget.html.TaskBar, dojo.widget.html.FloatingPane);

dojo.lang.extend(dojo.widget.html.TaskBar, {

	resizable: false,
	titleBarDisplay: "none",

	addChild: function(child) {
		if(!this.containerNode){ 
			this._addChildStack.push(child);
		}else if(this._addChildStack.length > 0){
			var oarr = this._addChildStack;
			this._addChildStack = [];
			dojo.lang.forEach(oarr, this.addChild, this);
		}
		var tbi = dojo.widget.createWidget("TaskBarItem",
			{	windowId: child.widgetId, 
				caption: child.title, 
				iconSrc: child.iconSrc
			});
		dojo.widget.html.TaskBar.superclass.addChild.call(this,tbi);
	}
});

__CPAN_FILE__ src/widget/html/TitlePane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.TitlePane");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.lfx.*");

dojo.widget.html.TitlePane = function(){
	dojo.widget.HtmlWidget.call(this);
	this.widgetType = "TitlePane";

	this.labelNode="";
	this.labelNodeClass="";
	this.containerNodeClass="";
	this.label="";

	this.open=true;
	this.templatePath = dojo.uri.dojoUri("src/widget/templates/TitlePane.html");
}

dojo.inherits(dojo.widget.html.TitlePane, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.TitlePane, {
	isContainer: true,
	postCreate: function() {
		if (this.label) {
			this.labelNode.appendChild(document.createTextNode(this.label));
		}

		if (this.labelNodeClass) {
			dojo.html.addClass(this.labelNode, this.labelNodeClass);
		}	

		if (this.containerNodeClass) {
			dojo.html.addClass(this.containerNode, this.containerNodeClass);
		}	

		if (!this.open) {
			dojo.lfx.wipeOut(this.containerNode,0).play();
		}
	},

	onLabelClick: function() {
		if (this.open) {
			dojo.lfx.wipeOut(this.containerNode,250).play();
			this.open=false;
		}else {
			dojo.lfx.wipeIn(this.containerNode,250).play();
			this.open=true;
		}
	},

	setContent: function(content) {
		this.containerNode.innerHTML=content;
	},

	setLabel: function(label) {
		this.labelNode.innerHTML=label;
	}
});

dojo.widget.tags.addParseTreeHandler("dojo:TitlePane");

__CPAN_FILE__ src/widget/html/GoogleMap.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.GoogleMap");
dojo.require("dojo.event.*");
dojo.require("dojo.html");
dojo.require("dojo.math");
dojo.require("dojo.uri.Uri");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.GoogleMap");

(function(){
	var gkey = djConfig["gMapKey"]||djConfig["googleMapKey"];

	//	the Google API key mechanism sucks.  We're hardcoding here for love and affection but I don't like it.
	var uri=new dojo.uri.Uri(window.location.href);
	if(uri.host=="www.dojotoolkit.org"){
		gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hRqjp7ri2mNiOEYqetD3xnFHpt5rBSjszDd1sdufPyQKUTyCf_YxoIxvw";
	}
	else if(uri.host=="blog.dojotoolkit.org"){
		gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hSkep6Av1xaMhVn3yCLkorJeXeLARQ6fammI_P3qSGleTJhoI5_1JmP_Q";
	}
	else if(uri.host=="archive.dojotoolkit.org"){
		gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hTaQpDt0dyGLIHbXMPTzg1kWeAfwRTwZNyrUfbfxYE9yIvRivEjcXoDTg";
	}
	else if(uri.host=="dojotoolkit.org"){
		gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hSaOaO_TgJ5c3mtQFnk5JO2zD5dZBRZk-ieqVs7BORREYNzAERmcJoEjQ";
	}

	if(!dojo.hostenv.post_load_){
		var tag = "<scr"+"ipt src='http://maps.google.com/maps?file=api&amp;v=2&amp;key="+gkey+"'></scri"+"pt>";
		if(!dj_global["GMap2"]){ // prevent multi-inclusion
			document.write(tag);
		}
	}else{
		dojo.debug("cannot initialize map system after the page has been loaded! Please either manually include the script block provided by Google in your page or require() the GoogleMap widget before onload has fired");
	}
})();

dojo.widget.html.GoogleMap=function(){
	dojo.widget.HtmlWidget.call(this);
	dojo.widget.GoogleMap.call(this);

	var gm=dojo.widget.GoogleMap;

	this.map=null;
	this.data=[];
	this.datasrc="";
	// FIXME: this is pehraps the stupidest way to specify this enum I can think of
	this.controls=[gm.Controls.LargeMap,gm.Controls.Scale,gm.Controls.MapType];
};
dojo.inherits(dojo.widget.html.GoogleMap, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.GoogleMap, {
	templatePath:null,
	templateCssPath:null,

	setControls:function(){
		var c=dojo.widget.GoogleMap.Controls;
		for(var i=0; i<this.controls.length; i++){
			var type=this.controls[i];
			switch(type){
				case c.LargeMap:{
					this.map.addControl(new GLargeMapControl());
					break;
				}
				case c.SmallMap:{
					this.map.addControl(new GSmallMapControl());
					break;
				}
				case c.SmallZoom:{
					this.map.addControl(new GSmallZoomControl());
					break;
				}
				case c.Scale:{
					this.map.addControl(new GScaleControl());
					break;
				}
				case c.MapType:{
					this.map.addControl(new GMapTypeControl());
					break;
				}
				case c.Overview:{
					this.map.addControl(new GOverviewMapControl());
					break;
				}
				default:{
					break;
				}
			}
		}
	},
	
	findCenter:function(bounds){
		var clat=(bounds.getNorthEast().lat()+bounds.getSouthWest().lat())/2;
		var clng=(bounds.getNorthEast().lng()+bounds.getSouthWest().lng())/2;
		return (new GLatLng(clat,clng));
	},

	createPinpoint:function(pt,overlay){
		var m=new GMarker(pt);
		if(overlay){
			GEvent.addListener(m,"click",function(){
				m.openInfoWindowHtml("<div>"+overlay+"</div>");
			});
		}
		return m;
	},

	parse:function(table){
		this.data=[];

		//	get the column indices
		var h=table.getElementsByTagName("thead")[0];
		if(!h){
			return;
		}

		var a=[];
		var cols=h.getElementsByTagName("td");
		if(cols.length==0){
			cols=h.getElementsByTagName("th");
		}
		for(var i=0; i<cols.length; i++){
			var c=cols[i].innerHTML.toLowerCase();
			if(c=="long") c="lng";
			a.push(c);
		}
		
		//	parse the data
		var b=table.getElementsByTagName("tbody")[0];
		if(!b){
			return;
		}
		for(var i=0; i<b.childNodes.length; i++){
			if(!(b.childNodes[i].nodeName&&b.childNodes[i].nodeName.toLowerCase()=="tr")){
				continue;
			}
			var cells=b.childNodes[i].getElementsByTagName("td");
			var o={};
			for(var j=0; j<a.length; j++){
				var col=a[j];
				if(col=="lat"||col=="lng"){
					o[col]=parseFloat(cells[j].innerHTML);					
				}else{
					o[col]=cells[j].innerHTML;
				}
			}
			this.data.push(o);
		}
	},
	render:function(){
		var bounds=new GLatLngBounds();
		var d=this.data;
		var pts=[];
		for(var i=0; i<d.length; i++){
			bounds.extend(new GLatLng(d[i].lat,d[i].lng));
		}

		this.map.setCenter(this.findCenter(bounds), this.map.getBoundsZoomLevel(bounds));

		for(var i=0; i<this.data.length; i++){
			var p=new GLatLng(this.data[i].lat,this.data[i].lng);
			var d=this.data[i].description||null;
			var m=this.createPinpoint(p,d);
			this.map.addOverlay(m);
		}
	},
	

	initialize:function(args, frag){
		if(!GMap2){
			dojo.raise("dojo.widget.GoogleMap: The Google Map script must be included (with a proper API key) in order to use this widget.");
		}
		if(this.datasrc){
			this.parse(dojo.byId(this.datasrc));
		}
		else if(this.domNode.getElementsByTagName("table")[0]){
			this.parse(this.domNode.getElementsByTagName("table")[0]);
		}
	},
	postCreate:function(){
		//	clean the domNode before creating the map.
		while(this.domNode.childNodes.length>0){
			this.domNode.removeChild(this.domNode.childNodes[0]);
		}
		this.map=new GMap2(this.domNode);
		this.render();
		this.setControls();
	}
});

__CPAN_FILE__ src/widget/html/MonthlyCalendar.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.MonthlyCalendar");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.html.DatePicker");
dojo.require("dojo.widget.MonthlyCalendar");
//dojo.require("dojo.widget.MonthlyCalendar.util");
dojo.require("dojo.event.*");
dojo.require("dojo.html");

dojo.widget.html.MonthlyCalendar= function(){
	dojo.widget.MonthlyCalendar.call(this);
	//dojo.widget.html.DatePicker.call(this);
	this.widgetType = "MonthlyCalendar";
	this.templatePath =  dojo.uri.dojoUri("src/widget/templates/HtmlMonthlyCalendar.html");
	this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlMonthlyCalendar.css");

	this.iCalendars = [];
}

dojo.inherits(dojo.widget.html.MonthlyCalendar, dojo.widget.html.DatePicker);

dojo.lang.extend(dojo.widget.html.MonthlyCalendar, {
	cache: function() {
	},

	addCalendar: function(/* dojo.iCalendar */ cal) {
		dojo.debug("Adding Calendar");
		this.iCalendars.push(cal);
		dojo.debug("Starting init");
		this.initUI()
		dojo.debug("done init");
	},

	createDayContents: function(node,mydate) {
		dojo.dom.removeChildren(node);
		node.appendChild(document.createTextNode(mydate.getDate()));	
			for(var x=0; x<this.iCalendars.length; x++) {
				var evts = this.iCalendars[x].getEvents(mydate);
				if ((dojo.lang.isArray(evts)) && (evts.length>0)) {
				for(var y=0;y<evts.length;y++) {
					var el = document.createElement("div");
					dojo.html.addClass(el, "dojoMonthlyCalendarEvent");          
					el.appendChild(document.createTextNode(evts[y].summary.value));
					el.width = dojo.style.getContentWidth(node);
					node.appendChild(el);
				}
			}
		}
	},

	initUI: function() {
		this.selectedIsUsed = false;
		this.currentIsUsed = false;
		var currentClassName = "";
		var previousDate = new Date();
		var calendarNodes = this.calendarDatesContainerNode.getElementsByTagName("td");
		var currentCalendarNode;
		// set hours of date such that there is no chance of rounding error due to 
		// time change in local time zones
		previousDate.setHours(8);
		var nextDate = new Date(this.firstSaturday.year, this.firstSaturday.month, this.firstSaturday.date, 8);
		var lastDay = new Date(this.firstSaturday.year, this.firstSaturday.month, this.firstSaturday.date + 42, 8);
		
		if (this.iCalendars.length > 0) {
			for (var x=0; x<this.iCalendars.length;x++) {
				this.iCalendars[x].preComputeRecurringEvents(lastDay);
			}
		}

		if(this.firstSaturday.date < 7) {
			// this means there are days to show from the previous month
			var dayInWeek = 6;
			for (var i=this.firstSaturday.date; i>0; i--) {
				currentCalendarNode = calendarNodes.item(dayInWeek);
				this.createDayContents(currentCalendarNode, nextDate);
				
				dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
				dayInWeek--;
				previousDate = nextDate;
				nextDate = this.incrementDate(nextDate, false);
			}
			for(var i=dayInWeek; i>-1; i--) {
				currentCalendarNode = calendarNodes.item(i);

				this.createDayContents(currentCalendarNode, nextDate);

				dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "previous"));
				previousDate = nextDate;
				nextDate = this.incrementDate(nextDate, false);				
			}
		} else {
			nextDate.setDate(1);
			for(var i=0; i<7; i++) {
				currentCalendarNode = calendarNodes.item(i);
				this.createDayContents(currentCalendarNode, nextDate);
				dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
				previousDate = nextDate;
				nextDate = this.incrementDate(nextDate, true);				
			}
		}
		previousDate.setDate(this.firstSaturday.date);
		previousDate.setMonth(this.firstSaturday.month);
		previousDate.setFullYear(this.firstSaturday.year);
		nextDate = this.incrementDate(previousDate, true);
		var count = 7;
		currentCalendarNode = calendarNodes.item(count);
		while((nextDate.getMonth() == previousDate.getMonth()) && (count<42)) {
			this.createDayContents(currentCalendarNode, nextDate);
			dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
			currentCalendarNode = calendarNodes.item(++count);
			previousDate = nextDate;
			nextDate = this.incrementDate(nextDate, true);
		}
		
		while(count < 42) {
			this.createDayContents(currentCalendarNode, nextDate);
			dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "next"));
			currentCalendarNode = calendarNodes.item(++count);
			previousDate = nextDate;
			nextDate = this.incrementDate(nextDate, true);
		}
		this.setMonthLabel(this.firstSaturday.month);
		this.setYearLabels(this.firstSaturday.year);
	}	
});

__CPAN_FILE__ src/widget/html/LinkPane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.LinkPane");
dojo.provide("dojo.widget.html.LinkPane");

//
// a div that loads from a URL.  (Similar to an iframe, but
// it's in the same environment as the main window)
//

dojo.require("dojo.widget.LinkPane");
dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.ContentPane");
dojo.require("dojo.html");
dojo.require("dojo.style");
dojo.require("dojo.dom");
dojo.require("dojo.string");


dojo.widget.html.LinkPane = function(){
	dojo.widget.html.ContentPane.call(this);
}

dojo.inherits(dojo.widget.html.LinkPane, dojo.widget.html.ContentPane);

dojo.lang.extend(dojo.widget.html.LinkPane, {
	widgetType: "LinkPane",

	// I'm using a template because the user may specify the input as
	// <a href="foo.html">label</a>, in which case we need to get rid of the
	// <a> because we don't want a link.
	templateString: '<div class="dojoLinkPane"></div>',

	fillInTemplate: function(args, frag){
		var source = this.getFragNodeRef(frag);

		// If user has specified node contents, they become the label
		// (the link must be plain text)
		this.label += source.innerHTML;

		var source = this.getFragNodeRef(frag);
		dojo.html.copyStyle(this.domNode, source);
	}
});

__CPAN_FILE__ src/widget/html/stabile.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

// Maintain state of widgets when user hits back/forward button

dojo.provide("dojo.widget.html.stabile");

dojo.widget.html.stabile = {
	// Characters to quote in single-quoted regexprs
	_sqQuotables: new RegExp("([\\\\'])", "g"),

	// Current depth.
	_depth: 0,

	// Set to true when calling v.toString, to sniff for infinite
	// recursion.
	_recur: false,

	// Levels of nesting of Array and object displays.
	// If when >= depth, no display or array or object internals.
	depthLimit: 2
};





//// PUBLIC METHODS

// Get the state stored for the widget with the given ID, or undefined
// if none.
// 
dojo.widget.html.stabile.getState = function(id){
	dojo.widget.html.stabile.setup();
	return dojo.widget.html.stabile.widgetState[id];
}


// Set the state stored for the widget with the given ID.  If isCommit
// is true, commits all widget state to more stable storage.
// 
dojo.widget.html.stabile.setState = function(id, state, isCommit){
	dojo.widget.html.stabile.setup();
	dojo.widget.html.stabile.widgetState[id] = state;
	if(isCommit){
		dojo.widget.html.stabile.commit(dojo.widget.html.stabile.widgetState);
	}
}


// Sets up widgetState: a hash keyed by widgetId, maps to an object
// or array writable with "describe".  If there is data in the widget
// storage area, use it, otherwise initialize an empty object.
// 
dojo.widget.html.stabile.setup = function(){
	if(!dojo.widget.html.stabile.widgetState){
		var text = dojo.widget.html.stabile.getStorage().value;
		dojo.widget.html.stabile.widgetState = text ? dj_eval("("+text+")") : {};
	}
}


// Commits all widget state to more stable storage, so if the user
// navigates away and returns, it can be restored.
// 
dojo.widget.html.stabile.commit = function(state){
	dojo.widget.html.stabile.getStorage().value = dojo.widget.html.stabile.description(state);
}

// Return a JSON "description string" for the given value.
// Supports only core JavaScript types with literals, plus Date,
// and cyclic structures are unsupported.
// showAll defaults to false -- if true, this becomes a simple symbolic
// object dumper, but you cannot "eval" the output.
//
dojo.widget.html.stabile.description = function(v, showAll){
	// Save and later restore dojo.widget.html.stabile._depth;
	var depth = dojo.widget.html.stabile._depth;

	var describeThis = function() {
		 return this.description(this, true);
	} 
	
	try {

		if(v===void(0)){
			return "undefined";
		}
		if(v===null){
			return "null";
		}
		if(typeof(v)=="boolean" || typeof(v)=="number"
		    || v instanceof Boolean || v instanceof Number){
			return v.toString();
		}

		if(typeof(v)=="string" || v instanceof String){
			// Quote strings and their contents as required.
			// Replacing by $& fails in IE 5.0
			var v1 = v.replace(dojo.widget.html.stabile._sqQuotables, "\\$1"); 
			v1 = v1.replace(/\n/g, "\\n");
			v1 = v1.replace(/\r/g, "\\r");
			// Any other important special cases?
			return "'"+v1+"'";
		}

		if(v instanceof Date){
			// Create a data constructor.
			return "new Date("+d.getFullYear+","+d.getMonth()+","+d.getDate()+")";
		}

		var d;
		if(v instanceof Array || v.push){
			// "push" test needed for KHTML/Safari, don't know why -cp

			if(depth>=dojo.widget.html.stabile.depthLimit)
			  return "[ ... ]";

			d = "[";
			var first = true;
			dojo.widget.html.stabile._depth++;
			for(var i=0; i<v.length; i++){
				// Skip functions and undefined values
				// if(v[i]==undef || typeof(v[i])=="function")
				//   continue;
				if(first){
					first = false;
				}else{
					d += ",";
				}
				d+=arguments.callee(v[i], showAll);
			}
			return d+"]";
		}

		if(v.constructor==Object
		    || v.toString==describeThis){
			if(depth>=dojo.widget.html.stabile.depthLimit)
			  return "{ ... }";

			// Instanceof Hash is good, or if we just use Objects,
			// we can say v.constructor==Object.
			// IE (5?) lacks hasOwnProperty, but perhaps objects do not always
			// have prototypes??
			if(typeof(v.hasOwnProperty)!="function" && v.prototype){
				throw new Error("description: "+v+" not supported by script engine");
			}
			var first = true;
			d = "{";
			dojo.widget.html.stabile._depth++;
			for(var key in v){
				// Skip values that are functions or undefined.
				if(v[key]==void(0) || typeof(v[key])=="function")
					continue;
				if(first){
					first = false;
				}else{
					d += ", ";
				}
				var kd = key;
				// If the key is not a legal identifier, use its description.
				// For strings this will quote the stirng.
				if(!kd.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/)){
					kd = arguments.callee(key, showAll);
				}
				d += kd+": "+arguments.callee(v[key], showAll);
			}
			return d+"}";
		}

		if(showAll){
			if(dojo.widget.html.stabile._recur){
				// Save the original definitions of toString;
				var objectToString = Object.prototype.toString;
				return objectToString.apply(v, []);
			}else{
				dojo.widget.html.stabile._recur = true;
				return v.toString();
			}
		}else{
			// log("Description? "+v.toString()+", "+typeof(v));
			throw new Error("Unknown type: "+v);
			return "'unknown'";
		}

	} finally {
		// Always restore the global current depth.
		dojo.widget.html.stabile._depth = depth;
	}

}



//// PRIVATE TO MODULE

// Gets an object (form field) with a read/write "value" property.
// 
dojo.widget.html.stabile.getStorage = function(){
	if (dojo.widget.html.stabile.dataField) {
		return dojo.widget.html.stabile.dataField;
	}
	var form = document.forms._dojo_form;
	return dojo.widget.html.stabile.dataField = form ? form.stabile : {value: ""};
}


__CPAN_FILE__ src/widget/html/ComboBox.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.ComboBox");
dojo.require("dojo.widget.ComboBox");
dojo.require("dojo.widget.*");
dojo.require("dojo.io.*");
dojo.require("dojo.lfx.*");
dojo.require("dojo.dom");
dojo.require("dojo.html");
dojo.require("dojo.string");
dojo.require("dojo.widget.html.stabile");

dojo.widget.defineWidget(
	"dojo.widget.html.ComboBox",
	[dojo.widget.HtmlWidget, dojo.widget.ComboBox],
	{
		autoComplete: true,
		formInputName: "",
		name: "", // clone in the name from the DOM node
		textInputNode: null,
		comboBoxValue: null,
		comboBoxSelectionValue: null,
		optionsListWrapper: null,
		optionsListNode: null,
		downArrowNode: null,
		cbTableNode: null,
		searchTimer: null,
		searchDelay: 100,
		dataUrl: "",
		fadeTime: 200,
		// maxListLength limits list to X visible rows, scroll on rest 
		maxListLength: 8, 
		// mode can also be "remote" for JSON-returning live search or "html" for
		// dumber live search
		mode: "local", 
		selectedResult: null,
		_highlighted_option: null,
		_prev_key_backspace: false,
		_prev_key_esc: false,
		_result_list_open: false,
		_gotFocus: false,
		_mouseover_list: false,
		dataProviderClass: "dojo.widget.ComboBoxDataProvider",

		templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlComboBox.html"),
		templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlComboBox.css"),
	
		setValue: function(value) {
			this.comboBoxValue.value = value;
			if (this.textInputNode.value != value) { // prevent mucking up of selection
				this.textInputNode.value = value;
			}
			dojo.widget.html.stabile.setState(this.widgetId, this.getState(), true);
		},
	
		getValue: function() {
			return this.comboBoxValue.value;
		},
	
		getState: function() {
			return {value: this.getValue()};
		},
	
		setState: function(state) {
			this.setValue(state.value);
		},
	
		getCaretPos: function(element){
			// khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22
			if(dojo.lang.isNumber(element.selectionStart)){
				// FIXME: this is totally borked on Moz < 1.3. Any recourse?
				return element.selectionStart;
			}else if(dojo.render.html.ie){
				// in the case of a mouse click in a popup being handled,
				// then the document.selection is not the textarea, but the popup
				// var r = document.selection.createRange();
				// hack to get IE 6 to play nice. What a POS browser.
				var tr = document.selection.createRange().duplicate();
				var ntr = element.createTextRange();
				tr.move("character",0);
				ntr.move("character",0);
				try {
					// If control doesnt have focus, you get an exception.
					// Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).
					// There appears to be no workaround for this - googled for quite a while.
					ntr.setEndPoint("EndToEnd", tr);
					return String(ntr.text).replace(/\r/g,"").length;
				} catch (e) {
					return 0; // If focus has shifted, 0 is fine for caret pos.
				}
				
			}
		},
	
		setCaretPos: function(element, location){
			location = parseInt(location);
			this.setSelectedRange(element, location, location);
		},
	
		setSelectedRange: function(element, start, end){
			if(!end){ end = element.value.length; }  // NOTE: Strange - should be able to put caret at start of text?
			// Mozilla
			// parts borrowed from http://www.faqts.com/knowledge_base/view.phtml/aid/13562/fid/130
			if(element.setSelectionRange){
				element.focus();
				element.setSelectionRange(start, end);
			}else if(element.createTextRange){ // IE
				var range = element.createTextRange();
				with(range){
					collapse(true);
					moveEnd('character', end);
					moveStart('character', start);
					select();
				}
			}else{ //otherwise try the event-creation hack (our own invention)
				// do we need these?
				element.value = element.value;
				element.blur();
				element.focus();
				// figure out how far back to go
				var dist = parseInt(element.value.length)-end;
				var tchar = String.fromCharCode(37);
				var tcc = tchar.charCodeAt(0);
				for(var x = 0; x < dist; x++){
					var te = document.createEvent("KeyEvents");
					te.initKeyEvent("keypress", true, true, null, false, false, false, false, tcc, tcc);
					element.dispatchEvent(te);
				}
			}
		},
	
		// does the keyboard related stuff
		_handleKeyEvents: function(evt){
			if(evt.ctrlKey || evt.altKey){ return; }
	
			// reset these
			this._prev_key_backspace = false;
			this._prev_key_esc = false;
	
			var k = dojo.event.browser.keys;
			var doSearch = true;
	
			// mozilla quirk 
			// space has no keyCode in mozilla
			var keyCode = evt.keyCode;
			if(keyCode==0 && evt.charCode==k.KEY_SPACE){
				keyCode = k.KEY_SPACE;
			}
			switch(keyCode){
	 			case k.KEY_DOWN_ARROW:
					if(!this._result_list_open){
						this.startSearchFromInput();
					}
					this.highlightNextOption();
					dojo.event.browser.stopEvent(evt);
					return;
				case k.KEY_UP_ARROW:
					this.highlightPrevOption();
					dojo.event.browser.stopEvent(evt);
					return;
				case k.KEY_ENTER:
					// prevent submitting form if we press enter with list open
					if(this._result_list_open){
						dojo.event.browser.stopEvent(evt);
					}
					// fallthrough
				case k.KEY_TAB:
					// using linux alike tab for autocomplete
					if(!this.autoComplete && this._result_list_open && this._highlighted_option){
						dojo.event.browser.stopEvent(evt);
						this.selectOption({ 'target': this._highlighted_option, 'noHide': true });
	
						// put caret last
						this.setSelectedRange(this.textInputNode, this.textInputNode.value.length, null);
					}else{
						this.selectOption();
						return;
					}
					break;
				case k.KEY_SPACE:
					if(this._result_list_open && this._highlighted_option){
						dojo.event.browser.stopEvent(evt);
						this.selectOption();
						this.hideResultList();
						return;
					}
					break;
				case k.KEY_ESCAPE:
					this.hideResultList();
					this._prev_key_esc = true;
					return;
				case k.KEY_BACKSPACE:
					this._prev_key_backspace = true;
					if(!this.textInputNode.value.length){
						this.setAllValues("", "");
						this.hideResultList();
						doSearch = false;
					}
					break;
				case k.KEY_RIGHT_ARROW: // fall through
				case k.KEY_LEFT_ARROW: // fall through
				case k.KEY_SHIFT:
					doSearch = false;
					break;
				default:// non char keys (F1-F12 etc..)  shouldn't open list
					if(evt.charCode==0){
						doSearch = false;
					}
			}
	
			if(this.searchTimer){
				clearTimeout(this.searchTimer);
			}
			if(doSearch){
				// if we have gotten this far we dont want to keep our highlight
				this.blurOptionNode();
	
				// need to wait a tad before start search so that the event bubbles through DOM and we have value visible
				this.searchTimer = setTimeout(dojo.lang.hitch(this, this.startSearchFromInput), this.searchDelay);
			}
		},
	
		onKeyDown: function(evt){
			// IE needs to stop keyDown others need to stop keyPress
			if(!document.createEvent){ // only IE
				this._handleKeyEvents(evt);
			}
			// FIXME: What about ESC ??
		},
	
		onKeyPress: function(evt){
			if(document.createEvent){ // never IE
				this._handleKeyEvents(evt);
			}
		},
	
		onKeyUp: function(evt){
			this.setValue(this.textInputNode.value);
		},
	
		setSelectedValue: function(value){
			// FIXME, not sure what to do here!
			this.comboBoxSelectionValue.value = value;
		},

		setAllValues: function(value1, value2){
			this.setValue(value1);
			this.setSelectedValue(value2);
		},
	
		// opera, khtml, safari doesnt support node.scrollIntoView(), workaround
		scrollIntoView: function(){
			var node = this._highlighted_option;
			var parent = this.optionsListNode;
			// don't rely on that node.scrollIntoView works just because the function is there
			// it doesnt work in Konqueror or Opera even though the function is there and probably
			// not safari either
			// dont like browser sniffs implementations but sometimes you have to use it
			if(dojo.render.html.ie || dojo.render.html.mozilla){
				// IE, mozilla
				node.scrollIntoView(false);	
			}else{
				var parentBottom = parent.scrollTop + dojo.style.getInnerHeight(parent);
				var nodeBottom = node.offsetTop + dojo.style.getOuterHeight(node);
				if(parentBottom < nodeBottom){
					parent.scrollTop += (nodeBottom - parentBottom);
				}else if(parent.scrollTop > node.offsetTop){
					parent.scrollTop -= (parent.scrollTop - node.offsetTop);
				}
			}
		},
	
		// does the actual highlight
		focusOptionNode: function(node){
			if(this._highlighted_option != node){
				this.blurOptionNode();
				this._highlighted_option = node;
				dojo.html.addClass(this._highlighted_option, "dojoComboBoxItemHighlight");
			}
		},
	
		// removes highlight on highlighted
		blurOptionNode: function(){
			if(this._highlighted_option){
				dojo.html.removeClass(this._highlighted_option, "dojoComboBoxItemHighlight");
				this._highlighted_option = null;
			}
		},
	
		highlightNextOption: function(){
			if((!this._highlighted_option) || !this._highlighted_option.parentNode){
				this.focusOptionNode(this.optionsListNode.firstChild);
			}else if(this._highlighted_option.nextSibling){
				this.focusOptionNode(this._highlighted_option.nextSibling);
			}
			this.scrollIntoView();
		},
	
		highlightPrevOption: function(){
			if(this._highlighted_option && this._highlighted_option.previousSibling){
				this.focusOptionNode(this._highlighted_option.previousSibling);
			}else{
				this._highlighted_option = null;
				this.hideResultList();
				return;
			}
			this.scrollIntoView();
		},
	
		itemMouseOver: function(evt){
			this.focusOptionNode(evt.target);
			dojo.html.addClass(this._highlighted_option, "dojoComboBoxItemHighlight");
		},
	
		itemMouseOut: function(evt){
			this.blurOptionNode();
		},
	
		fillInTemplate: function(args, frag){
			// FIXME: need to get/assign DOM node names for form participation here.
			this.comboBoxValue.name = this.name;
			this.comboBoxSelectionValue.name = this.name+"_selected";
	
			var source = this.getFragNodeRef(frag);
			dojo.html.copyStyle(this.domNode, source);
	
			var dpClass;
			if(this.mode == "remote"){
				dpClass = dojo.widget.incrementalComboBoxDataProvider;
			}else if(typeof this.dataProviderClass == "string"){
				dpClass = dojo.evalObjPath(this.dataProviderClass)
			}else{
				dpClass = this.dataProviderClass;
			}
			this.dataProvider = new dpClass();
			this.dataProvider.init(this, this.getFragNodeRef(frag));
	
			// Prevent IE bleed-through problem
			this.optionsIframe = new dojo.html.BackgroundIframe(this.optionsListWrapper);
			this.optionsIframe.size([0,0,0,0]);
		},
	
	
		focus: function(){
			// summary
			//	set focus to input node from code
			this.tryFocus();
		},
	
		openResultList: function(results){
			this.clearResultList();
			if(!results.length){
				this.hideResultList();
			}
	
			if(	(this.autoComplete)&&
				(results.length)&&
				(!this._prev_key_backspace)&&
				(this.textInputNode.value.length > 0)){
				var cpos = this.getCaretPos(this.textInputNode);
				// only try to extend if we added the last character at the end of the input
				if((cpos+1) > this.textInputNode.value.length){
					// only add to input node as we would overwrite Capitalisation of chars
					this.textInputNode.value += results[0][0].substr(cpos);
					// build a new range that has the distance from the earlier
					// caret position to the end of the first string selected
					this.setSelectedRange(this.textInputNode, cpos, this.textInputNode.value.length);
				}
			}
	
			var even = true;
			while(results.length){
				var tr = results.shift();
				if(tr){
					var td = document.createElement("div");
					td.appendChild(document.createTextNode(tr[0]));
					td.setAttribute("resultName", tr[0]);
					td.setAttribute("resultValue", tr[1]);
					td.className = "dojoComboBoxItem "+((even) ? "dojoComboBoxItemEven" : "dojoComboBoxItemOdd");
					even = (!even);
					this.optionsListNode.appendChild(td);
					dojo.event.connect(td, "onmouseover", this, "itemMouseOver");
					dojo.event.connect(td, "onmouseout", this, "itemMouseOut");
				}
			}
	
			// show our list (only if we have content, else nothing)
			this.showResultList();
		},
	
		onFocusInput: function(){
			this._hasFocus = true;
		},
	
		onBlurInput: function(){
			this._hasFocus = false;
			this._handleBlurTimer(true, 500);
		},
	
		// collect all blur timers issues here
		_handleBlurTimer: function(/*Boolean*/clear, /*Number*/ millisec){
			if(this.blurTimer && (clear || millisec)){
				clearTimeout(this.blurTimer);
			}
			if(millisec){ // we ignore that zero is false and never sets as that never happens in this widget
				this.blurTimer = dojo.lang.setTimeout(this, "checkBlurred", millisec);
			}
		},
	
		// these 2 are needed in IE and Safari as inputTextNode loses focus when scrolling optionslist
		_onMouseOver: function(evt){
			if(!this._mouseover_list){
				this._handleBlurTimer(true, 0);
				this._mouseover_list = true;
			}
		},
	
		_onMouseOut:function(evt){
			var relTarget = evt.relatedTarget;
			if(!relTarget || relTarget.parentNode!=this.optionsListNode){
				this._mouseover_list = false;
				this._handleBlurTimer(true, 100);
				this.tryFocus();
			}
		},
	
		_isInputEqualToResult: function(result){
			input = this.textInputNode.value;
			if(!this.dataProvider.caseSensitive){
				input = input.toLowerCase();
				result = result.toLowerCase();
			}
			return (input == result);
		},

		_isValidOption: function(){
			tgt = dojo.dom.firstElement(this.optionsListNode);
			isValidOption = false;
			while(!isValidOption && tgt){
				if(this._isInputEqualToResult(tgt.getAttribute("resultName"))){
					isValidOption = true;
				}else{
					tgt = dojo.dom.nextElement(tgt);
				}
			}
			return isValidOption;
		},

		checkBlurred: function(){
			if(!this._hasFocus && !this._mouseover_list){
				this.hideResultList();
				// clear the list if the user empties field and moves away.
				if(!this.textInputNode.value.length){
					this.setAllValues("", "");
					return;
				}
				
				isValidOption = this._isValidOption();
				// enforce selection from option list
				if(this.forceValidOption && !isValidOption){
					this.setAllValues("", "");
					return;
				}
				if(!isValidOption){// clear
					this.setSelectedValue("");
				}
			}
		},
	
		sizeBackgroundIframe: function(){
			var w = dojo.style.getOuterWidth(this.optionsListNode);
			var h = dojo.style.getOuterHeight(this.optionsListNode);
			if( w==0 || h==0 ){
				// need more time to calculate size
				dojo.lang.setTimeout(this, "sizeBackgroundIframe", 100);
				return;
			}
			if(this._result_list_open){
				this.optionsIframe.size([0,0,w,h]);
			}
		},
	
		selectOption: function(evt){
			var tgt = null;
			if(!evt){
				evt = { target: this._highlighted_option };
			}
	
			if(!dojo.dom.isDescendantOf(evt.target, this.optionsListNode)){
				// handle autocompletion where the the user has hit ENTER or TAB
	
				// if the input is empty do nothing
				if(!this.textInputNode.value.length){
					return;
				}
				tgt = dojo.dom.firstElement(this.optionsListNode);
	
				// user has input value not in option list
				if(!tgt || !this._isInputEqualToResult(tgt.getAttribute("resultName"))){
					return;
				}
				// otherwise the user has accepted the autocompleted value
			}else{
				tgt = evt.target; 
			}
	
			while((tgt.nodeType!=1)||(!tgt.getAttribute("resultName"))){
				tgt = tgt.parentNode;
				if(tgt === document.body){
					return false;
				}
			}
	
			this.textInputNode.value = tgt.getAttribute("resultName");
			this.selectedResult = [tgt.getAttribute("resultName"), tgt.getAttribute("resultValue")];
			this.setAllValues(tgt.getAttribute("resultName"), tgt.getAttribute("resultValue"));
			if(!evt.noHide){
				this.hideResultList();
				this.setSelectedRange(this.textInputNode, 0, null);
			}
			this.tryFocus();
		},
	
		clearResultList: function(){
			var oln = this.optionsListNode;
			while(oln.firstChild){
				dojo.event.disconnect(oln.firstChild, "onmouseover", this, "itemMouseOver");
				dojo.event.disconnect(oln.firstChild, "onmouseout", this, "itemMouseOut");
				oln.removeChild(oln.firstChild);
			}
		},
	
		hideResultList: function(){
			if(this._result_list_open){
				this._result_list_open = false;
				this.optionsIframe.size([0,0,0,0]);
				dojo.lfx.fadeHide(this.optionsListNode, this.fadeTime).play();
			}
		},
	
		showResultList: function(){
			// Our dear friend IE doesnt take max-height so we need to calculate that on our own every time
			var childs = this.optionsListNode.childNodes;
			if(childs.length){
				var visibleCount = this.maxListLength;
				if(childs.length < visibleCount){
					visibleCount = childs.length;
				}
	
				with(this.optionsListNode.style){
					display = "";
					height = ((visibleCount) ? (dojo.style.getOuterHeight(childs[0]) * visibleCount) : 0)+"px";
					width = dojo.html.getOuterWidth(this.cbTableNode)-2+"px";
				}
				// only fadein once (flicker)
				if(!this._result_list_open){
					dojo.html.setOpacity(this.optionsListNode, 0);
					dojo.lfx.fadeIn(this.optionsListNode, this.fadeTime).play();
				}
				
				// prevent IE bleed through
				this._iframeTimer = dojo.lang.setTimeout(this, "sizeBackgroundIframe", 200);
				this._result_list_open = true;
			}else{
				this.hideResultList();
			}
		},
	
		handleArrowClick: function(){
			this._handleBlurTimer(true, 0);
			this.tryFocus();
			if(this._result_list_open){
				this.hideResultList();
			}else{
				this.startSearchFromInput();
			}
		},
	
		tryFocus: function(){
			try {
				this.textInputNode.focus();
			} catch (e) {
				// element isn't focusable if disabled, or not visible etc - not easy to test for.
	 		};
		},
		
		startSearchFromInput: function(){
			this.startSearch(this.textInputNode.value);
		},
	
		postCreate: function(){
			dojo.event.connect(this, "startSearch", this.dataProvider, "startSearch");
			dojo.event.connect(this.dataProvider, "provideSearchResults", this, "openResultList");
			dojo.event.connect(this.textInputNode, "onblur", this, "onBlurInput");
			dojo.event.connect(this.textInputNode, "onfocus", this, "onFocusInput");
	
			var s = dojo.widget.html.stabile.getState(this.widgetId);
			if (s) {
				this.setState(s);
			}
		}
	}
);

__CPAN_FILE__ src/widget/html/YahooMap.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.YahooMap");
dojo.require("dojo.event.*");
dojo.require("dojo.html");
dojo.require("dojo.math");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.YahooMap");

(function(){
	var yappid = djConfig["yAppId"]||djConfig["yahooAppId"]||"dojotoolkit";
	if(!dojo.hostenv.post_load_){
		if(yappid == "dojotoolkit"){
			dojo.debug("please provide a unique Yahoo App ID in djConfig.yahooAppId when using the map widget");
		}
		var tag = "<scr"+"ipt src='http://api.maps.yahoo.com/ajaxymap?v=3.0&appid="+yappid+"'></scri"+"pt>";
		if(!dj_global["YMap"]){
			document.write(tag);
		}
	}else{
		dojo.debug("cannot initialize map system after the page has been loaded! Please either manually include the script block provided by Yahoo in your page or require() the YahooMap widget before onload has fired");
	}
})();

dojo.widget.html.YahooMap=function(){
	dojo.widget.HtmlWidget.call(this);
	dojo.widget.YahooMap.call(this);

	this.map=null;
	this.datasrc="";
	this.data=[];
	this.width=0;
	this.height=0;
	this.controls=["zoomlong","maptype","pan"];
};
dojo.inherits(dojo.widget.html.YahooMap, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.YahooMap, {
	widgetType: "YahooMap",
	templatePath:null,
	templateCssPath:null,

	findCenter:function(aPts){
		var start=new YGeoPoint(37,-90);
		if(aPts.length==0) return start;
		var minLat,maxLat, minLon, maxLon, cLat, cLon;
		minLat=maxLat=aPts[0].Lat;
		minLon=maxLon=aPts[0].Lon;
		for(var i=0; i<aPts.length; i++){
			minLat=Math.min(minLat,aPts[i].Lat);
			maxLat=Math.max(maxLat,aPts[i].Lat);
			minLon=Math.min(minLon,aPts[i].Lon);
			maxLon=Math.max(maxLon,aPts[i].Lon);
		}
		cLat=dojo.math.round((minLat+maxLat)/2,6);
		cLon=dojo.math.round((minLon+maxLon)/2,6);
		return new YGeoPoint(cLat,cLon);
	},
	setControls:function(){
		var c=this.controls;
		var t=dojo.widget.YahooMap.Controls;
		for(var i=0; i<c.length; i++){
			switch(c[i]){
				case t.MapType:{
					this.map.addTypeControl();
					break;
				}
				case t.Pan:{
					this.map.addPanControl();
					break;
				}
				case t.ZoomLong:{
					this.map.addZoomLong();
					break;
				}
				case t.ZoomShort:{
					this.map.addZoomShort();
					break;
				}
			}
		}
	},
	
	parse:function(table){
		this.data=[];

		//	get the column indices
		var h=table.getElementsByTagName("thead")[0];
		if(!h){
			return;
		}

		var a=[];
		var cols=h.getElementsByTagName("td");
		if(cols.length==0){
			cols=h.getElementsByTagName("th");
		}
		for(var i=0; i<cols.length; i++){
			var c=cols[i].innerHTML.toLowerCase();
			if(c=="long") c="lng";
			a.push(c);
		}
		
		//	parse the data
		var b=table.getElementsByTagName("tbody")[0];
		if(!b){
			return;
		}
		for(var i=0; i<b.childNodes.length; i++){
			if(!(b.childNodes[i].nodeName&&b.childNodes[i].nodeName.toLowerCase()=="tr")){
				continue;
			}
			var cells=b.childNodes[i].getElementsByTagName("td");
			var o={};
			for(var j=0; j<a.length; j++){
				var col=a[j];
				if(col=="lat"||col=="lng"){
					o[col]=parseFloat(cells[j].innerHTML);					
				}else{
					o[col]=cells[j].innerHTML;
				}
			}
			this.data.push(o);
		}
	},
	render:function(){
		var pts=[];
		var d=this.data;
		for(var i=0; i<d.length; i++){
			var pt=new YGeoPoint(d[i].lat, d[i].lng);
			pts.push(pt);
			var icon=d[i].icon||null;
			if(icon){
				icon=new YImage(icon);
			}
			var m=new YMarker(pt,icon);
			if(d[i].description){
				m.addAutoExpand("<div>"+d[i].description+"</div>");
			}
			this.map.addOverlay(m);
		}
		var c=this.findCenter(pts);
		var z=this.map.getZoomLevel(pts);
		this.map.drawZoomAndCenter(c,z);
	},
	
	initialize:function(args, frag){
		if(!YMap || !YGeoPoint){
			dojo.raise("dojo.widget.YahooMap: The Yahoo Map script must be included in order to use this widget.");
		}
		if(this.datasrc){
			this.parse(dojo.byId(this.datasrc));
		}
		else if(this.domNode.getElementsByTagName("table")[0]){
			this.parse(this.domNode.getElementsByTagName("table")[0]);
		}
	},
	postCreate:function(){
		//	clean the domNode before creating the map.
		while(this.domNode.childNodes.length>0){
			this.domNode.removeChild(this.domNode.childNodes[0]);
		}

		if(this.width>0&&this.height>0){
			this.map=new YMap(this.domNode, YAHOO_MAP_REG, new YSize(this.width, this.height));
		}else{
			this.map=new YMap(this.domNode);
		}
		this.setControls();
		this.render();
	}
});

__CPAN_FILE__ src/widget/html/SortableTable.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.SortableTable");
dojo.require("dojo.lang");
dojo.require("dojo.date");
dojo.require("dojo.html");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.SortableTable");

dojo.widget.html.SortableTable=function(){
	//	summary
	//	Constructor for the SortableTable widget
	dojo.widget.SortableTable.call(this);
	dojo.widget.HtmlWidget.call(this);

	this.headClass="";
	this.tbodyClass="";
	this.headerClass="";
	this.headerSortUpClass="selected";
	this.headerSortDownClass="selected";
	this.rowClass="";
	this.rowAlternateClass="alt";
	this.rowSelectedClass="selected";
	this.columnSelected="sorted-column";
};
dojo.inherits(dojo.widget.html.SortableTable, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.SortableTable, {
	templatePath:null,
	templateCssPath:null,

	getTypeFromString:function(/* string */ s){
		//	summary
		//	Find the constructor that matches param s by searching through the entire object tree.
		var parts=s.split("."),i=0,obj=dj_global; 
		do{obj=obj[parts[i++]];}while(i<parts.length&&obj); 
		return(obj!=dj_global)?obj:null;	//	function
	},
	compare:function(/* object */ o1, /* object */ o2){
		//	summary
		//	Compare two objects using a shallow property compare
		for(var p in o1){
			if(!(p in o2)) return false;	//	boolean
			if(o1[p].valueOf()!=o2[p].valueOf()) return false;	//	boolean
		}
		return true;	// boolean
	},
	isSelected:function(/* object */ o){
		//	summary
		//	checked to see if the passed object is in the current selection.
		for(var i=0;i<this.selected.length;i++){
			if(this.compare(this.selected[i],o)){
				return true; // boolean
			}
		}
		return false;	// boolean
	},
	removeFromSelected:function(/* object */ o){
		//	summary
		//	remove the passed object from the current selection.
		var idx=-1;
		for(var i=0;i<this.selected.length;i++){
			if(this.compare(this.selected[i],o)){
				idx=i;
				break;
			}
		}
		if(idx>=0){
			this.selected.splice(idx,1);
		}
	},
	getSelection:function(){
		//	summary
		//	return the array of currently selected objects (JSON format)
		return this.selected;	//	array
	},
	getValue:function(){
		//	summary
		//	return a comma-delimited list of selected valueFields.
		var a=[];
		for(var i=0;i<this.selected.length;i++){
			if (this.selected[i][this.valueField]){
				a.push(this.selected[i][this.valueField]);
			}
		}
		return a.join();	//	string
	},
	reset:function(){
		//	summary
		//	completely resets the internal representations.
		this.columns=[];
		this.data=[];
		this.resetSelections(this.domNode.getElementsByTagName("tbody")[0]);
	},
	resetSelections:function(/* HTMLTableBodyElement */ body){
		this.selected=[];
		var idx=0;
		var rows=body.getElementsByTagName("tr");
		for(var i=0; i<rows.length; i++){
			if(rows[i].parentNode==body){
				rows[i].removeAttribute("selected");
				if(this.enableAlternateRows&&idx%2==1){
					rows[i].className=this.rowAlternateClass;
				}else{
					rows[i].className="";
				}
				idx++;
			}
		}
	},

	getObjectFromRow:function(/* HTMLTableRowElement */ row){
		//	summary
		//	creates a JSON object based on the passed row
		var cells=row.getElementsByTagName("td");
		var o={};
		for(var i=0; i<this.columns.length;i++){
			if(this.columns[i].sortType=="__markup__"){
				//	FIXME: should we parse this instead?  Because if the user may not get back the markup they put in...
				o[this.columns[i].getField()]=cells[i].innerHTML;
			}else{
				var text=dojo.html.renderedTextContent(cells[i]);
				var val=new (this.columns[i].getType())(text);
				o[this.columns[i].getField()]=val;
			}
		}
		if(dojo.html.hasAttribute(row,"value")){
			o[this.valueField]=dojo.html.getAttribute(row,"value");
		}
		return o;	//	object
	},
	setSelectionByRow:function(/* HTMLTableElementRow */ row){
		//	summary
		//	create the selection object based on the passed row, makes sure it's unique.
		//	note that you need to call render manually (because of multi-select operations)
		var o=this.getObjectFromRow(row);
		var b=false;
		for(var i=0;i<this.selected.length;i++){
			if(this.compare(this.selected[i], o)){
				b=true;
				break;
			}
		}
		if(!b){
			this.selected.push(o);
		}
	},

	parseColumns:function(/* HTMLTableHeadElement */ node){
		//	summary
		//	parses the passed element to create column objects
		this.reset();
		var row=node.getElementsByTagName("tr")[0];
		var cells=row.getElementsByTagName("td");
		if (cells.length==0) cells=row.getElementsByTagName("th");
		for(var i=0; i<cells.length; i++){
			var o={
				field:null,
				format:null,
				noSort:false,
				sortType:"String",
				dataType:String,
				sortFunction:null,
				label:null,
				align:"left",
				valign:"middle",
				getField:function(){ return this.field||this.label; },
				getType:function(){ return this.dataType; }
			};
			//	presentation attributes
			if(dojo.html.hasAttribute(cells[i], "align")){
				o.align=dojo.html.getAttribute(cells[i],"align");
			}
			if(dojo.html.hasAttribute(cells[i], "valign")){
				o.valign=dojo.html.getAttribute(cells[i],"valign");
			}

			//	sorting features.
			if(dojo.html.hasAttribute(cells[i], "nosort")){
				o.noSort=dojo.html.getAttribute(cells[i],"nosort")=="true";
			}
			if(dojo.html.hasAttribute(cells[i], "sortusing")){
				var trans=dojo.html.getAttribute(cells[i],"sortusing");
				var f=this.getTypeFromString(trans);
				if (f!=null && f!=window && typeof(f)=="function") 
					o.sortFunction=f;
			}

			if(dojo.html.hasAttribute(cells[i], "field")){
				o.field=dojo.html.getAttribute(cells[i],"field");
			}
			if(dojo.html.hasAttribute(cells[i], "format")){
				o.format=dojo.html.getAttribute(cells[i],"format");
			}
			if(dojo.html.hasAttribute(cells[i], "dataType")){
				var sortType=dojo.html.getAttribute(cells[i],"dataType");
				if(sortType.toLowerCase()=="html"||sortType.toLowerCase()=="markup"){
					o.sortType="__markup__";	//	always convert to "__markup__"
					o.noSort=true;
				}else{
					var type=this.getTypeFromString(sortType);
					if(type){
						o.sortType=sortType;
						o.dataType=type;
					}
				}
			}
			o.label=dojo.html.renderedTextContent(cells[i]);
			this.columns.push(o);

			//	check to see if there's a default sort, and set the properties necessary
			if(dojo.html.hasAttribute(cells[i], "sort")){
				this.sortIndex=i;
				var dir=dojo.html.getAttribute(cells[i], "sort");
				if(!isNaN(parseInt(dir))){
					dir=parseInt(dir);
					this.sortDirection=(dir!=0)?1:0;
				}else{
					this.sortDirection=(dir.toLowerCase()=="desc")?1:0;
				}
			}
		}
	},

	parseData:function(/* array */ data){
		//	summary
		//	Parse the passed JSON data structure, and cast based on columns.
		this.data=[];
		this.selected=[];
		for(var i=0; i<data.length; i++){
			var o={};	//	new data object.
			for(var j=0; j<this.columns.length; j++){
				var field=this.columns[j].getField();
				if(this.columns[j].sortType=="__markup__"){
					o[field]=String(data[i][field]);
				}else{
					var type=this.columns[j].getType();
					var val=data[i][field];
					var t=this.columns[j].sortType.toLowerCase();
					if(val){
						o[field]=new type(val);
					}else{
						o[field]=new type();	//	let it use the default.
					}
				}
			}
			//	check for the valueField if not already parsed.
			if(data[i][this.valueField]&&!o[this.valueField]){
				o[this.valueField]=data[i][this.valueField];
			}
			this.data.push(o);
		}
	}, 

	parseDataFromTable:function(/* HTMLTableBodyElement */ tbody){
		//	summary
		//	parses the data in the tbody of a table to create a set of objects.
		//	Will add objects to this.selected if an attribute 'selected="true"' is present on the row.
		this.data=[];
		this.selected=[];
		var rows=tbody.getElementsByTagName("tr");
		for(var i=0; i<rows.length; i++){
			if(dojo.html.getAttribute(rows[i],"ignoreIfParsed")=="true"){
				continue;
			}
			var o={};	//	new data object.
			var cells=rows[i].getElementsByTagName("td");
			for(var j=0; j<this.columns.length; j++){
				var field=this.columns[j].getField();
				if(this.columns[j].sortType=="__markup__"){
					//	FIXME: parse this?
					o[field]=cells[j].innerHTML;
				}else{
					var type=this.columns[j].getType();
					var val=dojo.html.renderedTextContent(cells[j]); //	should be the same index as the column.
					if (val) o[field]=new type(val);
					else o[field]=new type();	//	let it use the default.
				}
			}
			if(dojo.html.hasAttribute(rows[i],"value")&&!o[this.valueField]){
				o[this.valueField]=dojo.html.getAttribute(rows[i],"value");
			}
			//	FIXME: add code to preserve row attributes in __metadata__ field?
			this.data.push(o);
			
			//	add it to the selections if selected="true" is present.
			if(dojo.html.getAttribute(rows[i],"selected")=="true"){
				this.selected.push(o);
			}
		}
	},
	
	showSelections:function(){
		var body=this.domNode.getElementsByTagName("tbody")[0];
		var rows=body.getElementsByTagName("tr");
		var idx=0;
		for(var i=0; i<rows.length; i++){
			if(rows[i].parentNode==body){
				if(dojo.html.getAttribute(rows[i],"selected")=="true"){
					rows[i].className=this.rowSelectedClass;
				} else {
					if(this.enableAlternateRows&&idx%2==1){
						rows[i].className=this.rowAlternateClass;
					}else{
						rows[i].className="";
					}
				}
				idx++;
			}
		}
	},
	render:function(bDontPreserve){
		//	summary
		//	renders the table to the browser
		var data=[];
		var body=this.domNode.getElementsByTagName("tbody")[0];

		if(!bDontPreserve){
			//	rebuild data and selection
			this.parseDataFromTable(body);
		}

		//	clone this.data for sorting purposes.
		for(var i=0; i<this.data.length; i++){
			data.push(this.data[i]);
		}
		
		var col=this.columns[this.sortIndex];
		if(!col.noSort){
			var field=col.getField();
			if(col.sortFunction){
				var sort=col.sortFunction;
			}else{
				var sort=function(a,b){
					if (a[field]>b[field]) return 1;
					if (a[field]<b[field]) return -1;
					return 0;
				}
			}
			data.sort(sort);
			if(this.sortDirection!=0) data.reverse();
		}

		//	build the table and pop it in.
		while(body.childNodes.length>0) body.removeChild(body.childNodes[0]);
		for(var i=0; i<data.length;i++){
			var row=document.createElement("tr");
			dojo.html.disableSelection(row);
			if (data[i][this.valueField]){
				row.setAttribute("value",data[i][this.valueField]);
			}
			if(this.isSelected(data[i])){
				row.className=this.rowSelectedClass;
				row.setAttribute("selected","true");
			} else {
				if(this.enableAlternateRows&&i%2==1){
					row.className=this.rowAlternateClass;
				}
			}
			for(var j=0;j<this.columns.length;j++){
				var cell=document.createElement("td");
				cell.setAttribute("align", this.columns[j].align);
				cell.setAttribute("valign", this.columns[j].valign);
				dojo.html.disableSelection(cell);
				if(this.sortIndex==j){
					cell.className=this.columnSelected;
				}
				if(this.columns[j].sortType=="__markup__"){
					cell.innerHTML=data[i][this.columns[j].getField()];
					for(var k=0; k<cell.childNodes.length; k++){
						var node=cell.childNodes[k];
						if(node&&node.nodeType==dojo.html.ELEMENT_NODE){
							dojo.html.disableSelection(node);
						}
					}
				}else{
					if(this.columns[j].getType()==Date){
						var format=this.defaultDateFormat;
						if(this.columns[j].format) format=this.columns[j].format;
						cell.appendChild(document.createTextNode(dojo.date.format(data[i][this.columns[j].getField()], format)));
					}else{
						cell.appendChild(document.createTextNode(data[i][this.columns[j].getField()]));
					}
				}
				row.appendChild(cell);
			}
			body.appendChild(row);
			dojo.event.connect(row, "onclick", this, "onUISelect");
		}
		
		//	if minRows exist.
		var minRows=parseInt(this.minRows);
		if (!isNaN(minRows) && minRows>0 && data.length<minRows){
			var mod=0;
			if(data.length%2==0) mod=1;
			var nRows=minRows-data.length;
			for(var i=0; i<nRows; i++){
				var row=document.createElement("tr");
				row.setAttribute("ignoreIfParsed","true");
				if(this.enableAlternateRows&&i%2==mod){
					row.className=this.rowAlternateClass;
				}
				for(var j=0;j<this.columns.length;j++){
					var cell=document.createElement("td");
					cell.appendChild(document.createTextNode("\u00A0"));
					row.appendChild(cell);
				}
				body.appendChild(row);
			}
		}
	},

	//	the following the user can override.
	onSelect:function(/* DomEvent */ e){ 
		//	summary
		//	empty function for the user to attach code to, fired by onUISelect
	},
	onUISelect:function(/* DomEvent */ e){
		//	summary
		//	fired when a user selects a row
		var row=dojo.html.getParentByType(e.target,"tr");
		var body=dojo.html.getParentByType(row,"tbody");
		if(this.enableMultipleSelect){
			if(e.metaKey||e.ctrlKey){
				if(this.isSelected(this.getObjectFromRow(row))){
					this.removeFromSelected(this.getObjectFromRow(row));
					row.removeAttribute("selected");
				}else{
					//	push onto the selection stack.
					this.setSelectionByRow(row);
					row.setAttribute("selected","true");
				}
			}else if(e.shiftKey){
				//	the tricky one.  We need to figure out the *last* selected row above, 
				//	and select all the rows in between.
				var startRow;
				var rows=body.getElementsByTagName("tr");
				//	if there's a selection above, we go with that first. 
				for(var i=0;i<rows.length;i++){
					if(rows[i].parentNode==body){
						if(rows[i]==row) break;
						if(dojo.html.getAttribute(rows[i],"selected")=="true"){
							startRow=rows[i];
						}
					}
				}
				//	if there isn't a selection above, we continue with a selection below.
				if(!startRow){
					startRow=row;
					for(;i<rows.length;i++){
						if(dojo.html.getAttribute(rows[i],"selected")=="true"){
							row=rows[i];
							break;
						}
					}
				}
				this.resetSelections(body);
				if(startRow==row){
					//	this is the only selection
					row.setAttribute("selected","true");
					this.setSelectionByRow(row);
				}else{
					var doSelect=false;
					for(var i=0; i<rows.length; i++){
						if(rows[i].parentNode==body){
							rows[i].removeAttribute("selected");
							if(rows[i]==startRow){
								doSelect=true;
							}
							if(doSelect){
								this.setSelectionByRow(rows[i]);
								rows[i].setAttribute("selected","true");
							}
							if(rows[i]==row){
								doSelect=false;
							}
						}
					}
				}
			}else{
				//	reset the selection
				this.resetSelections(body);
				row.setAttribute("selected","true");
				this.setSelectionByRow(row);
			}
		}else{
			//	reset the data selection and go.
			this.resetSelections(body);
			row.setAttribute("selected","true");
			this.setSelectionByRow(row);
		}
		this.showSelections();
		this.onSelect(e);
		e.stopPropagation();
		e.preventDefault();
	},
	onHeaderClick:function(/* DomEvent */ e){
		//	summary
		//	Main handler function for each header column click.
		var oldIndex=this.sortIndex;
		var oldDirection=this.sortDirection;
		var source=e.target;
		var row=dojo.html.getParentByType(source,"tr");
		var cellTag="td";
		if(row.getElementsByTagName(cellTag).length==0) cellTag="th";

		var headers=row.getElementsByTagName(cellTag);
		var header=dojo.html.getParentByType(source,cellTag);
		
		for(var i=0; i<headers.length; i++){
			if(headers[i]==header){
				if(i!=oldIndex){
					//	new col.
					this.sortIndex=i;
					this.sortDirection=0;
					headers[i].className=this.headerSortDownClass
				}else{
					this.sortDirection=(oldDirection==0)?1:0;
					if(this.sortDirection==0){
						headers[i].className=this.headerSortDownClass;
					}else{
						headers[i].className=this.headerSortUpClass;
					}
				}
			}else{
				//	reset the header class.
				headers[i].className=this.headerClass;
			}
		}
		this.render();
	},

	postCreate:function(){ 
		// 	summary
		//	overridden from HtmlWidget, initializes and renders the widget.
		var thead=this.domNode.getElementsByTagName("thead")[0];
		if(this.headClass.length>0){
			thead.className=this.headClass;
		}

		//	disable selections
		dojo.html.disableSelection(this.domNode);

		//	parse the columns.
		this.parseColumns(thead);

		//	attach header handlers.
		var header="td";
		if(thead.getElementsByTagName(header).length==0) header="th";
		var headers=thead.getElementsByTagName(header);
		for(var i=0; i<headers.length; i++){
			if(!this.columns[i].noSort){
				dojo.event.connect(headers[i], "onclick", this, "onHeaderClick");
			}
			if(this.sortIndex==i){
				if(this.sortDirection==0){
					headers[i].className=this.headerSortDownClass;
				}else{
					headers[i].className=this.headerSortUpClass;
				}
			}
		}

		//	parse the tbody element and re-render it.
		var tbody=this.domNode.getElementsByTagName("tbody")[0];
		if (this.tbodyClass.length>0) {
			tbody.className=this.tbodyClass;
		}

		this.parseDataFromTable(tbody);
		this.render(true);
	}
});

__CPAN_FILE__ src/widget/html/DebugConsole.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.DebugConsole");

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.FloatingPane");

dojo.widget.html.DebugConsole= function(){

	dojo.widget.html.FloatingPane.call(this);
	dojo.widget.DebugConsole.call(this);
}

dojo.inherits(dojo.widget.html.DebugConsole, dojo.widget.html.FloatingPane);

dojo.lang.extend(dojo.widget.html.DebugConsole, {
	fillInTemplate: function() {
		dojo.widget.html.DebugConsole.superclass.fillInTemplate.apply(this, arguments);
		this.containerNode.id = "debugConsoleClientPane";
		djConfig.isDebug = true;
		djConfig.debugContainerId = this.containerNode.id;
	}
});

__CPAN_FILE__ src/widget/html/ShowAction.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.ShowAction");

dojo.require("dojo.widget.ShowAction");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.lang.common");

dojo.widget.defineWidget(
	"dojo.widget.html.ShowAction",
	dojo.widget.HtmlWidget,
	null,
	"html",
	function(){
		dojo.widget.ShowAction.call(this);
	}
);
dojo.lang.extend(dojo.widget.html.ShowAction, dojo.widget.ShowAction.prototype);
dojo.lang.extend(dojo.widget.html.ShowAction, {
});
__CPAN_FILE__ src/widget/html/AccordionPane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.AccordionPane");
dojo.require("dojo.widget.TitlePane");

dojo.widget.html.AccordionPane = function(){

	dojo.widget.html.TitlePane.call(this);
	this.widgetType = "AccordionPane";

	this.open=false;
	this.allowCollapse=true;
	this.label="";
	this.open=false;

	this.labelNodeClass="";
	this.containerNodeClass="";
}

dojo.inherits(dojo.widget.html.AccordionPane, dojo.widget.html.TitlePane);

dojo.lang.extend(dojo.widget.html.AccordionPane, {
        postCreate: function() {
                dojo.widget.html.AccordionPane.superclass.postCreate.call(this);
		this.domNode.widgetType=this.widgetType;
		this.setSizes();
		dojo.html.addClass(this.labelNode, this.labelNodeClass);
		dojo.html.disableSelection(this.labelNode);
		dojo.html.addClass(this.containerNode, this.containerNodeClass);
        },

	collapse: function() {
		//dojo.fx.html.wipeOut(this.containerNode,250);
		//var anim = dojo.fx.html.wipe(this.containerNode, 1000, this.containerNode.offsetHeight, 0, null, true);
		this.containerNode.style.display="none";
		this.open=false;
	},

	expand: function() {
		//dojo.fx.html.wipeIn(this.containerNode,250);
		this.containerNode.style.display="block";
		//var anim = dojo.fx.html.wipe(this.containerNode, 1000, 0, this.containerNode.scrollHeight, null, true);
		this.open=true;
	},

	getCollapsedHeight: function() {
		return dojo.style.getOuterHeight(this.labelNode)+1;
	},

	setSizes: function() {
		var siblings = this.domNode.parentNode.childNodes;
		var height=dojo.style.getInnerHeight(this.domNode.parentNode)-this.getCollapsedHeight();

		this.siblingWidgets = [];
	
		for (var x=0; x<siblings.length; x++) {
			if (siblings[x].widgetType==this.widgetType) {
				if (this.domNode != siblings[x]) {
					var ap = dojo.widget.byNode(siblings[x]);
					this.siblingWidgets.push(ap);
					height -= ap.getCollapsedHeight();
				}
			}
		}
	
		for (var x=0; x<this.siblingWidgets.length; x++) {
			dojo.style.setOuterHeight(this.siblingWidgets[x].containerNode,height);
		}

		dojo.style.setOuterHeight(this.containerNode,height);
	},

	onLabelClick: function() {
		this.setSizes();
		if (!this.open) { 
			for (var x=0; x<this.siblingWidgets.length;x++) {
				if (this.siblingWidgets[x].open) {
					this.siblingWidgets[x].collapse();
				}
			}
			this.expand();
		} else {
			if (this.allowCollapse) {
				this.collapse();
			}
		}
	}
});

dojo.widget.tags.addParseTreeHandler("dojo:AccordionPane");

__CPAN_FILE__ src/widget/html/ContextMenu.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.ContextMenu");
dojo.require("dojo.html");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.ContextMenu");
dojo.require("dojo.lang");

dojo.widget.html.ContextMenu = function(){
	dojo.widget.ContextMenu.call(this);
	dojo.widget.HtmlWidget.call(this);

	this.isShowing = 0;
	this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlContextMenuTemplate.html");
	this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/Menu.css");

	this.targetNodeIds = []; // fill this with nodeIds upon widget creation and it only responds to those nodes

	// default event detection method 
	var eventType = "oncontextmenu"; 

	var doc = document.documentElement  || document.body; 

	var _blockHide = false; 

	this.fillInTemplate = function(args, frag){

		var func = "onOpen";
		var attached = false;

		// connect with rightclick if oncontextmenu is not around
		// NOTE: It would be very nice to have a dojo.event.browser.supportsEvent here
		// NOTE: Opera does not have rightclick events, it is listed here only because
		//     it bails out when connecting with oncontextmenu event

		if((dojo.render.html.khtml && !dojo.render.html.safari) || (dojo.render.html.opera)){
			eventType = "onmousedown";
			func = "_checkRightClick";
		}

		// attach event listeners to our selected nodes
		for(var i=0; i<this.targetNodeIds.length; i++){
			var node = document.getElementById(this.targetNodeIds[i]);
			if(node){
				dojo.event.connect(node, eventType, this, func);
				attached = true;
			}else{
				// remove this nodeId
				dojo.debug("Couldent find "+this.targetNodeIds[i]+", cant do ContextMenu on this node");
				this.targetNodeIds.splice(i,1);
			}
		}

		// if we got attached to a node, hide on all non node contextevents
		if(attached){ func = "_canHide"; }

		dojo.event.connect(doc, eventType, this, func);
	}

	this.onOpen = function(evt){
		// if (this.isShowing){ this.onHide(evt); } // propably not needed
		this.isShowing = 1;

		// if I do this, I cant preventDefault in khtml
		//evt = dojo.event.browser.fixEvent(evt);
 
		// stop default contextmenu, needed in khtml
		if (evt.preventDefault){ evt.preventDefault(); }

		// need to light up this one before we check width and height
		this.domNode.style.left = "-9999px";
		this.domNode.style.top  = "-9999px";
		this.domNode.style.display = "block";

		// calculate if menu is going to apear within window
		// or if its partially out of visable area
		with(dojo.html){

			var menuW = getInnerWidth(this.domNode);
			var menuH = getInnerHeight(this.domNode);

			var viewport = getViewportSize();
			var scrolloffset = getScrollOffset();
		}

		var minX = viewport[0];
		var minY = viewport[1];

		var maxX = (viewport[0] + scrolloffset[0]) - menuW;
		var maxY = (viewport[1] + scrolloffset[1]) - menuH;

		var posX = evt.clientX + scrolloffset[0];
		var posY = evt.clientY + scrolloffset[1];

		if (posX > maxX){ posX = posX - menuW; }
		if (posY > maxY){ posY = posY - menuH; }

		this.domNode.style.left = posX + "px";
		this.domNode.style.top = posY + "px";


		// block the onclick that follows this particular right click
		// not if the eventtrigger is documentElement and always when
		// we use onmousedown hack
		_blockHide = (evt.currentTarget!=doc || eventType=='onmousedown');

		//return false; // we propably doesnt need to return false as we dont stop the event as we did before
	}

	/*
	* _canHide is meant to block the onHide call that follows the event that triggered
	* onOpen. This is (hopefully) faster that event.connect and event.disconnect every
	* time the code executes and it makes connecting with onmousedown event possible
	* and we dont have to stop the event from bubbling further.
	*
	* this code is moved into a separete function because it makes it possible for the
	* user to connect to a onHide event, if anyone would like that.
	*/

	this._canHide = function(evt){
		// block the onclick that follows the same event that turn on contextmenu
		if(_blockHide){
			// the onclick check is needed to prevent displaying multiple
			// menus when we have 2 or more contextmenus loaded and are using
			// the onmousedown hack
			if(evt.type=='click' || eventType=='oncontextmenu'){
				_blockHide = false;
				return;
			}else{
				return;
			}
		}

		this.onHide(evt);
	}
	
	this.onHide = function(evt){
		// FIXME: use whatever we use to do more general style setting?
		this.domNode.style.display = "none";
		//dojo.event.disconnect(doc, "onclick", this, "onHide");
		this.isShowing = 0;
	}

	// callback for rightclicks, needed for browsers that doesnt implement oncontextmenu, konqueror and more? 
	this._checkRightClick = function(evt){ 

		// for some reason konq comes here even when we are not clicking on the attached nodes 
		// added check for targetnode 
		if (evt.button==2 && (this.targetNodeIds.length==0 || (evt.currentTarget.id!="" && dojo.lang.inArray(this.targetNodeIds, evt.currentTarget.id)))){

			return this.onOpen(evt);
		}
	}

	dojo.event.connect(doc, "onclick", this, "_canHide");
}

dojo.inherits(dojo.widget.html.ContextMenu, dojo.widget.HtmlWidget);

__CPAN_FILE__ src/widget/html/DatePicker.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.DatePicker");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.DatePicker");
dojo.require("dojo.event.*");
dojo.require("dojo.html");
dojo.require("dojo.date");

/*
	Some assumptions:
	- I'm planning on always showing 42 days at a time, and we can scroll by week,
	not just by month or year
	- To get a sense of what month to highlight, I basically initialize on the 
	first Saturday of each month, since that will be either the first of two or 
	the second of three months being partially displayed, and then I work forwards 
	and backwards from that point.
	Currently, I assume that dates are stored in the RFC 3339 format,
	because I find it to be most human readable and easy to parse
	http://www.faqs.org/rfcs/rfc3339.html: 		2005-06-30T08:05:00-07:00
*/

dojo.widget.defineWidget(
	"dojo.widget.html.DatePicker",
	dojo.widget.HtmlWidget,
	{
		classConstructor: function() {
			// mixin dojo.widget.DatePicker non-demoninational code
			dojo.widget.DatePicker.call(this);
			// today's date, JS Date object
			this.today = "";
			// selected date, JS Date object
			this.date = "";
			// rfc 3339 date
			this.storedDate = "";
			// date currently selected in the UI, stored in year, month, date in the format that will be actually displayed
			this.currentDate = {};
			// stored in year, month, date in the format that will be actually displayed
			this.firstSaturday = {};
		},
		classNames: {
			previous: "previousMonth",
			current: "currentMonth",
			next: "nextMonth",
			currentDate: "currentDate",
			selectedDate: "selectedItem"
		},
		templatePath:  dojo.uri.dojoUri("src/widget/templates/HtmlDatePicker.html"),
		templateCssPath:  dojo.uri.dojoUri("src/widget/templates/HtmlDatePicker.css"),

		fillInTemplate: function(){
			dojo.widget.DatePicker.call(this);
			this.initData();
			this.initUI();
		},
		initData: function() {
			this.today = new Date();
			if(this.storedDate && (this.storedDate.split("-").length > 2)) {
				this.date = dojo.widget.DatePicker.util.fromRfcDate(this.storedDate);
			} else {
				this.date = this.today;
			}
			// calendar math is simplified if time is set to 0
			this.today.setHours(0);
			this.date.setHours(0);
			var month = this.date.getMonth();
			var tempSaturday = dojo.widget.DatePicker.util.initFirstSaturday(this.date.getMonth().toString(), this.date.getFullYear());
			this.firstSaturday.year = tempSaturday.year;
			this.firstSaturday.month = tempSaturday.month;
			this.firstSaturday.date = tempSaturday.date;
		},
		
		setDate: function(rfcDate) {
			this.storedDate = rfcDate;
		},
		
		initUI: function() {
			this.selectedIsUsed = false;
			this.currentIsUsed = false;
			var currentClassName = "";
			var previousDate = new Date();
			var calendarNodes = this.calendarDatesContainerNode.getElementsByTagName("td");
			var currentCalendarNode;
			// set hours of date such that there is no chance of rounding error due to 
			// time change in local time zones
			previousDate.setHours(8);
			var nextDate = new Date(this.firstSaturday.year, this.firstSaturday.month, this.firstSaturday.date, 8);
			
			if(this.firstSaturday.date < 7) {
				// this means there are days to show from the previous month
				var dayInWeek = 6;
				for (var i=this.firstSaturday.date; i>0; i--) {
					currentCalendarNode = calendarNodes.item(dayInWeek);
					currentCalendarNode.innerHTML = nextDate.getDate();
					dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
					dayInWeek--;
					previousDate = nextDate;
					nextDate = this.incrementDate(nextDate, false);
				}
				for(var i=dayInWeek; i>-1; i--) {
					currentCalendarNode = calendarNodes.item(i);
					currentCalendarNode.innerHTML = nextDate.getDate();
					dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "previous"));
					previousDate = nextDate;
					nextDate = this.incrementDate(nextDate, false);				
				}
			} else {
				nextDate.setDate(this.firstSaturday.date-6);
				for(var i=0; i<7; i++) {
					currentCalendarNode = calendarNodes.item(i);
					currentCalendarNode.innerHTML = nextDate.getDate();
					dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
					previousDate = nextDate;
					nextDate = this.incrementDate(nextDate, true);				
				}
			}
			previousDate.setDate(this.firstSaturday.date);
			previousDate.setMonth(this.firstSaturday.month);
			previousDate.setFullYear(this.firstSaturday.year);
			nextDate = this.incrementDate(previousDate, true);
			var count = 7;
			currentCalendarNode = calendarNodes.item(count);
			while((nextDate.getMonth() == previousDate.getMonth()) && (count<42)) {
				currentCalendarNode.innerHTML = nextDate.getDate();
				dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
				currentCalendarNode = calendarNodes.item(++count);
				previousDate = nextDate;
				nextDate = this.incrementDate(nextDate, true);
			}
			
			while(count < 42) {
				currentCalendarNode.innerHTML = nextDate.getDate();
				dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "next"));
				currentCalendarNode = calendarNodes.item(++count);
				previousDate = nextDate;
				nextDate = this.incrementDate(nextDate, true);
			}
			this.setMonthLabel(this.firstSaturday.month);
			this.setYearLabels(this.firstSaturday.year);
		},
		
		incrementDate: function(date, bool) {
			// bool: true to increase, false to decrease
			var time = date.getTime();
			var increment = 1000 * 60 * 60 * 24;
			time = (bool) ? (time + increment) : (time - increment);
			var returnDate = new Date();
			returnDate.setTime(time);
			return returnDate;
		},
		
		incrementWeek: function(evt) {
			var date = this.firstSaturday.date;
			var month = this.firstSaturday.month;
			var year = this.firstSaturday.year;
			switch(evt.target) {
				case this.increaseWeekNode.getElementsByTagName("img").item(0): 
				case this.increaseWeekNode:
					date = date + 7;
					if (date>this._daysIn(month,year)) {
						date = date - this._daysIn(month,year);
						if (month < 11) {
							month++;	
						} else {
							month=0;
							year++;
						}
					}
					break;
				case this.decreaseWeekNode.getElementsByTagName("img").item(0):
				case this.decreaseWeekNode:
					if (date > 7) {
						date = date - 7;
					} else {
						var diff = 7 - date;
						if (month > 0) {
							month--;
							date = this._daysIn(month,year) - diff;
						}else {
							year--;
							month=11;
							date = 31 - diff;
						}
					}
					break;
	
			}
	
			this.firstSaturday.date=date;
			this.firstSaturday.month=month;
			this.firstSaturday.year=year;
			this.initUI();
		},
	
		incrementMonth: function(evt) {
			var month = this.firstSaturday.month;
			var year = this.firstSaturday.year;
			switch(evt.currentTarget) {
				case this.increaseMonthNode:
					if(month < 11) {
						month++;
					} else {
						month = 0;
						year++;
						
						this.setYearLabels(year);
					}
					break;
				case this.decreaseMonthNode:
					if(month > 0) {
						month--;
					} else {
						month = 11;
						year--;
						this.setYearLabels(year);
					}
					break;
				case this.increaseMonthNode.getElementsByTagName("img").item(0):
					if(month < 11) {
						month++;
					} else {
						month = 0;
						year++;
						this.setYearLabels(year);
					}
					break;
				case this.decreaseMonthNode.getElementsByTagName("img").item(0):
					if(month > 0) {
						month--;
					} else {
						month = 11;
						year--;
						this.setYearLabels(year);
					}
					break;
			}
			var tempSaturday = dojo.widget.DatePicker.util.initFirstSaturday(month.toString(), year);
			this.firstSaturday.year = tempSaturday.year;
			this.firstSaturday.month = tempSaturday.month;
			this.firstSaturday.date = tempSaturday.date;
			this.initUI();
		},
	
		incrementYear: function(evt) {
			var year = this.firstSaturday.year;
			switch(evt.target) {
				case this.nextYearLabelNode:
					year++;
					break;
				case this.previousYearLabelNode:
					year--;
					break;
			}
			var tempSaturday = dojo.widget.DatePicker.util.initFirstSaturday(this.firstSaturday.month.toString(), year);
			this.firstSaturday.year = tempSaturday.year;
			this.firstSaturday.month = tempSaturday.month;
			this.firstSaturday.date = tempSaturday.date;
			this.initUI();
		},
	
		_daysIn: function(month,year) {
			var daysIn = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 
			
			if (month==1) {
				return (year%400 == 0) ? 29: (year%100 == 0) ? 28: (year%4 == 0) ? 29: 28;
			} else {
				return daysIn[month];
			}
		},
	
		onIncrementDate: function(evt) {
			dojo.unimplemented('dojo.widget.html.DatePicker.onIncrementDate');
		},
	
		onIncrementWeek: function(evt) {
			evt.stopPropagation();
			this.incrementWeek(evt);
		},
	
		onIncrementMonth: function(evt) {
			evt.stopPropagation();
			this.incrementMonth(evt);
		},
		
		onIncrementYear: function(evt) {
			evt.stopPropagation();
			this.incrementYear(evt);
		},
	
		setMonthLabel: function(monthIndex) {
			this.monthLabelNode.innerHTML = dojo.date.months[monthIndex];
		},
		
		setYearLabels: function(year) {
			this.previousYearLabelNode.innerHTML = year - 1;
			this.currentYearLabelNode.innerHTML = year;
			this.nextYearLabelNode.innerHTML = year + 1;
		},
		
		getDateClassName: function(date, monthState) {
			var currentClassName = this.classNames[monthState];
			if ((!this.selectedIsUsed) && (date.getDate() == this.date.getDate()) && (date.getMonth() == this.date.getMonth()) && (date.getFullYear() == this.date.getFullYear())) {
				currentClassName = this.classNames.selectedDate + " " + currentClassName;
				this.selectedIsUsed = 1;
			}
			if((!this.currentIsUsed) && (date.getDate() == this.today.getDate()) && (date.getMonth() == this.today.getMonth()) && (date.getFullYear() == this.today.getFullYear())) {
				currentClassName = currentClassName + " "  + this.classNames.currentDate;
				this.currentIsUsed = 1;
			}
			return currentClassName;
		},
	
		onClick: function(evt) {
			dojo.event.browser.stopEvent(evt)
		},
		
		onSetDate: function(evt) {
			dojo.event.browser.stopEvent(evt);
			this.selectedIsUsed = 0;
			this.todayIsUsed = 0;
			var month = this.firstSaturday.month;
			var year = this.firstSaturday.year;
			if (dojo.html.hasClass(evt.target, this.classNames["next"])) {
				month = ++month % 12;
				// if month is now == 0, add a year
				year = (month==0) ? ++year : year;
			} else if (dojo.html.hasClass(evt.target, this.classNames["previous"])) {
				month = --month % 12;
				// if month is now == 0, add a year
				year = (month==11) ? --year : year;
			}
			this.date = new Date(year, month, evt.target.innerHTML);
			this.setDate(dojo.widget.DatePicker.util.toRfcDate(this.date));
			this.initUI();
		}
	}
);

__CPAN_FILE__ src/widget/html/MenuItem.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.MenuItem");

/* HtmlMenuItem
 ***************/

dojo.widget.html.MenuItem = function(){
	dojo.widget.HtmlWidget.call(this);
}
dojo.inherits(dojo.widget.html.MenuItem, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.MenuItem, {
	widgetType: "MenuItem",
	templateString: '<li class="dojoMenuItem" dojoAttachEvent="onMouseOver; onMouseOut; onMouseDown; onMouseUp; onClick;"></li>',
	title: "",

	fillInTemplate: function(args, frag){
		dojo.html.disableSelection(this.domNode);

		if(!dojo.string.isBlank(this.title)){
			this.domNode.appendChild(document.createTextNode(this.title));
		}else{
			this.domNode.appendChild(frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"]);
		}
	},
	
	onMouseOver: function(e){
		dojo.html.addClass(this.domNode, "dojoMenuItemHover");
	},
	
	onMouseOut: function(e){
		dojo.html.removeClass(this.domNode, "dojoMenuItemHover");
	},
	
	onClick: function(e){ this.onSelect(this, e); },
	onMouseDown: function(e){},
	onMouseUp: function(e){},
	
	// By default, when I am clicked, click the item inside of me
	onSelect: function (item, e) {
		var child = dojo.dom.getFirstChildElement(this.domNode);
		if(child){
			if(child.click){
				child.click();
			}else if(child.href){
				location.href = child.href;
			}
		}
	}
});


__CPAN_FILE__ src/widget/html/Checkbox.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.Checkbox");

dojo.require("dojo.widget.*");
dojo.require("dojo.event");
dojo.require("dojo.html");

dojo.widget.defineWidget(
	"dojo.widget.html.Checkbox",
	dojo.widget.HtmlWidget,
	{
		widgetType: "Checkbox",
	
		templatePath: dojo.uri.dojoUri('src/widget/templates/HtmlCheckBox.html'),

		srcOn: dojo.uri.dojoUri('src/widget/templates/check_on.gif'),
		srcOff: dojo.uri.dojoUri('src/widget/templates/check_off.gif'),
		srcDisabledOn: dojo.uri.dojoUri('src/widget/templates/check_disabled_on.gif'),
		srcDisabledOff: dojo.uri.dojoUri('src/widget/templates/check_disabled_off.gif'),
		srcHoverOn: dojo.uri.dojoUri('src/widget/templates/check_hover_on.gif'),
		srcHoverOff: dojo.uri.dojoUri('src/widget/templates/check_hover_off.gif'),

		imgSrc: null,

		// parameters
		disabled: "enabled",
		name: "",
		checked: false,
		tabIndex: -1,

		imgNode: null,
		inputNode: null,

		postMixInProperties: function(){
			// set correct source for image before instantiating template
			this._updateImgSrc();
		},

		onMouseUp: function(){
			if(this.disabled == "enabled"){
				this.checked = !this.checked;
				this.inputNode.checked = this.checked;
				this._updateImgSrc();
			}
		},

		onMouseOver: function(){
			this.hover=true;
			this._updateImgSrc();
		},

		onMouseOut: function(){
			this.hover=false;
			this._updateImgSrc();
		},

		_updateImgSrc: function(){
			if(this.disabled == "enabled"){
				if(this.hover){
					this.imgSrc = this.checked ? this.srcHoverOn : this.srcHoverOff;
				}else{
					this.imgSrc = this.checked ? this.srcOn : this.srcOff;
				}
			}else{
				this.imgSrc = this.checked ? this.srcDisabledOn : this.srcDisabledOff;
			}
			if(this.imgNode){
				this.imgNode.src = this.imgSrc;
			}
		}
	}
);


__CPAN_FILE__ src/widget/html/Button2.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

// this is a stub that will be removed in 0.4, see ../Button2.html for details

dojo.provide("dojo.widget.html.Button2");

dojo.widget.html.Button2 = function(){}
dojo.inherits(dojo.widget.html.Button2, dojo.widget.html.Button);
dojo.lang.extend(dojo.widget.html.Button2, { widgetType: "Button2" });

dojo.widget.html.DropDownButton2 = function(){}
dojo.inherits(dojo.widget.html.DropDownButton2, dojo.widget.html.DropDownButton);
dojo.lang.extend(dojo.widget.html.DropDownButton2, { widgetType: "DropDownButton2" });

dojo.widget.html.ComboButton2 = function(){}
dojo.inherits(dojo.widget.html.ComboButton2, dojo.widget.html.ComboButton);
dojo.lang.extend(dojo.widget.html.ComboButton2, { widgetType: "ComboButton2" });
__CPAN_FILE__ src/widget/html/Show.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.Show");

dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.Show");
dojo.require("dojo.uri.Uri");
dojo.require("dojo.event");
dojo.require("dojo.animation.Animation");
dojo.require("dojo.math.curves");
dojo.require("dojo.html");
dojo.require("dojo.lang.common");
dojo.require("dojo.lang.func");

dojo.widget.defineWidget(
	"dojo.widget.html.Show",
	dojo.widget.HtmlWidget,
	null,
	"html",
	function(){
		dojo.widget.Show.call(this);
	}
);
dojo.lang.extend(dojo.widget.html.Show, dojo.widget.Show.prototype);
dojo.lang.extend(dojo.widget.html.Show, {
	body: null,
	nav: null,
	hider: null,
	select: null,
	option: null,
	inNav: false,
	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlShow.html"),
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlShow.css"),
	fillInTemplate: function(args, frag){
		var source = this.getFragNodeRef(frag);
		this.sourceNode = document.body.appendChild(source.cloneNode(true));
		for(var i = 0, child; child = this.sourceNode.childNodes[i]; i++){
			if(child.tagName && child.getAttribute("dojotype").toLowerCase() == "showslide"){
				child.className = "dojoShowPrintSlide";
				child.innerHTML = "<h1>" + child.title + "</h1>" + child.innerHTML;
			}
		}
		this.sourceNode.className = "dojoShowPrint";
		this.sourceNode.style.display = "none";
		
		dojo.event.connect(document, "onclick", this, "gotoSlideByEvent");
		dojo.event.connect(document, "onkeypress", this, "gotoSlideByEvent");
		dojo.event.connect(window, "onresize", this, "resizeWindow");
		dojo.event.connect(this.nav, "onmousemove", this, "popUpNav");
	},
	postCreate: function(){		
		this._slides = [];
		for(var i = 0, child; child = this.children[i]; i++){
			if(child.widgetType == "ShowSlide"){
				this._slides.push(child);
				this.option.text = child.title;
				this.option.parentNode.insertBefore(this.option.cloneNode(true), this.option);
			}
		}
		this.option.parentNode.removeChild(this.option);

		document.body.style.display = "block";
		this.resizeWindow();
		this.gotoSlide(0);
	},
	gotoSlide: function(/*int*/ slide){
		if(slide == this._slide){
			return;
		}

		if(!this._slides[slide]){
			// slide: string
			for(var i = 0, child; child = this._slides[i]; i++){
				if(child.title == slide){
					slide = i;
					break;
				}
			}
		}
		
		if(!this._slides[slide]){
			return;
		}
		
		if(this._slide != -1){
			while(this._slides[this._slide].previousAction()){}
		}
		
		this._slide = slide;
		this.select.selectedIndex = slide;
		while(this.contentNode.hasChildNodes()){ this.contentNode.removeChild(this.contentNode.firstChild); }
		this.contentNode.appendChild(this._slides[slide].domNode);
	},
	gotoSlideByEvent: function(/*Event*/ event){
		var node = event.target;
		var type = event.type;
		if(type == "click"){
			if(node.tagName == "OPTION"){
				this.gotoSlide(node.index);
			}else if(node.tagName == "SELECT"){
				this.gotoSlide(node.selectedIndex);
			}else if(node.tagName != "A"){
				this.nextSlide(event);
			}
		}else if(type == "keypress"){
			var key = event.keyCode;
			var ch = event.charCode;
			if(key == 63234 || key == 37){
				this.previousSlide(event);
			}else if(key == 63235 || key == 39 || ch == 32){
				this.nextSlide(event);
			}
		}
	},
	nextSlide: function(/*Event?*/ event){
		this.stopEvent(event);
		return dojo.widget.Show.prototype.nextSlide.call(this, event);
	},
	previousSlide: function(/*Event?*/ event){
		this.stopEvent(event);
		return dojo.widget.Show.prototype.previousSlide.call(this, event);
	},
	stopEvent: function(/*Event*/ ev){
		if(window.event){
			ev.returnValue = false;
			ev.cancelBubble = true;
		}else{
			ev.preventDefault();
			ev.stopPropagation();
		}
	},
	popUpNav: function(){
		if(!this.inNav){
			dojo.widget.Show.node = this.nav;
			var anim = new dojo.animation.Animation(new dojo.math.curves.Line([5], [30]), 250, -1);
			dojo.event.connect(anim, "onAnimate", function(e) {
				dojo.widget.Show.node.style.height = e.x + "px";
			});
			dojo.event.connect(anim, "onEnd", function(e) {
				dojo.widget.Show.node.style.height = e.x + "px";
			});
			anim.play(true);
		}
		clearTimeout(this.inNav);
		this.inNav = setTimeout(dojo.lang.hitch(this, "hideNav"), 2000);
	},
	hideNav: function(){
		clearTimeout(this.inNav);
		this.inNav = false;

		dojo.widget.Show.node = this.nav;
		var anim = new dojo.animation.Animation(new dojo.math.curves.Line([30], [5]), 250, 1);
		dojo.event.connect(anim, "onAnimate", function(e) {
			dojo.widget.Show.node.style.height = e.x + "px";
		});
		dojo.event.connect(anim, "onEnd", function(e) {
			dojo.widget.Show.node.style.height = e.x + "px";
		});
		anim.play(true);
	},
	resizeWindow: function(/*Event*/ ev){
		document.body.style.height = "auto";
		var h = Math.max(
			document.documentElement.scrollHeight || document.body.scrollHeight,
			dojo.html.getViewportHeight());
		document.body.style.height = h + "px";
	}
});
__CPAN_FILE__ src/widget/html/ShowSlide.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.ShowSlide");

dojo.require("dojo.widget.*");
dojo.require("dojo.lang.common");
dojo.require("dojo.widget.ShowSlide");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.lfx.html");
dojo.require("dojo.animation.Animation");
dojo.require("dojo.graphics.color");

dojo.widget.defineWidget(
	"dojo.widget.html.ShowSlide",
	dojo.widget.HtmlWidget,
	null,
	"html",
	function(){
		dojo.widget.ShowSlide.call(this);
	}
);
dojo.lang.extend(dojo.widget.html.ShowSlide, dojo.widget.ShowSlide.prototype);
dojo.lang.extend(dojo.widget.html.ShowSlide, {
	htmlTitle: null,
	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlShowSlide.html"),
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlShowSlide.css"),
	fillInTemplate: function(){
		this.htmlTitle.innerHTML = this.title;

		this._components = {};
		var nodes = this.containerNode.all ? this.containerNode.all : this.containerNode.getElementsByTagName('*');
		for(var i = 0, node; node = nodes[i]; i++){
			var as = node.getAttribute("as");
			if(as){
				if(!this._components[as]){
					this._components[as] = [];
				}
				this._components[as].push(node);
			}
		}
	},
	postCreate: function(){
		this._actions = [];
		for(var i = 0, child; child = this.children[i]; i++){
			if(child.widgetType == "ShowAction"){
				this._actions.push(child);
				var components = this._components[child.on];
				for(var j = 0, component; component = components[j]; j++){
					if(child.action && child.action != "remove"){
						this.hideComponent(component);
					}
				}
			}
		}
	},
	previousAction: function(/*Event?*/ event){
		this.stopEvent(event);

		var action = this._actions[this._action];
		if(!action){
			return false;
		}

		var on = action.on;
		while(action.on == on){
			var components = this._components[on];
			for(var i = 0, component; component = components[i]; i++){
				if(action.action == "remove"){
					if(component.style.display == "none"){
						component.style.display = "";
						component.style.visibility = "visible";
						var exits = true;
					}
				}else if(action.action){
					this.hideComponent(component);
				}
			}

			--this._action;

			if(exits){
				return true;
			}	

			if(action.auto == "true"){
				on = this._actions[this._action].on;
			}

			action = this._actions[this._action];
			if(!action){
				return false;
			}
		}
		return true;
	},
	hideComponent: function(/*Node*/ component){
		component.style.visibility = "hidden";
		component.style.backgroundColor = "transparent";
		var parent = component.parentNode;
		if((parent)&&(parent.tagName == "LI")){
			parent.oldType = parent.style.listStyleType;
			parent.style.listStyleType = "none";
		}
	},
	nextAction: function(/*Event?*/ event){
		this.stopEvent(event);

		if(!dojo.widget.ShowSlide.prototype.nextAction.call(this, event)){
			return false;
		}

		var action = this._actions[this._action];
		if(!action){
			return false;
		}
		
		var components = this._components[action.on];
		for(var i = 0, component; component = components[i]; i++){
			if(action.action){
				var duration = action.duration || 1000;
				if(action.action == "fade"){
					dojo.style.setOpacity(component, 0);
					dojo.lfx.html.fadeIn(component, duration).play(true);
				}else if(action.action == "fly"){
					var width = dojo.style.getMarginBoxWidth(component);
					var position = dojo.style.getAbsolutePosition(component);
					// alert(position);
					component.style.position = "relative";
					component.style.left = -(width + position.x) + "px";
					dojo.lfx.html.slideBy(component, [0, (width + position.x)], duration, -1, this.callWith).play(true);
				}else if(action.action == "wipe"){
					dojo.lfx.html.wipeIn(component, duration).play();
				}else if(action.action == "color"){
					var from = new dojo.graphics.color.Color(action.from).toRgb();
					var to = new dojo.graphics.color.Color(action.to).toRgb();
					var anim = new dojo.animation.Animation(new dojo.math.curves.Line(from, to), duration, 0);
					node = component;
					dojo.event.connect(anim, "onAnimate", function(e) {
						node.style.color = "rgb(" + e.coordsAsInts().join(",") + ")";
					});
					anim.play(true);
				}else if(action.action == "bgcolor"){
					dojo.lfx.html.unhighlight(component, action.to, duration).play();
				}else if(action.action == "remove"){
					component.style.display = "none";
				}
				component.style.visibility = "visible";
			}
		}
		
		action = this._actions[this._action + 1];
		if(action && action.auto == "true"){
			this.nextAction();
		}

		return true;
	},
	callWith: function(/*Node*/ node){
		if(!node){ return; }
		if(dojo.lang.isArray(node)){
			dojo.lang.forEach(node, arguments.callee);
			return;
		}
		var parent = node.parentNode;
		if((parent)&&(parent.tagName.toLowerCase() == "li")){
			parent.style.listStyleType = parent.oldType;
		}
	},
	stopEvent: function(/*Event*/ ev){
		if(!ev){
			return;
		}
		if(window.event){
			ev.returnValue = false;
			ev.cancelBubble = true;
		}else{
			ev.preventDefault();
			ev.stopPropagation();
		}
	}
});

__CPAN_FILE__ src/widget/html/Spinner.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.Spinner");
dojo.require("dojo.widget.Spinner");
dojo.require("dojo.widget.Manager.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.io.*");
dojo.require("dojo.lfx.*");
dojo.require("dojo.dom");
dojo.require("dojo.html");
dojo.require("dojo.string");
dojo.require("dojo.widget.html.stabile");

dojo.widget.html.Spinner = function(){
	dojo.widget.Spinner.call(this);
	dojo.widget.HtmlWidget.call(this);
}

dojo.inherits(dojo.widget.html.Spinner, dojo.widget.HtmlWidget);

// copied from superclass since we can't really over-ride via prototype
dojo.lang.extend(dojo.widget.html.Spinner, dojo.widget.Spinner.defaults);

dojo.lang.extend(dojo.widget.html.Spinner, {

	name: "", // clone in the name from the DOM node
	inputNode: null,
	upArrowNode: null,
	downArrowNode: null,
	absNode: null,
	relNode: null,
	innerRelNode: null,
	spacerNode: null,
	inputWidgetId: "",
	inputWidget: null,
	typamaticTimer: null,
	typamaticFunction: null,
	defaultTimeout: 500,
	currentTimeout: this.defaultTimeout,
	eventCount: 0,

	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlSpinner.html"),
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlSpinner.css"),

	setValue: function(value){
		this.inputWidget.setValue(value);
		this.inputWidget.adjustValue(0);
		dojo.widget.html.stabile.setState(this.widgetId, this.getState(), true);
	},

	getValue: function(){
		return this.inputWidget.getValue();
	},

	getState: function(){
		return {value: this.getValue()};
	},

	setState: function(state){
		this.setValue(state.value);
	},

	// does the keyboard related stuff
	_handleKeyEvents: function(evt){
		var k = dojo.event.browser.keys;
		var keyCode = evt.keyCode;

		switch(keyCode){
 			case k.KEY_DOWN_ARROW:
				dojo.event.browser.stopEvent(evt);
				this.downArrowPressed(evt);
				return;
			case k.KEY_UP_ARROW:
				dojo.event.browser.stopEvent(evt);
				this.upArrowPressed(evt);
				return;
		}
		this.eventCount++;

	},

	onKeyDown: function(evt){
		// IE needs to stop keyDown others need to stop keyPress
		if(!document.createEvent){ // only IE
			this._handleKeyEvents(evt);
		}
	},

	onKeyPress: function(evt){
		if(document.createEvent){ // never IE
			this._handleKeyEvents(evt);
		}
	},

	fillInTemplate: function(args, frag){
		var source = this.getFragNodeRef(frag);
		dojo.html.copyStyle(this.domNode, source);
	},


	resizeUpArrow: function(){
		var newh = dojo.style.getContentBoxHeight(this.inputNode) >> 1;
		if(newh==0){
			// need more time to calculate size
			dojo.lang.setTimeout(this, "resizeUpArrow", 100);
			return;
		}
		var oldh = this.upArrowNode.height;
		if(oldh==0){
			// need more time to calculate size
			dojo.lang.setTimeout(this, "resizeUpArrow", 100);
			return;
		}
		var ratio = newh / oldh;
		this.upArrowNode.width=Math.floor(this.upArrowNode.width * ratio);
		this.upArrowNode.height=newh;
	},

	resizeDownArrow: function(){
		var newh = dojo.style.getContentBoxHeight(this.inputNode) >> 1;
		if(newh==0){
			// need more time to calculate size
			dojo.lang.setTimeout(this, "resizeDownArrow", 100);
			return;
		}
		var oldh = this.downArrowNode.height;
		if(oldh==0){
			// need more time to calculate size
			dojo.lang.setTimeout(this, "resizeDownArrow", 100);
			return;
		}
		var ratio = newh / oldh;
		this.downArrowNode.width=Math.floor(this.downArrowNode.width * ratio);
		this.downArrowNode.height=newh;
	},

	resizeSpacer: function(){
		var newh = dojo.style.getContentBoxHeight(this.inputNode) >> 1;
		if( newh==0 ){
			// need more time to calculate size
			dojo.lang.setTimeout(this, "resizeSpacer", 100);
			return;
		}
		var oldh = this.downArrowNode.height;
		if( oldh==0 ){
			// need more time to calculate size
			dojo.lang.setTimeout(this, "resizeSpacer", 100);
			return;
		}
		var ratio = newh / oldh;
		this.spacerNode.width=Math.floor(this.spacerNode.width * ratio);
		this.spacerNode.height=newh;
	},

	_pressButton: function(node){
		with(node.style){
			borderRight = "0px";
			borderBottom = "0px";
			borderLeft = "1px solid black";
			borderTop = "1px solid black";
		}
	},

	_releaseButton: function(node){
		with(node.style){
			borderLeft = "0px";
			borderTop = "0px";
			borderRight = "1px solid gray";
			borderBottom = "1px solid gray";
		}
	},

	downArrowPressed: function(evt){
		if(typeof evt != "number"){
		    if(this.typamaticTimer != null){
				if(this.typamaticFunction == this.downArrowPressed){
					return;
				}
		        clearTimeout(this.typamaticTimer);
		    }
		    this._releaseButton(this.upArrowNode);
		    this.eventCount++;
		    this.typamaticTimer = null;
		    this.currentTimeout = this.defaultTimeout;

		}else if (evt != this.eventCount){
		    this._releaseButton(this.downArrowNode);
		    return;
		}
		this._pressButton(this.downArrowNode);
		this.setCursorX(this.inputWidget.adjustValue(-1,this.getCursorX()));
		this.typamaticFunction = this.downArrowPressed;
		this.typamaticTimer = setTimeout( dojo.lang.hitch(this,function(){this.downArrowPressed(this.eventCount);}), this.currentTimeout);
		this.currentTimeout = Math.round(this.currentTimeout * 90 / 100);
	},

	upArrowPressed: function(evt){
		if(typeof evt != "number"){
		    if(this.typamaticTimer != null){
				if(this.typamaticFunction == this.upArrowPressed){
					return;
				}
		        clearTimeout(this.typamaticTimer);
		    }
		    this._releaseButton(this.downArrowNode);
		    this.eventCount++;
		    this.typamaticTimer = null;
		    this.currentTimeout = this.defaultTimeout;
		}else if(evt != this.eventCount) {
		    this._releaseButton(this.upArrowNode);
		    return;
		}
		this._pressButton(this.upArrowNode);
		this.setCursorX(this.inputWidget.adjustValue(+1,this.getCursorX()));
		this.typamaticFunction = this.upArrowPressed;
		this.typamaticTimer = setTimeout( dojo.lang.hitch(this,function(){this.upArrowPressed(this.eventCount);}), this.currentTimeout);
		this.currentTimeout = Math.round(this.currentTimeout * 90 / 100);
	},

	arrowReleased: function(evt){
		this.inputNode.focus();
		if(evt.keyCode && evt.keyCode != null){
			var keyCode = evt.keyCode;
			var k = dojo.event.browser.keys;

			switch(keyCode){
				case k.KEY_DOWN_ARROW:
				case k.KEY_UP_ARROW:
					dojo.event.browser.stopEvent(evt);
					break;
			}
		}
		this._releaseButton(this.upArrowNode);
		this._releaseButton(this.downArrowNode);
		this.eventCount++;
		if(this.typamaticTimer != null){
		    clearTimeout(this.typamaticTimer);
		}
		this.typamaticTimer = null;
		this.currentTimeout = this.defaultTimeout;
	},

	mouseWheeled: function(evt) {
		var scrollAmount = 0;
		if(typeof evt.wheelDelta == 'number'){ // IE
		    scrollAmount = evt.wheelDelta;
		}else if (typeof evt.detail == 'number'){ // Mozilla+Firefox
		    scrollAmount = -evt.detail;
		}
		if(scrollAmount > 0){
		    this.upArrowPressed(evt);
		    this.arrowReleased(evt);
		}else if (scrollAmount < 0){
		    this.downArrowPressed(evt);
		    this.arrowReleased(evt);
		}
	},

	getCursorX: function(){
		var x = -1;
		try{
		    this.inputNode.focus();
		    if (typeof this.inputNode.selectionEnd == "number"){
				x = this.inputNode.selectionEnd;
		    }else if (document.selection && document.selection.createRange) {
				var range = document.selection.createRange().duplicate();
				if(range.parentElement() == this.inputNode){
					range.moveStart('textedit', -1);
					x = range.text.length;
				}
		    }
		}catch(e){ /* squelch! */ }
		return x;
	},

	setCursorX: function(x){
		try{
			this.inputNode.focus();
		    if(!x){ x = 0 }
		    if(typeof this.inputNode.selectionEnd == "number"){
		        this.inputNode.selectionEnd = x;
		    }else if(this.inputNode.createTextRange){
		        var range = this.inputNode.createTextRange();
		        range.collapse(true);
		        range.moveEnd('character', x);
		        range.moveStart('character', x);
		        range.select();
		    }
		}catch(e){ /* squelch! */ }
	},

	postCreate: function(){
		this.domNode.style.display="none";

		if((typeof this.inputWidgetId != 'string')||(this.inputWidgetId.length == 0)){
		    var w=dojo.widget.manager.getAllWidgets();
		    for(var i=w.length-1; i>=0; i--){
		        if(w[i].adjustValue){
					this.inputWidget = w[i];
					break;
		        }
		    }
		}else{
		    this.inputWidget = dojo.widget.getWidgetById(this.inputWidgetId);
		}

		if(typeof this.inputWidget != 'object'){
			dojo.lang.setTimeout(this, "postCreate", 100); 
			return;
		}
		var widgetNode = this.inputWidget.domNode;
		var inputNodes = widgetNode.getElementsByTagName('INPUT');
		this.inputNode = inputNodes[0];

		/*
		// unlink existing dom nodes from domNode
		this.downArrowNode = dojo.dom.removeNode(this.downArrowNode);
		this.upArrowNode = dojo.dom.removeNode(this.upArrowNode);
		this.spacerNode = dojo.dom.removeNode(this.spacerNode);
		this.innerRelNode = dojo.dom.removeNode(this.innerRelNode);
		this.absNode = dojo.dom.removeNode(this.absNode);
		this.relNode = dojo.dom.removeNode(this.relNode);
		*/

		// create a disconnected node
		this.innerRelNode.appendChild(this.upArrowNode);
		this.innerRelNode.appendChild(this.downArrowNode);
		this.absNode.appendChild(this.innerRelNode);
		this.relNode.appendChild(this.absNode);
		this.relNode.appendChild(this.spacerNode);

		dojo.event.connect(this.inputNode, "onkeypress", this, "onKeyPress");
		dojo.event.connect(this.inputNode, "onkeydown", this, "onKeyDown");
		dojo.event.connect(this.inputNode, "onkeyup", this, "arrowReleased");
		dojo.event.connect(this.downArrowNode, "onmousedown", this, "downArrowPressed");
		dojo.event.connect(this.downArrowNode, "onmouseup", this, "arrowReleased");
		dojo.event.connect(this.upArrowNode, "onmousedown", this, "upArrowPressed");
		dojo.event.connect(this.upArrowNode, "onmouseup", this, "arrowReleased");
		if(this.inputNode.addEventListener){
			// FIXME: why not use dojo.event.connect() to DOMMouseScroll here?
		    this.inputNode.addEventListener('DOMMouseScroll', dojo.lang.hitch(this, "mouseWheeled"), false); // Mozilla + Firefox + Netscape
		}else{
		    dojo.event.connect(this.inputNode, "onmousewheel", this, "mouseWheeled"); // IE + Safari
		}

		this.resizeDownArrow();
		this.resizeUpArrow();
		this.resizeSpacer();

		// make sure the disconnected node will fit right next to the INPUT tag w/o any interference
		dojo.html.copyStyle(this.relNode, this.inputNode);
		with(this.relNode.style){
			display = "inline";
			position = "relative";
			backgroundColor = "";
			marginLeft = "-1px";
			paddingLeft = "0";
		}
		this.inputNode.style.marginRight = "0px";
		this.inputNode.style.paddingRight = "0px";

		// add the disconnected node right after the INPUT tag
		dojo.dom.insertAfter(this.relNode, this.inputNode, false);
		this.domNode = dojo.dom.removeNode(this.domNode);
		// realign the spinner vertically in case there's a slight difference
		var absOffset = dojo.html.getAbsoluteY(this.relNode,true)-dojo.html.getAbsoluteY(this.absNode,true);
		this.absNode.style.top = absOffset-dojo.style.getBorderExtent(this.inputNode, "top")+"px";

		var s = dojo.widget.html.stabile.getState(this.widgetId);
		this.setValue(this.getValue());
		if(s){
			this.setState(s);
		}
	}
});

__CPAN_FILE__ src/widget/html/Menu.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.widget.Menu");
dojo.provide("dojo.widget.html.Menu");

/* HtmlMenu
 ***********/
 
dojo.widget.html.Menu = function(){
	dojo.widget.html.Menu.superclass.constructor.call(this);
	this.items = [];
}
dojo.inherits(dojo.widget.html.Menu, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.Menu, {
	widgetType: "Menu",
	isContainer: true,

	// copy children widgets output directly to parent (this node), to avoid
	// errors trying to insert an <li> under a <div>
	snarfChildDomOutput: true,

	templateString: '<ul></ul>',
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/Menu.css"),
	
	fillInTemplate: function (args, frag){
		//dojo.widget.HtmlMenu.superclass.fillInTemplate.apply(this, arguments);
		this.domNode.className = "dojoMenu";
	},
	
 
	_register: function (item ) {
		dojo.event.connect(item, "onSelect", this, "onSelect");
		this.items.push(item);
	},

	push: function (item) {
		this.domNode.appendChild(item.domNode);
		this._register(item);
	}

});


__CPAN_FILE__ src/widget/html/DropdownButton.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/* TODO:
 * - make the dropdown "smart" so it can't get cutoff on bottom of page, sides of page, etc.
 */

dojo.provide("dojo.widget.html.DropdownButton");

dojo.require("dojo.event.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.uri.Uri");
dojo.require("dojo.dom");
dojo.require("dojo.style");
dojo.require("dojo.html");

dojo.widget.html.DropdownButton = function() {
	// mix in the button properties
	dojo.widget.DropdownButton.call(this);
	dojo.widget.HtmlWidget.call(this);
}

dojo.inherits(dojo.widget.html.DropdownButton, dojo.widget.HtmlWidget);

dojo.lang.extend(dojo.widget.html.DropdownButton, {
	
	// In IE, event handlers on objects inside buttons don't work correctly, so
	// we just set onClick on the button itself.
	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlDropDownButtonTemplate.html"),
	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlButtonTemplate.css"),

	// attach points
	button: null,
	table: null,
	labelCell: null,
	borderCell: null,
	arrowCell: null,
	arrow: null,

	fillInTemplate: function(args, frag) {
		// input data (containing the anchor for the button itself, plus the
		// thing to display when you push the down arrow)
		var input = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];

		// Recursively expand widgets inside of the <dojo:dropdownButton>
		var parser = new dojo.xml.Parse();
		var frag = parser.parseElement(input, null, true);
		var ary = dojo.widget.getParser().createComponents(frag);

		this.a = dojo.dom.getFirstChildElement(input);	// the button contents
		this.menu = dojo.dom.getNextSiblingElement(this.a);	// the menu under the button
		
		this.disabled = dojo.html.hasClass(this.a, "disabled");
		if( this.disabled ) {
			dojo.html.addClass(this.button, "dojoDisabled");
			this.domNode.setAttribute("disabled", "true");
		}

		dojo.html.disableSelection(this.a);
		this.a.style["text-decoration"]="none";
		this.labelCell.appendChild(this.a);

		this.arrow.src =
			dojo.uri.dojoUri("src/widget/templates/images/dropdownButtonsArrow" +
			(this.disabled ? "-disabled" : "") + ".gif");

		// Attach menu to body so that it appears above other buttons
		this.menu.style.position="absolute";
		this.menu.style.display="none";
		this.menu.style["z-index"] = 99;
		document.body.appendChild(this.menu);
	},

	postCreate: function() {
		if ( dojo.render.html.ie ) {
			// Compensate for IE's weird padding of button content, which seems to be relative
			// to the length of the content
			var contentWidth = dojo.style.getOuterWidth(this.table);
			this.labelCell.style["left"] = "-" + (contentWidth / 10) + "px";
			this.arrowCell.style["left"] = (contentWidth / 10) + "px";
		}

		// Make menu at least as wide as the button
		var buttonWidth = dojo.style.getOuterWidth(this.button);
		var menuWidth = dojo.style.getOuterWidth(this.menu);
		if ( buttonWidth > menuWidth ) {
			dojo.style.setOuterWidth(this.menu, buttonWidth);
		}
	},

	// If someone clicks anywhere else on the screen (including another menu),
	// then close this menu.
	onCanvasMouseDown: function(e) {
		if( !dojo.dom.isDescendantOf(e.target, this.button) &&
			!dojo.dom.isDescendantOf(e.target, this.menu) ) {
			this.hideMenu();
		}
	},

	eventWasOverArrow: function(e) {
		// want to use dojo.html.overElement() but also need to detect clicks
		// on the area between the arrow and the edge of the button
		var eventX = e.clientX;
		var borderX = dojo.style.totalOffsetLeft(this.borderCell);
		return (eventX > borderX );
	},

	onMouseOver: function(e) {
		dojo.html.addClass(this.button, "dojoButtonHover");
		dojo.html.removeClass(this.button, "dojoButtonNoHover");
	},
	
	onMouseOut: function(e) {
		dojo.html.removeClass(this.button, "dojoButtonHover");
		dojo.html.addClass(this.button, "dojoButtonNoHover");
	},

	onClick: function(e) {
		if ( this.eventWasOverArrow(e) ) {
			this._onClickArrow();
		} else {
			this._onClickButton();
		}
	},

	// Action when the user presses the button
	_onClickButton: function(e) {
		if ( this.a ) {
			if ( this.a.click ) {
				this.a.click();
			} else if ( this.a.href ) {
				location.href = this.a.href;
			}
		}
	},

	// Action when user presses the arrow
	_onClickArrow: function() {
		if ( this.menu.style.display == "none" ) {
			this.showMenu();
		} else {
			this.hideMenu();
		}
	},
	
	showMenu: function() {
		if ( this.disabled )
			return;

		// Position it accordingly, relative to screen root (since
		// it's attached to document.body)
		this.menu.style.left = dojo.style.totalOffsetLeft(this.button) + "px";
		this.menu.style.top = dojo.style.totalOffsetTop(this.button) + dojo.style.getOuterHeight(this.button) + "px";

		// Display the menu; do this funky code below to stop the menu from extending
		// all the way to the right edge of the screen.
		// TODO: retest simple display="" to confirm that it doesn't work.
		try {
			this.menu.style.display="table";	// mozilla
		} catch(e) {
			this.menu.style.display="block";	// IE
		}

		// If someone clicks somewhere else on the screen then close the menu
		dojo.event.connect(document.documentElement, "onmousedown", this, "onCanvasMouseDown");
		
		// When someone clicks the menu, after the menu handles the event,
		// close the menu (be careful not to close the menu too early or else
		// the menu will never receive the event.)
		dojo.event.connect(this.menu, "onclick", this, "hideMenu");
	},

	hideMenu: function() {
		this.menu.style.display = "none";
		dojo.event.disconnect(document.documentElement, "onmousedown", this, "onCanvasMouseDown");
		dojo.event.disconnect(this.menu, "onclick", this, "hideMenu");
	}
});



__CPAN_FILE__ src/widget/html/TimePicker.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.TimePicker");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.TimePicker");
dojo.require("dojo.event.*");
dojo.require("dojo.date");
dojo.require("dojo.html");

dojo.widget.html.TimePicker = function(){
	dojo.widget.TimePicker.call(this);
	dojo.widget.HtmlWidget.call(this);


	var _this = this;
	// selected time, JS Date object
	this.time = "";
	// set following flag to true if a default time should be set
	this.useDefaultTime = false;
	// set the following to true to set default minutes to current time, false to // use zero
	this.useDefaultMinutes = false;
	// rfc 3339 date
	this.storedTime = "";
	// time currently selected in the UI, stored in hours, minutes, seconds in the format that will be actually displayed
	this.currentTime = {};
	this.classNames = {
		selectedTime: "selectedItem"
	}
	this.any = "any"
	// dom node indecies for selected hour, minute, amPm, and "any time option"
	this.selectedTime = {
		hour: "",
		minute: "",
		amPm: "",
		anyTime: false
	}

	// minutes are ordered as follows: ["12", "6", "1", "7", "2", "8", "3", "9", "4", "10", "5", "11"]
	this.hourIndexMap = ["", 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 11, 0];
	// minutes are ordered as follows: ["00", "30", "05", "35", "10", "40", "15", "45", "20", "50", "25", "55"]
	this.minuteIndexMap = [0, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 11];

	this.templatePath =  dojo.uri.dojoUri("src/widget/templates/HtmlTimePicker.html");
	this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlTimePicker.css");

	this.fillInTemplate = function(){
		this.initData();
		this.initUI();
	}

	this.initData = function() {
		// FIXME: doesn't currently validate the time before trying to set it
		// Determine the date/time from stored info, or by default don't 
		//  have a set time
		// FIXME: should normalize against whitespace on storedTime... for now 
		// just a lame hack
		if(this.storedTime.indexOf("T")!=-1 && this.storedTime.split("T")[1] && this.storedTime!=" " && this.storedTime.split("T")[1]!="any") {
			this.time = dojo.widget.TimePicker.util.fromRfcDateTime(this.storedTime, this.useDefaultMinutes, this.selectedTime.anyTime);
		} else if (this.useDefaultTime) {
			this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", this.useDefaultMinutes, this.selectedTime.anyTime);
		} else {
			this.selectedTime.anyTime = true;
			this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", 0, 1);
		}
	}

	this.initUI = function() {
		// set UI to match the currently selected time
		if(!this.selectedTime.anyTime && this.time) {
			var amPmHour = dojo.widget.TimePicker.util.toAmPmHour(this.time.getHours());
			var hour = amPmHour[0];
			var isAm = amPmHour[1];
			var minute = this.time.getMinutes();
			var minuteIndex = parseInt(minute/5);
			this.onSetSelectedHour(this.hourIndexMap[hour]);
			this.onSetSelectedMinute(this.minuteIndexMap[minuteIndex]);
			this.onSetSelectedAmPm(isAm);
		} else {
			this.onSetSelectedAnyTime();
		}
	}

	this.setDateTime = function(rfcDate) {
		this.storedTime = rfcDate;
	}
	
	this.onClearSelectedHour = function(evt) {
		this.clearSelectedHour();
	}

	this.onClearSelectedMinute = function(evt) {
		this.clearSelectedMinute();
	}

	this.onClearSelectedAmPm = function(evt) {
		this.clearSelectedAmPm();
	}

	this.onClearSelectedAnyTime = function(evt) {
		this.clearSelectedAnyTime();
		if(this.selectedTime.anyTime) {
			this.selectedTime.anyTime = false;
			this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", this.useDefaultMinutes);
			this.initUI();
		}
	}

	this.clearSelectedHour = function() {
		var hourNodes = this.hourContainerNode.getElementsByTagName("td");
		for (var i=0; i<hourNodes.length; i++) {
			dojo.html.setClass(hourNodes.item(i), "");
		}
	}

	this.clearSelectedMinute = function() {
		var minuteNodes = this.minuteContainerNode.getElementsByTagName("td");
		for (var i=0; i<minuteNodes.length; i++) {
			dojo.html.setClass(minuteNodes.item(i), "");
		}
	}

	this.clearSelectedAmPm = function() {
		var amPmNodes = this.amPmContainerNode.getElementsByTagName("td");
		for (var i=0; i<amPmNodes.length; i++) {
			dojo.html.setClass(amPmNodes.item(i), "");
		}
	}

	this.clearSelectedAnyTime = function() {
		dojo.html.setClass(this.anyTimeContainerNode, "anyTimeContainer");
	}

	this.onSetSelectedHour = function(evt) {
		this.onClearSelectedAnyTime();
		this.onClearSelectedHour();
		this.setSelectedHour(evt);
		this.onSetTime();
	}

	this.setSelectedHour = function(evt) {
		if(evt && evt.target) {
			dojo.html.setClass(evt.target, this.classNames.selectedTime);
			this.selectedTime["hour"] = evt.target.innerHTML;
		} else if (!isNaN(evt)) {
			var hourNodes = this.hourContainerNode.getElementsByTagName("td");
			if(hourNodes.item(evt)) {
				dojo.html.setClass(hourNodes.item(evt), this.classNames.selectedTime);
				this.selectedTime["hour"] = hourNodes.item(evt).innerHTML;
			}
		}
		this.selectedTime.anyTime = false;
	}

	this.onSetSelectedMinute = function(evt) {
		this.onClearSelectedAnyTime();
		this.onClearSelectedMinute();
		this.setSelectedMinute(evt);
		this.selectedTime.anyTime = false;
		this.onSetTime();
	}

	this.setSelectedMinute = function(evt) {
		if(evt && evt.target) {
			dojo.html.setClass(evt.target, this.classNames.selectedTime);
			this.selectedTime["minute"] = evt.target.innerHTML;
		} else if (!isNaN(evt)) {
			var minuteNodes = this.minuteContainerNode.getElementsByTagName("td");
			if(minuteNodes.item(evt)) {
				dojo.html.setClass(minuteNodes.item(evt), this.classNames.selectedTime);
				this.selectedTime["minute"] = minuteNodes.item(evt).innerHTML;
			}
		}
	}

	this.onSetSelectedAmPm = function(evt) {
		this.onClearSelectedAnyTime();
		this.onClearSelectedAmPm();
		this.setSelectedAmPm(evt);
		this.selectedTime.anyTime = false;
		this.onSetTime();
	}

	this.setSelectedAmPm = function(evt) {
		if(evt && evt.target) {
			dojo.html.setClass(evt.target, this.classNames.selectedTime);
			this.selectedTime["amPm"] = evt.target.innerHTML;
		} else {
			evt = evt ? 0 : 1;
			var amPmNodes = this.amPmContainerNode.getElementsByTagName("td");
			if(amPmNodes.item(evt)) {
				dojo.html.setClass(amPmNodes.item(evt), this.classNames.selectedTime);
				this.selectedTime["amPm"] = amPmNodes.item(evt).innerHTML;
			}
		}
	}

	this.onSetSelectedAnyTime = function(evt) {
		this.onClearSelectedHour();
		this.onClearSelectedMinute();
		this.onClearSelectedAmPm();
		this.setSelectedAnyTime();
		this.onSetTime();
	}

	this.setSelectedAnyTime = function(evt) {
		this.selectedTime.anyTime = true;
		dojo.html.setClass(this.anyTimeContainerNode, this.classNames.selectedTime + " " + "anyTimeContainer");
	}

	this.onClick = function(evt) {
		dojo.event.browser.stopEvent(evt)
	}

	this.onSetTime = function() {
		if(this.selectedTime.anyTime) {
			this.time = new Date();
			var tempDateTime = dojo.widget.TimePicker.util.toRfcDateTime(this.time);
			this.setDateTime(tempDateTime.split("T")[0]);
		} else {
			var hour = 12;
			var minute = 0;
			var isAm = false;
			if(this.selectedTime["hour"]) {
				hour = parseInt(this.selectedTime["hour"], 10);
			}
			if(this.selectedTime["minute"]) {
				minute = parseInt(this.selectedTime["minute"], 10);
			}
			if(this.selectedTime["amPm"]) {
				isAm = (this.selectedTime["amPm"].toLowerCase() == "am");
			}
			this.time = new Date();
			this.time.setHours(dojo.widget.TimePicker.util.fromAmPmHour(hour, isAm));
			this.time.setMinutes(minute);
			this.setDateTime(dojo.widget.TimePicker.util.toRfcDateTime(this.time));
		}
	}

}
dojo.inherits(dojo.widget.html.TimePicker, dojo.widget.HtmlWidget);

__CPAN_DIR__ src/widget/demoEngine
__CPAN_FILE__ src/widget/demoEngine/DemoNavigator.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.demoEngine.DemoNavigator");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.Button");
dojo.require("dojo.widget.demoEngine.DemoItem");
dojo.require("dojo.io.*");
dojo.require("dojo.lfx.*");
dojo.require("dojo.lang.Common");

dojo.widget.defineWidget("my.widget.demoEngine.DemoNavigator", 
	dojo.widget.HtmlWidget, 
	{
		templatePath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoNavigator.html"),
		templateCssPath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoNavigator.css"),
		postCreate: function() {
			dojo.html.addClass(this.domNode,this.domNodeClass);
			dojo.html.addClass(this.demoListWrapperNode,this.demoListWrapperClass);
			dojo.html.addClass(this.demoListContainerNode,this.demoListContainerClass);

			if (dojo.render.html.ie) {
				dojo.debug("render ie");
				dojo.html.hide(this.demoListWrapperNode); 
			} else {
				dojo.debug("render non-ie");
				dojo.lfx.html.fadeHide(this.demoListWrapperNode, 0).play();	
			}

			this.getRegistry(this.demoRegistryUrl);

			this.demoContainer = dojo.widget.createWidget("DemoContainer",{returnImage: this.returnImage},this.demoNode);
			dojo.event.connect(this.demoContainer,"returnToDemos", this, "returnToDemos");
			this.demoContainer.hide();
		},

		returnToDemos: function() {
			this.demoContainer.hide();
			if (dojo.render.html.ie) {
				dojo.debug("render ie");
				dojo.html.show(this.navigationContainer) ;
			} else {	
				dojo.debug("render non-ie");
				dojo.lfx.html.fadeShow(this.navigationContainer,250).play();
			}

			//if (dojo.render.html.ie) {
			//	dojo.html.setOpacity(this.navigationContainer);
			//}

			dojo.lang.forEach(this.categoriesChildren, dojo.lang.hitch(this, function(child){
				child.checkSize();
			}));

			dojo.lang.forEach(this.demoListChildren, dojo.lang.hitch(this, function(child){
				child.checkSize();
			}));
		},

		show: function() {
			//dojo.widget.demoEngine.DemoNavigator.superclass.show.call(this);
			dojo.html.show(this.domNode);
			dojo.html.setOpacity(this.domNode,1);
			//dojo.html.setOpacity(this.navigationContainer);	
			//dojo.html.show(this.navigationContainer);
			dojo.html.setOpacity(this.navigationContainer,1);

			dojo.lang.forEach(this.categoriesChildren, dojo.lang.hitch(this, function(child){
				child.checkSize();
			}));

			dojo.lang.forEach(this.demoListChildren, dojo.lang.hitch(this, function(child){
				child.checkSize();
			}));
		},
		getRegistry: function(url) {
			dojo.io.bind({
				url: url,
				load: dojo.lang.hitch(this,this.processRegistry),
				mimetype: "text/json"
			});
		},

		processRegistry: function(type,registry,e) {
			dojo.debug("Processing Registry");
			this.registry = registry;
			dojo.lang.forEach(this.registry.navigation, dojo.lang.hitch(this,this.addCategory)); 
		},

		addCategory: function(category) {
				var newCat = dojo.widget.createWidget("Button",{caption: category.name});

				if(!dojo.lang.isObject(this.registry.categories)) {
					this.registry.categories=function(){};
				}

				this.registry.categories[category.name] = category;
				this.categoriesChildren.push(newCat);
				this.categoriesButtonsNode.appendChild(newCat.domNode);	
				newCat.domNode.categoryName = category.name;
				dojo.event.connect(newCat,"onClick", this, "onSelectCategory");
		},

		addDemo: function(demoName) {
			var demo = this.registry.definitions[demoName];

			if (dojo.render.html.ie) {
				dojo.html.show(this.demoListWrapperNode) 
			} else {
				dojo.lfx.html.fadeShow(this.demoListWrapperNode, 250).play();
			}

			var newDemo = dojo.widget.createWidget("DemoItem",{viewDemoImage: this.viewDemoImage, name: demoName, description: demo.description, thumbnail: demo.thumbnail});
			this.demoListChildren.push(newDemo);
			this.demoListContainerNode.appendChild(newDemo.domNode);	
			dojo.event.connect(newDemo,"onSelectDemo",this,"onSelectDemo");
		},

		onSelectCategory: function(e) {
			catName = e.currentTarget.categoryName;	
			dojo.debug("Selected Category: " + catName);
			//Remove current list of demos
			dojo.lang.forEach(this.demoListChildren, function(child) {
					child.destroy();
			});
			this.demoListChildren=[];

			//add demos from this cat
			dojo.lang.forEach(this.registry.categories[catName].demos, dojo.lang.hitch(this,function(demoName){
				this.addDemo(demoName);
			}));
		},

		onSelectDemo: function(e) {
			//Attach to this to do something when a demo is selected
			dojo.debug("Demo Selected: " + e.target.name);

			if (dojo.render.html.ie) {
				dojo.debug("render ie");
				dojo.html.hide(this.navigationContainer) ;
				this.demoContainer.show();
				this.demoContainer.showDemo();
			} else {
				dojo.debug("render non-ie");
				dojo.lfx.html.fadeHide(this.navigationContainer,250,null,dojo.lang.hitch(this, function() {
					this.demoContainer.show();	
					this.demoContainer.showDemo();
				})).play();
			}

			this.demoContainer.loadDemo(this.registry.definitions[e.target.name].url);
			this.demoContainer.setName(e.target.name);
			this.demoContainer.setSummary(this.registry.definitions[e.target.name].description);
		}
		
	},
	"",
	function() {
		this.demoRegistryUrl="demoRegistry.json";
		this.registry=function(){};

		this.categoriesNode="";
		this.categoriesButtonsNode="";
		this.navigationContainer="";

		this.domNodeClass="demoNavigator";

		this.demoNode="";
		this.demoContainer="";

		this.demoListWrapperNode="";
		this.demoListWrapperClass="demoNavigatorListWrapper";
		this.demoListContainerClass="demoNavigatorListContainer";

		this.returnImage="images/dojoDemos.gif";
		this.viewDemoImage="images/viewDemo.png";
		this.demoListChildren = [];
		this.categoriesChildren = [];
	}
);

__CPAN_FILE__ src/widget/demoEngine/DemoContainer.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.demoEngine.DemoContainer");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.demoEngine.DemoPane");
dojo.require("dojo.widget.demoEngine.SourcePane");
dojo.require("dojo.widget.TabContainer");

dojo.widget.defineWidget("my.widget.demoEngine.DemoContainer", 
	dojo.widget.HtmlWidget, 
	{
		templatePath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoContainer.html"),
		templateCssPath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoContainer.css"),
		postCreate: function() {
			dojo.html.addClass(this.domNode,this.domNodeClass);
			dojo.html.addClass(this.tabNode, this.tabClass);
			dojo.html.addClass(this.returnImageNode, this.returnClass);
			this.returnImageNode.src=this.returnImage;

			this.tabContainer = dojo.widget.createWidget("TabContainer",{},this.tabNode);

			this.demoTab = dojo.widget.createWidget("DemoPane",{});
			this.tabContainer.addChild(this.demoTab);

			this.sourceTab= dojo.widget.createWidget("SourcePane",{});
			this.tabContainer.addChild(this.sourceTab);

			dojo.html.setOpacity(this.domNode,0);
			dojo.html.hide(this.domNode);
		},

		loadDemo: function(url) {
			this.demoTab.setHref(url);
			this.sourceTab.setHref(url);
			this.showDemo();
		},

		setName: function(name) {
			dojo.html.removeChildren(this.demoNameNode);
			this.demoNameNode.appendChild(document.createTextNode(name));
		},

		setSummary: function(summary) {
			dojo.html.removeChildren(this.summaryNode);
			this.summaryNode.appendChild(document.createTextNode(summary));
		},

		showSource: function() {
			dojo.html.removeClass(this.demoButtonNode,this.selectedButtonClass);
			dojo.html.addClass(this.sourceButtonNode,this.selectedButtonClass);
			this.tabContainer.selectTab(this.sourceTab);	
		},

		showDemo: function() {
			dojo.html.removeClass(this.sourceButtonNode,this.selectedButtonClass);
			dojo.html.addClass(this.demoButtonNode,this.selectedButtonClass);
			this.tabContainer.selectTab(this.demoTab);
		},

		returnToDemos: function() {
			dojo.debug("Return To Demos");
		},

		show: function() {
			dojo.html.setOpacity(this.domNode,1);
			dojo.html.show(this.domNode);
			this.tabContainer.checkSize();
		}
	},
	"",
	function() {
		dojo.debug("DemoPane Init");
		this.domNodeClass="demoContainer";

		this.tabContainer="";
		this.sourceTab="";
		this.demoTab="";

		this.headerNode="";
		this.returnNode="";
	
		this.returnImageNode="";
		this.returnImage="images/dojoDemos.gif";
		this.returnClass="return";
		
		this.summaryNode="";
		this.demoNameNode="";
		this.tabControlNode="";

		this.tabNode="";
		this.tabClass = "demoContainerTabs";

		this.sourceButtonNode="";
		this.demoButtonNode="";

		this.selectedButtonClass="selected";
	}
);

__CPAN_FILE__ src/widget/demoEngine/DemoItem.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.demoEngine.DemoItem");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");

dojo.widget.defineWidget("my.widget.demoEngine.DemoItem", 
	dojo.widget.HtmlWidget, 
	{
		templatePath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoItem.html"),
		templateCssPath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoItem.css"),
		postCreate: function() {
			dojo.html.addClass(this.domNode,this.domNodeClass);
			dojo.html.addClass(this.summaryBoxNode, this.summaryBoxClass);
			dojo.html.addClass(this.screenshotTdNode, this.screenshotTdClass);
			dojo.html.addClass(this.summaryContainerNode, this.summaryContainerClass);
			dojo.html.addClass(this.summaryNode, this.summaryClass);
			dojo.html.addClass(this.viewDemoLinkNode, this.viewDemoLinkClass);

			this.nameNode.appendChild(document.createTextNode(this.name));
			this.descriptionNode.appendChild(document.createTextNode(this.description));
			this.thumbnailImageNode.src = this.thumbnail;
			this.thumbnailImageNode.name=this.name;
			this.viewDemoImageNode.src = this.viewDemoImage;
			this.viewDemoImageNode.name=this.name;
		},
		onSelectDemo: function() {
			//Attach to this to do something when a demo is selected
		}
	},
	"",
	function() {
		this.demo = "";

		this.domNodeClass="demoItemWrapper";

		this.summaryBoxNode="";
		this.summaryBoxClass="demoItemSummaryBox";

		this.nameNode="";
		this.thumbnailImageNode="";
		this.viewDemoImageNode="";

		this.screenshotTdNode="";
		this.screenshotTdClass="demoItemScreenshot";

		this.summaryContainerNode="";
		this.summaryContainerClass="demoItemSummaryContainer";

		this.summaryNode="";
		this.summaryClass="demoItemSummary";

		this.viewDemoLinkNode="";
		this.viewDemoLinkClass="demoItemView";

		this.descriptionNode="";

		this.name="Some Demo";
		this.description="This is the description of this demo.";
		this.thumbnail="images/test_thumb.gif";
		this.viewDemoImage="images/viewDemo.png";
	}
);

__CPAN_FILE__ src/widget/demoEngine/SourcePane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.demoEngine.SourcePane");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.io.*");

dojo.widget.defineWidget("my.widget.demoEngine.SourcePane", 
	dojo.widget.HtmlWidget, 
	{
		templatePath: dojo.uri.dojoUri("src/widget/demoEngine/templates/SourcePane.html"),
		templateCssPath: dojo.uri.dojoUri("src/widget/demoEngine/templates/SourcePane.css"),
		postCreate: function() {
			dojo.html.addClass(this.domNode,this.domNodeClass);
			dojo.debug("PostCreate");
		},
	
		getSource: function() {
			if (this.href) {
				dojo.io.bind({
					url: this.href,
					load: dojo.lang.hitch(this, "fillInSource"),
					mimetype: "text/plain"
				});
			}
		},	

		fillInSource: function(type, source, e) {
			this.sourceNode.value=source;
		},

		setHref: function(url) {
			this.href = url;
			this.getSource();
		}
	},
	"",
	function() {
		dojo.debug("SourcePane Init");
		this.domNodeClass="sourcePane";
		this.sourceNode = "";
		this.href = "";
	}
);

__CPAN_FILE__ src/widget/demoEngine/DemoPane.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.demoEngine.DemoPane");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");

dojo.widget.defineWidget("my.widget.demoEngine.DemoPane", 
	dojo.widget.HtmlWidget, 
	{
		templatePath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoPane.html"),
		templateCssPath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoPane.css"),
		postCreate: function() {
			dojo.html.addClass(this.domNode,this.domNodeClass);
			dojo.debug("PostCreate");
			this._launchDemo();
		},
		
		_launchDemo: function() {
			dojo.debug("Launching Demo");
			dojo.debug(this.demoNode);
			this.demoNode.src=this.href;
		},

		setHref: function(url) {
			this.href = url;
			this._launchDemo();
		}
	},
	"",
	function() {
		dojo.debug("DemoPane Init");
		this.domNodeClass="demoPane";
		this.demoNode = "";
		this.href = "";
	}
);

__CPAN_FILE__ src/widget/demoEngine/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	browser: [
		"dojo.widget.demoEngine.DemoItem",
		"dojo.widget.demoEngine.DemoNavigator",
		"dojo.widget.demoEngine.DemoPane",
		"dojo.widget.demoEngine.SourcePane",
		"dojo.widget.demoEngine.DemoContainer"
	]
});
dojo.provide("dojo.widget.demoEngine.*");

__CPAN_DIR__ src/widget/demoEngine/templates
__CPAN_FILE__ src/widget/demoEngine/templates/DemoContainer.html
<div dojoAttachPoint="domNode">
	<table width="100%" cellspacing="0" cellpadding="5">
		<tbody>
			<tr dojoAttachPoint="headerNode">
				<td dojoAttachPoint="returnNode" valign="middle" width="1%">
					<img dojoAttachPoint="returnImageNode" dojoAttachEvent="onclick: returnToDemos"/>
				</td>
				<td>
					<h1 dojoAttachPoint="demoNameNode"></h1>
					<p dojoAttachPoint="summaryNode"></p>
				</td>
				<td dojoAttachPoint="tabControlNode" valign="middle" align="right" nowrap>
					<span dojoAttachPoint="sourceButtonNode" dojoAttachEvent="onclick: showSource">source</span>
					<span dojoAttachPoint="demoButtonNode" dojoAttachEvent="onclick: showDemo">demo</span>
				</td>
			</tr>
			<tr>
				<td colspan="3">
					<div dojoAttachPoint="tabNode">
					</div>
				</td>
			</tr>
		</tbody>
	</table>
</div>

__CPAN_FILE__ src/widget/demoEngine/templates/SourcePane.html
<div dojoAttachPoint="domNode">
	<textarea dojoAttachPoint="sourceNode" rows="100%"></textarea>
</div>

__CPAN_FILE__ src/widget/demoEngine/templates/general.css
.demoListWrapper {
	border:1px solid #dcdbdb;
	background-color:#f8f8f8;
	padding:2px;
}

.demoListContainer {
	border:1px solid #f0f0f0;
	background-color:#fff;
	padding:1em;
}

.demoSummaryBox {
	background: #efefef;
	border:1px solid #dae3ee;
}

.screenshot {
	padding:0.65em;
	width:175px;
	border-right:1px solid #fafafa;
	text-align:center;
}

.demoSummary {
	margin-bottom:1em;
}

.demoSummary a:link, .demoSummary a:visited {
	color:#a6238f;
	text-decoration:none;
}

.summaryContainer {
	border-left:1px solid #ddd;
}

.summaryContainer h1 {
	background-color:#e8e8e8;
	border-bottom: 1px solid #e6e6e6;
	color:#738fb9;
	margin:1px;
	padding:0.5em;
	font-family:"Lucida Grande", "Tahoma", serif;
	font-size:1.25em;
	font-weight:normal;
}

.summaryContainer h1 .packageSummary {
	display:block;
	color:#000;
	font-size:10px;
	margin-top:2px;
}

.summaryContainer .summary {
	padding:1em;
}

.summaryContainer .summary p {
	font-size:0.85em;
	padding:0;
	margin:0;
}

.reflection {
	background: url("images/demoBoxReflection.gif") repeat-x top left;
	height:25px;
}

.view {
	text-align:right;
}

__CPAN_FILE__ src/widget/demoEngine/templates/DemoNavigator.html
<div dojoAttachPoint="domNode">
	<table width="100%" cellspacing="0" cellpadding="5">
		<tbody>
			<tr dojoAttachPoint="navigationContainer">
				<td dojoAttachPoint="categoriesNode" valign="top" width="1%">
					<h1>Categories</h1>
					<div dojoAttachPoint="categoriesButtonsNode"></div>
				</td>

				<td dojoAttachPoint="demoListNode" valign="top">
					<div dojoAttachPoint="demoListWrapperNode">
						<div dojoAttachPoint="demoListContainerNode">
						</div>
					</div>
				</td>
			</tr>
			<tr>
				<td colspan="2">
					<div dojoAttachPoint="demoNode"></div>
				</td>
			</tr>
		</tbody>
	</table>
</div>

__CPAN_FILE__ src/widget/demoEngine/templates/DemoItem.html
<div dojoAttachPoint="domNode">
	<div dojoAttachPoint="summaryBoxNode">
		<table width="100%" cellspacing="0" cellpadding="0">
			<tbody>
				<tr>
					<td dojoAttachPoint="screenshotTdNode" valign="top" width="1%">
						<img dojoAttachPoint="thumbnailImageNode" dojoAttachEvent="onclick: onSelectDemo" />
					</td>
					<td dojoAttachPoint="summaryContainerNode" valign="top">
						<h1 dojoAttachPoint="nameNode">
						</h1>
						<div dojoAttachPoint="summaryNode">
							<p dojoAttachPoint="descriptionNode"></p>
							<div dojoAttachPoint="viewDemoLinkNode"><img dojoAttachPoint="viewDemoImageNode"/ dojoAttachEvent="onclick: onSelectDemo"></div>
						</div>
					</td>
				</tr>
			</tbody>
		</table>
	</div>
</div>

__CPAN_FILE__ src/widget/demoEngine/templates/DemoPane.html
<div dojoAttachPoint="domNode">
	<iframe dojoAttachPoint="demoNode"></iframe>
</div>

__CPAN_FILE__ src/widget/demoEngine/templates/DemoItem.css
.demoItemSummaryBox {
	background: #efefef;
	border:1px solid #dae3ee;
}

.demoItemScreenshot {
	padding:0.65em;
	width:175px;
	border-right:1px solid #fafafa;
	text-align:center;
	cursor: pointer;
}

.demoItemWrapper{
	margin-bottom:1em;
}

.demoItemWrapper a:link, .demoItemWrapper a:visited {
	color:#a6238f;
	text-decoration:none;
}

.demoItemSummaryContainer {
	border-left:1px solid #ddd;
}

.demoItemSummaryContainer h1 {
	background-color:#e8e8e8;
	border-bottom: 1px solid #e6e6e6;
	color:#738fb9;
	margin:1px;
	padding:0.5em;
	font-family:"Lucida Grande", "Tahoma", serif;
	font-size:1.25em;
	font-weight:normal;
}

.demoItemSummaryContainer h1 .packageSummary {
	display:block;
	color:#000;
	font-size:10px;
	margin-top:2px;
}

.demoItemSummaryContainer .demoItemSummary{
	padding:1em;
}

.demoItemSummaryContainer .demoItemSummary p {
	font-size:0.85em;
	padding:0;
	margin:0;
}

.demoItemView {
	text-align:right;
	cursor: pointer;
}

__CPAN_FILE__ src/widget/demoEngine/templates/SourcePane.css
.sourcePane {
	width: 100%;
	height: 100%;
	padding: 0px;
	margin: 0px;
	overflow: hidden;
}

.sourcePane textarea{
	width: 100%;
	height: 100%;
	border: 0px;
	overflow: auto;
	padding: 0px;
	margin:0px;
}

* html .sourcePane {
	overflow: auto;
}

__CPAN_FILE__ src/widget/demoEngine/templates/DemoContainer.css
.demoContainer{
	width: 100%;
	height: 100%;
	padding: 0px;
	margin: 0px;
}

.demoContainer .return {
	cursor: pointer;
}

.demoContainer span {
	margin-right: 10px;
	cursor: pointer;
}

.demoContainer .selected {
	border-bottom: 5px solid #95bfff;
}

.demoContainer table {
	background: #f5f5f5;
	width: 100%;
	height: 100%;
}

.demoContainerTabs {
	width: 100%;
	height: 400px;
}

.demoContainerTabs .dojoTabLabels-top {
	display: none;
}

.demoContainerTabs .dojoTabPaneWrapper {
	border: 0px;
}


__CPAN_FILE__ src/widget/demoEngine/templates/DemoPane.css
.demoPane {
	width: 100%;
	height: 100%;
	padding: 0px;
	margin: 0px;
	overflow: hidden;
}

.demoPane iframe {
	width: 100%;
	height: 100%;
	border: 0px;
	border: none;
	overflow: auto;
	padding: 0px;
	margin:0px;
	background: #ffffff;
}

__CPAN_FILE__ src/widget/demoEngine/templates/DemoNavigator.css
.demoNavigatorListWrapper {
	border:1px solid #dcdbdb;
	background-color:#f8f8f8;
	padding:2px;
}

.demoNavigatorListContainer {
	border:1px solid #f0f0f0;
	background-color:#fff;
	padding:1em;
}

.demoNavigator h1 {
	margin-top: 0px;
	margin-bottom: 10px;
	font-size: 1.2em;
	border-bottom:1px dotted #a9ccf5;
}

.demoNavigator .dojoButton {
	margin-bottom: 5px;
}

.demoNavigator .dojoButton .dojoButtonContents {
	font-size: 1.1em;
	width: 100px;
	color: black;
}

__CPAN_DIR__ src/widget/demoEngine/templates/images
__CPAN_FILE__ src/widget/demoEngine/templates/images/test_thumb.gif
GIF89a´�÷# ÞÞÞèèèêêêëëëíííéééçççäääæææåååðððìììîîî($%þþþñññúúúóóóÐÐÐÜÜÜYVWüüüýýý301¤¢¢òòòôôô845ÁÀÀ&"#VSTÙØÙ+'(÷÷÷”’“-**EAB<89ÖÖÖ'#$øøøûûû:78?<=GDEÜÛÛïîîõôõ%!",()gdeùùùb_`àßà\YZ1-.URS.*+öõõ>:;–””ããã¹¸¸öööolmÊÉÊÍÌÌB??OLMãââ�FCDFBC@=>^[[XUU)%&QNNáààéèè512411A>?…ƒ„�‹ŒIFFSPQWTT;88ßÞß¿¾¾ žŸˆ††ÎÍÍ¤££ŽŒŒ¡Ÿ ¬««âááLIJmkkljj•““TQRpmnPMM$ !*&'çæçhefxuvROP·µ¶nklÃÂÃ2./üûü956kii´³³0,-_\\LHIC@@=9:“‘’ÂÁÁœšš�››°®¯c`a»ººMJK²±±xvwZWXº¹¹ÚÙÙ`]^„�‚‹ˆ‰×××©§¨£¡¡734°¯¯ifg¢ ¡NKL�ŽŽàààèççš˜™µ³´ÈÇÇÌËËîíîdabª¨¨¥¤¤~|}khi|yz&##­¬¬‚€€ƒ��jgh„‚ƒ¾½½ÃÂÂ§¥¦trrRNO’�‘ËÊËØ×ØÏÎÎ«ªª~{|¸··rop—••KGHÆÅÅHEF‰‡‡ŒŠ‹XUVŸ�žÒÑÒ½¼½3/0ÅÄÄ‡……·¶¶ª©©eccÐÏÏ‘��ÛÚÚÊÉÉ,)*³²²���[XYÄÃÄÇÆÆ623}~˜–—]Z[zxxÉÈÈ?;</+,urs†„…ebb½»¼a^_ÝÝÝ—––_\]ÖÕÕÔÓÓŠˆˆ}z{ïïïÿÿÿ!ù,´�ÿË	H° Áƒ*\È°¡Ã‡#JœH±¢Å‹3jÜÈ±£Ç� CŠI²¤É“(Sª\É²¥Ë—0cÊœI³¦Í›8sêÜÉ³§ÏŸ@ƒrT ¨Ñ£H“*]Ê´©Ó§P£J�UÇæ²jÝÊµ«×¯`ÃŠK¶¬Ù³e\EË¶­Û·pã†U»«Ü»xóêmKW£Ý½€ÆÛ7ãßÁˆ+[ãáÅ�#n|ñ±äË˜áR¶h9³çÏc7Wìº´é¬¢)’>Í:sê‰«[Ë†üZbìÙ¸×Žx;·o½»!öþM<nð‡Ã‹+g{ÜaòåÐÉ6oø<ºõ¯ÓV¿Î]kö…Û»sÿÿ®0¼xëäš?==Âõì•»??>ñùëÛ÷�¿ þý¸õGÐÊ&à@ÈÚ�%¨ i–ãàƒ E8!…žYˆa|nx^‡vbˆ×�Hbt&ž¸\Š*Çb‹¿½cn2z–Cüñ	iäðÄŒ5fæ-`¤‘º¸nLq¤F¹$nj©CRÖåÛGâ@@–~ù†Å‘¼¦a¾Updœé˜oÎiÇnVæÛ
Gš°ƒ[<0Þ”³ái$@°uA¸âK‰€Ê&(J¤°Õ~Œ`é¥g|©UGàW°d ê¨|QÎiA~öè’jUC§�Úÿ°Õ0�²ÂÕ«°éª�¶ö(4hUG%k¬}H°ÕG’rÂV”�++ÀÀ«–¬YÐ	~.q$°Z] ä–K�~nÅEK$Â•âL ï¼€°`¯™ýÊ- âD9|,Œ©&ö@( ‡;0@Gò1°YD ÂŠlÑzøJŠ‘Y@ #�–WtpK–h’ÀVx˜RƒÁx]E  `T!­<˜GZ²•li²VrM~ü�
8¡i
üÑi
\I²ÇGüÐƒÈáÂµaz¦Á
F’ËV$¡ôÉæ@à-¥h•‰‘%ÈÿšÕéI¸o9ŽVª‰4v¼%G¶`WN™„
æ¨ ‡‘ºLž•iE›æ$@Â‘Ûh%�‘t0°Šûý™Ð€=»‘wt°‘H`È‘¼puÇ‘ÍdUG“•ÖFÂÕ4GNRí{ù�´‘�tÅÄ‘H<ðGÂÕÞ¬P·GÎ`Ž·ÐWÂt:A…Ž'FH§�t¥&ïæ<rdáàJ:õ	s€.}æPF§âÀ-4áHT ¶0ÓƒNáAG²‚9f`%Lpå3RÌ¶É
æèB§8Á•DáHE�`Ú0S¸#mŒ+ûÀ$Àƒ#q@Y[A€ÿ2ø˜ zæèÅ‘<`¯­Ð€]’!š2Ó�NmƒFRƒ#f¤Hq¥t8’$�>I8¢‘B0®<€GZƒß”™"IX¶Ð©$ÐM+ˆÄ‘B °àHe(ÇéŒD,q…KGš£�2I#á‡Gú€!:Õ‚:pe&€´p�CŠP�3’ Ð;I’œñÌ˜Ž4‡<~@}ücV@y¤&<¡”G
‚¸€F¶²S°�gÑ)MhïH9àÔ‘” ®h tFZ†y$9@!ƒl#WÐ€ÌÙÕ1‡èTŽi$WX£S?äJ9Àg$;A¦€D@ÿO0±+EXb2Uã™3t*‚ã<|�‡#aƒ•[�‚Ž¤sˆ ‡FB…9ZÐ©!p¥5R
ÏÔ¢Sƒ£÷"P‰%6Q+ÞH%Þ`Ž˜ñ„æ0C§Üµ•dáH83ç/c™² UYyã‘¦`ŽStª–[‘E§QS5@}_è¸b€†	$µ�g,Pˆ8²P+*àCž0üqGŠ„™`ðS#‰¢t‹@5>B<K¨3Ä :uˆ­P@¦Q "Ž”®4âHgøœŽd‹¬�ÌH{HWV˜%Âé�1åÀ&š°…¬X@5\wpR«PZÙŸèd
ÿDãHäÈ
ÔØÙ™ÃŠ'`§è™YtŠ
»…¸°ˆ#¡ÀY‘‹¡ŽgËÊ<�T­x}Ð CG‚†•7¥ñ¬b°Î€FlÜ0G8êA`ÂÒªÁ�´2¯[9Áöð
(p‚G7TÏä¢E¸B°ò€l¤á¥xÆ1’a-s�£ FÌ@…KqˆFºâV°
*,áe00‡6âÊF³oq³Ðáö|V<8ÒÕà
2Ð‘« ÿà*2€Ü€îF™Éñy�6@	)ˆA<ÔS2˜°ˆ#D	Ì?žQ�é¨f%I¹ÿÍ³	3œ1#ç9K¦Îv¦MšóLç=óùÎ~þ³žß,èá²¹Ðkž$¢ËE3Z™Žf0–#ÝgBSzÐ“¾tdð¬é»pºÓÆ	4¨	#êQËåÓ¦æK©SýT³ú,®~uZV-k´ÄºÖb¹5®Cë]K§×¾Î5°ƒÍkK»ÕÃ>vWt­lÔd„8@’Ž`�€€n#`ÚÄ€·»}4`!€ÆÝmp[ÜìF€�mƒ4€Ûñnw³�“ooàÜI@¿õ½oÂ¼Û	(ˆÀ~	ª8üá�¸Ä'Þ”K(È½^€Ž{üã ¹ÈGNò’›üä(ÿO¹ÊWžò‹ÿû é^w¼	@óšÛüæ8Ï¹ÎwÎóžûüç@ºÐ�Þïy×;!
Ø6»Àô¦;ýéP�ºÔ§Nõª[ýêXÏºÖ±ïrü!€`€²›ýìhO»Ú×Îö¶»ýíp�»Üçw$@(@FPŽ@ì¼àOøÂþðˆO¼âÏøÆ;þñƒôþu�@àò˜ç{@à ½èGOúÒ›þô¨O½êWÏúÖ�^ ô¾Ì_Þ#È½îw¿û4€œï¼�€âÿøÈO¾ò—Ïüæ;ÿùÐ�þÊNsàûž÷ØÏ=î³Ï}î—£›~[ÓŸ˜ÿüèO¿ú×Ïþö»ÿýï¿{à›üÙŸ»ûøß½P~�ßêŠwð—~ xPwsWyû·€Ø€ø€�8�X�x�˜�¸�Ø�X;
__CPAN_FILE__ src/widget/demoEngine/templates/images/viewDemo.png
‰PNG


IHDRX	ú#gAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<íIDATxÚì˜ÏkAÇ7µZBYõVôü<K²=y04®Ô“B@/z¬ñ(Bº� ¹ä(ºrð–%g)ÝazñdŽ¥µ5~_xSãgóÃK÷Ácggß›Ÿyóc§P©T¬¤½ýlbE‘uUecA¿"4l4ï™•ËÊÏ$I’}×u÷†Ãáóå³<©V«/ûýþ‹çß²)ÒÇü¶µ÷õz}§ÓéÜn·ÛïM
(
>=èDd«<—&4^a_}‘¦:CzN§ÓÿØ)—ËË”µ¸o[­Ö�n·ûÚÀ¾õ¨zoB¨ÍºJ9€îª¾r@¢þµžÉx<^¦¼"à¾B4ßÅ’Qû×áBìi�MRc"l|¤|UÄ—xôæÔ©ž¤#i‡Yå±ˆÈN8¯Éåºõª>Š~éks¾-ý7Ö1j€»W«Õ¾òi#UÐ€�­"µ©u $à
x¾ˆBWØ{"mýT^0.:àò	Ì'¦R
à±h‹Çð•Œ¸^²á›³6À$ƒÁà»�™‚ìpt&)6M-ò|‘vG³´UD_Ìíˆ¹ÞÙ#Þp@P~€tÄ³Ç‘#?`»@ùo®‰/ECÛ0ŠÔ†6Š£�àCQŽ- 'u“½ »*Š5ÿ,lI«3QðW
øZ‡~4´9"'bš·nú1œ!•Ä7ß0zmœ€—«�)ÙCz²@¿#^V”ÿå¬“€ãb±H¿¿?
�i÷µ¼ÐÇÐ#ÓVQcÐ¨X�Ò$à1�‘QlËN¦„¥­“VJ9$OÒå»)lØÑZÿÙr1[>¼‹xý"Þ�xJ|Ëï"Vÿ'G>çÁÍ•—“w¹'9JÃ�›™g^Wæ€³Ë8G—
ðvŸ-èMè9ôzÁÏsNŸÒÆš£åŸºMr]÷^ŸkÐë)ùö7Ã>ãeä'ˆé•œE07øŽ�`þ"Ä‹<VÓå�Õˆ€\à«IEND®B`‚
__CPAN_DIR__ src/widget/svg
__CPAN_FILE__ src/widget/svg/Chart.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.svg.Chart");

dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.Chart");
dojo.require("dojo.math");
dojo.require("dojo.html");
dojo.require("dojo.svg");
dojo.require("dojo.graphics.color");

dojo.widget.svg.Chart=function(){
	dojo.widget.Chart.call(this);
	dojo.widget.HtmlWidget.call(this);
};
dojo.inherits(dojo.widget.svg.Chart, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.svg.Chart, {
	//	widget props
	templatePath:null,
	templateCssPath:null,

	//	state
	_isInitialized:false,
	hasData:false,

	//	chart props
	vectorNode:null,
	plotArea:null,
	dataGroup:null,
	axisGroup:null,

	properties:{
		height:400,	//	defaults, will resize to the domNode.
		width:600,
		plotType:null,
		padding:{
			top:10,
			bottom:2,
			left:60,
			right:30
		},
		axes:{
			x:{
				plotAt:0,
				label:"",
				unitLabel:"",
				unitType:Number,
				nUnitsToShow:10,
				range:{
					min:0,
					max:200
				}
			},
			y:{
				plotAt:0,
				label:"",
				unitLabel:"",
				unitType:Number,
				nUnitsToShow:10,
				range:{
					min:0,
					max:200
				}
			}
		}
	},
	
	fillInTemplate:function(args,frag){
		this.initialize();
		this.render();
	},
	parseData:function(){
	},
	initialize:function(){
		this.parseData();
	
		//	begin by grabbing the table, and reading it in.
		var table=this.domNode.getElementsByTagName("table")[0];
		if (!table) return;
		
		var bRangeX=false;
		var bRangeY=false;
		
		//	properties off the table
		if (table.getAttribute("width")) this.properties.width=table.getAttribute("width");
		if (table.getAttribute("height")) this.properties.height=table.getAttribute("height");
		if (table.getAttribute("plotType")) this.properties.plotType=table.getAttribute("plotType");
		if (table.getAttribute("padding")){
			if (table.getAttribute("padding").indexOf(",") > -1)
				var p=table.getAttribute("padding").split(","); 
			else var p=table.getAttribute("padding").split(" ");
			if (p.length==1){
				var pad=parseFloat(p[0]);
				this.properties.padding.top=pad;
				this.properties.padding.right=pad;
				this.properties.padding.bottom=pad;
				this.properties.padding.left=pad;
			} else if(p.length==2){
				var padV=parseFloat(p[0]);
				var padH=parseFloat(p[1]);
				this.properties.padding.top=padV;
				this.properties.padding.right=padH;
				this.properties.padding.bottom=padV;
				this.properties.padding.left=padH;
			} else if(p.length==4){
				this.properties.padding.top=parseFloat(p[0]);
				this.properties.padding.right=parseFloat(p[1]);
				this.properties.padding.bottom=parseFloat(p[2]);
				this.properties.padding.left=parseFloat(p[3]);
			}
		}
		if (table.getAttribute("rangeX")){
			var p=table.getAttribute("rangeX");
			if (p.indexOf(",")>-1) p=p.split(",");
			else p=p.split(" ");
			this.properties.axes.x.range.min=parseFloat(p[0]);
			this.properties.axes.x.range.max=parseFloat(p[1]);
			bRangeX=true;
		}
		if (table.getAttribute("rangeY")){
			var p=table.getAttribute("rangeY");
			if (p.indexOf(",")>-1) p=p.split(",");
			else p=p.split(" ");
			this.properties.axes.y.range.min=parseFloat(p[0]);
			this.properties.axes.y.range.max=parseFloat(p[1]);
			bRangeY=true;
		}

		var thead=table.getElementsByTagName("thead")[0];
		var tbody=table.getElementsByTagName("tbody")[0];
		if(!(thead&&tbody)) dojo.raise("dojo.widget.Chart: supplied table must define a head and a body.");

		//	set up the series.
		var columns=thead.getElementsByTagName("tr")[0].getElementsByTagName("th");	//	should be <tr><..>
		
		//	assume column 0 == X
		for (var i=1; i<columns.length; i++){
			var key="column"+i;
			var label=columns[i].innerHTML;
			var plotType=columns[i].getAttribute("plotType")||"line";
			var color=columns[i].getAttribute("color");
			var ds=new dojo.widget.Chart.DataSeries(key,label,plotType,color);
			this.series.push(ds);
		}

		//	ok, get the values.
		var rows=tbody.getElementsByTagName("tr");
		var xMin=Number.MAX_VALUE,xMax=Number.MIN_VALUE;
		var yMin=Number.MAX_VALUE,yMax=Number.MIN_VALUE;
		var ignore = [
			"accesskey","align","bgcolor","class",
			"colspan","height","id","nowrap",
			"rowspan","style","tabindex","title",
			"valign","width"
		];

		for(var i=0; i<rows.length; i++){
			var row=rows[i];
			var cells=row.getElementsByTagName("td");
			var x=Number.MIN_VALUE;
			for (var j=0; j<cells.length; j++){
				if (j==0){
					x=parseFloat(cells[j].innerHTML);
					xMin=Math.min(xMin, x);
					xMax=Math.max(xMax, x);
				} else {
					var ds=this.series[j-1];
					var y=parseFloat(cells[j].innerHTML);
					yMin=Math.min(yMin,y);
					yMax=Math.max(yMax,y);
					var o={x:x, value:y};
					var attrs=cells[j].attributes;
					for(var k=0; k<attrs.length; k++){
						var attr=attrs.item(k);
						var bIgnore=false;
						for (var l=0; l<ignore.length; l++){
							if (attr.nodeName.toLowerCase()==ignore[l]){
								bIgnore=true;
								break;
							}
						}
						if(!bIgnore) o[attr.nodeName]=attr.nodeValue;
					}
					ds.add(o);
				}
			}
		}

		//	fix the axes
		if(!bRangeX){
			this.properties.axes.x.range={min:xMin, max:xMax};
		}
		if(!bRangeY){
			this.properties.axes.y.range={min:yMin, max:yMax};
		}

		//	where to plot the axes
		if (table.getAttribute("axisAt")){
			var p=table.getAttribute("axisAt");
			if (p.indexOf(",")>-1) p=p.split(",");
			else p=p.split(" ");
			
			//	x axis
			if (!isNaN(parseFloat(p[0]))){
				this.properties.axes.x.plotAt=parseFloat(p[0]);
			} else if (p[0].toLowerCase()=="ymin"){
				this.properties.axes.x.plotAt=this.properties.axes.y.range.min;
			} else if (p[0].toLowerCase()=="ymax"){
				this.properties.axes.x.plotAt=this.properties.axes.y.range.max;
			}

			// y axis
			if (!isNaN(parseFloat(p[1]))){
				this.properties.axes.y.plotAt=parseFloat(p[1]);
			} else if (p[1].toLowerCase()=="xmin"){
				this.properties.axes.y.plotAt=this.properties.axes.x.range.min;
			} else if (p[1].toLowerCase()=="xmax"){
				this.properties.axes.y.plotAt=this.properties.axes.x.range.max;
			}
		} else {
			this.properties.axes.x.plotAt=this.properties.axes.y.range.min;
			this.properties.axes.y.plotAt=this.properties.axes.x.range.min;
		}

		//	table values should be populated, now pop it off.
		this.domNode.removeChild(table);

		//	get the width and the height.
//		this.properties.width=dojo.html.getInnerWidth(this.domNode);
//		this.properties.height=dojo.html.getInnerHeight(this.domNode);

		// ok, lets create the chart itself.
		dojo.svg.g.suspend();		
		if(this.vectorNode) this.destroy();
		this.vectorNode=document.createElementNS(dojo.svg.xmlns.svg, "svg");
		this.vectorNode.setAttribute("width", this.properties.width);
		this.vectorNode.setAttribute("height", this.properties.height);

		//	set up the clip path for the plot area.
		var defs = document.createElementNS(dojo.svg.xmlns.svg, "defs");
		var clip = document.createElementNS(dojo.svg.xmlns.svg, "clipPath");
		clip.setAttribute("id","plotClip"+this.widgetId);
		var rect = document.createElementNS(dojo.svg.xmlns.svg, "rect");		
		rect.setAttribute("x", this.properties.padding.left);
		rect.setAttribute("y", this.properties.padding.top);
		rect.setAttribute("width", this.properties.width-this.properties.padding.left-this.properties.padding.right);
		rect.setAttribute("height", this.properties.height-this.properties.padding.bottom-this.properties.padding.bottom);
		clip.appendChild(rect);
		defs.appendChild(clip);
		this.vectorNode.appendChild(defs);

		//	the plot background.
		this.plotArea = document.createElementNS(dojo.svg.xmlns.svg, "g");
		this.vectorNode.appendChild(this.plotArea);
		var rect = document.createElementNS(dojo.svg.xmlns.svg, "rect");		
		rect.setAttribute("x", this.properties.padding.left);
		rect.setAttribute("y", this.properties.padding.top);
		rect.setAttribute("width", this.properties.width-this.properties.padding.left-this.properties.padding.right);
		rect.setAttribute("height", this.properties.height-this.properties.padding.bottom-this.properties.padding.bottom);
		rect.setAttribute("fill", "#fff");
		this.plotArea.appendChild(rect);

		//	data group
		this.dataGroup = document.createElementNS(dojo.svg.xmlns.svg, "g");
		this.dataGroup.setAttribute("style","clip-path:url(#plotClip"+this.widgetId+");");
		this.plotArea.appendChild(this.dataGroup);

		//	axis group
		this.axisGroup = document.createElementNS(dojo.svg.xmlns.svg, "g");
		this.plotArea.appendChild(this.axisGroup);

		//	x axis
		var stroke=1;
		var line = document.createElementNS(dojo.svg.xmlns.svg, "line");
		var y=dojo.widget.svg.Chart.Plotter.getY(this.properties.axes.x.plotAt, this);
		line.setAttribute("y1", y);
		line.setAttribute("y2", y);
		line.setAttribute("x1",this.properties.padding.left-stroke);
		line.setAttribute("x2",this.properties.width-this.properties.padding.right);
		line.setAttribute("style","stroke:#000;stroke-width:"+stroke+";");
		this.axisGroup.appendChild(line);
		
		//	x axis units.
		//	(min and max)
		var textSize=10;
		var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
		text.setAttribute("x", this.properties.padding.left);
		text.setAttribute("y", this.properties.height-this.properties.padding.bottom+textSize+2);
		text.setAttribute("style", "text-anchor:middle;font-size:"+textSize+"px;fill:#000;");
		text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.x.range.min),2)));
		this.axisGroup.appendChild(text);
		
		var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
		text.setAttribute("x", this.properties.width-this.properties.padding.right-(textSize/2));
		text.setAttribute("y", this.properties.height-this.properties.padding.bottom+textSize+2);
		text.setAttribute("style", "text-anchor:middle;font-size:"+textSize+"px;fill:#000;");
		text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.x.range.max),2)));
		this.axisGroup.appendChild(text);	
		
		//	y axis
		var line=document.createElementNS(dojo.svg.xmlns.svg, "line");
		var x=dojo.widget.svg.Chart.Plotter.getX(this.properties.axes.y.plotAt, this);
		line.setAttribute("x1", x);
		line.setAttribute("x2", x);
		line.setAttribute("y1", this.properties.padding.top);
		line.setAttribute("y2", this.properties.height-this.properties.padding.bottom);
		line.setAttribute("style", "stroke:#000;stroke-width:"+stroke+";");
		this.axisGroup.appendChild(line);

		//	y axis units
		var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
		text.setAttribute("x", this.properties.padding.left-4);
		text.setAttribute("y", this.properties.height-this.properties.padding.bottom);
		text.setAttribute("style", "text-anchor:end;font-size:"+textSize+"px;fill:#000;");
		text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.y.range.min),2)));
		this.axisGroup.appendChild(text);
		
		var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
		text.setAttribute("x", this.properties.padding.left-4);
		text.setAttribute("y", this.properties.padding.top+(textSize/2));
		text.setAttribute("style", "text-anchor:end;font-size:"+textSize+"px;fill:#000;");
		text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.y.range.max),2)));
		this.axisGroup.appendChild(text);	

		this.domNode.appendChild(this.vectorNode);
		dojo.svg.g.resume();

		//	this is last.
		this.assignColors();
		this._isInitialized=true;
	},
	destroy:function(){
		while(this.domNode.childNodes.length>0){
			this.domNode.removeChild(this.domNode.childNodes.item(0));
		}
		this.vectorNode=this.plotArea=this.dataGroup=this.axisGroup=null;
	},
	render:function(){
		dojo.svg.g.suspend();
		
		if (this.dataGroup){
			while(this.dataGroup.childNodes.length>0){
				this.dataGroup.removeChild(this.dataGroup.childNodes.item(0));
			}
		} else {
			this.initialize();
		}

		//	the remove/append is an attempt to streamline the rendering, it's totally optional
//		var p=this.dataGroup.parentNode;
//		p.removeChild(this.dataGroup);
		for(var i=0; i<this.series.length; i++){
			dojo.widget.svg.Chart.Plotter.plot(this.series[i], this);
		}
//		p.appendChild(this.dataGroup);
		
		dojo.svg.g.resume();
	}
});

dojo.widget.svg.Chart.Plotter=new function(){
	var _this=this;
	var plotters = {};
	var types=dojo.widget.Chart.PlotTypes;
	
	this.getX=function(value, chart){
		var v=parseFloat(value);
		var min=chart.properties.axes.x.range.min;
		var max=chart.properties.axes.x.range.max;
		var ofst=0-min;
		min+=ofst; max+=ofst; v+=ofst;

		var xmin=chart.properties.padding.left;
		var xmax=chart.properties.width-chart.properties.padding.right;
		var x=(v*((xmax-xmin)/max))+xmin;
		return x;
	};
	this.getY=function(value, chart){
		var v=parseFloat(value);
		var max=chart.properties.axes.y.range.max;
		var min=chart.properties.axes.y.range.min;
		var ofst=0;
		if(min<0)ofst+=Math.abs(min);
		min+=ofst; max+=ofst; v+=ofst;
		
		var ymin=chart.properties.height-chart.properties.padding.bottom;
		var ymax=chart.properties.padding.top;
		var y=(((ymin-ymax)/(max-min))*(max-v))+ymax;
		return y;
	};

	this.addPlotter=function(name, func){
		plotters[name]=func;
	};
	this.plot=function(series, chart){
		if (series.values.length==0) return;
		if (series.plotType && plotters[series.plotType]){
			return plotters[series.plotType](series, chart);
		}
		else if (chart.plotType && plotters[chart.plotType]){
			return plotters[chart.plotType](series, chart);
		}
	};

	//	plotting
	plotters[types.Bar]=function(series, chart){
		var space=1;
		var lastW = 0;
		for (var i=0; i<series.values.length; i++){
			var x=_this.getX(series.values[i].x, chart);
			var w;
			if (i==series.values.length-1){
				w=lastW;
			} else{
				w=_this.getX(series.values[i+1].x, chart)-x-space;
				lastW=w;
			}
			x-=(w/2);

			var yA=_this.getY(chart.properties.axes.x.plotAt, chart);
			var y=_this.getY(series.values[i].value, chart);
			var h=Math.abs(yA-y);
			if (parseFloat(series.values[i].value)<chart.properties.axes.x.plotAt){
				var oy=yA;
				yA=y;
				y=oy;
			}

			var bar=document.createElementNS(dojo.svg.xmlns.svg, "rect");
			bar.setAttribute("fill", series.color);
			bar.setAttribute("title", series.label + ": " + series.values[i].value);
			bar.setAttribute("stroke-width", "0");
			bar.setAttribute("x", x);
			bar.setAttribute("y", y);
			bar.setAttribute("width", w);
			bar.setAttribute("height", h);
			bar.setAttribute("fill-opacity", "0.9");
			chart.dataGroup.appendChild(bar);
		}
	};
	plotters[types.Line]=function(series, chart){
		var tension=3;
		var line = document.createElementNS(dojo.svg.xmlns.svg, "path");
		line.setAttribute("fill", "none");
		line.setAttribute("stroke", series.color);
		line.setAttribute("stroke-width", "2");
		line.setAttribute("stroke-opacity", "0.85");
		line.setAttribute("title", series.label);
		chart.dataGroup.appendChild(line);

		var path = [];
		for (var i=0; i<series.values.length; i++){
			var x = _this.getX(series.values[i].x, chart)
			var y = _this.getY(series.values[i].value, chart);

			var dx = chart.properties.padding.left+1;
			var dy = chart.properties.height-chart.properties.padding.bottom;
			if (i>0){
				dx=x-_this.getX(series.values[i-1].x, chart);
				dy=_this.getY(series.values[i-1].value, chart);
			}
			
			if (i==0) path.push("M");
			else {
				path.push("C");
				var cx=x-(tension-1)*(dx/tension);
				path.push(cx+","+dy);
				cx=x-(dx/tension);
				path.push(cx+","+y);
			}
			path.push(x+","+y);
		}
		line.setAttribute("d", path.join(" "));
	};
	plotters[types.Scatter]=function(series, chart){
		var r=7;
		for (var i=0; i<series.values.length; i++){
			var x=_this.getX(series.values[i].x, chart);
			var y=_this.getY(series.values[i].value, chart);
			var point = document.createElementNS(dojo.svg.xmlns.svg, "path");
			point.setAttribute("fill", series.color);
			point.setAttribute("stroke-width", "0");
			point.setAttribute("title", series.label + ": " + series.values[i].value);
			point.setAttribute("d",
				"M " + x + "," + (y-r) + " " +
				"Q " + x + "," + y + " " + (x+r) + "," + y + " " +
				"Q " + x + "," + y + " " + x + "," + (y+r) + " " +
				"Q " + x + "," + y + " " + (x-r) + "," + y + " " +
				"Q " + x + "," + y + " " + x + "," + (y-r) + " " +
				"Z"
			);
			chart.dataGroup.appendChild(point);
		}
	};
	plotters[types.Bubble]=function(series, chart){
		//	added param for series[n].value: size
		var minR=1;
		
		//	do this off the x axis?
		var min=chart.properties.axes.x.range.min;
		var max=chart.properties.axes.x.range.max;
		var ofst=0-min;
		min+=ofst; max+=ofst;

		var xmin=chart.properties.padding.left;
		var xmax=chart.properties.width-chart.properties.padding.right;
		var factor=(max-min)/(xmax-xmin)*25;
		
		for (var i=0; i<series.values.length; i++){
			var size = series.values[i].size;
			if (isNaN(parseFloat(size))) size=minR;
			var point=document.createElementNS(dojo.svg.xmlns.svg, "circle");
			point.setAttribute("stroke-width", 0);
			point.setAttribute("fill", series.color);
			point.setAttribute("fill-opacity", "0.8");
			point.setAttribute("r", (parseFloat(size)*factor)/2);
			point.setAttribute("cx", _this.getX(series.values[i].x, chart));
			point.setAttribute("cy", _this.getY(series.values[i].value, chart));
			point.setAttribute("title", series.label + ": " + series.values[i].value + " (" + size + ")");
			chart.dataGroup.appendChild(point);
		}
	};
}();

__CPAN_DIR__ src/widget/templates
__CPAN_FILE__ src/widget/templates/HtmlResizableTextarea.css
div.statusBar {
	background-color: ThreeDFace;
	height: 28px;
	padding: 1px;
	overflow: hidden;
	font-size: 12px;
}

div.statusPanel {
	background-color: ThreeDFace;
	border: 1px solid;
	border-color: ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow;
	margin: 1px;
	padding: 2px 6px;
}

__CPAN_FILE__ src/widget/templates/HtmlEditorToolbar.css
.StyleDropdownContainer {
	position: absolute;
	z-index: 1000;
	overflow: auto;
	cursor: default;
	width: 250px;
	height: 250px;
	background-color: white;
	border: 1px solid black;
}

.ColorDropdownContainer {
	position: absolute;
	z-index: 1000;
	overflow: auto;
	cursor: default;
	width: 250px;
	height: 150px;
	background-color: white;
	border: 1px solid black;
}

.EditorToolbarDomNode {
	background-image: url(buttons/bg-fade.png);
	background-repeat: repeat-x;
	background-position: 0px -50px;
}

.EditorToolbarSmallBg {
	background-image: url(images/toolbar-bg.gif);
	background-repeat: repeat-x;
	background-position: 0px 0px;
}

/*
body {
	background:url(images/blank.gif) fixed;
}*/

.IEFixedToolbar {
	position:absolute;
	/* top:0; */
	top: expression(eval((document.documentElement||document.body).scrollTop));
}

div.bigIcon {
	width: 40px;
	height: 40px; 
	/* background-color: white; */
	/* border: 1px solid #a6a7a3; */
	font-family: Verdana, Trebuchet, Tahoma, Arial;
}

.iconContainer {
	font-family: Verdana, Trebuchet, Tahoma, Arial;
	font-size: 13px;
	float: left;
	height: 18px;
	display: block;
	/* background-color: white; */
	/* border: 1px solid white; */
	/* border: 1px solid #a6a7a3; */
	padding-right: 3px;
	cursor: pointer;
	border: 1px solid transparent;
	_border: none;
}

span.icon {
	display: block;
	text-align: center;
	min-width: 18px;
	width: 18px;
	height: 18px;
	/* background-color: #a6a7a3; */
	background-repeat: no-repeat;
	background-image: url(buttons/aggregate.gif);
}


span.icon[class~=icon] {
}

.headingContainer {
	width: 150px;
	height: 30px;
	margin: 0px;
	/* padding-left: 5px; */
	overflow: hidden;
	line-height: 25px;
	border-bottom: 1px solid black;
	border-top: 1px solid white;
}

.EditorToolbarDomNode select {
	font-size: 14px;
}

.sep { width: 5px; min-width: 5px; max-width: 5px; background-position: 0px 0px}
.backcolor { background-position: -18px 0px}
.bold { background-position: -36px 0px}
.cancel { background-position: -54px 0px}
.copy { background-position: -72px 0px}
.createlink { background-position: -90px 0px}
.cut { background-position: -108px 0px}
.delete { background-position: -126px 0px}
.forecolor { background-position: -144px 0px}
.hilitecolor { background-position: -162px 0px}
.indent { background-position: -180px 0px}
.inserthorizontalrule { background-position: -198px 0px}
.insertimage { background-position: -216px 0px}
.insertorderedlist { background-position: -234px 0px}
.inserttable { background-position: -252px 0px}
.insertunorderedlist { background-position: -270px 0px}
.italic { background-position: -288px 0px}
.justifycenter { background-position: -306px 0px}
.justifyfull { background-position: -324px 0px}
.justifyleft { background-position: -342px 0px}
.justifyright { background-position: -360px 0px}
.left_to_right { background-position: -378px 0px}
.list_bullet_indent { background-position: -396px 0px}
.list_bullet_outdent { background-position: -414px 0px}
.list_num_indent { background-position: -432px 0px}
.list_num_outdent { background-position: -450px 0px}
.outdent { background-position: -468px 0px}
.paste { background-position: -486px 0px}
.redo { background-position: -504px 0px}
.removeformat { background-position: -522px 0px}
.right_to_left { background-position: -540px 0px}
.save { background-position: -558px 0px}
.space { background-position: -576px 0px}
.strikethrough { background-position: -594px 0px}
.subscript { background-position: -612px 0px}
.superscript { background-position: -630px 0px}
.underline { background-position: -648px 0px}
.undo { background-position: -666px 0px}
.wikiword { background-position: -684px 0px}


__CPAN_FILE__ src/widget/templates/Menu.css
.dojoMenu {
	border:1px solid #000000;
	list-style-type:none;
	margin:0;
	padding:0;
	padding-bottom: 1px;
	background-color:#f4f4f4;
	font-size: 8pt;
}

.dojoMenuSeparator {
	list-style-type:none;
	margin:0;
	padding:1px 0;
	border-bottom:1px solid #000000;
	line-height:1px;
	height:1px;
}

li:hover.dojoMenuSeparator {
	background-color:#e5e5e5;
	cursor:default;
}




.dojoContextMenu {
	position: absolute;
	display: none;
	border: 2px solid;
	border-color: ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight;
	list-style-type: none;
	margin: 0;
	padding: 1px;
	background-color: ThreeDFace;
	font-size: 8pt;
}

.dojoMenuItem {
	white-space: nowrap;
	padding: 2px;
	font: menu;
	color: WindowText;
}

.dojoMenuItem a {
	text-decoration: none;
	color: WindowText;
	font: inherit;
}

.dojoMenuItemHover {
	padding: 2px;
	background-color: blue;
	cursor: pointer;
	_cursor: hand;
	background-color: Highlight;
	color: HighlightText;
}
__CPAN_FILE__ src/widget/templates/HtmlMonthlyCalendar.html
<div class="datePickerContainer" dojoAttachPoint="datePickerContainerNode">
	<h3 class="monthLabel">
	<!--
	<span 
		dojoAttachPoint="decreaseWeekNode" 
		dojoAttachEvent="onClick: onIncrementWeek;" 
		class="incrementControl">
		<img src="${dojoRoot}src/widget/templates/decrementWeek.gif" alt="&uarr;" />
	</span>
	-->
	<span 
		dojoAttachPoint="decreaseMonthNode" 
		dojoAttachEvent="onClick: onIncrementMonth;" class="incrementControl">
		<img src="${dojoRoot}src/widget/templates/decrementMonth.gif" 
			alt="&uarr;" dojoAttachPoint="decrementMonthImageNode">
	</span>
	<span dojoAttachPoint="monthLabelNode" class="month">July</span>
	<span 
		dojoAttachPoint="increaseMonthNode" 
		dojoAttachEvent="onClick: onIncrementMonth;" class="incrementControl">
		<img src="${dojoRoot}src/widget/templates/incrementMonth.gif" 
			alt="&darr;"  dojoAttachPoint="incrementMonthImageNode">
	</span>
	<!--
		<span dojoAttachPoint="increaseWeekNode" 
			dojoAttachEvent="onClick: onIncrementWeek;" 
			class="incrementControl">
			<img src="${dojoRoot}src/widget/templates/incrementWeek.gif" 
			alt="&darr;" />
		</span>
	-->
	</h3>
	<table class="calendarContainer">
		<thead>
			<tr>
				<td>Sunday</td>
				<td>Monday</td>
				<td>Tuesday</td>
				<td>Wednesday</td>
				<td>Thursday</td>
				<td>Friday</td>
				<td>Saturday</td>
			</tr>
		</thead>
		<tbody dojoAttachPoint="calendarDatesContainerNode" 
			dojoAttachEvent="onClick: onSetDate;">
			<tr dojoAttachPoint="calendarRow0">
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
			</tr>
			<tr dojoAttachPoint="calendarRow1">
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
			</tr>
			<tr dojoAttachPoint="calendarRow2">
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
			</tr>
			<tr dojoAttachPoint="calendarRow3">
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
			</tr>
			<tr dojoAttachPoint="calendarRow4">
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
			</tr>
			<tr dojoAttachPoint="calendarRow5">
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
				<td></td>
			</tr>
		</tbody>
	</table>
	<h3 class="yearLabel">
		<span dojoAttachPoint="previousYearLabelNode"
			dojoAttachEvent="onClick: onIncrementYear;" class="previousYear"></span>
		<span class="selectedYear" dojoAttachPoint="currentYearLabelNode"></span>
		<span dojoAttachPoint="nextYearLabelNode" 
			dojoAttachEvent="onClick: onIncrementYear;" class="nextYear"></span>
	</h3>
</div>

__CPAN_FILE__ src/widget/templates/HtmlShowSlide.html
<div class="dojoShowSlide">
	<div class="dojoShowSlideTitle">
		<h1 dojoAttachPoint="htmlTitle">Title</h1>
	</div>
	<div class="dojoShowSlideBody" dojoAttachPoint="containerNode"></div>
</div>
__CPAN_FILE__ src/widget/templates/HtmlComboBox.html
<div style="position: relative; z-index: 100;">
	<input type="hidden" name="" value="" 
		dojoAttachPoint="comboBoxValue">
	<input type="hidden" name="" value="" 
		dojoAttachPoint="comboBoxSelectionValue">
	<table class="dojoComboBox"
		cellpadding="0"
		cellmargin="0"
		border="0"
		dojoAttachPoint="cbTableNode">
		<tr valign="top">
			<td width=100%>
				<input type="text" autocomplete="off" class="dojoComboBoxInput"
					dojoAttachEvent="keyDown: onKeyDown; keyUp: onKeyUp; keyPress: onKeyPress;"
					dojoAttachPoint="textInputNode"
					style="width: 100%;">
			</td>
			<td>
				<img border="0" 
					hspace="0"
					vspace="0"
					dojoAttachPoint="downArrowNode"
					dojoAttachEvent="onMouseUp: handleArrowClick;"
					src="${dojoRoot}src/widget/templates/images/combo_box_arrow.png">
			</td>
		</tr>
	</table>
	<div dojoAttachPoint="optionsListWrapper" style="position:relative;" tabindex="-1">
		<div class="dojoComboBoxOptions" dojoAttachPoint="optionsListNode"
			dojoAttachEvent="onClick: selectOption;  onMouseOver: _onMouseOver; onMouseOut: _onMouseOut;"
			style="display:none;" tabindex="-1">
		</div>
	</div>
</div>

__CPAN_FILE__ src/widget/templates/decrementMonth.gif
GIF89a	Äÿÿÿ000ÖÖÖWWWõõõóóóøøøÎÎÎØØØaaaéééyyyýýýððð222žžž¶¶¶:::………FFFúúú!ù,	#  Äh6eŠRð¬ˆDŠ™ø2Bx�“nÀ(ŽH�!;
__CPAN_FILE__ src/widget/templates/HtmlSpinner.css
input.dojoSpinnerInput {
	/* font-size: 0.8em; */
	border: 0px;
}

.dojoSpinnerOptions {
	font-family: Verdana, Helvetica, Garamond, sans-serif;
	/* font-size: 0.7em; */
	background-color: white;
	border: 1px solid #afafaf;
	position: absolute;
	z-index: 1000; 
	overflow: auto;
	-moz-opacity: 0;
	cursor: default;
}

table.dojoSpinner {
	border: 1px solid #afafaf;
}

.dojoSpinnerItem {
	padding-left: 2px;
	padding-top: 2px;
	margin: 0px;
}

.dojoSpinnerItemEven {
	background-color: #f4f4f4;
}

.dojoSpinnerItemOdd {
	background-color: white;
}

.dojoSpinnerItemHighlight {
	background-color: #63709A;
	color: white;
}

__CPAN_FILE__ src/widget/templates/HtmlComboBox.css
input.dojoComboBoxInput {
	/* font-size: 0.8em; */
	border: 0px;
	
}

.dojoComboBoxOptions {
	font-family: Verdana, Helvetica, Garamond, sans-serif;
	/* font-size: 0.7em; */
	background-color: white;
	border: 1px solid #afafaf;
	position: absolute;
	z-index: 1000; 
	overflow: auto;
	-moz-opacity: 0;
	cursor: default;
}

table.dojoComboBox {
	border: 1px solid #afafaf;
}

.dojoComboBoxItem {
	padding-left: 2px;
	padding-top: 2px;
	margin: 0px;
}

.dojoComboBoxItemEven {
	background-color: #f4f4f4;
}

.dojoComboBoxItemOdd {
	background-color: white;
}

.dojoComboBoxItemHighlight {
	background-color: #63709A;
	color: white;
}

__CPAN_FILE__ src/widget/templates/check_off.gif
GIF89aÕøøø¯Èîþþþööö®Èîôôô÷÷÷ûûûŸ¸Ýððð«Æí­ÇîŸ¹Þ€žÈ¯ÉîªÁâœÇªÅí¬Çí€œÈ¡»á�žÊ ¹ß¬Æí°Çé³Êíóóó­Äæ´Ìï¡ºà�žÉ©¿à±Éë«Âã©Àá£½ã€�È¨Ãê®Æè~›Å~šÆ¬Ãå¦Àç›Æ£½ä~›Æ§Áè©Äì¥¿æ�žÈñññòòòüüüúúúïïïùùùýýýõõõy–Áÿÿÿ!ù,’@�pH,
‡Ih.$E¤¢ì®Øì•ãÑ´`A&ægq4PC·0ïèfÝÖÂiµÀDÒI´hy:
Xp‚z99)‡‰;q��!:‹5„9332›/4–£¥2	+:%ƒ¢®		66"-:.7¶¯ºÄ':*0,#Ñ(F×CA;
__CPAN_FILE__ src/widget/templates/HtmlSlideShow.html
<div style="position: relative; padding: 3px;">
		<div dojoAttachPoint="controlsContainer">
			<input type="button" value="pause" 
				dojoAttachPoint="startStopButton"
				dojoAttachEvent="onClick: togglePaused;">
		</div>
		<div style="position: relative; width: 800px; height: 600px;"
			dojoAttachPoint="imagesContainer"
			dojoAttachEvent="onClick: togglePaused;">
			<img dojoAttachPoint="img1" class="slideShowImg" 
				style="z-index: 1;"  />
			<img dojoAttachPoint="img2" class="slideShowImg" 
				style="z-index: 0;" />
		</div>	
</div>
__CPAN_FILE__ src/widget/templates/HtmlTimePicker.css
.timePickerContainer {
	margin:1.75em 0 0.5em 0;
	width:10em;
	float:left;
}

.timeContainer {
	border-collapse:collapse;
	border-spacing:0;
}

.timeContainer thead td{
	border-bottom:1px solid #e6e6e6;
	padding:0 0.4em 0.2em 0.4em;
}

.timeContainer td {
	font-size:0.9em;
	padding:0 0.25em 0 0.25em;
	text-align:left;
	cursor:pointer;cursor:hand;
}

.timeContainer td.minutesHeading {
	border-left:1px solid #e6e6e6;
	border-right:1px solid #e6e6e6;	
}

.timeContainer .minutes {
	border-left:1px solid #e6e6e6;
	border-right:1px solid #e6e6e6;
}

.selectedItem {
	background-color:#3a3a3a;
	color:#ffffff;
}

__CPAN_FILE__ src/widget/templates/HtmlSpinner.html
<span style="display:none;">
	<span style="position:relative;" dojoAttachPoint="relNode">
		<span style="position:absolute; left:0; top:0;" dojoAttachPoint="absNode">
			<span style="position:relative;" dojoAttachPoint="innerRelNode">
				<img border="0"
					hspace="0"
					vspace="0"
					style="position:absolute; left:0;top:0; border-right:1px solid black;border-bottom:1px solid black;"
					dojoAttachPoint="upArrowNode"
					src="${dojoRoot}src/widget/templates/images/spinnerIncrement.gif">
				<img border="0"
					hspace="0"
					vspace="0"
					style="vertical-align:bottom;border-right:1px solid black;border-bottom:1px solid black;"
					dojoAttachPoint="downArrowNode"
					src="${dojoRoot}src/widget/templates/images/spinnerDecrement.gif">
			</span>
		</span>
		<span style="position:relative;" dojoAttachPoint="spacerRelNode">
			<img border="0"
				hspace="0"
				vspace="0"
				style="visibility:hidden;"
				dojoAttachPoint="spacerNode"
				src="${dojoRoot}src/widget/templates/images/spinnerIncrement.gif">
		</span>
	</span>
</span>

__CPAN_FILE__ src/widget/templates/HtmlDialog.html
<div id="${this.widgetId}" class="dojoDialog" dojoAttachPoint="wrapper">

	<span dojoAttachPoint="tabStart" 
		dojoOnFocus="trapTabs" 
		dojoOnBlur="clearTrap" tabindex="0"></span>

	<div dojoAttachPoint="containerNode" style=" position: relative; z-index: 2;"></div>

	<span dojoAttachPoint="tabEnd" 
		dojoOnFocus="trapTabs" 
		dojoOnBlur="clearTrap" tabindex="0"></span>

</div>

__CPAN_FILE__ src/widget/templates/HtmlMonthlyCalendar.css
.datePickerContainer {
	margin:0.5em 2em 0.5em 0;
	/*width:10em;*/
	float:left;
}

.previousMonth {
	background-color:#bbbbbb;
}

.currentMonth {
	background-color:#8f8f8f;
}

.nextMonth {
	background-color:#eeeeee;
}

.currentDate {
	text-decoration:underline;
	font-style:italic;
}

.selectedItem {
	background-color:#3a3a3a;
	color:#ffffff;
}

.calendarContainer {
	border-collapse:collapse;
	border-spacing:0;
	border-bottom:1px solid #e6e6e6;
	overflow: hidden;
	text-align: right;
}

.calendarContainer thead{
	border-bottom:1px solid #e6e6e6;
}

.calendarContainer tbody * td {
        height: 100px;
        border: 1px solid gray;
}

.calendarContainer td {
        width: 100px;
        padding: 2px;
	vertical-align: top;
}

.monthLabel {
	font-size:0.9em;
	font-weight:400;
	margin:0;
	text-align:center;
}

.monthLabel .month {
	padding:0 0.4em 0 0.4em;
}

.yearLabel {
	font-size:0.9em;
	font-weight:400;
	margin:0.25em 0 0 0;
	text-align:right;
	color:#a3a3a3;
}

.yearLabel .selectedYear {
	color:#000;
	padding:0 0.2em;
}

.nextYear, .previousYear {
	cursor:pointer;cursor:hand;
}

.incrementControl {
	cursor:pointer;cursor:hand;
	width:1em;
}

.dojoMonthlyCalendarEvent {
	font-size:0.7em;
	overflow: hidden;
	font-color: grey;
	white-space: nowrap;
	text-align: left;
}

__CPAN_FILE__ src/widget/templates/HtmlTooltipTemplate.css
.dojoTooltip {
	border: solid black 1px;
	background: beige;
	color: black;
	position: absolute;
	font-size: small;
	padding: 2px 2px 2px 2px;
	z-index: 10;
}

__CPAN_FILE__ src/widget/templates/richtextframe.html
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html>
  <head>
    <title></title>
    <script type="text/javascript">
    function init(){
       document.designMode = 'On';
       parentPageDomain = document.location.href.split('#')[1];
       if (parentPageDomain) {
          document.domain = parentPageDomain;
       }
    }
    window.onload = init;
    </script>
  </head>
  <body>
  <br />
  </body>
</html>

__CPAN_FILE__ src/widget/templates/HtmlResizeHandle.css
.dojoHtmlResizeHandle {
	float: right;
	position: absolute;
	right: 2px;
	bottom: 2px;
	width: 13px;
	height: 13px;
	z-index: 20;
	cursor: nw-resize;
	background-image: url(grabCorner.gif);
	line-height: 0px;
}
__CPAN_FILE__ src/widget/templates/HtmlContextMenuTemplate.html
<ul class="dojoContextMenu" 
	dojoAttachPoint="containerNode">
</ul>

__CPAN_FILE__ src/widget/templates/HtmlInlineEditBox.css
.editLabel {
	font-size : small;
	padding : 0 5px;
	display : none;
}

.editableRegion {
	background-color : #ffc !important;
	cursor : pointer;
	_cursor : hand;
}

.editableRegion .editLabel {
	display : inline;
}

.editableTextareaRegion .editLabel {
	display : block;
}

.inlineEditBox {
	/*background-color : #ffc;*/
	display : inline;
}

__CPAN_FILE__ src/widget/templates/HtmlShow.css
@media screen {
	html, body {
		margin: 0px;
		padding: 0px;
		width: 100%;
	}
	body {
		display: none;
	}
	h1 {
		font-size: 50px;
	}
	p, li {
		font-size: 30px;
	}
	.dojoShowNav {
		background: #369;
		overflow: hidden;
		position: absolute;
		height: 5px;
		bottom: 0px;
		left: 0px;
		width: 100%;
		text-align: center;
	}
	.dojoShowNav input {
		margin: 0px;
	}
	.dojoShowHider {
		height: 5px;
		overflow: hidden;
		width: 100%;
	}
	.dojoShowPrint {
		position: absolute;
		left: 5px;
		top: 0px;
	}
}
@media print {
	.dojoShow {
		display: none !important;
	}
	.dojoShowPrint {
		display: block !important;
	}
	.dojoShowPrintSlide {
		border: 1px solid #aaa;
		padding: 10px;
		margin-bottom: 15px;
	}
	.dojoShowPrintSlide, ul {
	page-break-inside: avoid;
	}
	h1 {
		margin-top: 0;
		page-break-after: avoid;
	}
}
__CPAN_FILE__ src/widget/templates/incrementWeek.gif
GIF89aÄÿÿÿ000øøøúúúžžž¶¶¶cccÂÂÂÖÖÖyyyßßß………CCCâââÌÌÌFFFjjjmmmØØØ!ù, ÒäP�QâŒ@¸!�·N’… ;
__CPAN_FILE__ src/widget/templates/HtmlEditorToolbarOneline.html
<div class="EditorToolbarDomNode EditorToolbarSmallBg" 
	unselectable="on" dojoOnMouseDown="preventSelect">
	<table cellpadding="1" cellspacing="0" border="0">
		<!--
			toobar options, in order:

				* wikiword
				* paste
				* copy
				* undo
				* redo
				* link
				* insert image
				* insert <hr>
				* font-select
				* bold
				* italic
				* underline
				* strikethrough
				* numlist
				* dotlist
				* indent
				* outdent
				* text color
				* bg color

		-->
		<tbody>
			<tr valign="top" align="left" dojoAttachPoint="oneLineTr">
				<td>
					<!-- htmltoggle -->
					<span class="iconContainer" dojoAttachPoint="htmltoggleButton"
						dojoOnClick="htmltoggleClick; buttonClick;" style="display: none;">
						<span title="Toggle Rich Text and HTML Markup Editing Modes" class="icon" 
						style="background-image: none; width: 30px;" 
						unselectable="on">&lt;h&gt;</span>
					</span>
				</td>
				<td>
					<!-- wikiword -->
					<span class="iconContainer" dojoAttachPoint="wikiwordButton"
						dojoOnClick="wikiwordClick; buttonClick;" style="display: none;">
						<span title="Toggle Wiki Word" class="icon wikiword" 
						unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- paste -->
					<span class="iconContainer" dojoAttachPoint="copyButton"
						unselectable="on" dojoOnClick="copyClick; buttonClick;">
						<span title="Copy (Ctrl-C)" class="icon copy" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- copy -->
					<span class="iconContainer" dojoAttachPoint="pasteButton"
						dojoOnClick="pasteClick; buttonClick;" unselectable="on">
						<span title="Paste (Ctrl-V)" class="icon paste" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- undo -->
					<span class="iconContainer" dojoAttachPoint="undoButton"
						dojoOnClick="undoClick; buttonClick;" unselectable="on">
						<!-- FIXME: should we have the text "undo" here? -->
						<span title="Undo (Ctrl-Z)" class="icon undo" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- redo -->
					<span class="iconContainer" dojoAttachPoint="redoButton"
						dojoOnClick="redoClick; buttonClick;" unselectable="on">
						<span title="Redo (Ctrl-R)" class="icon redo" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td isSpacer="true">
					<!-- spacer -->
					<span class="iconContainer">
						<span class="icon sep" unselectable="on" 
							style="width: 5px; min-width: 5px;"></span>
					</span>
				</td>
				<td>
					<!-- link -->
					<span class="iconContainer" dojoAttachPoint="linkButton"
						unselectable="on" dojoOnClick="linkClick; buttonClick;">
						<span title="Create Link" class="icon createlink" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- insertimage -->
					<span class="iconContainer" 
						style="display: none;"
						dojoAttachPoint="insertimageButton"
						unselectable="on" dojoOnClick="insertimageClick; buttonClick;">
						<span title="Insert Image" class="icon insertimage" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- inserthorizontalrule -->
					<span class="iconContainer" dojoAttachPoint="inserthorizontalruleButton"
						unselectable="on" dojoOnClick="inserthorizontalruleClick; buttonClick;">
						<span title="Insert Horizontal Rule" class="icon inserthorizontalrule " unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- bold -->
					<span class="iconContainer" dojoAttachPoint="boldButton"
						unselectable="on" dojoOnClick="boldClick; buttonClick;">
						<span title="Toggle Bold (Ctrl-B)" class="icon bold" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- italic -->
					<span class="iconContainer" dojoAttachPoint="italicButton"
						dojoOnClick="italicClick; buttonClick;">
						<span title="Toggle Italic (Ctrl-I)" class="icon italic" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- underline -->
					<span class="iconContainer" dojoAttachPoint="underlineButton"
						dojoOnClick="underlineClick; buttonClick;">
						<span title="Toggle Underline (Ctrl-U)" class="icon underline" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- strikethrough -->
					<span class="iconContainer" dojoAttachPoint="strikethroughButton"
						dojoOnClick="strikethroughClick; buttonClick;">
						<span title="Toggle Strike-Through" 
							class="icon strikethrough" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td isSpacer="true">
					<!-- spacer -->
					<span class="iconContainer">
						<span class="icon sep" unselectable="on" 
							style="width: 5px; min-width: 5px;"></span>
					</span>
				</td>
				<td>
					<!-- insertunorderedlist -->
					<span class="iconContainer" dojoAttachPoint="insertunorderedlistButton"
						unselectable="on" 
						dojoOnClick="insertunorderedlistClick; buttonClick;">
						<span title="Insert Bullet List" 
							class="icon insertunorderedlist" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- insertorderedlist -->
					<span class="iconContainer" dojoAttachPoint="insertorderedlistButton"
						unselectable="on" dojoOnClick="insertorderedlistClick; buttonClick;">
						<span title="Insert Numbered List" 
							class="icon insertorderedlist" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td isSpacer="true">
					<!-- spacer -->
					<span class="iconContainer">
						<span class="icon sep" unselectable="on" 
							style="width: 5px; min-width: 5px;"></span>
					</span>
				</td>
				<td>
					<!-- indent -->
					<span class="iconContainer" dojoAttachPoint="indentButton"
						unselectable="on" dojoOnClick="indentClick; buttonClick;">
						<span title="Indent Selection" class="icon indent" 
							unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- outdent -->
					<span class="iconContainer" dojoAttachPoint="outdentButton"
						unselectable="on" dojoOnClick="outdentClick; buttonClick;">
						<span title="Outdent Selection" class="icon outdent" 
							unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td isSpacer="true">
					<!-- spacer -->
					<span class="iconContainer">
						<span class="icon sep" unselectable="on" 
							style="width: 5px; min-width: 5px;"></span>
					</span>
				</td>
				<td>
					<!-- forecolor -->
					<span class="iconContainer" dojoAttachPoint="forecolorButton"
						unselectable="on" dojoOnClick="forecolorClick; buttonClick;">
						<span title="Change Text Color" class="icon forecolor" 
							unselectable="on">&nbsp;</span>
					</span>
					<div class="ColorDropdownContainer" 
						style="display: none; margin-top: 22px;"
						dojoAttachPoint="forecolorDropDown">
					</div>
				</td>
				<td>
					<!-- hilitecolor -->
					<span class="iconContainer" dojoAttachPoint="hilitecolorButton"
						unselectable="on" dojoOnClick="hilitecolorClick; buttonClick;">
						<span title="Change Background Color" class="icon hilitecolor" 
							unselectable="on">&nbsp;</span>
					</span>
					<div class="ColorDropdownContainer" 
						style="display: none; margin-top: 22px;"
						dojoAttachPoint="hilitecolorDropDown">
					</div>
				</td>
				<td isSpacer="true">
					<!-- spacer -->
					<span class="iconContainer">
						<span class="icon sep" unselectable="on" 
							style="width: 5px; min-width: 5px;"></span>
					</span>
				</td>
				<td>
					<!-- justify left -->
					<span class="iconContainer" dojoAttachPoint="justifyleftButton"
						dojoOnClick="justifyleftClick; buttonClick;">
						<span title="Justify Left" class="icon justifyleft" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- justify center -->
					<span class="iconContainer" dojoAttachPoint="justifycenterButton"
						dojoOnClick="justifycenterClick; buttonClick;">
						<span title="Center" class="icon justifycenter" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- justify right -->
					<span class="iconContainer" dojoAttachPoint="justifyrightButton"
						dojoOnClick="justifyrightClick; buttonClick;">
						<span title="Justify Right" class="icon justifyright" unselectable="on">&nbsp;</span>
					</span>
				</td>
				<td>
					<!-- justify full -->
					<span class="iconContainer" dojoAttachPoint="justifyfullButton"
						dojoOnClick="justifyfullClick; buttonClick;">
						<span title="Justify Both" class="icon justifyfull" unselectable="on">&nbsp;</span>
					</span>
				</td>	
				<td>
					<!-- font select -->
					<select dojoOnChange="formatSelectClick; buttonClick;"
						dojoAttachPoint="formatSelectBox" unselectable="on">
						<!-- FIXME: using "p" here inserts a paragraph in most cases! -->
						<option value="">-- format --</option>
						<option value="p">Normal</option>
						<option value="pre">Fixed Font</option>
						<option value="h1">Main Heading</option>
						<option value="h2">Section Heading</option>
						<option value="h3">Sub-Heading</option>
						<!-- <option value="blockquote">Block Quote</option> -->
					</select>
				</td>
				<td width="*">&nbsp;</td>
			</tr>
		</tbody>
	</table>
</div>

__CPAN_FILE__ src/widget/templates/HtmlResizableTextarea.html
<div>
	<div style="border: 2px solid black; width: 90%; height: 200px;"
		dojoAttachPoint="rootLayoutNode">
		<div dojoAttachPoint="textAreaContainerNode" 
			style="border: 0px; margin: 0px; overflow: hidden;">
		</div>
		<div dojoAttachPoint="statusBarContainerNode" class="statusBar">
			<div dojoAttachPoint="statusLabelNode" 
				class="statusPanel"
				style="padding-right: 0px; z-index: 1;">drag to resize</div>
			<div dojoAttachPoint="resizeHandleNode"></div>
		</div>
	</div>
</div>

__CPAN_FILE__ src/widget/templates/HtmlMenu2.css

.dojoPopupMenu2 {
	position: absolute;
	border: 1px solid;
	border-color: ThreeDLightShadow ThreeDDarkShadow ThreeDDarkShadow ThreeDLightShadow;
}

.dojoPopupMenu2Client {
	border: 1px solid;
	border-color: ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight;
	background-color: ThreeDFace;
	padding: 1px;
}

.dojoMenuItem2 {
	position: relative;
	white-space: nowrap;
	font: menu;
	color: WindowText;
	margin: 0;
}

.dojoMenuItem2 span {
	margin: 0;
}

.dojoMenuItem2Hover {
	background-color: Highlight;
	color: HighlightText;
}

.dojoMenuItem2Icon {
	position: absolute;
	background-position: center center;
	background-repeat: no-repeat;
	z-index: 1;
}

.dojoMenuItem2Label {
	position: absolute;
	vertical-align: middle;
	z-index: 1;
}

.dojoMenuItem2Label span {
	position: relative;
	vertical-align: middle;
	z-index: 2;
}

.dojoMenuItem2Label span span {
	position: absolute;
	color: ThreeDHighlight;
	display: none;
	left: 1px;
	top: 1px;
	z-index: -2;
}

.dojoMenuItem2Accel {
	position: absolute;
	vertical-align: middle;
	z-index: 1;
}

.dojoMenuItem2Accel span {
	position: relative;
	vertical-align: middle;
	z-index: 2;
}

.dojoMenuItem2Accel span span {
	position: absolute;
	color: ThreeDHighlight;
	display: none;
	left: 1px;
	top: 1px;
	z-index: -2;
}

.dojoMenuItem2Disabled .dojoMenuItem2Label span,
.dojoMenuItem2Disabled .dojoMenuItem2Accel span {
	color: ThreeDShadow;
}

.dojoMenuItem2Disabled .dojoMenuItem2Label span span,
.dojoMenuItem2Disabled .dojoMenuItem2Accel span span {
	color: ThreeDHighlight;
	display: block;
}

.dojoMenuItem2Hover .dojoMenuItem2Label span span,
.dojoMenuItem2Hover .dojoMenuItem2Accel span span {
	display: none;
}

.dojoMenuItem2Submenu {
	position: absolute;
	background-position: center center;
	background-repeat: no-repeat;
}

.dojoMenuItem2Target {
	position: absolute;
	z-index: 10;
	font-size: 1px;
	background-image: url('images/transparent.gif');
}

.dojoMenuSeparator2 {
	font-size: 1px;
	margin: 0;
}

.dojoMenuSeparator2Top {
	height: 50%;
	border-bottom: 1px solid ThreeDShadow;
	margin: 0px 2px;
	font-size: 1px;
}

.dojoMenuSeparator2Bottom {
	height: 50%;
	border-top: 1px solid ThreeDHighlight;
	margin: 0px 2px;
	font-size: 1px;
}



.dojoMenuBar2 {
	/*position: relative;*/
	background-color: ThreeDFace;
	border-bottom: 1px solid ThreeDHighlight;
}

.dojoMenuBar2Client {
	padding: 1px;
	border-top: 1px solid ThreeDHighlight;
	border-bottom: 1px solid ThreeDShadow;
}

.dojoMenuBarItem2 {
	position: absolute;
	white-space: nowrap;
	font: menu;
	color: WindowText;
	margin: 0;
}

.dojoMenuBarItem2 span {
	margin: 0;
}

.dojoMenuBarItem2Target {
	position: absolute;
	z-index: 10;
	font-size: 1px;
	background-image: url('images/transparent.gif');
}

.dojoMenuBarItem2Label {
	position: absolute;
	vertical-align: middle;
	z-index: 1;
	padding: 3px 8px;
}

.dojoMenuBarItem2Label span {
	position: relative;
	z-index: 2;
}

.dojoMenuBarItem2Label span span {
	position: absolute;
	color: ThreeDHighlight;
	display: none;
	left: 1px;
	top: 1px;
	z-index: -2;
}

.dojoMenuBarItem2Hover {
	background-color: Highlight;
	color: HighlightText;
}

.dojoMenuBarItem2Disabled .dojoMenuBarItem2Label span,
.dojoMenuBarItem2Disabled .dojoMenuBarItem2Accel span {
	color: ThreeDShadow;
}

.dojoMenuBarItem2Disabled .dojoMenuBarItem2Label span span,
.dojoMenuBarItem2Disabled .dojoMenuBarItem2Accel span span {
	color: ThreeDHighlight;
	display: block;
}

.dojoMenuBarItem2Hover .dojoMenuBarItem2Label span span,
.dojoMenuBarItem2Hover .dojoMenuBarItem2Accel span span {
	display: none;
}

__CPAN_FILE__ src/widget/templates/HtmlSlider.css
.sliderMain { 
  position: relative; 
  /*top: 80px; left: 0px;*/
  padding: 0px; 
  border: 1px solid black;
  width: 300px; height: 300px; 
}

.sliderHandle { 
  color: #FF0000;
  position: relative; 
  background-image: url(images/slider-button.png);
  width: 25px; 
  height: 25px;
}

.sliderMainHorizontal { 
  position: relative; 
  /*top: 80px; left: 0px;*/
  padding: 0px; 
  width: 300px; height: 35px; 
  background: url(images/slider-bg.gif) no-repeat 0px 4px;
}

.sliderHandleHorizontal { 
  color: #FF0000;
  position: relative; 
  background-image: url(images/slider-button-horz.png);
  width: 25px; 
  height: 35px;
}

.sliderMainVertical { 
  position: relative; 
  /*top: 80px; left: 0px;*/
  padding: 0px; 
  width: 35px; height: 300px; 
  background: url(images/slider-bg-vert.gif) no-repeat 4px 0px;
}

.sliderHandleVertical { 
  color: #FF0000;
  position: relative; 
  background-image: url(images/slider-button-vert.png);
  width: 35px; 
  height: 25px;
}
__CPAN_FILE__ src/widget/templates/check_hover_off.gif
GIF89aÄ�žÉ®Èï��É¬Çï€�È­ÈïœÇ�žÊ«Çï­ÇïªÅî€œÈ«ÆïœÈªÆïÆÜþÍáÿ½ÖüºÔü¶Òû¬Ëú±ÎúÃÛý§ÈùÉÞþËàÿÀÙýªÅíy–Á!ù,d 'Žd)nhªª·Ap,Ãàfx®ãµ‹ýÀà¯·y�HcÁ¶±8ŸPgAàÒX¯Xk‚º‰x¿`ï€+)›ÏåÁ5i»ßmÄzS©ÛïuÆÂEéûÿ}
.…†‡…
.+�(‹&‘"!;
__CPAN_FILE__ src/widget/templates/HtmlEditorToolbar.html
<div dojoAttachPoint="domNode" class="EditorToolbarDomNode" unselectable="on">
	<table cellpadding="3" cellspacing="0" border="0">
		<!--
			our toolbar should look something like:

			+=======+=======+=======+=============================================+
			| w   w | style | copy  | bo | it | un | le | ce | ri |
			| w w w | style |=======|==============|==============|
			|  w w  | style | paste |  undo | redo | change style |
			+=======+=======+=======+=============================================+
		-->
		<tbody>
			<tr valign="top">
				<td rowspan="2">
					<div class="bigIcon" dojoAttachPoint="wikiWordButton"
						dojoOnClick="wikiWordClick; buttonClick;">
						<span style="font-size: 30px; margin-left: 5px;">
							W
						</span>
					</div>
				</td>
				<td rowspan="2">
					<div class="bigIcon" dojoAttachPoint="styleDropdownButton"
						dojoOnClick="styleDropdownClick; buttonClick;">
						<span unselectable="on"
							style="font-size: 30px; margin-left: 5px;">
							S
						</span>
					</div>
					<div class="StyleDropdownContainer" style="display: none;"
						dojoAttachPoint="styleDropdownContainer">
						<table cellpadding="0" cellspacing="0" border="0"
							height="100%" width="100%">
							<tr valign="top">
								<td rowspan="2">
									<div style="height: 245px; overflow: auto;">
										<div class="headingContainer"
											unselectable="on"
											dojoOnClick="normalTextClick">normal</div>
										<h1 class="headingContainer"
											unselectable="on"
											dojoOnClick="h1TextClick">Heading 1</h1>
										<h2 class="headingContainer"
											unselectable="on"
											dojoOnClick="h2TextClick">Heading 2</h2>
										<h3 class="headingContainer"
											unselectable="on"
											dojoOnClick="h3TextClick">Heading 3</h3>
										<h4 class="headingContainer"
											unselectable="on"
											dojoOnClick="h4TextClick">Heading 4</h4>
										<div class="headingContainer"
											unselectable="on"
											dojoOnClick="blahTextClick">blah</div>
										<div class="headingContainer"
											unselectable="on"
											dojoOnClick="blahTextClick">blah</div>
										<div class="headingContainer"
											unselectable="on"
											dojoOnClick="blahTextClick">blah</div>
										<div class="headingContainer">blah</div>
										<div class="headingContainer">blah</div>
										<div class="headingContainer">blah</div>
										<div class="headingContainer">blah</div>
									</div>
								</td>
								<!--
								<td>
									<span class="iconContainer" dojoOnClick="buttonClick;">
										<span class="icon justifyleft" 
											style="float: left;">&nbsp;</span>
									</span>
									<span class="iconContainer" dojoOnClick="buttonClick;">
										<span class="icon justifycenter" 
											style="float: left;">&nbsp;</span>
									</span>
									<span class="iconContainer" dojoOnClick="buttonClick;">
										<span class="icon justifyright" 
											style="float: left;">&nbsp;</span>
									</span>
									<span class="iconContainer" dojoOnClick="buttonClick;">
										<span class="icon justifyfull" 
											style="float: left;">&nbsp;</span>
									</span>
								</td>
								-->
							</tr>
							<tr valign="top">
								<td>
									thud
								</td>
							</tr>
						</table>
					</div>
				</td>
				<td>
					<!-- copy -->
					<span class="iconContainer" dojoAttachPoint="copyButton"
						unselectable="on"
						dojoOnClick="copyClick; buttonClick;">
						<span class="icon copy" 
							unselectable="on"
							style="float: left;">&nbsp;</span> copy
					</span>
					<!-- "droppable" options -->
					<span class="iconContainer" dojoAttachPoint="boldButton"
						unselectable="on"
						dojoOnClick="boldClick; buttonClick;">
						<span class="icon bold" unselectable="on">&nbsp;</span>
					</span>
					<span class="iconContainer" dojoAttachPoint="italicButton"
						dojoOnClick="italicClick; buttonClick;">
						<span class="icon italic" unselectable="on">&nbsp;</span>
					</span>
					<span class="iconContainer" dojoAttachPoint="underlineButton"
						dojoOnClick="underlineClick; buttonClick;">
						<span class="icon underline" unselectable="on">&nbsp;</span>
					</span>
					<span class="iconContainer" dojoAttachPoint="leftButton"
						dojoOnClick="leftClick; buttonClick;">
						<span class="icon justifyleft" unselectable="on">&nbsp;</span>
					</span>
					<span class="iconContainer" dojoAttachPoint="fullButton"
						dojoOnClick="fullClick; buttonClick;">
						<span class="icon justifyfull" unselectable="on">&nbsp;</span>
					</span>
					<span class="iconContainer" dojoAttachPoint="rightButton"
						dojoOnClick="rightClick; buttonClick;">
						<span class="icon justifyright" unselectable="on">&nbsp;</span>
					</span>
				</td>
			</tr>
			<tr>
				<td>
					<!-- paste -->
					<span class="iconContainer" dojoAttachPoint="pasteButton"
						dojoOnClick="pasteClick; buttonClick;" unselectable="on">
						<span class="icon paste" style="float: left;" unselectable="on">&nbsp;</span> paste
					</span>
					<!-- "droppable" options -->
					<span class="iconContainer" dojoAttachPoint="undoButton"
						dojoOnClick="undoClick; buttonClick;" unselectable="on">
						<span class="icon undo" style="float: left;" unselectable="on">&nbsp;</span> undo
					</span>
					<span class="iconContainer" dojoAttachPoint="redoButton"
						dojoOnClick="redoClick; buttonClick;" unselectable="on">
						<span class="icon redo" style="float: left;" unselectable="on">&nbsp;</span> redo
					</span>
				</td>	
			</tr>
		</tbody>
	</table>

__CPAN_FILE__ src/widget/templates/HtmlInlineEditBox.html
<form class="inlineEditBox" style="display: none" dojoAttachPoint="form" dojoAttachEvent="onSubmit:saveEdit; onReset:cancelEdit; onKeyUp: checkForValueChange;">
	<input type="text" dojoAttachPoint="text" style="display: none;" />
	<textarea dojoAttachPoint="textarea" style="display: none;"></textarea>
	<input type="submit" value="Save" dojoAttachPoint="submitButton" />
	<input type="reset" value="Cancel" dojoAttachPoint="cancelButton" />
</form>

__CPAN_FILE__ src/widget/templates/HtmlDatePicker.css
.calendarContainer {
/*	border:1px solid #566f8f;*/
}

.calendarBodyContainer {
	width:160px;
	background: #7591bc url("images/dpBg.gif") top left repeat-x;
}

.calendarBodyContainer thead tr td {
	color:#293a4b;
	font:bold 0.75em Helvetica, Arial, Verdana, sans-serif;
	text-align:center;
	padding:0.25em;
	background: url("images/dpHorizLine.gif") bottom left repeat-x;
}

.calendarBodyContainer tbody tr td {
	color:#fff;
	font:bold 0.7em Helvetica, Arial, Verdana, sans-serif;
	text-align:center;
	padding:0.4em;
	background: url("images/dpVertLine.gif") top right repeat-y;
	cursor:pointer;
	cursor:hand;
}


.monthWrapper {
	padding-bottom:2px;
	background: url("images/dpHorizLine.gif") bottom left repeat-x;
}

.monthContainer {
	width:100%;
}

.monthLabelContainer {
	text-align:center;
	font:bold 0.75em Helvetica, Arial, Verdana, sans-serif;
	background: url("images/dpMonthBg.png") repeat-x top left !important;
	color:#293a4b;
	padding:0.25em;
}

.monthCurve {
	width:12px;
}

.monthCurveTL {
	background: url("images/dpCurveTL.png") no-repeat top left !important;
}

.monthCurveTR {
		background: url("images/dpCurveTR.png") no-repeat top left !important;
}


.yearWrapper {
	background: url("images/dpHorizLineFoot.gif") top left repeat-x;
	padding-top:2px;
}

.yearContainer {
	width:100%;
}

.yearContainer td {
	background:url("images/dpYearBg.png") top left repeat-x;
}

.yearContainer .yearLabel {
	margin:0;
	padding:0.45em 0 0.45em 0;
	color:#fff;
	font:bold 0.75em Helvetica, Arial, Verdana, sans-serif;
	text-align:center;
}

.curveBL {
	background: url("images/dpCurveBL.png") bottom left no-repeat !important;
	width:9px !important;
	padding:0;
	margin:0;
}

.curveBR {
	background: url("images/dpCurveBR.png") bottom left no-repeat !important;
	width:9px !important;
	padding:0;
	margin:0;
}


.previousMonth {
	background-color:#6782a8 !important;
}

.currentMonth {
}

.nextMonth {
	background-color:#6782a8 !important;
}

.currentDate {
	text-decoration:underline;
	font-style:italic;
}

.selectedItem {
	background-color:#fff !important;
	color:#6782a8 !important;
}

.yearLabel .selectedYear {
	padding:0.2em;
	background-color:#9ec3fb !important;
}

.nextYear, .previousYear {
	cursor:pointer;cursor:hand;
	margin:0 0.55em;
}

.incrementControl {
	cursor:pointer;cursor:hand;
	width:1em;
}

.increase {
	float:right;
}

.decrease {
	float:left;
}

.lastColumn {
	background-image:none !important;
}



__CPAN_FILE__ src/widget/templates/TitlePane.html
<div dojoAttachPoint="domNode">
<div dojoAttachPoint="labelNode" dojoAttachEvent="onclick: onLabelClick"></div>
<div dojoAttachPoint="containerNode"></div>
</div>

__CPAN_FILE__ src/widget/templates/HtmlTaskBar.css
.dojoTaskBarItem {
	display: inline-block;
	background-color: ThreeDFace;
	border: outset 2px;
	margin-right: 5px;
	cursor: pointer;
	height: 35px;
	width: 100px;
	font-size: 10pt;
	white-space: nowrap;
	text-align: center;
	float: left;
	overflow: hidden;
}

.dojoTaskBarItem img {
	vertical-align: middle;
	margin-right: 5px;
	margin-left: 5px;	
	height: 32px;
	width: 32px;
}

.dojoTaskBarItem a {
	 color: black;
	text-decoration: none;
}



__CPAN_FILE__ src/widget/templates/HtmlDropDownButtonTemplate.html
<button dojoAttachPoint="button" class="dojoButton dojoButtonNoHover" dojoAttachEvent="onMouseOver: ; onMouseOut: ; onClick: ;">
  <table dojoAttachPoint="table" style="margin:0 0 0 0;"><tr>
    <td class="label" dojoAttachPoint="labelCell"></td>
    <td class="border" dojoAttachPoint="borderCell"></td>
    <td class="downArrow" dojoAttachPoint="arrowCell">
      <img dojoAttachPoint="arrow">
    </td>
  </tr></table>
</button>
__CPAN_FILE__ src/widget/templates/HtmlSliderVertical.html
<div class="sliderMainVertical">
    <div class="sliderHandleVertical" dojoAttachPoint="sliderHandle"></div>
</div>

__CPAN_FILE__ src/widget/templates/HtmlDatePicker.html
<div class="datePickerContainer" dojoAttachPoint="datePickerContainerNode">
	<table cellspacing="0" cellpadding="0" class="calendarContainer">
		<thead>
			<tr>
				<td class="monthWrapper" valign="top">
					<table class="monthContainer" cellspacing="0" cellpadding="0" border="0">
						<tr>
							<td class="monthCurve monthCurveTL" valign="top"></td>
							<td class="monthLabelContainer" valign="top">
								<span dojoAttachPoint="increaseWeekNode" 
									dojoAttachEvent="onClick: onIncrementWeek;" 
									class="incrementControl increase">
									<img src="${dojoRoot}src/widget/templates/images/incrementMonth.png" 
									alt="&darr;" style="width:7px;height:5px;" />
								</span>
								<span 
									dojoAttachPoint="increaseMonthNode" 
									dojoAttachEvent="onClick: onIncrementMonth;" class="incrementControl increase">
									<img src="${dojoRoot}src/widget/templates/images/incrementMonth.png" 
										alt="&darr;"  dojoAttachPoint="incrementMonthImageNode">
								</span>
								<span 
									dojoAttachPoint="decreaseWeekNode" 
									dojoAttachEvent="onClick: onIncrementWeek;" 
									class="incrementControl decrease">
									<img src="${dojoRoot}src/widget/templates/images/decrementMonth.png" alt="&uarr;" style="width:7px;height:5px;" />
								</span>
								<span 
									dojoAttachPoint="decreaseMonthNode" 
									dojoAttachEvent="onClick: onIncrementMonth;" class="incrementControl decrease">
									<img src="${dojoRoot}src/widget/templates/images/decrementMonth.png" 
										alt="&uarr;" dojoAttachPoint="decrementMonthImageNode">
								</span>
								<span dojoAttachPoint="monthLabelNode" class="month">July</span>
							</td>
							<td class="monthCurve monthCurveTR" valign="top"></td>
						</tr>
					</table>
				</td>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td colspan="3">
					<table class="calendarBodyContainer" cellspacing="0" cellpadding="0" border="0">
						<thead>
							<tr>
								<td>S</td>
								<td>M</td>
								<td>T</td>
								<td>W</td>
								<td>T</td>
								<td>F</td>
								<td>S</td>
							</tr>
						</thead>
						<tbody dojoAttachPoint="calendarDatesContainerNode" 
							dojoAttachEvent="onClick: onSetDate;">
							<tr dojoAttachPoint="calendarRow0">
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
							</tr>
							<tr dojoAttachPoint="calendarRow1">
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
							</tr>
							<tr dojoAttachPoint="calendarRow2">
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
							</tr>
							<tr dojoAttachPoint="calendarRow3">
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
							</tr>
							<tr dojoAttachPoint="calendarRow4">
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
							</tr>
							<tr dojoAttachPoint="calendarRow5">
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
								<td></td>
							</tr>
						</tbody>
					</table>
				</td>
			</tr>
		</tbody>
		<tfoot>
			<tr>
				<td colspan="3" class="yearWrapper">
					<table cellspacing="0" cellpadding="0" border="0" class="yearContainer">
						<tr>
							<td class="curveBL" valign="top"></td>
							<td valign="top">
								<h3 class="yearLabel">
									<span dojoAttachPoint="previousYearLabelNode"
										dojoAttachEvent="onClick: onIncrementYear;" class="previousYear"></span>
									<span class="selectedYear" dojoAttachPoint="currentYearLabelNode"></span>
									<span dojoAttachPoint="nextYearLabelNode" 
										dojoAttachEvent="onClick: onIncrementYear;" class="nextYear"></span>
								</h3>
							</td>
							<td class="curveBR" valign="top"></td>
						</tr>
					</table>
				</td>
			</tr>
		</tfoot>
	</table>
	
</div>

__CPAN_FILE__ src/widget/templates/HtmlTooltipTemplate.html
<div class='dojoTooltip' style="display:none" dojoAttachPoint="containerNode">
</div>
__CPAN_FILE__ src/widget/templates/HtmlTimePicker.html
<div class="timePickerContainer" dojoAttachPoint="timePickerContainerNode">
	<table class="timeContainer" cellspacing="0" >
		<thead>
			<tr>
				<td>Hour</td>
				<td class="minutesHeading">Minute</td>
				<td>&nbsp;</td>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td valign="top">
					<table>
						<tbody dojoAttachPoint="hourContainerNode"  
							dojoAttachEvent="onClick: onSetSelectedHour;">
							<tr>
								<td>12</td>
								<td>6</td>
							</tr>
							<tr>
								<td>1</td>
								<td>7</td>
							</tr>
							<tr>
								<td>2</td>
								<td>8</td>
							</tr>
							<tr>
								<td>3</td>
								<td>9</td>
							</tr>
							<tr>
								<td>4</td>
								<td>10</td>
							</tr>
							<tr>
								<td>5</td>
								<td>11</td>
							</tr>
						</tbody>
					</table>
				</td>
				<td valign="top" class="minutes">
					<table>
						<tbody dojoAttachPoint="minuteContainerNode" 
							dojoAttachEvent="onClick: onSetSelectedMinute;">
							<tr>
								<td>00</td>
								<td>30</td>
							</tr>
							<tr>
								<td>05</td>
								<td>35</td>
							</tr>
							<tr>
								<td>10</td>
								<td>40</td>
							</tr>
							<tr>
								<td>15</td>
								<td>45</td>
							</tr>
							<tr>
								<td>20</td>
								<td>50</td>
							</tr>
							<tr>
								<td>25</td>
								<td>55</td>
							</tr>
						</tbody>
					</table>
				</td>
				<td valign="top">
					<table>
						<tbody dojoAttachPoint="amPmContainerNode" 
							dojoAttachEvent="onClick: onSetSelectedAmPm;">
							<tr>
								<td>AM</td>
							</tr>
							<tr>
								<td>PM</td>
							</tr>
						</tbody>
					</table>
				</td>
			</tr>
			<tr>
				<td></td>
				<td>
					<div dojoAttachPoint="anyTimeContainerNode" 
						dojoAttachEvent="onClick: onSetSelectedAnyTime;" 
						class="anyTimeContainer">any</div>
				</td>
				<td></td>
			</tr>
		</tbody>
	</table>
</div>

__CPAN_FILE__ src/widget/templates/HtmlTabContainer.html
<div id="${this.widgetId}" class="dojoTabContainer" waiRole="tabpanel">
	<div dojoAttachPoint="dojoTabLabels"></div>
	<div class="dojoTabPaneWrapper" dojoAttachPoint="containerNode" ></div>
</div>

__CPAN_FILE__ src/widget/templates/HtmlSlideShow.css
.slideShowImg {
	position: absolute;
	left: 0px;
	top: 0px; 
	border: 2px solid #4d4d4d;
	padding: 0px;
	margin: 0px;
}


__CPAN_FILE__ src/widget/templates/HtmlDocPane.html
<div>
	<div dojoAttachPoint="containerNode"></div>
	<div dojoAttachPoint="select">
		<h1>Detail: <span dojoAttachPoint="fn">dojo.select</span></h1>
		<div dojoAttachPoint="description">Description</div>
		<div class="dojoDocParams" dojoAttachPoint="parameters">
			<h2>Parameters</h2>
			<div dojoAttachPoint="pRow"><span dojoAttachPoint="pOpt"><em>optional</em> </span><span><span dojoAttachPoint="pType">type</span> </span><a href="#" dojoAttachPoint="pLink">variable</a><span> - <span dojoAttachPoint="pDesc"></span></span></div>
		</div>
		<div class="dojoDocVars" dojoAttachPoint="variables">
			<h2>Variables</h2>
			<div dojoAttachPoint="vRow"><a href="#" dojoAttachPoint="vLink">variable</a><span> - <span dojoAttachPoint="vDesc"></span></span></div>
		</div>
		<div>
			<h2>Source Code</h2>
			<div class="dojoDocSrc"><span class="dojoDocReturn" dojoAttachPoint="sType">returnType</span> <span class="dojoDocFunction" dojoAttachPoint="sName">foo</span>(<span dojoAttachPoint="sParams"><span class="dojoDocParamType" dojoAttachPoint="sPType">type </span><span class="dojoDocParamName" dojoAttachPoint="sPName">paramName</span></span>){<span dojoAttachPoint="source">...</span>}</div>
		</div>
	</div>
	<div dojoAttachPoint="result">
		<h1>Search Results: <span dojoAttachPoint="count">0</span> matches</h1>
		<div dojoAttachPoint="row"><a href="#" dojoAttachPoint="fnLink">dojo.fnLink</a><span> - <span dojoAttachPoint="summary">summary</span></span></div>
	</div>
</div>

__CPAN_FILE__ src/widget/templates/DemoEngine.html
<div dojoAttachPoint="domNode">
	<div dojoAttachPoint="navigationNode">
		<table border="0" cellspacing="0" cellpadding="0">
			<tr>
				<td width="1%" valign="top" class="navigationCell"><h1>Categories</h1><div dojoAttachPoint="menuNavigationNode"></div></td>
				<td width="99%" valign="top">
					<div dojoAttachPoint="demoNavigationNode">
					</div>
				</td>
			</tr>
		</table>
	</div>

	<div dojoAttachPoint="demoContainerNode">

		<div dojoAttachPoint="demoPaneNode">
		</div>

		<div dojoAttachPoint="demoHeaderNode">
			<span dojoAttachPoint="collapsedMenuNode" dojoAttachEvent="onclick: expandDemoNavigation"></span>
			<div dojoAttachPoint="aboutNode">About this Demo</div>
		</div>
	</div>
</div>

__CPAN_FILE__ src/widget/templates/Tree.css
.dojoTree {
	font: caption;
	font-size: 11px;
	font-weight: normal;
	overflow: auto;
}

.dojoTreeNodeLabel {
	padding: 1px 2px;
	color: WindowText;
	cursor: default;
}

.dojoTreeNodeLabel:hover {
	text-decoration: underline;
}

.dojoTreeNodeLabelSelected {
	background-color: Highlight;
	color: HighlightText;
}

.dojoTree div {
	white-space: nowrap;
}

.dojoTree img {
	vertical-align: middle;
}

__CPAN_FILE__ src/widget/templates/HtmlMenuItemTemplate.html
<div dojoAttachPoint="labelNode" dojoAttachEvent="onClick">
</div>

__CPAN_FILE__ src/widget/templates/check_disabled_on.gif
GIF89aæÈÈÈÉÉÉ£££ÃÃÃÕÕÕÇÇÇ÷÷÷ÒÒÒ©©©ÓÓÓÚÚÚ³³³ìììôôô“““ÆÆÆÊÊÊ»»»×××ûûûÎÎÎ¸¸¸ÁÁÁÑÑÑ™™™­­­ÞÞÞøøø´´´ŽŽŽÐÐÐýýýœœœ¥¥¥½½½þþþ———ééé¦¦¦öööŸŸŸîîîØØØëëëæææçççÂÂÂ···¡¡¡ÛÛÛºººúúú¶¶¶ðððËËË¿¿¿ÀÀÀÙÙÙ±±±ÅÅÅ¾¾¾ÏÏÏÍÍÍÌÌÌÿÿÿ!ù,»€=‚ƒ„…=9‰Š‹915
=>9>”••	/??*––3@'>6Ÿ”
@@!?œ´œ+­%66?¦6
­ ?	)@
0(;,­@@#8;-Þ@?=;=8?Þ&8ú€£Ç�ƒ;Þ! Áãà
."ØàA‘¾*ò ¢�<Y@‡(SªTIC‡Ë—0cê;
__CPAN_FILE__ src/widget/templates/Wizard.css
.WizardContainer {
	background: #EEEEEE;
	border: #798EC5 1px solid;
	padding: 2px;
}

.WizardTitle {
	color: #003366;
	padding: 8px 5px 15px 2px;
	font-weight: bold;
	font-size: x-small;
	font-style: normal;
	font-family: Verdana, Arial, Helvetica;
	text-align: left;
}

.WizardText {
	color: #000033;
	font-weight: normal;
	font-size: xx-small;
	font-family: Verdana, Arial, Helvetica;
	padding: 2 50; text-align: justify;
}

.WizardLightText {
	color: #666666;
	font-weight: normal;
	font-size: xx-small;
	font-family: verdana, arial, helvetica;
	padding: 2px 50px;
	text-align: justify;
}

.WizardButtonHolder {
	text-align: right;
	padding: 10px 5px;
}

.WizardButton {
	color: #ffffff;
	background: #798EC5;
	font-size: xx-small;
	font-family: verdana, arial, helvetica, sans-serif;
	border-right: #000000 1px solid;
	border-bottom: #000000 1px solid;
	border-left: #666666 1px solid;
	border-top: #666666 1px solid;
	padding-right: 4px;
	padding-left: 4px;
	text-decoration: none; height: 18px;
}

.WizardButton:hover {
	cursor: pointer;
}

.WizardButtonDisabled {
	color: #eeeeee;
	background-color: #999999;
	font-size: xx-small;
	FONT-FAMILY: verdana, arial, helvetica, sans-serif;
	border-right: #000000 1px solid;
	border-bottom: #000000 1px solid;
	border-left: #798EC5 1px solid;
	border-top: #798EC5 1px solid;
	padding-right: 4px;
	padding-left: 4px;
	text-decoration: none;
	height: 18px;
}



__CPAN_FILE__ src/widget/templates/HtmlSliderHorizontal.html
<div class="sliderMainHorizontal">
    <div class="sliderHandleHorizontal" dojoAttachPoint="sliderHandle"></div>
</div>

__CPAN_FILE__ src/widget/templates/HtmlSplitContainer.css
.dojoSplitContainer{
	position: relative;
	overflow: hidden;
}

.dojoSplitPane{
	position: absolute;
}

.dojoSplitContainerSizerH,
.dojoSplitContainerSizerV {
	font-size: 1px;
	cursor: move;
	cursor: w-resize;
	background-color: ThreeDFace;
	border: 1px solid;
	border-color: ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight;
	margin: 0;
}

.dojoSplitContainerSizerV {
	cursor: n-resize;
}

.dojoSplitContainerVirtualSizerH,
.dojoSplitContainerVirtualSizerV {
	font-size: 1px;
	cursor: move;
	cursor: w-resize;
	background-color: ThreeDShadow;
	-moz-opacity: 0.5;
	opacity: 0.5;
	filter: Alpha(Opacity=50);
	margin: 0;
}

.dojoSplitContainerVirtualSizerV {
	cursor: n-resize;
}

__CPAN_FILE__ src/widget/templates/HtmlFloatingPane.html
<div id="${this.widgetId}" class="dojoFloatingPane">
	<div dojoAttachPoint="titleBar" class="dojoFloatingPaneTitleBar"  dojoAttachEvent="onMouseDown" style="display:none">
	  	<img dojoAttachPoint="titleBarIcon"  class="dojoFloatingPaneTitleBarIcon">
		<div dojoAttachPoint="closeAction" dojoAttachEvent="onClick:closeWindow"
   	  		class="dojoFloatingPaneCloseIcon"></div>
		<div dojoAttachPoint="restoreAction" dojoAttachEvent="onClick:restoreWindow"
   	  		class="dojoFloatingPaneRestoreIcon"></div>
		<div dojoAttachPoint="maximizeAction" dojoAttachEvent="onClick:maximizeWindow"
   	  		class="dojoFloatingPaneMaximizeIcon"></div>
		<div dojoAttachPoint="minimizeAction" dojoAttachEvent="onClick:minimizeWindow"
   	  		class="dojoFloatingPaneMinimizeIcon"></div>
	  	<div dojoAttachPoint="titleBarText" class="dojoFloatingPaneTitleText">${this.title}</div>
	</div>

	<div id="${this.widgetId}_container" dojoAttachPoint="containerNode" class="dojoFloatingPaneClient"></div>

	<div dojoAttachPoint="resizeBar" class="dojoFloatingPaneResizebar" style="display:none"></div>
</div>
__CPAN_FILE__ src/widget/templates/HtmlCheckBox.html
<span>
	<input type="checkbox" name="${this.name}" checked="${this.checked}" tabIndex="${this.tabIndex}" style="display: none"
		dojoAttachPoint="inputNode">
	<img src='${this.imgSrc}' class='dojoHtmlCheckbox'
		dojoAttachPoint="imgNode" dojoAttachEvent="onMouseUp;onMouseOver;onMouseOut">
</span>
__CPAN_FILE__ src/widget/templates/HtmlToolbar.css
.toolbarContainer {
	border-bottom : 0;
	background-color : #def;
	color : ButtonText;
	font : Menu;
	background-image: url(images/toolbar-bg.gif);
}

.toolbar {
	padding : 2px 4px;
	min-height : 26px;
	_height : 26px;
}

.toolbarItem {
	float : left;
	padding : 1px 2px;
	margin : 0 2px 1px 0;
	cursor : pointer;
}

.toolbarItem.selected, .toolbarItem.down {
	margin : 1px 1px 0 1px;
	padding : 0px 1px;
	border : 1px solid #bbf;
	background-color : #fafaff;
}

.toolbarButton img {
	vertical-align : bottom;
}

.toolbarButton span {
	line-height : 16px;
	vertical-align : middle;
}

.toolbarButton.hover {
	padding : 0px 1px;
	border : 1px solid #99c;
}

.toolbarItem.disabled {
	opacity : 0.3;
	filter : alpha(opacity=30);
	cursor : default;
}

.toolbarSeparator {
	cursor : default;
}

.toolbarFlexibleSpace {
}

__CPAN_FILE__ src/widget/templates/HtmlButtonTemplate.css
/* ---- button --- */
.dojoButton {
	padding: 0 0 0 0;
	font-size: 8pt;
	white-space: nowrap;
	cursor: pointer;
	font-family: Myriad, Tahoma, Verdana, sans-serif;
}

.dojoButton .dojoButtonContents {
	padding: 2px 2px 2px 2px;
	text-align: center;		/* if icon and label are split across two lines, center icon */
	color: white;
}

.dojoButtonLeftPart .dojoButtonContents {
	padding-right: 8px;
}

.dojoButtonDisabled {
	cursor: url("images/no.gif"), default;
}


.dojoButtonContents img {
	vertical-align: middle;	/* if icon and label are on same line, center them */
}

/* -------- colors ------------ */

.dojoButtonHover .dojoButtonContents {
}

.dojoButtonDepressed .dojoButtonContents {
	color: #293a4b;
}

.dojoButtonDisabled .dojoButtonContents {
	color: #eeeeee;
}


/* ---------- drop down button specific ---------- */

/* border between label and arrow (for drop down buttons */
.dojoButton .border {
	width: 1px;
	background: gray;
}

/* button arrow */
.dojoButton .downArrow {
	padding-left: 10px;
	text-align: center;
}

.dojoButton.disabled .downArrow {
	cursor : default;
}
__CPAN_FILE__ src/widget/templates/HtmlSlider.html
<div class="sliderMain">
    <div class="sliderHandle" dojoAttachPoint="sliderHandle"></div>
</div>

__CPAN_FILE__ src/widget/templates/check_on.gif
GIF89aæŠ®äœ¿ó��É�žÉ¥Áë�³èœÇ€�Èùúüðõý�•µßêú€œÈe…µÞèøžÁó“­Ó‡ªßóøÿÛãðu˜Ëâèð¹ÆÙµÅÛ�²æ¡¼å�˜¼‡œ»y•¿÷úÿ]y¢�¥Ãš½ðšºê“·ì´Íô}šÃüýÿôöùðó÷ÁÖô¤Àê—ºí‚—·ýþþo’Ç—ºîk…­¨Äí¦Âìåéñ­Çîƒ˜¸Ñá÷¡·×¥Çù�¨Ê¹Ò÷rŽ·¡Âôz“¹˜»ðŒ¢Ã§ÃíÙçûÂÏãx—Æåêñ¹Å×êòþóöú³Òþ€�Ç¯Îü§Ãì‡¨Ú‚¦Ü�žÊl‡¯h„°¯ÈîœÈƒ§Þ£ÆùŸÂö|¡Ø¦Èü¨Ëþv›ÓªÅíy–Áÿÿÿ!ù,¯€Z‚ƒ„…‚Yˆ‰ŠYP3MZYW“””G%8H‘V�ž�I[F
‘S¨©S7E[[&4¦YT´µT@®>+²;¾9®C<$‘=#	* 	['.0ÉY5®[A([,:"?Ø!Û[NKJ‘Û2/Bû1òYRm¨Ûð„	@)DªÂ°
"(4¬B J$,1¶h�c
‘‰DÒ�IA�;
__CPAN_FILE__ src/widget/templates/Wizard.html
<div class="WizardContainer" dojoAttachPoint="wizardNode">
    <div class="WizardText" dojoAttachPoint="wizardPanelContainerNode">
    </div>
    <div class="WizardButtonHolder" dojoAttachPoint="wizardControlContainerNode">
        <input class="WizardButton" type="button" dojoAttachPoint="previousButton"/>
        <input class="WizardButton" type="button" dojoAttachPoint="nextButton"/>
        <input class="WizardButton" type="button" dojoAttachPoint="cancelButton"/>
        <input class="WizardButton" type="button" dojoAttachPoint="doneButton" style="display:none"/>
    </div>
</div>


__CPAN_FILE__ src/widget/templates/HtmlTaskBarItemTemplate.html
<div class="dojoTaskBarItem" dojoAttachEvent="onClick">
</div>
__CPAN_FILE__ src/widget/templates/HtmlFloatingPane.css

/********** Outer Window ***************/

.dojoFloatingPane {
	/* essential css */
	position: absolute;
	overflow: visible;		/* so drop shadow is displayed */
	z-index: 10;

	/* styling css */
	border: 1px solid;
	border-color: ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight;
	background-color: ThreeDFace;
}


/********** Title Bar ****************/

.dojoFloatingPaneTitleBar {
	vertical-align: top;
	margin: 2px 2px 2px 2px;
	z-index: 10;
	background-color: #7596c6;
	cursor: default;
	overflow: hidden;
	border-color: ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight;
	vertical-align: middle;
}

.dojoFloatingPaneTitleText {
	float: left;
	padding: 2px 4px 2px 2px;
	white-space: nowrap;
	color: CaptionText;
	font: small-caption;
}

.dojoTitleBarIcon {
	float: left;
	height: 22px;
	width: 22px;
	vertical-align: middle;
	margin-right: 5px;
	margin-left: 5px;
}

.dojoFloatingPaneActions{
	float: right;
	position: absolute;
	right: 2px;
	top: 2px;
	vertical-align: middle;
}


.dojoFloatingPaneActionItem {
	vertical-align: middle;
	margin-right: 1px;
	height: 22px;
	width: 22px;
}


.dojoFloatingPaneTitleBarIcon {
	/* essential css */
	float: left;

	/* styling css */
	margin-left: 2px;
	margin-right: 4px;
	height: 22px;
}

/* minimize/maximize icons are specified by CSS only */
.dojoFloatingPaneMinimizeIcon,
.dojoFloatingPaneMaximizeIcon,
.dojoFloatingPaneRestoreIcon,
.dojoFloatingPaneCloseIcon {
	vertical-align: middle;
	height: 22px;
	width: 22px;
	float: right;
}
.dojoFloatingPaneMinimizeIcon {
	background-image: url(images/floatingPaneMinimize.gif);
}
.dojoFloatingPaneMaximizeIcon {
	background-image: url(images/floatingPaneMaximize.gif);
}
.dojoFloatingPaneRestoreIcon {
	background-image: url(images/floatingPaneRestore.gif);
}
.dojoFloatingPaneCloseIcon {
	background-image: url(images/floatingPaneClose.gif);
}

/* bar at bottom of window that holds resize handle */
.dojoFloatingPaneResizebar {
	z-index: 10;
	height: 13px;
	background-color: ThreeDFace;
}

/************* Client Area ***************/

.dojoFloatingPaneClient {
	position: relative;
	z-index: 10;
	border: 1px solid;
	border-color: ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow;
	margin: 2px;
	background-color: ThreeDFace;
	padding: 8px;
	font-family: Verdana, Helvetica, Garamond, sans-serif;
	font-size: 12px;
	overflow: auto;
}


__CPAN_FILE__ src/widget/templates/HtmlComboButtonTemplate.html
<div class="dojoButton" style="position:relative;top:0px;left:0px; text-align:none;">

	<div dojoAttachPoint="leftPart" class="dojoButtonLeftPart" style="position:absolute;left:0px;top:0px;"
		dojoAttachEvent="onMouseOver:leftOver; onMouseOut:leftOut; onMouseUp:leftUp; onClick:leftClick;">
		<div class="dojoButtonContents" dojoAttachPoint="containerNode" style="position:absolute;top:0px;right:0px;z-index:2;"></div>
		<img dojoAttachPoint="leftImage" style="position:absolute;left:0px;top:0px;">
		<img dojoAttachPoint="centerImage" style="position:absolute;right:0px;top:0px;z-index:1;">
	</div>

	<div dojoAttachPoint="rightPart" class="dojoButtonRightPart" style="position:absolute;top:0px;right:0px;"
		dojoAttachEvent="onMouseOver:rightOver; onMouseOut:rightOut; onMouseUp:rightUp; onClick:rightClick;">
		<img dojoAttachPoint="arrowBackgroundImage" style="position:absolute;top:0px;left:0px;z-index:1;">
		<img src="${dojoRoot}src/widget/templates/images/whiteDownArrow.gif"
		  		style="z-index:2;position:absolute;left:3px;top:50%;">
		<img dojoAttachPoint="rightImage" style="position:absolute;top:0px;right:0px;">
	</div>

</div>

__CPAN_FILE__ src/widget/templates/PopUpButton.css
.PopUpButton {
	padding : 2px 6px 2px 9px;
	border : 1px outset #ccc;
	background : #f4f4f4;
	color : #333;
	text-decoration : none;
}

.PopUpButton .downArrow {
	margin-left: 0.5em;
	margin-bottom: 2px;
}

.downArrow.disabled {
	background-image : url(images/dropdownButtonsArrow-disabled.gif);
	cursor : default;
}

ul.dropdownButtons li a:hover,
ul.dropdownButtons li span.downArrow:hover {
	color : black;
	background-color : #ddd;
}

ul.dropdownButtons li .downArrow.pressed, ul.dropdownButtons li .downArrow:focus {
	border-style : inset;
	background-position : 5px 10px;
	padding : 2px 4px;
}

ul.dropdownButtons li a.disabled:hover,
ul.dropdownButtons li span.downArrow.disabled:hover {
	color : #999;
	background-color : #f4f4f4;
}

__CPAN_FILE__ src/widget/templates/HtmlDocPane.css
.dojoDocSrc {
	white-space: pre;
	font-family: Courier, "Courier New", monospace;
	font-size: 0.8em;
}
.dojoDocReturn {
	color: #369;
}
.dojoDocFunction {
	color: #98543F;
	font-weight: bold;
}
.dojoDocParamType {
	font-style: italic;
	color: #D17575;
}
.dojoDocParamName {
	color: #D14040;
}
__CPAN_FILE__ src/widget/templates/incrementMonth.gif
GIF89a	Äÿÿÿ000ÖÖÖéééóóóøøøðððúúúžžžyyyÎÎÎFFFUUUõõõWWW222ýýý¶¶¶ØØØƒƒƒaaa:::!ù,	%`!Œ¤@@N ªK(«t²R4=TÁ#å4D`¤ƒ"Í;
__CPAN_FILE__ src/widget/templates/HtmlFisheyeList.css
.dojoHtmlFisheyeListItemLabel {
	font-family: Arial, Helvetica, sans-serif;
	background-color: #eee;
	border: 2px solid #666;
	padding: 2px;
	text-align: center;
	position: absolute;
	display: none;
}

.dojoHtmlFisheyeListItemLabel.selected {
	display: block;
}

.dojoHtmlFisheyeListItemImage {
	border: 0px;
	position: absolute;
}

.dojoHtmlFisheyeListItem {
	position: absolute;
	z-index: 2;
}

.dojoHtmlFisheyeListBar {
	position: relative;
}

__CPAN_FILE__ src/widget/templates/HtmlButtonTemplate.html
<div class="dojoButton" style="position:relative;" dojoAttachEvent="onMouseOver; onMouseOut; onMouseDown; onMouseUp; onClick:buttonClick;">
  <div class="dojoButtonContents" align=center dojoAttachPoint="containerNode" style="position:absolute;z-index:2;"></div>
  <img dojoAttachPoint="leftImage" style="position:absolute;left:0px;">
  <img dojoAttachPoint="centerImage" style="position:absolute;z-index:1;">
  <img dojoAttachPoint="rightImage" style="position:absolute;top:0px;right:0px;">
</div>

__CPAN_FILE__ src/widget/templates/decrementWeek.gif
GIF89aÄÿÿÿ000øøøfffúúú¶¶¶âââßßßÂÂÂyyyFFFˆˆˆÌÌÌCCCØØØžžžmmm   ÖÖÖjjj!ù, …(
C�i<ÀLN0	D‡‚;‘A;
__CPAN_FILE__ src/widget/templates/HtmlTabContainer.css
.dojoTabContainer {
	position : relative;
}

.dojoTabPaneWrapper {
	position : relative;
	border : 1px solid #6290d2;
	clear: both;
}

.dojoTabLabels-top {
	position : absolute;
	top : 0px;
	left : 0px;
	overflow : visible;
	margin-bottom : -1px;
	width : 100%;
	z-index: 2;	/* so the bottom of the tab label will cover up the border of dojoTabPaneWrapper */
}
.dojoTabLabels-top-noLayout {
	overflow : visible;
	margin-bottom : -1px;
	width : 100%;
	z-index: 2;
}

.dojoTabPaneTab {
	position : relative;
	float : left;
	padding-left : 9px;
	border-bottom : 1px solid #6290d2;
	background : url(images/tab_left.gif) no-repeat left top;
	cursor: pointer;
}

.dojoTabPaneTab span {
	display : block;
	padding : 4px 15px 4px 6px;
	background : url(images/tab_top_right.gif) no-repeat right top;
	color : #333;
	font-size : 90%;
}

.dojoTabPanePaneClose {
	position : absolute;
	bottom : 0px;
	right : 6px;
	height : 12px;
	width : 12px;
	background : url(images/tab_close.gif) no-repeat right top;
}

.dojoTabPanePaneCloseHover {
	background-image : url(images/tab_close_h.gif);
}

.dojoTabPaneTabClose {
	display : inline;
	height : 12px;
	width : 12px;
	padding : 0 12px 0 0;
	margin : 0 -10px 0 10px;
	background : url(images/tab_close.gif) no-repeat right top;
	cursor : default;
}

.dojoTabPaneTabCloseHover {
	background-image : url(images/tab_close_h.gif);
}

.dojoTabPaneTab.current {
	padding-bottom : 1px;
	border-bottom : 0;
	background-position : 0 -150px;
}

.dojoTabPaneTab.current span {
	padding-bottom : 5px;
	margin-bottom : -1px;
	background-position : 100% -150px;
}

/* bottom tabs */

.dojoTabLabels-bottom {
	position : absolute;
	bottom : 0px;
	left : 0px;
	overflow : visible;
	margin-top : -1px;
	width : 100%;
	z-index: 2;
}

.dojoTabLabels-bottom .dojoTabPaneTab {
	border-top :  1px solid #6290d2;
	border-bottom : 0;
	background : url(images/tab_bot_left.gif) no-repeat left bottom;
}

.dojoTabLabels-bottom .dojoTabPaneTab span {
	background : url(images/tab_bot_right.gif) no-repeat right bottom;
}

.dojoTabLabels-bottom .dojoTabPaneTab.current {
	padding-top : 1px;
	border-top : 0;
	background : url(images/tab_bot_left_curr.gif) no-repeat left bottom;
}

.dojoTabLabels-bottom .dojoTabPaneTab.current span {
	padding-top : 5px;
	margin-top : -1px;
	background : url(images/tab_bot_right_curr.gif) no-repeat right bottom;
}

/* right-h tabs */

.dojoTabLabels-right-h {
	position : absolute;
	top : 0px;
	right : 0px;
	overflow : visible;
	margin-left : -1px;
	z-index: 2;
}

.dojoTabLabels-right-h .dojoTabPaneTab {
	padding-left : 0;
	border-left :  1px solid #6290d2;
	border-bottom : 0;
	background : url(images/tab_bot_right.gif) no-repeat right bottom;
	float : none;
}

.dojoTabLabels-right-h .dojoTabPaneTab span {
	padding : 4px 15px 4px 15px;
}

.dojoTabLabels-right-h .dojoTabPaneTab.current {
	border-left :  0;
	border-bottom :  1px solid #6290d2;
}

/* left-h tabs */

.dojoTabLabels-left-h {
	position : absolute;
	top : 0px;
	left : 0px;
	overflow : visible;
	margin-right : -1px;
	z-index: 2;
}

.dojoTabLabels-left-h .dojoTabPaneTab {
	border-right :  1px solid #6290d2;
	border-bottom : 0;
	float : none;
	background : url(images/tab_top_left.gif) no-repeat left top;
}

.dojoTabLabels-left-h .dojoTabPaneTab.current {
	border-right : 0;
	border-bottom :  1px solid #6290d2;
	padding-bottom : 0;
	background : url(images/tab_top_left.gif) no-repeat 0 -150px;
}

.dojoTabLabels-left-h .dojoTabPaneTab span {
	background : 0;
	border-bottom :  1px solid #6290d2;
}

__CPAN_FILE__ src/widget/templates/check_disabled_off.gif
GIF89aÕÇÇÇØØØÎÎÎÒÒÒÉÉÉ×××ÔÔÔÊÊÊÕÕÕÓÓÓ½½½¶¶¶ÑÑÑºººÂÂÂÐÐÐ´´´ÆÆÆÖÖÖ»»»¸¸¸ÁÁÁ¿¿¿ÀÀÀËËËÃÃÃÙÙÙÈÈÈ±±±ÏÏÏ¾¾¾ÅÅÅÍÍÍÌÌÌ!ù,vÀŽpH,vš¤r¹ì€4 ¨t
BªTaºÛ©$D@„ÎèôÙpØ 0ð¸ÎŽ$6ø¼?Ø|�‚ƒ�Š‹ŒŠ“”•“ œ�žœ ¥¦§¥
¨®
„´‚¸¹º»A;
__CPAN_FILE__ src/widget/templates/grabCorner.gif
GIF89a

‘djp†Ž–ÿÿÿ!ù,

”�©‹œ�RPy›ÊúEtÓZÞ¤u3¢á[!;
__CPAN_FILE__ src/widget/templates/HtmlSimpleDropdownButtons.css
ul.dojoSimpleDropdownButtons {
	margin : 0;
	padding : 5px 0;
}

ul.dojoSimpleDropdownButtons li {
	display : inline;
	margin-right : 5px;
	padding : 2px 0;
}

ul.dojoSimpleDropdownButtons li a {
	padding : 2px 9px;
	border : 2px outset #ccc;
	border-right-width : 1px;
	background : #f4f4f4;
	color : #333;
	text-decoration : none;
}

ul.dojoSimpleDropdownButtons li ul {
	display : none;
}

ul.dojoSimpleDropdownButtons li a.disabled {
	color : #999;
	cursor : default;
}

ul.dojoSimpleDropdownButtons li .downArrow {
	display : inline;
	padding : 2px 4px;
	border : 2px outset #ccc;
	border-left : 0;
	background : #f4f4f4 url(images/dropdownButtonsArrow.gif) no-repeat 4px 9px;
	text-decoration : none;
	color : black;
	cursor : pointer;
	_cursor : hand;
}

ul.dojoSimpleDropdownButtons li .downArrow.disabled {
	background-image : url(images/dropdownButtonsArrow-disabled.gif);
	cursor : default;
}

ul.dojoSimpleDropdownButtons li a:hover,
ul.dojoSimpleDropdownButtons li span.downArrow:hover {
	color : black;
	background-color : #ddd;
}

ul.dojoSimpleDropdownButtons li .downArrow.pressed, ul.dojoSimpleDropdownButtons li .downArrow:focus {
	border-style : inset;
	background-position : 5px 10px;
	padding : 2px 4px;
}

ul.dojoSimpleDropdownButtons li a.disabled:hover,
ul.dojoSimpleDropdownButtons li span.downArrow.disabled:hover {
	color : #999;
	background-color : #f4f4f4;
}

ul.dojoSimpleDropdownButtons li a:focus {
	padding : 3px 8px 1px 10px;
	color : #333;
	border-style : inset;
}

/* Menu
 ******************** */
ul.dojoSimpleDropdownButtonsMenu {
	position : absolute;
	margin : 0;
	_margin : -2px;
	padding : 0;
	display : none;
	border : 1px solid #aaa;
	background : #f4f4f4;
	list-style : none;
	z-index : 99;
}

ul.dojoSimpleDropdownButtonsMenu li {
	_display : inline;
}

ul.dojoSimpleDropdownButtonsMenu a {
	display : block;
	padding : 2px 5px;
	color : #333;
	text-decoration : none;
}

ul.dojoSimpleDropdownButtonsMenu a:hover {
	background : #ddd;
	color : black;
}


__CPAN_FILE__ src/widget/templates/HtmlCiviCrmDatePicker.html
<table cellpadding="0" cellspacing="0" border="0" width="400">
	<tr>
		<td id="dateHolderTd" width="200">
		</td>
		<td id="timeHolderTd" width="200">
		</td>
	</tr>
	<tr style="display: none;" id="formItemsTr">
		<td id="formItemsTd">&nbsp;</td>
		<td>&nbsp;</td>
	</tr>
</table>

__CPAN_FILE__ src/widget/templates/HtmlShowSlide.css
.dojoShowSlideTitle {
	height: 100px;
	background: #369;
}
.dojoShowSlideTitle h1 {
	margin-top: 0;
	line-height: 100px;
	margin-left: 30px;
}
.dojoShowSlideBody {
	margin: 15px;
}
__CPAN_FILE__ src/widget/templates/check_hover_on.gif
GIF89aæÃÛý¶Òû��É�žÉ¬Çï€�ÈœÇöøúöúÿºÔüªÆï™­ÉœÈ­Çïúüÿûüý¢²ËÉÓâ°Ìø�¬ÖÒÛê¢¿ëøûÿûûý¸Ðõóõø¤³ÈÈÔå‹Ÿ¾µÊë�°Ë¼Íè€�ÇãîþŒ£Æ©¶Í«ÆïÊßþ¿Öú�¼ê¦Àæ„—µÆÝýþþþýþÿÑãÿ«Çïœ­ÅÀÙýÀØüÄÜý²Íõ�˜»êîóêîô“¦ÄåëôªÅîÓåÿëóþÁÚýóøÿ€œÈ¯Èî¯Èíž¶Ú†›¹“©Ê�žÊÙçýÕæþèñÿ–§À­Çî…š¸Ñãþèìñ½ÖüŒ ¾Þèø¾×ûÈÒà±ÎúÆÜþÉÞþËàÿ¬ËúÍáÿ§ÈùªÅíy–Áÿÿÿ!ù,¯€Z‚ƒ„…‚Yˆ‰ŠY?OIDZYW“””:,C ‘U�ž�-[)‘T¨©T%=[£B¦YS³´SG®LJ±2*½F®5H(‘0K;&<[/P
ÈY!®[E[+#7M×18Ú[QN@		‘3Ú6Aú.ñYRÿ.l� BÂ?)$|D²ÂÐJ‡4*4´¢€A$,1ž˜�c‘‰DÒ�IA�;
__CPAN_FILE__ src/widget/templates/HtmlShow.html
<div class="dojoShow">
	<div dojoAttachPoint="contentNode"></div>
	<div class="dojoShowNav" dojoAttachPoint="nav">
		<div class="dojoShowHider" dojoAttachPoint="hider"></div>
		<span dojoAttachEvent="onClick:previousSlide">&lt;</span>
		<select dojoAttachEvent="onClick:gotoSlideByEvent" dojoAttachPoint="select">
			<option dojoAttachPoint="option">Title</option>
		</select>
		<span dojoAttachEvent="onClick:nextSlide">&gt;</span>
	</div>
</div>
__CPAN_DIR__ src/widget/templates/images
__CPAN_FILE__ src/widget/templates/images/slider-button-horz.png
‰PNG


IHDR#a¡¨gAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<wIDATxÚìV]lU>wfö—)-”]h·[ZI‰öM@jÒÄÔã‹Æc|óÁL„ ULx�GKš¢1þ5!¨©A,B‹úÃ¶@³@w·Ëîvw»³ÝÙÝ™Ý™;ž-³¦ÛŸí6Qâ'99™9s¿oÎÏ=÷MÓà¿‚<’GòÿRÌyèø6JÕ×�g	!;��º¼OÓ¨‡ªê-UÉ^œ¹ëúòûOßákZ2	‚ór˜æMÛV‡±lc˜Ì0�9ø…o2™,HR
Äù8„ƒ3’$%�»þ:wô|ïÇsèVã±K	»°ÿzÀ¾ÍÙùBG++AìyÌ±ù4×pÒhY|NÃî<¤ÑßÑVÏESÜSå•Õ¯îÜµÿúÈÀOþÅQ�øä·–3:ê*;öÔÀ¤/µèòkÐ¸�‡÷hršØZLø)4;LÎ$a_£b3¯RíÅÍvçùÛ£—Ây¢‚ÍÈ°ìû[ÛùöV;Lzæ¡Çý,4Õá†O…æj(°Mý4:ù…joµÁ¶šzkÝãmï!\Y>¦°@ä¹gvUÁ„7�µ<Œúÿ”�1¯ZÜú4xÂi…›^Úq½eCÙ^„+G5äp¹Â6 ›F=
X9F<*–˜ }�Úµ-€‰0àòe1#\%¾²è$éì¨ÙL6Sµ�ÓsûO'•*æ[¨ªzªÈ²H4J'¤t²Šš­@©‚¤d�ã–b[Ë ¥E·ÞÆÚ²šd³r_2!€BsŠÑ¬OY¢A<.@lÖ?”ƒËï—Ï­ëß&bIÊPà.TKWñd@ˆ•+g¿êËÕUYFrúdW£9‰Î��Õ0}*”¦&¬£0/‚Ÿp»þ"\rE’Üæ‰=Æ#÷³I™‚Å •DÀbÔ"|ÓtìÊÏ_èÒŠéÊÉ©£¯ß”åÔ×ÁÐ,XML®åÖL•Å@ �C|.ôûå¾žq„I ÊÅŽ_õÞäµ®DlVðfŠ¢¬ªfìO6kÀïM÷ÿpâ˜N .’+‘hg>?L‘w� ˜
FD ‹€+©­Âþ`pÜ69|a×zÚZ	µûÝ—zDaö¬/{…ˆFAÉ*ZYf„9A„€×=ÖÛ}ð�@\:ê‹ÝV²Sco`K†B‘8lÞh*ˆ œ7oáÀ3}7qñÇ“Gd))è$™¥£‚-6%¦Æ.‹
-O�cxÙfÛÂ8â¢f#uÕàvß¡#ƒ¿t]êë¹Šß‡õz¨K�Ø5ìó¶ìëœÏhÆNgÕŒB…
Þ1A€©‰áS½Ýzu!¿/ÖK²@4Üzt÷þçë%•iÙá´ƒ$Kpç¶kèÄ¯ATWyµ‰Ê–8ú¨
ô×6<Ùž’ÁòOßÃB¿•Â¹ËC5Uld—J¢EÓ£Éüë&»£íÜwr»†¼:Abµ[JIW¢„Ó�U«>ú´…“$=§w‘ºî“í‘¬%0‚Ýâ÷wò¤1IEND®B`‚
__CPAN_FILE__ src/widget/templates/images/soriaActive-r.gif
GIF89a6w÷ÅÚú¥Èû Ã÷“¶ë‘´ê�²è�¡Îv–ÅzŸ×x�ÕušÒÃÙúÆÝý¿ÔöÞçô¼Óô}œËzšÈ†¥Òˆ§ÔÉÞþÀÖ÷p‘À„£ÑµÍîàéöºÐò¸Îðäìùr’Ââê÷¹Ðñãëø¯ÆèªÂäÈÞý±Èê‹ª×ãìù€ŸÍ~�Ëx˜Ç­Åç¬Ãæ¦¿á¦½áu”Ã¹Ôþ¸Ôýp‹³´Ðú¶Óý¤Âí³Ïù£Áì¯Ëö®ËõµÒü¯Ì÷©Æñ¦Ãï¹Õÿ·Óý¥Âî±Îøp•Î©Ìþr—Ïp–În”Í¨Ëþo•Ír˜Ðq–Îq—Ïo”Í‰¨Ö‰§Öš¸å™·ä´Ñû¢¿ë‹ªØ›¹æ¬Êô´ÐûŒ«Ù‹©Ø¨Æð”²ß�¯Ý˜¶ã°Í÷«Çó«Éô“±Þ­ËõµÑû ½ê´Ïú§Äï¡¾ë¢¾ë²Îø‹«Ø²Ïùœ¹æ—µâ¹ÕþŠ©×ªÇò·Ôý«Èó�¼è¨Åð°Íø¢Àì�­Û�®Ü�¯Ü¶Òü’°ÝŽ¬Ú¢Àë¬Éô«Èô¦Äï§Åð”³à�«Ù²Ïø–´á•´áªÆò­ÊôŸ½é�»ç�Àô£Æùv›Ó§ÊýžÁõŸÂöœ¿ó›¾ò¨Êý}¢Ù§Éüêòþs™Ñƒ§Þœ¿ô�³é¢Äø¢ÅùŒ°æ‹¯å•¸íš½ñ’µê˜»ðŸÂõ—ºï¡ÄøŽ²ç�´é{ ×€¤Û¥Çú�±ç•¹í¤Û‡«âyžÖt™ÑŠ¯ä£ÅùŽ±ç�¥Ü�¦Ý‚§Ý…©ß|¡Ø~£Ús˜Ð…ªà†«á¤Æú¤Çú¥Çû¡Ä÷¢Åø¦Èü¦Éü“·ì–ºî—»ï�±æŠ®ä˜¼ð™¼ð™¼ñ”¸í”·ì–¹îˆ¬â‰­ã„¨ßwœÔš½òéñýçïûåíúŠ©Öèðüæîû‰¨Õßèõƒ¢Ðáê÷èñý‹©Öåîúçïüæïûx—ÆŠ¨ÕÂ×øçðü‡¦Óéñþéòþs“Ã|›Êˆ¦Ó³Éì©ÀãèðýÇÝýêóÿëóÿ…¤Ò¥¼àp�¿¼Òó´ËíÆÛû»Ñó°Çêo�¿¨¿âàèõp�¿©ËþªÌÿÿÿÿ!ù,6wÿcH° Áƒ&ôÇ°¡Ã‡#Jœ(±Å‹3F´¨±£Ç�C†,!¤¤É“(Sª\Ére‰~0cÊœI³¦Í›6»áÜÉ³gM�>ƒ
ýi¤¨Ñ£H“*]ÊtiµP£J�JµªÕªð"iÝºµZ�¯`ÃŠK¶ìX
Y¹rõj¶­[·Þ1šK—n56xóêÝË·¯_¾që
®ö¢°áÃˆ+^œ˜¥I�#GÇ¸²åËŽ%k¦|¹³çÂŽƒ‰=ŒÓ¨S«^ÍºõjÇÀbË–mÚµíÛ·aÏž]·ïß0Nœ8¶7È“+_Î¼¹sæ#(õšN�zØ³kßÎ½»wîî(¡ÿOžü„ïèÓ«Ï«½{÷fÈŸO¿¾ýûøí‡ßÅ¿ÿøù( €îœ£È�"86èàƒF(!„&há9d¨á†vèá‡2`,$–X¢: ¦¨âŠ"jââ‹/ªÆŒ4Öhã�8æx#Òüâã�?ªÅ�Diä‘H&y$�™4é¤“êT!å”TViå•XZi�4£té¥—åÈ æ˜d–iæ™hš¹¥/l¶Ùf˜iÆ)§œ[
`ç�wJ0Æž|öéçŸ€ú'Òài¨5$ªè¢Œ6êè£�À�#”VZ)¢�fª©¦’Zê©i„*ê¨¤–jê©¥JÊª¬²*� °Æÿ*ë¬´Öj+­´ÓÈ®¼òÏÀ+ì°Äk,±¹öªl<@4ëì³ÐF+í´Ñ.`M"Øf›-³Ôvë­·Öj+n<s”kî¹è¦«îºéZ{É»ðÂ{ôÖkï½øæ«/¾Ö>âï¿ÿ^ ÃÀlðÁ'|ð8Öì°À
G,±Äã�ÉÅc|Á
wìñÇ ‡,2ÈglòÆ#§¬²Êã|ÍË0Ã|4×lóÍ8ç¬3Î-{âóÏ?Ï¼óÐDÝr2H'�´6`4íôÓPG-õÔQW0
2Xg�µ6†tíõ×`‡-öØa[}ÌÙh£­
l·íöÛpÇ-7ÜVƒb÷ÝwkÃÇÞ|÷ÿí÷ß€þ·ÕÄn¸áÚx¡øâŒ7îøã�;nµ(”W^¹}d®ùæœwîùç�7Î0¤—^ºp¤®úê¬·îúë­‹ÎÌì´Ón@¸ç®ûî¼÷î;ï¢«"üðÃàÆñÈ'¯üòÌ7¿|×t"ýôÓPÈõØg¯ýöÜw¿=ôÊ„/¾øì`þùè§¯þúì«ÿÀ5ËÄ/¿üå·oÿý÷¿/Ìþüó HÀ�€ï€¸ÀÈá�Œ 'HÁ
NðÞ` Oð‡zðƒ ¡GB~â„(Dá	ÈÀÂºð…0Œ¡aHo¤ð†'ðƒwÈÃúð‡@ô!=ÿ¨A€"Ñˆ'à�—ÈÄ&:ñ‰Ptâ=¨QŠ*ZÑŠIŒ¢·¸Å)bâ‹`ã	~@Æ2šñŒhL£Ñ¨j„ñ�c\£ç8Ç6àŽxÄ#
hÀÇ>úñ�€¤ ùj�â�ˆDäÉÈF6²�±ˆ¤$%‰Xò’˜Ì¤&7ÉIM2 e(+ÙÉRšÒ”…,†*W¹JÐá•°Œ¥,gIËZÎrØ„.w¹Kìá—À¦0‡IÌb—œH¦2•	�(8ó™ÐŒ¦4§IMinÀ¯È¦6µ	3xó›à§8ÇINq^ÓèLg:ÓQ†vºó�ðŒ§<çÏk:ãžøÄg:ÄÀÿÏ~úóŸ
¨@Š4ã Eh:ÁÐ†:ô¡�¨D!ZPVXô¢�@6ÊÑŽzô£ 
éGë]˜ô¤'�"VÊÒ–ºô¥0�éKIš‹šÚÔ¦PƒNwÊÓžúô§@õé:@P‹¢Õ¨˜‚R—ÊÔ¦:õ©PuêPŸAÕªV5NÈªV·ÊÕ®zõ«]]‡,AÖ²–5OH«Z×ÊÖ¶ºõ­m%�hA×ºÖ5[È«^÷Ê×¾úõ¯}ÅÇ6fAØÂ6kH¬bËØÆ:ö±�
Á6dAÙÊV6ƒÈ¬f7ËÙÎzö³�•ì)FKZÒ†ƒ¨M­jWËÚÖº–µ’]…lg;Ûpÿâ¶¸Í­nwËÛÞîV¸…p‡;Üdá¸ÈM®r—ËÜæ.¸’ˆ®t¥{€/X÷ºØÍ®v·Ë]í® Ó
ïò@Þòš÷¼èM¯zÑû][¸÷½ï=€æKßúÚ÷¾øÍï}E�Sø÷¿ÿuÁLàøÀNð�E°8øÁv�&Lá
[øÂÎð…á»  ±ˆGLâ›˜ÄìÈF+VÌb»@0Ž±ŒgLãÛ˜Æ)N€Žw¼ctâÇ@²�‡Lä"YÙà±’Ña…&;ùÉPŽ²”§e$CãÊXÆ2:ÐÀå.{ùË`³˜ÁÌ,âÌhF3:¤Àæ6»ùþÍpŽ³œá\æ4ÛWÈ³ž÷Ìç>ûùÏ}n�@èBºmH´¢ÍèF;úÑ�´¡'Ý&XúÒ˜Î´¦7ÍiMËÃ®µ¨EÝ�&˜úÔ¨NµªWÍjUº°Žu¬;p•ZÛúÖÿp.vÍk^[	À¶°‡MìbûØÆ¶À–Íìf;ûÙÐŽ¶´£m%XûÚØÎ¶¶·ÍínsÛI·¸ÇMîr›ûÜè>7?ˆÀîv»ûÝðŽ·¼ç-o~áÞøÎ·¾÷Íï~û»ßü8‚ÀNð‚üàO8Âù±„†;üá�¸Ä'Nñ‰Ï£Ï¸Æ7ÎñŽ{üãÏ‡BFNò’#$ ;
__CPAN_FILE__ src/widget/templates/images/combo_box_arrow.png
‰PNG


IHDR�‘h6tEXtSoftwareAdobe ImageReadyqÉe<òIDAT8Ëc¨œv�$ÄÄ«Ž¾%5Î;Õ°âô?‚hÕ±÷�óNB5,;ñ‡ ZuIÃâc?	¢•Gß!4Ì?ô
ˆÚ–^*èÙ„†€‚Y
sö¢ž5·ulý5­¼áÈ
BdWy×8¦aÆî[>Y�—Zqä-BÃäío ¨oã÷ˆj È…K-?Œ¤¡ó8Êj_Ñ�ÙºY|ùá7
sO@5t­{G�kYd��,¾ì’†æå÷�Q^ïn B\zðuÃ˜†š…7" †z¸†²Ù—	¢%^ÕÏ9NZâƒj 	øÍÔ:ÄIEND®B`‚
__CPAN_FILE__ src/widget/templates/images/treenode_grid_z.gif
GIF89a€999!ù,Œ�©Ëí£œt‚zi¶¸kÏ}M;
__CPAN_FILE__ src/widget/templates/images/soriaActive-l.gif
GIF89a6w÷ÁÚÿ¾×ü¥¿ç¡¼ä�¸à™³Ý·Ðõ«Åì™´Ý—²Û¸Ôý¹Ôþ©Æñ¥ÂîµÒü¹Õÿ£Áì¤Âí¯Ì÷´Ðú³Ïù±Îø®Ëõ·Óý¶Óý¯Ëö¦Ãï¨Ëþr˜Ðq—Ï©Ìþn”Íp•Îr—Ïp–Îq–Îo”Ío•Í§ÄïªÇò�»ç›¹æ™·ä«Çó´Ñû¢¾ë«Èó«Èô‹ªØ¢Àë¡¾ë¹Õþ¬Éô°Í÷´Ïú´Ðû²Îø•´á¨Æð­Ëõ‰¨Ö‹©Ø¢Àì‰§Öš¸å˜¶ã’°Ý�­Û”²ß¦Äï”³à�«Ù ½ê§Åð¨Åð²ÏùµÑû²Ïø·Ôý¶Òüœ¹æ–´á¬Êô­ÊôªÆò�¯Ý�¼è°Íø—µâŸ½é�®Ü�¯Ü“±ÞŽ¬ÚŠ©×«Éô¢¿ëŒ«Ù‹«Øv›Ó§ÊýžÁõ£Æù¨Êý}¢Ù§Éüœ¿óŸÂö›¾òôøþ�Àôó÷ý�±ç£ÅùwœÔõùÿƒ§Þ¥ÇúušÒ…ªà¤Æú¢Äø¢Åø¤Û–ºî‰­ã…©ß¥Èû’¶ë‘µêtšÒŽ²ç–¹î„¨ß‹¯åš½ñš½ò™¼ñŸÂõ•¹í—»ïs™Ñ¡Äø�´é’µê€¤Ûœ¿ô Ã÷¦ÈûyžÖ˜»ð”·ìt™Ñ‡«â�²è~£ÚŽ±çˆ¬â�¥Ü�¦Ý‚§Ý|¡Øx�Ôs˜Ð†«á¤Çú¡Ä÷¥Çû¢Åù¦Èü¦Éü—ºïŒ°æ�±æŠ®äŠ¯ä˜¼ð™¼ð”¸í•¸í“¶ë�³é“·ì Ãö‘´ê�³è{ ×zŸÖzŸ×x�Õïóúòöüðôûòöýñõûñõüïôú½Öû¿Øýó÷þñöüò÷ýðõûÀÙýÁÙþ³Íóóøþ­Çí¸Ñ÷°ÉðšµÝ¯ÉïµÎô¸Òø®ÈîºÔù°Êñ¼Õú¸Ñö£¾å¶Ïõ¾Öûœ·ß©Äëôøÿôùÿ ºâ½ÕûµÏõ·Ñö»Õú§Áéðôú¿Ùý»Õù›¶Þ­Çî´Íô±Ìò±Ëñ¢½å©Ãê¹Óù´ÎôµÎõïóù¹Óø²Ìò²Íò»Ôù°Ëñ­Æí©ËþªÌÿp‹³ÿÿÿ!ù,6wÿý	H° Áƒ*ìÇ°¡Ã‡#Jœ(ÑÅ‹3F´¨±£Ç�C†ôç¡¤É“(Sª\Ér¥?~0cÊœI³¦Í›6_âÜÉ³'M�>ƒ
ý¹¡¨Ñ£H“*]Êt©¿3P£F�ó¯ªÕ«X³jÝªõ©T©s<K¶¬Ù³hÓžõG¦­[·aÕÊ�K—íÛ·agèÝË·¯ß¿€ýúKC¸pá9Ì(^Ì¸±ãÇ�6lqäË˜3ûSÅ¹sgË™C‹Vì/•éÓ§ç,SÀºµë×°cË†í�’íÛ·UÏÞÍ»·¿?Àƒ·º·ñã¬ý�ZÎœ9¸tN¢KŸN½ºõëÕýÕÙÎ�{cÂ‹ÿO¾¼ùóåý•ZÏžýwôðãË÷‡§¾}ûß1èßÏ¿¿ÿÿúç�X`~&¨ ‚h`<!á„Vhá…ZèOvØ!„„(âˆ$–hâ‰%úƒÊŠ,²"Š0Æ£?zÔh£�mtÃÄŽ<öèã�@ù£?yi¤‘mÃÂ’L6éä“PFù¤?ŽTi¥•IÞ å–\véå—`zé�)d–Yf’¤©æšl¶éæ›mú3ÉœtÒ‰&œxæ™§?·ôé§ŸmŒcÃ „jè¡ˆ&z¨?k4ê¨£mdCÁ¤”Vjé¥˜fz)£�>©¦ †*ª?Š”jª©m˜³Äª¬¶êê«°Æÿúª?eÔj«­m¨ÓÄ®¼öêë¯Àû+­·ÞÚF>8$«ì²Ì6ëì³ÍúãÆ´ÔRëÌ5d«í¶Üvëí·ÝJ[mµ×‚kî¹èú#Éºì²{Œ<WÄ+ï¼ôÖkï½õú£Æ¾üò{Œ=5,ðÀlðÁëÛo¿ÇT#ÁÃG,ñÄW<±?ld¬±Æo8lñÇ ƒŒñÆ¿M(§¬òÊ,·ì2Ëþ "óÌ3›üòÍ8çìÏ!<÷ÜóÚX ôÐDmôÑHíO"L7Ý4ÐIG-õÔþÄbõÕW¿QÎ\wíõ×`‡-6ØþÀböÙg¿aÀl·íöÛpÇ-7ÜþXb÷Ýw«-ÅÞ|÷ÿí÷ß€þ·?Œn¸áopCÃâŒ7îøã�Gþ¸?«Tn¹åo�óÅæœwîùç ‡þ¹?|”nºéoÐóÂê¬·îúë°Çþº?„Ôn»íoPãÂî¼÷îûïÀÿ»?‹o¼ñ¹¯ üòÌ7ïüóÐ;ïÏ,ÔW_ýóœ ýöÜwïý÷à{ï�,ä—_~2íP¡þúì·ïþûð»ïÏ%ô×_2Í0 ÿþü÷ïÿÿôŸ?lAÀL èZ8ð�>t@Á
Zð‚Ì 1è@xðƒÆ=”@Âšð„(L¡
QèH¸ð…/†;’@ÃÚð†8Ì¡qè�@øð‡?Æ;ÿL@Ä"ñˆHL¢‘è\8ñ‰O†>Š@Å*ZñŠXÌ¢±è�Gxñ‹_ü64@Æ2šñŒhL£Ñè�Z¸ñ�oãçHÇ:ú#xÌc�øñ�€¤ IHAúCˆLd"ùXÈF:ò‘þ„$'9É_L#˜Ì¤&7ÉÉNz’“þà„(G9JK~ò”¨L¥?àÀÊV¶òÖ€€,gIËZÚò–¸´¥?ZÁË^ö–¹¦0‡éVó˜ÇD;|ÀÌf:ó™ÐŒ¦4¡éCXóš×DÆ3bÀÍnzó›à§8Áé�W˜óœçÔ&ÖÉÎvºó�ðŒç;ýáŠzÚÓžÃØGöÉÿÏ~úóŸ
è?ýÑ‡‚Ô ù”�BÊÐ†:ô¡u¨?:AÑŠVt@‚F7ÊÑŽzô£ õ¨?2AÒ’–£YH©JWÊÒ–ºô¥-õ)fJSš
ãVÈ©NwÊÓžúô§=õÇ†JT¢
#(HªR—ÊÔ¦:õ©Mõ‡¦JUª
ãPÈªV·ÊÕ®zõ«]õG!ÆJV²^5hM«Z×ÊÖ¶º•­þ ƒ\ç:WexÍ«^÷Ê×¾ú•¯þ…`;X»ªà°ˆM¬bËØÆ.ÖŸˆ¬d%k× Xö²˜Í¬f7ËYÍúÃ 
mh�±
,˜ö´¨M­jWËZÕú#°�ml��(ÿØö¶¸Í­nwË[ÝúcÀ
npi›ƒâ÷¸ÈM®r—›\lâ¹Ð….0`„êZ÷ºØÍ®v·›] á»àït‰@Þòš÷¼èM¯zÑëÝð†âà‚|çKßúÚ÷¾øµ¯?BÁßþöâ‚€LàøÀ6°?tÁà7˜¨‚„'Lá
[øÂ¶°?xÁáwÂ[±ˆGLâ›øÄ%öÇ.VÌbCX0Ž±ŒgLãÛ˜Æþ¨„Žw¼cbxc@²�‡Lä"™Èþè…’—¼d_¬£PŽ²”§Lå*[™Êþ…–·¼e_Hã`³˜ÇLæ2›™Ìþ�ƒš×¼f/‡áÿÍpŽ³œçLç:ÏÙcÈ³žõìe1øùÏ€´ MhAãyÏ{ö`ÀèF;úÑ�Ž´¤!í;XúÒ—öEzÀéN{úÓ µ¨AíA˜úÔ§Ö´VÍêV»úÕ°Žõ«ý�‰ZÛÚÖ¾HvÍë^ûú×Àö¯ýÑˆbÛØ¹þ�²—Íìf;ûÙÐv¶?FAíjW»\É¶¶·ýpàÛà·¸ÇMîr›»Üþ�º×Íîv»ûÝðŽ7¼ýÑ�zÛûÞøÎ·¾÷Íï}ûc¸ÀNð‚üà÷‡Îð†;üá�¸Ä#îXüâÏ¸Æ7ÎñŽsÜ%¹ÈGNò’›üä()?¹?HÀò–»üå0�¹Ìg.s|àæ8Ï¹ÎwÎóžû¼ç
	ºÐ‡Ž�€;
__CPAN_FILE__ src/widget/templates/images/treenode_node.gif
GIF89aÄ©Äí¨Äí¨ÃìªÅî©Åî©Åí§Ãì¤Çú–ºî‘´ê Ã÷yžÖ›¿ó‚¦Ý‹¯åªÅí!ù,@ $Ždižhª®éã¾0útM²¢ï:!3À ° C�F€,Ál2•§‡cJ�d�¬6+�-¾à¯A+³Îè´ú;
__CPAN_FILE__ src/widget/templates/images/bdYearBg.gif
GIF89a¢t‘»u‘»t�¹s�¸sŽ¸rŽ·s�¹t�º!ù,pþPC+x�Í‹ÿ	;
__CPAN_FILE__ src/widget/templates/images/tab_right.gif
GIF89a�,Õ7b�Òåíøöùýèïùòõûýþþúûþíòúâë÷•¿ÿŸÆÿßéöÝçö­ÎÿØãô¸ÔÿÀÚÿÚåõÖâôÈÞÿÔáóÎâÿd‘Ó¨Âæh”Ô|¢Ù¹ÍëŽ¯ß�¦Ûûüþ£¾åçîø’²àãë÷k—ÕÓàóŽ´ìž½ëÊÚð¦ÀæŒ°å‹°æ½ÑìÆÖïÚæõ¸Òö•½ø“½ýÍáþ•´áºÓù¡½ä·Óþÿÿÿ”¾ÿÿÿÿ!ù7,�,ÿ@€pH,�È¤rÉl:ŸÐ¨tJ­Z¯Ø¬vë´p.Ÿ›øV)›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûã0-%c‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ –2(7¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁ¹)7ÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàØ4!
æçèéêëìíîïðñòóôõö÷øùúûüýþÿøHxP@° Áƒ*\È°¡Ã‡#JœH±¢Å‹3jÜÈ±£EˆI²¤É“(Sª\É²¥Ë—0cÊœI³¦Í›8sêÜIóÿ@ƒ
J´¨Ñ£H“*]Ê´©Ó§P£J�JµªÕ«X³N µ«×¯`ÃŠK¶¬Y²\Ïª]Ë¶­Û·pã&M+·®Ý»xóêUKw¯ß¿€¾Ûw°áÃˆ+fZx±ãÇ�#×m,¹²åË˜«RÎÌ¹³gÎ›?‹MzpèÒ¨S«v{zµë×°³¶ŽM»¶m¤³oëÞ;7ïßÀGûN¼xåáÆ“+?Œ|¹óçy›CŸN½­ôêØ³‡½®½»wÍßÃ‹ß>¾¼y«ÜÏ«Ÿ~½ûîíßË§¾ýåõïë'ž¿ÿÝýý' mhàj¨ i	.è`g
>(¡eNhác^¨!bnèÿa`~(¢^!Žhâd'¦èY‰*¶È—‹0JÆbŒ4~5c�8bucŽ<nÕã�~íä�J	Iä‘E‰ä’@)É$’N>Id”RIe•=^‰eŽZnYc—^Æf˜.ŽI¦ŠfžybšjŽÈf›¾	ç†rÎya�vNˆgžîÉç‚~þy` ‚Hh¡ÿŠè~Š.z_£ŽÎi¤ïMJéz–^z^¦š–Çi§â}
êw¢Ž
Ÿ©m–Š*vª®JŸ«d¶
ës²ÎŠŸ­[ÖŠ«qºîÊŸ¯Rö
ìoÂ ±K‹¬mÊ.K ³SB;d³ÒºFmµª]‹-jÚnË ·\‚‹c·â®X.�äž›ÿYºê^Æn»ÇÁÛâ»òBFo½ŽÝ‹¯búîË¡¿n,b¿FpÁ€Œp�k¨pÃÑAláÃÛEqÅr]Œ1\oÌšÇ€‚¬`Ç"¿X²¡'£œr¢+³Ü2£/Ãó£3Ó\³¤7ãœs¥;óÜ3¦?cÊÅÐDmôÑH'­ôÒL7íôÓPG-õÔTW
µ`Œq\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×�ö*Ì@Èôí÷ß€.øà„nøáˆ'®øâŒ7îøã�G.ùä”Wn9ã+€PÊ
tîùç ‡.úè¤—núé¨§®úê¬·îúë°Ç.ûì´×nÿ»ë1\pC¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWß¼ÀÀöÜwïý÷à‡/þøä—oþùè§¯þúì·ïþûðÇ/ÿüô·Âä¯ÿþü÷ïÿÿ HÀð€L ÈÀ:ð�Œ h‚ à‚Ì 7ÈÁzðƒ ¡GHÂšð„(L¡
WÈÂºð…0L!D€Úð†8Ì¡wÈÃúð‡@¢‡HÄ"ñˆHL¢—ÈÄ&:‰€§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹`£ÇHÆ2šñŒhL£×XFà�pŒ£çHÇ:ÚÿñŽxÌ£÷ÈÇ>úñ�€¤ IÈBò�ˆ$ÀÈF:ò‘�Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“ ¥(GIÊR~H¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À¦0y	ó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›Ù@ÆIÎršóœèL§:×ÉÎvºó�ðŒ§<çIÏzÚóžøÌ§>÷ÉO{ 
¨@JÐ‚ô M¨BÊÐ†:ô¡�¨D'JÑŠZô¢ÍèDÿ©ÑŽzô£ 
©HGJÒ’št¤=©JWÊÒ–ºô¥ÿ0�)BS*ÓšÚô¦8Í©NOJÓ�úô§@
ªPmÚÓ¡õ¨HMªRZÔ¥:õ©P�ªL›*ÕªZõªX¥(U³ÊÕ®z5«[ýªXÇJV¡†µ¬hM«Z[zÖµºõ­pÅh[ãJ×ºÚõ s½«^÷
×¼òõ¯€«_KØÂJu°†M¬b�ŠØÅ:ö±8m,d'KY–J¶²˜Í,H/«ÙÎzV«Ÿ
­hCÊÙÑšö´--jWZÕ²öµ™u-lgYÙÒö¶‰µ-nwXÝòö·wõ-p‡ÛWâ³Â=®rÇšÜå:—«Í}®t«ÝéZ×©Õ½®v�šÝíz¨Ýý®xsÞñšwªçMÿ¯WË«ÞöòÔ½ð=l|ç‹]úÚ©ì½¯~A»ßþî4¿þ
0SL`ôøÀlE°‚U
à¸Á&0„#à	S¸¿¾°~3¬aûr¸Ãóý0ˆá+â··Ä&N/ŠSlÞ³X¼.~±wc,cíÒ¸ÆÖ½1Ž¥«ã;·Ç>V.�ƒlÜ!y¸F>òo“¬äÝ2¹É·}2”g+å)¿¶ÊV^-–³|Ú-sy´^þrkÅ<â0“¹³f>slÕ¬á4³™²n~småá8Óy±v¾snõ¬à<ó™°~þso]à@z¯†>tp]aFû7ÑŽŽ+¤#ýÖISz­–¾tZ3­é²rºÓÌuˆoEßO“º«¦>5XU}bV«7Õ®¦n¬ÏëYCµÖ¶®o®¿‹ë]'µ×¾æn°·ìa›ÕØ×-6²ªìeÿ×Ù<†ös›-í›R»Ú5½6¶cªím¿´ÛÞNp¸‘<nr—{ÉçFwº�¼nv·;ÊïŽr;
__CPAN_FILE__ src/widget/templates/images/decrementMonth.gif
GIF89aÄBXq™²Ö­ÊõŸ»áÌÙì}’®q�¸ˆªÚ�¥Æ˜¼ò©Åï­ËöŸÌ­Éõ”·ë]wš®Ëö€ Î?Tm,=O5H]š¾ô™¾ô™½óÄÏß):K!ù,$`%2$Z( -èuY†®CÅ”r%O�ÃÄ—™"˜¤’;
__CPAN_FILE__ src/widget/templates/images/spinnerIncrement.gif
GIF89a		³‡¥Ò…¤Ñx—Æ� ÎžÌƒ¢Ï{šÉ“·ì›¾ò¡Äø€¤ÛušÒ§Éü):Ky–Á!ù,		$ÐÉ9»˜¹�zë‰S Hc’Îp˜ìálìJm+Ž°ìüBýŽ;
__CPAN_FILE__ src/widget/templates/images/tab_close_h.gif
GIF89aÕè��ì~~ä~~ï‚‚ðƒƒóŠŠÐmmò‰‰éŽŽêwwèvvÝvväyyÕeeç„„î††üññâ||ýòòà‡‡àˆˆÓddê~~ázzÕkkãŠŠúîîçuuÔnnÐiiØppä‹‹å~~ì‘‘ÝttÖggé��ÐnnüïïÒiiîÑjjüôôÑrrÓjjïƒƒÐhhí„„ë��â€€Ùiiç||Þxxé}}õ��ÔppáuuØmmæssýôôÀÿÿÿ!ù,VÀžpHòŽÈ¤�g+PÀÁ[�ÄÀˆT{¼ÖKB@.¢// €ívYN]Ó‘v*Jƒ¥ž�L7)j8#.%j14'+jI™E›BA;
__CPAN_FILE__ src/widget/templates/images/floatingPaneRestore.gif
GIF89aæ–¹í™¼ïÂÓì§Ç÷ªÉù®Íû¬Ëú°Ïüp‹³6FVr�µ„©à†ªáœ¾ï´Ñý¦Éü Ã÷¢ÅùÄÕí›¿óž¿ðmˆ°}¢Ù§Æõ±ÏûÃÕí¡Áò¤Äô®ÌùqŒ´¤ÇúÁÓë–¸ë‘´ê™»í¯Îú¨Êýn‰±³ÐüoŠ²v›ÓÁÓì‚¦Ý�°åyžÖl‡¯“·ìŽ²ç¬Êø©ÈöžÁõ–ºî‹¯å™¼ñœ¾ðqŒ³›»ê’´å•¶æq�´˜¸èo‹²r�´¢Ãô¥ÅõŸÀòlˆ°ž½ë�²ãÄÕîÃÔí‰®ä²Ðý³Ñþ“¶ë€¦ßr˜Ðlˆ²©ËþÆÖík…«):Kÿÿÿ!ù,ÿ€P‚ƒ„…†‚N‰Š‹ŒŒ
P$EO“”•–OE$�EIŸ ¡¡E�E&H«¬­­&E>PEQ¹º»½E;PE#»ÈQË#EP2É»Ø2Ð0QRãäãQè07P5F1âåäQ÷1F5P3F@æ™K6ä‚‘ü\ÙðC k86qÁ/„
A:”’€‡#!z@ya„‚�dôè `äÅ	(4Œ4@³æÆ9¡ñ’�‚
µFD„% ¨B‰Ó§P¡‚ "©+ŽhÝÊ•ë
*@a‘bÁ’³hÓ¦]�‚…X.É¥ô…(LòêÝË—o(ML˜p‹@;
__CPAN_FILE__ src/widget/templates/images/spinnerDecrement.gif
GIF89a		³‡¥Ò…¤Ñx—Æ� ÎžÌƒ¢Ï{šÉ“·ìŒ°æ€¤ÛušÒ¡Äø§Éü):Ky–Á!ù,		%ÐÉ9»˜¹°º_NÑŒdãGÙ� äëIÝÔ‰#(|¯P@G;
__CPAN_FILE__ src/widget/templates/images/treenode_grid_l.gif
GIF89a€rrr!ù,Œ€Ë¦
S„o®jÎ’k¯âH‚æ‰¦êÊz;
__CPAN_FILE__ src/widget/templates/images/tab_left_r.gif
GIF89a	–Ä–Àÿ Æÿ¸Ôÿ­ÎÿÀÚÿÈÞÿçîød‘ÓŸ»ã€¥Úáê÷h”Ôf“Ó“½þ�¹ù¬Íþ£¾å¹Íëš»ë³Ðùûüþ¨Âæ†°ì‡®æx ØµÏ÷‰®å‰«Ýb�Ò”¾ÿÿÿÿ!ù,	–¥ 'Ždgž&‡¢êšº/ÜºóZ³pwŸ{Lç=p(#þŠÈ£Òfd&�KÜSå5©Ð,vk�v«>íWæ–Çf¡÷ÌVƒÝdx:H¿¢ïíúZŽççí{zoƒq…s€~Š‡}Œ�„‰Ž‹‘”‚•�–™˜›†—�šŸœi
0©ª¯°
¶·¼½ÄÇÇÇ	"!;
__CPAN_FILE__ src/widget/templates/images/treenode_grid_t.gif
GIF89a€rrr!ù,!Œ€Ë¦
S„o®jÎ’k¯âH6[vZé´F-:q¾;
__CPAN_FILE__ src/widget/templates/images/dpCurveTL.png
‰PNG


IHDRÈÜEtEXtSoftwareAdobe ImageReadyqÉe<›IDAThÞíØ±
Â@…á?áJ*@b$FÊBL€Ø%bÆAT¦¹‚
òŠˆÿÕþdûÜÝPU\oÏp&>¤õâ0{¾d¸Ì�
pŽ,ÈØGXTÜGª‰ �â�¢¶		ÓèwFZ¹C¾C¥;@ºtñëâg�@ �@ Þ²þ?Ÿ@ �@ ‚ÿ/
�$»S­ß¡IEND®B`‚
__CPAN_FILE__ src/widget/templates/images/floatingPaneClose.gif
GIF89aæ™¼ï¢Ãô¬Ëú¥ÅõÂÓì§Ç÷ŸÀòªÉùœ¾ðr�µ:Nd<Pfp‹³‹¯å>Qg”³âž¼é;Nd}¢Ù¯Îú�°åž¿ð¢ÅùZs’‘²àžÁõ–ºî†ªá®Ìù¡Áò™»ímˆ°¦Äñ‘´ê¦Éü¤Çú;OdŽ²ç Ã÷ ½ên‰±yžÖ©Èö¢Áï“·ìœ¾ï>RhqŒ´l‡¯ÁÓë³Ðü§ÆõÁÓì@Sj–¸ë•¶æ„©à›¿ó¤Äô±Ïû—¶ä�²ã¬Êø‚¦ÝoŠ²?Rh<PgÄÕí¨Êý�»é™¼ñ´Ñý;OeŽ°à›ºçÃÕív›Ó`w•<Odo‹²qŒ³q�´r�´<Oelˆ°ÄÕî–¹íÃÔí®Íû):K‰®ä²Ðý°Ïü³Ñþ“¶ë€¦ßlˆ²©Ëþr˜ÐÆÖík…«!ù,ÿ€d‚ƒ„…†‚a‰Š‹ŒŒ	dDUc“”•–cUD�"UG]Ÿ ¡¡GU"�#U2[«¬­­2U#RdU;\¸¹ºº;UQd&UXÅX ÆÇÉU&/dCÔMA'Ô'AMÔCÏ9K>+5Y..Y5+æ>K9PdFW*ûEYSN²8(²¯€Š+F�ÑpeÆ€‡”�È’…„ˆf\Ñ �ÅBà�„""è¸ÂBaˆ+È| $‹‚Y„<�i Ã•OÈ”¸R‚²DÀ€!é‚F+\)„Lƒ+-h½  ‰Ö$
.hÐâJƒªx°ÂÖJ�¶nMáz °™lxÙË·o_~Ø•@€‚–Ãˆ'¦@@Â2)hàøB¹²eË8h¤xÌ$Æ¥Ï”b0¡BFŒéÓ¨S§†AŒë×°cÇ†;
__CPAN_FILE__ src/widget/templates/images/tab_right_r_curr.gif
GIF89a�–Õ"b�ÒúûþýþþèïùíòúòõûöùýßéöåíøÚåõâë÷ÝçöØãôÖâô¦Àæh”Ôçîø“²à€¥Ú¹Íë¢½åÀÓî–µái•Ôãë÷¨ÂæûüþŽ¯ß|¢ÙÇ×ï©ÂæÍÜñd‘Óÿÿÿÿÿÿ!ù",�–ÿÀ�pH,�È¤rÉl:ŸÐ¨tJ­Z¯Ø¬v[p¿à°xL.›Ïh³7Ín»ßð¸|¾\Óïø¼~ÏgÛû€�‚ƒ„y…ˆ‰Š‹ŒN‡��‘’“w�”—˜™šW–›žŸ ž�¡¤¥¦…£§ª«¬p©­°±²[¯³¶·¸Jµ¹¼½³»¾ÁÂ¥ÀÃÆÇ—ÅÈËÌ‰ÊÍÐÑ{ÏÒÕÖoÔ×ÚÛcÙÜßàœáãäÝåçèXÞéìåëíðßïñôÖóõøÍ÷ùüÆûý{ýHÐÖÀ‚[LÈÐÔÂ†?=ŒHÓÄŠ#]ÌÈQÑÆŽ }I’ÏÈ’(+¥\	ê$Ë—~`Ê¤är¦Í05oêÔ’s§Ïÿ.?ƒê)´(¢F“Aª´©¦N•B�jt*U¡V¯þÌªu'×®7¿‚�)v,Ì²fY¢M›r-Û’nß†Œ+·#Ýºïâ­¨woÄ¾~œp0á‚†L¬¸ãÆùC®'yr¼Ê–ÛaÎœn3çsž?“-:éÒòP¿=­ZëÖö`›}-;íÚúpw½­ïÞþ€Sý-<ñâ‘7=®óæ¡W•^ô9uXÖ¯³Ê®]÷îÁ{¯ó;ù–çmšO¿i=ûLîß'“ÿ2>}IöïCÊ¯Ÿÿþ—€$ýG !(H‚
Õ G>8�„EH!^HG†ÊÁÿa‡®€(˜ˆ}HbL'"–¢Š+.Ö¢‹/:£Œ3FV£�7R&ÀŽ<öèã�@)ä�Diä‘H&©ä’L6éä“PF)å”T:	@Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ¹&Ôiç�xæ©çž|öéçŸ€*è „jè¡ˆ&ªè¢Œ6ê(¢ é¤”Vjé¥˜fªé¦œvêé§ †*ê¨¤–jê©¨¦ªêª¥@À«°Æ*ë¬´Öjë­¸æªë®¼öêë¯À+ì°Äkì±È
ÀÌ6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–û-¤«ÿîºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ð¾\ ÀÁ'¬ðÂ7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ gü”lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÍ8°ÀÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\S�$ öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þs[à€.øà„nøáˆ'®øâŒ7îøã�G.ùä”Wnùå˜g®9äD°�"4 úè¤—núé¨§®úê¬·îúë°Ç.ûì´×n;ûí¸ç®ûî¯W@Áˆ <ÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜw½@ ¼ðA;
__CPAN_FILE__ src/widget/templates/images/tab_bot_right.gif
GIF89a�–Äb�Ò Æÿ–Àÿ­Îÿ¸ÔÿÀÚÿÈÞÿh”Ô€¥Ú³Ðùçîø£¾å‰«Ýš»ë¡¼äd‘Ó‰®å‡®æ|¢Ù�¸ø†°ì’¼ýûüþáê÷µÏ÷¨Âæ¬Íþ¹Íë”¾ÿÿÿÿ!ù,�–ÿ  Ždižhª®lë¾p,Ïtmßx®ï6çÿÀ pH,�È¤rÉl:ŸÐ¨tJ­Z¯QvËíz¿à°xLkËè´zÍn»ßÇ3|N¯Ûïx´<Ïïûÿ€u{�„…†‡ˆJƒ‰Œ�Ž�s‹�“”•–S’—š›œš™� ¡¢�Ÿ£¦§¨l¥©¬­®W«¯²³´F±µ¸¹¯·º½¾¡¼¿ÂÃ“ÁÄÇÈ…ÆÉÌÍwËÎÑÒkÐÓÖ×_ÕØÛÜ˜ÝßàÙáãäTÚåèáçéìÛëíðÒïñôÉóõøÂ÷ùü¹ûýeýH0ÕÀ‚ELÈpÓÂ†)=ŒH±ÑÄŠ
]ÌÈñÏÆŽ ñ|I2RÉ“œFÿ¢\©‡¥KH*_Êìs¦M+5oêÌ²³'Ÿœ>ƒ"*´è¢F“ú@ªÔ(Ó¦BŸBõ)uêÎªVobÍ:s+×—^¿²+%Ù²%Ï¢
©vmÇ¶n3Â�[q.Ýˆvï6Ì«7!ß¾ÿ(xp¿Â†ó!N\o1ãxŽ·‹,9åÊå.c§y3¸Îž»�íŽôÚÑ¦­¡N-�µØÕ®›ÁŽm�vÖÙ¶‰áÎ­�7ÔÝ¾{î�xÒáÆi!O.�yTçA—Cg%}:ªêÖMaÏ®�»Vï6·ƒO9^¦øò—Î£¯¤~}1÷+ÛÃw$>£úöáÏ¯‘?[ÿ í  èG�þ” ÿF.øŒƒ5!NG…º�a†ªpè—‡mbK#V¢‰'–¢Š+*Ö¢‹/6£Œ3BV£�7N–£Ž;ZÖ£�?’SÁiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå•HÀ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiç�xæ©çž|ÖIÁ*è „jè¡ˆ&ªè¢Œ6êè£�F*é¤”Vjé¥˜fª©¤<p †*ê¨¤–jê©¨¦ªêª¬¶êê«°Æ*ë¬´Öjë­¸æktPÀ¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíKµØ:›XÐ�à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæÛ.
°Aó ðÀlðÁ'¬ðÂ#��;
__CPAN_FILE__ src/widget/templates/images/treenode_expand_plus.gif
GIF89aæH999~šÃDDDCCDïòöçëñ€›ÄîñõùúûìïôûüýþþþÄÎÝãçïÙßéÛáêÚàéýþþßåíëïôùúüøùûÃÍÜÞäì~™Ãâåêðóöäèïö÷úÉÒà¾ÉÙàåíöøúåéðÓÚåðòö}™ÃšÃàæí}™ÂÑÙäüüýÐØäØÞèêìîûûýíîðÞãìÒÙåCDDòô÷ôõøåêðèìñêíóóõøâçîÊÓàËÔáòôøßâç›Äüýýôöù÷ùûßäìêîóëîóþþÿ×Þèy–Áÿÿÿ!ùH,{€H‚ƒ„…†‡ˆ‚F‹Œ�F‡FG’-@3C�’
?#š†‘�.	8=�D),	5
/%�>½E�21A+*Ã¥ ;<(�76!09$�B4&":'�ŽŽ‰óôõö÷øô�;
__CPAN_FILE__ src/widget/templates/images/treenode_blank.gif
GIF89a÷'ÿÿÿþþþýýýüüüûûûúúúùùùøøø÷÷÷öööõõõôôôòòòñññïïïîîîìììëëëêêêèèèçççæææäääãããâââáááàààÝÝÝÜÜÜÛÛÛÚÚÚÙÙÙÖÖÖÕÕÕÓÓÓÒÒÒ½½½___!ù',OH° Áƒ*\È°¡Ã‡#JœH±¢Å‹1;
__CPAN_FILE__ src/widget/templates/images/blank.gif
GIF89a€ÿÿÿÿÿÿ!ù
,L;
__CPAN_FILE__ src/widget/templates/images/dpCurveBL.png
‰PNG


IHDR	È:%ËtEXtSoftwareAdobe ImageReadyqÉe<ŠIDATXÃíÊË	Â`EáW¶ba ¿eäa5ÆˆMXFjLn„,ÍÍÂ…ÂYœË0|q¹>Ò �@ �@ �@ ¿BEãŠÒöéúQtOW”F‡)Î×WQ—®�¨ÖašÑ¸½,:Õ·£Êµf´Sý*Ê|Ã½ªÔø-éqP­zªaAb´Né.ðÊšIEND®B`‚
__CPAN_FILE__ src/widget/templates/images/submenu_on.gif
GIF89a	³äääîîîëëëøøøõõõåååâââìììéééýýýúúúêêêòòòÿÿÿÿÿÿ!ù,	°¹éšœöæQ	‚Â,…Ã ÆtÔB9;
__CPAN_FILE__ src/widget/templates/images/soriaActive-c.gif
GIF89a6wæ¥Âî£Áì¯Ì÷¹Õÿ¯ËöµÒü±Îø¤Âí©Æñ¦Ãï´Ðú®Ëõ³Ïùp‹³¶Óý·Óý�®Üq—Ïq–Îp–Î¢ÀìªÇò�»ç‹©Ø�¼è¢¿ëªÆò­Êô—µâ¬Êô•´á“±ÞŠ©×�¯Ý²Ïù²ÏøµÑû‰§Ön”Íš¸å¨Æðp•Îr—Ï‰¨Ö©Ìþ¡¾ë«Éô§Äï¢¾ë¨Ëþ�«Ù­Ëõ´ÏúŒ«Ù´Ñû’°Ý˜¶ã�¯Ü¨Åð›¹æŽ¬Ú°Í÷™·ä�­Û¶Òü´Ðûo•Í ½ê‹«Ø«Èô«Çó–´á¬Éô¹Õþ«Èó¢Àë°Íø·Ôý§Åðr˜Ð¦Äïo”Íœ¹æ”²ß”³àŸ½é²Îø‹ªØ¹Ôþ©Ëþ¸ÔýªÌÿÿÿÿ!ù,6wÿ€
‚ƒ„…†‡ˆ‰‰[Œ�Ž��‘’“”•–—˜™š›œ�ž�,¡¢£¤¥¦§¨¨Y«¬­®¯°±²³´µ¶·¸¹º²1½¾¿ÀÁÂÃÄÄ\ÇÈÉÊËÌÍÎÎÑÒÓÔÕÖ×ØÙÚÛÜÝÒIàáâãäåæççXêëìíîïðñòóôõö÷øùñZüýþÿ
H° Áƒ*\8°‰Ã‡#JœH±bÅ3jÜÈ±£Ç� CŠI2£ƒ“(Sª\É²¥Ë—0cÊœ‰ˆÍ›8sêÜÉ³gÏ@ƒ
J´¨Ñ£H“*]Ê4(‰§P£J�JµªU«6²jÝÊµ«×¯`ÁK¶¬Ù³hÓªU« ­Û·pÿãÊ�K·®Ý»xóº¥Á·¯ß¿€<˜�áÃˆ+^Ì¸±ãÇ�#K>,¢²åË˜3kÞÌ™óˆÏ C‹Mº´iÓVR«^Íºµë×°a˜M»¶íÛ¸sëÞÍ»·ïß´™N¼¸ñãÈ“'ïÁ¼¹óçÐ£KŸ>]€õëØ³kßÎ½»÷ïàÃ‹¿N ¼ùóèÓ«_Ï¾½û÷ðã›_@¿¾ýûøóëßÏ¿¿ÿÿÖ7Ã€hà�&¨ ‚4èàƒF(á„RØÁ…f¨á†vè¡‡H„(âˆ$–hâ‰(¢èÂŠ,¶èâ‹0Æ(£ŒEÔhã�8æ¨ãŽ<ò¨Ä�@)ä�Di¤‘F$©äÿ’L6éä“PBYÁ”TViå•Xf©¥–téå—`†)æ˜d’‰À™h¦©æšl¶éæ›pÆ)çœh¢`ç�xæ©çž|öÙ§€*è „jè¡‡:¡è¢Œ6êè£�Fé”Vjé¥˜fªé¦›Báé§ †*ê¨¤–Zj¨¦ªêª¬¶êê«°Æ*ë¬´¦
À­¸æªë®¼öêë¯À+ì°¸`ì±È&«ì²Ì6ëì³ÐF+í±TkíµØf«í¶Üvëí·à†k-ä–kî¹è¦«îºë.áî»ðÆ+ï¼ôÖ[oøæ«ï¾üöëï¿ÿÂ ðÀlðÁ'œp7ìðÃG,ñÄañÿÅg¬ñÆwÜq ‡,òÈ$—lòÉ'c òÊ,·ìòË0Ç³4×lóÍ8ç¬óÎ;KáóÏ@-ôÐD]ôH'­ôÒL7íôÓOŸ õÔTWmõÕXg�µ\wíõ×`‡-öØcã`öÙh§­öÚl·Ý6pÇ-÷Üt×m÷Ýw¡÷Þ|÷í÷ß€¸„nøáˆ'®øâ‹Sáøã�G.ùä”W^ù˜g®ùæœwîùçŸ úè¤—núé¨§žú
¬·îúë°Ç.ûì³‡`ûí¸ç®ûî¼÷Þ{À/üðÄoüñÇC üòÌ7ïüóÐGýÔWoýõØg¯ýöÛóàý÷à‡/þûøä—_¾è§¯þúì·ïþûï× ÿüô×oÿýøçŸ?ü÷ïÿÿ 8À+ð€L ÈÀ6ðŒ 'HÁ
Zð‚�7ÈÁzðƒ aW@Âšð„(L¡
W¸Â¸ð…0Œ¡gHÃÖð8Ì¡›ñ„úð‡@¢‡HD"ªàˆHL¢—ÈÄ&:Ñ‰ˆ¢§HÅ*ZñŠXÄ¢¶ÈÅ.zñ‹`£Å8�2šñŒhL£×ÈF6¦à�pŒ£çHÇ:ÚÑŽBÈ£÷ÈÇ>úñ�€dIÈBò�ˆL¤"i‚F:ò‘�Œ¤$'IIJ*â’˜Ì$";
__CPAN_FILE__ src/widget/templates/images/toolbar-bg.gif
GIF89aÄçççàààæææÓÓÓöööóóóêêêúúúðððÚÚÚííí÷÷÷ÖÖÖäääñññÔÔÔîîîÑÑÑûûûÞÞÞëëëøøøõõõØØØòòòâââùùùÜÜÜééé!ù,1 $¤fVè¢¬å0&;4bC¸¢S¼ás@€P@l3È€rÂÜ8Ð‹”A}XØˆ6;
__CPAN_FILE__ src/widget/templates/images/dropdownButtonsArrow-disabled.gif
GIF89a÷ÿÿÿ¥¥¥!ù,
8`à€ƒ;
__CPAN_FILE__ src/widget/templates/images/dpHorizLineFoot.gif
GIF89a€qŒµ‘§É!ù,D
;
__CPAN_FILE__ src/widget/templates/images/verticalbar.gif
GIF89a"ÄÙÙÙƒƒƒYYY+++“““hhh999IIIœœœ¦¦¦²²²ªªªppp}}}mmm‡‡‡”””®®®tttŽŽŽ˜˜˜ˆˆˆxxx   ³³³!ù," äPÙ#`Vq)Ú2mðÆ4šeÆ�D œ@;
__CPAN_FILE__ src/widget/templates/images/treenode_child.gif
GIF89a€!ù, Œ�©Ëí¢œ`ÑkïÌ:òþi!¦tÒH¡[iVÏÇòS;
__CPAN_FILE__ src/widget/templates/images/treenode_grid_p.gif
GIF89a€rrr!ù,Œ�©Ëí£œ”�‹o»Sþy8ŠK;
__CPAN_FILE__ src/widget/templates/images/no.gif
GIF89a³	ÜX\ê� í«­Ó.4öÕÖÖ<AÙJOüññÐ &ÿÿÿ!ù	,`0Éº&É)WxDGH!l‡er€ÆÆ�ã¤¶„ @€˜P5Â�¸ô~¬KqCö¤N�•s�ZÐŽ’¹+l¹AhÙ“Y
6œŠåBÀLkQ*Ö¡X0‚ƒ‚;
__CPAN_FILE__ src/widget/templates/images/floatingPaneMinimize.gif
GIF89aæ€¦ßœ¾ð“¶ë¥ÅõÃÔíÄÕîÂÓì™¼ï–¹íp‹³r�µ®Ìù¯Îú�°å¦ÉüŽ²ç¢Åù–ºî„©àÃÕí±Ïûn‰±–¸ë¡Áò‚¦Ý Ã÷¨Êý™»íÁÓë‹¯åžÁõmˆ°‘´ê¬ÊøqŒ´†ªá³Ðü¤Äôv›ÓyžÖoŠ²œ¾ï§Æõl‡¯›¿ó“·ì}¢ÙÄÕí¤Çú™¼ñÁÓì©Èö´Ñýž¿ðqŒ³q�´lˆ°r�´o‹²‰®äŸÀò²Ðý¢Ãô§Ç÷ªÉù¬Ëú®Íû°Ïü³Ñþ):Kr˜Ðlˆ²©ËþÆÖík…«!ù,ÿ€J‚ƒ„…†‚H‰Š‹ŒŒ
JI“”•–I�4DŸ ¡¡4�0$=«¬­­$09JC¸¹ºº7JBÅÆÇÇ"J/AÒÓÔÔ/Í,!@Þßàà!,6J13?ëìíí31	J*øùúú*ó-”ðA° Aƒ%´˜‚À#J”x�J¨ £Ç�kx€BI)(Â²¥K•)t(9ÂÀ\ê,‚sƒ�”`0`A€Ñ£H‘Z0€!¨
vH�J•j.>(9!C€¯`Ã†• ã„V.©¥ÄÁ%FâÊ�K—î
%GòêÝË—ïŠ@;
__CPAN_FILE__ src/widget/templates/images/soriaPressed-c.gif
GIF89a6wæ±Îø­Êô¹Ôþ·Óý³Ïù«Èó¯Ëõ¹Õþp‹³¶Óý�ºæ¯ÌöµÒü´Ðú¬Éôq—Ï§Äïž¼ær˜Ð´Ïù®Êô²Îø£Àë°Í÷·ÔýŸ¼ç¬Éó²Ïøq–Îp•Î®Ëô¦Âí¡½è±Íø¡½éo”Ío•Í¢¿ëp–Î©Ìþ ½èªÆð°Ì÷´Ïú¤Áë«Çò¸Ôþ¨ÅïµÑû¯Ëö¥Âì¢¾ên”Í¨Ëþ¶Òü´Ñû´Ðû¦Ãî«Æñ�¹å©Æðr—Ïž»æ©Ëþ¸ÔýªÌÿÿÿÿ¹Õÿ!ù,6wÿ€‚ƒ„…†‡ˆ‰‰AŒ�Ž��‘’“”•–—˜™š›œ�ž�'¡¢£¤¥¦§¨¨?«¬­®¯°±²³´µ¶·¸¹º²5½¾¿ÀÁÂÃÄÄBÇÈÉÊËÌÍÎÎ;ÑÒÓÔÕÖ×ØØ
ÛÜÝÞßàáâãäåæçÜ>êëìíîïðññôõö÷øùúûûþÿ
H°`A*\È°¡Ã‡AHœH±¢Å‹3fÁ±£Ç� CŠ9r†É“(Sª\É²eË0cÊœI³¦Í›7-èÜÉ³§ÏŸ@ƒeA´¨Ñ£H“*]ºT†Ó§P£J�JµjÕX³jÝÊµ«×¯_sˆK¶¬Ù³hÓ¦…À¶­Û·pÿãÊ�;÷…Ý»xóêÝË·o_€L¸°áÃ‡S(^Ì¸±ãÇ�#GÖA¹²åË˜3kÞ¼¹…çÏ C‹Mºté¨S«^Íºµë×°cËžM;µ†Û¸sëÞÍ»·oß‚N¼¸ñãÈ‘XÎ¼¹óçÐ£KŸN½ºõëÌ)hßÎ½»÷ïàÃ‡÷@¾¼ùóèÓ«_¿Þ€û÷ðãËŸO¿¾ýûøóë£¿ÿÿ(à€¸À�&¨à‚6èàƒF(á„ª`á…f¨á†vØá †(âˆ$–hâ‰'† âŠ,¶èâ‹0Æ#4Öhã�8æ¨ãŽ<öèã�@ÖXÁ�Diä‘H&©¤ÿ’4éä“PF)å”TRIÀ•Xf©å–\véå—`†)æ˜XN`æ™h¦©æšl¶Ùæ
pÆ)çœtÖiç�w6 çž|öéçŸ€*è „jèž8$ªè¢Œ6êè£�BzÃ¤”Vjé¥˜fª©¦0têé§ †*ê¨¤’ÊÀ©¨¦ªêª¬¶êê«°Æ*ë¬¨Ú`ë­¸æªë®¼öÚkÀ+ì°Äkì±È&«ì²Ì;À³ÐF+í´ÔVkíµØf«í¶Ðbàí·à†+î¸ä–[.è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½ïº ï¾üöëï¿°lðÁ'¬ðÂ7ìðÃ|ÀÄWlñÒÅg¬ñÆwìñÇ!òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXãüÌÖ\wÝŒ`‡-öØd—möÙg÷ öÚl·íöÛpÇ÷t×m÷Ýxç­÷Þ{sà÷ß€.øà„^¸	ˆ'®øâŒ7îøã�w ùä”Wnùå˜gž9	œwîùç ‡.úè£�`úé¨§®úê¬·Þ:
°Ç.ûì´×nûí·+¢ûî¼#;
__CPAN_FILE__ src/widget/templates/images/tab_top_left.gif
GIF89a�,Õ;b�Òåíøíòúöùýúûþòõûßéöèïùýþþâë÷•¿ÿŸÆÿÝçö­ÎÿÀÚÿ¸ÔÿÚåõØãôÖâôÈÞÿÔáóÎâÿd‘ÓŽ¯ßh”Ôf“Óçîø�¦Ûûüþ¨Âæ¹Íë¦Àæ‹°æ•´á¡¼äãë÷”¾þŽ´ìŒ°åÓàó§Áæ£¾å×ãôÌÛðx Øz¡Ù¡½äÍáþºÓùáê÷ž½ë–¾ù½Ñì¸Òö·Óþ’²àÆÖïÿÿÿ”¾ÿÿÿÿ!ù;,�,ÿÀ�p§él,€¤rÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°¸:ô`dµWeÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€�‚ƒ„w;&0Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤¥›;" «¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ¼16ÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãÛ)%
èéêëìíîïðñòóôõö÷øùúûüýþÿêc1c�Áƒ*\È°¡Ã‡#JœH±¢Å‹3jÜÈ±£Ç�3�P@²¤É“(Sª\É²¥Ë—0cÊœI³¦Í›8sêÜÉ³§Mÿ:‚
J´¨Ñ£H“*]Ê´©Ó§P£J�JµªÕ«X³j¥
t«×¯`ÃŠK¶¬Ù³d»¢]Ë¶­Û·pãÊMªv®Ý»xóêÝ‹¶.ß¿€|×/áÃˆ+^ÌÔ0ãÇ�#Kžëx²åË˜3W­¬¹³çÏš9ƒMºô`Ñ¦S«^í5ë×°cgu-»¶íÛHiãÞÍ;¶îÞÀƒ�þ-¼¸ñÉÄ�+_~89óçÐó:�N½zÛéÖ³k‹}»÷ï›Á‹/¶;ùóè…šOÏ^üúöðµ¿�O?úüúø•ßÏÏ?øþþâö_€úVà�Ù
ˆà‚¤)Èàƒ�9á„–IHá…�Yˆá†ˆiÈÿá‡�yâˆz‰Hâ‰”¡¨âg&®èb_/ÆˆœŒ4fXã�‰µˆãŽáñè#_:þ(dcC™¢‘H¶–ä’kÉ$’N>Yd”R
Ie•>^‰åŽZnyc—^Òf˜1ŽI¦‹fž©bšjžÈf›#¾	ç‡rÎ¹a�v^ˆgžîÉçƒ~þ¹` ‚Hh¡Š(€Š.Ê_£Žâi¤ôMJ)|–^Ê^¦š¢Çi§ä}
ª{£’)j©Þ�Šª|«n©j«Õ½
«}³J)k­ÌÝŠ«~».©k¯Åý
¬Ã)l±¼‹¬€ËZÙì�Ê>+[´ÒÂFmµ¬]‹­jÚnkZ·Þ6®˜ãÊn¹ž�‹ÿnhë¢ÙîŠê¾[¡¼(ÆKodöÞk£¾ æË¯bþþÛ¡ÀLðichpÂ€-Ì0�÷1„OŒWÅÛ…qÆrmÌ1\¬¤È‰’\²ÉŒ¢œ²Ê�²Ü²Ë’Â³Ì•Ò\³Í˜âœ³Î›ò¼é@-ôÐDmôÑH'}ôD�„ÒPG-õÔTWmõÕK”��4œ@Á×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýx¯}È7à Áß€.øà„nøáˆ'®øâŒ7îøã�G.ùä”Wnùå˜;¾Ã!Dàùç ‡.úè¤—núé¨§®úê¬·îúë°Ç.ûì´×nÿûí¯�`�
ôîûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWo½ó ÀÀöÜwïý÷à‡/þøä—oþùè§¯þúì·ïþûðÇ/ÿüô·ßÂ
ä¯ÿþü÷ïÿÿ HÀð€L ÈÀ:ð�Œ ˜$à‚Ì 7ÈÁzðƒ ¡GHÂšð„(L¡
WÈÂºð…0L!@ÃÚð†8Ì¡wÈÃúð‡@¢‡HÄ"ñˆHL¢—ÈÄ&ˆ¢§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹`£ÇHÆ2šñŒhL£É¸ñ�pŒ£çHÇ:ÚÿñŽxÌ£÷ÈÇ>úñ�€¤ IÈBò��@ÉÈF:ò‘�Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“ ¥(GIJO`¨L¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—Àæ.@€bó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnz›@€8ÇIÎršóœèL§:×ÉÎvºó�ðŒ§<çIÏzÚóžøÌ§>÷YOäàŸ
¨@JÐ‚ô M¨BÊÐ†:ô¡�¨D'JÑŠZô¢•¨?3ÊÑŽzô£ 
©HGJÒ’Št£&M©JWÊÒ–ºô¥ÿ0=(JcJÓšÚô¦8Í©IgªÓžúô§@
jMy*Ô¢õ¨HMªB‰ªÔ¦:õ©P�)S£JÕªZõª�*V·ÊÕ®bU«^
«XÇT°’õ¬hM+KÍªÖ¶ºõ­e+\çJ×ºT®vÍ«^ßŠ×½úõ¯aí+`KØ¨
¶°ˆMlQ«ØÆ:ö¦Œ}¬d'»ÒÈRö²˜ý¨e3ËÙÎfÕ³ 
-H7+ÚÒš ¤=­jA›ÚÕº³­}­lÛÙÚ±µ½­nÿšÛÝúÖ®½ý­pù:Üâ^6¸ÆM®X‘«Üæn•¹Î�.U¡+Ýê6•ºÖÍ®Q±«Ýîþ”»Þ
/NÁ+ÞòJÕ¼èíÿ*yÓËÞ�¶÷½†…¯|¯;ßúu½öÍïgõË_�â·¿^j€|^x­NpJÿ«`3¸Á~0„,á	ó·ÂÎ/†3\ß
sX¾þð{C,bö’¸Äè=1ŠË«â‡·Å.î.ŒcœÝÓ¸º6¾qts¬ãæò¸ÇÉý1�‹+ä!·ÈFö-’“¬Û%3Ù¶N~²l£,e×R¹Êª½2–M«å-‹¶Ë^fm˜Eæ1s¶Ìf†mš3Œæ5O¶Ín¦mœ!ç9+¶ÎvÆmžŒç=¶Ï~æm 	èAëµÐ†n¢)¼èþ"ºÑp}4¤Ý*éI«µÒ–F+¦3MÖMsz¹Ÿq¨máëéQsµÔ¦þjªM¼êô¢ºÕÓ…µy_-ë§ÒºÖôÅµwo­k¤òº×Û¶v-ì²ÛºÄ>¶O“­lÿ6{ÇÏv.³£mÓiS›¦Ö¾6L³­m—r»Û÷‘Å=nr+ÙÜçFw“Õ½nvCÙÝ¶
;
__CPAN_FILE__ src/widget/templates/images/treenode_grid_c.gif
GIF89a€rrr!ù,Œ�©Ëí£œ”�‹oÝ¼û†L;
__CPAN_FILE__ src/widget/templates/images/tab_bot_left.gif
GIF89a	–Ä–Àÿ Æÿ¸Ôÿ­ÎÿÀÚÿÈÞÿçîød‘ÓŸ»ã€¥Úáê÷h”Ôf“Ó“½þ�¹ù¬Íþ£¾å¹Íëš»ë³Ðùûüþ¨Âæ†°ì‡®æx ØµÏ÷‰®å‰«Ýb�Ò”¾ÿÿÿÿ!ù,	–¥ 'Ždgž&‡¢êšº/ÜºóZ³pwŸ{Lç=p(#þŠÈ£Òfd&�KÜSå5©Ð,vk�v«>íWæ–Çf¡÷ÌVƒÝdx:H¿¢ïíúZŽççí{zoƒq…s€~Š‡}Œ�„‰Ž‹‘”‚•�–™˜›†—�šŸœi
0©ª¯°
¶·¼½ÄÇÇÇ	"!;
__CPAN_FILE__ src/widget/templates/images/tab_left.gif
GIF89a	,Õ;òõûúûþßéöåíøíòúöùýýþþèïù•¿ÿŸÆÿ­Îÿâë÷ÝçöØãô¸ÔÿÀÚÿÚåõÈÞÿÖâôd‘Ó�¦ÛŽ¯ßh”Ô¹Íëçîøf“Ó¨Âæ¦Àæûüþ½Ñì‹°æx Ø•´áŽ´ìáê÷¡¼äÔáó¸Òöž½ë·Óþ¡½äºÓùãë÷z¡Ù£¾åÎâÿÍáþÓàó’²àÆÖï×ãô”¾þ§ÁæŒ°åÌÛð–¾ùb�Òÿÿÿ”¾ÿÿÿÿ!ù;,	,ÿÀ�p‡ÑP&¸áÅb*¹Z;N¥–ŠX#»‘çÁíŠ&'‡xÌ
)ÎhÅç–h»™bNGàtø<þ®Ïóû:}‚z„~€{ˆ�Š†‰ˆ�‹�Œ“’•€�˜”—šƒœ…ž‡–�¢Ÿ¤¡›¦Ž¨«£¬¥®§­²¯³±´·¶¹ªµ»¸½º‘°¿ÃÁ¼Å¾ÇÀ™©ÉÄËÂÍÑÏÆÓÈÕÊ ÎÙÒÛ×ÚÌÞÜàÝäãæÐáéåèëÔíÖïØçÔ8õöõCDFHJ(/HD©#†„ƒvlÑ ¡Cd@˜Hq
32XaC€Ç�2X@²äRªL‰ã€Ë—.q˜Is&8sâÄQ §Ï˜ž8*‡�£H�âÈÁ´)Ó¥N›B�šcjT«N±J¥ú”kU¯Z»r
ûu,Ø³fÓR%ËíZ·Wáf•»Um\»sñÖ}«W,ß¿wç¼7°áÁ‡#^¬¸±ßÄ�Gv\–ðäË•!g–¼™rÛ¾�1¶ºôhÍ§9§öLWtkÓ¯W»-6íØ¸oë&]»wnÞ¿QWý:;
__CPAN_FILE__ src/widget/templates/images/bdYearBg.1.gif

__CPAN_FILE__ src/widget/templates/images/treenode_grid_x.gif
GIF89a€rrr!ù,Œ�©Ëí£œt‚‹3¨¼û†`;
__CPAN_FILE__ src/widget/templates/images/dpBg.gif
GIF89akæw“¾y–Ây–Á{™Åz˜Ä€ŸÍu‘¼€žÌ†¦Ö‡§×ƒ¢Ñ~œÉ|šÇv“½v’½‚¡Ð…¥Õ„£Ò{™ÆŒ®à~�ÊžÌ†§Ö�±ä�Ë�ŸÍƒ£Òy—Â|™Æ“¶ê{˜Åw”¾“¶ëŠ«Ü‚¡Ïx”Àˆ©Ú�³æ’µéx•Á‰ªÚˆ¨Ù�±ã…¥ÔŽ°â…¤Ôv’¼�Ê‡¨Ø}›Ç‹­Þ�¯á�²å†¦Õu’¼Œ­ß{˜Ä’µèƒ£Ñ|šÆ‚¢Ð�¯â‘³ç‹¬Ý�¡Ï‘´ç”·ë~œÊžËŠªÛ}œÉv“¾w”¿„¤Óx•Àz—Ã� Î}›È!ù,kg€B &9A>%4*,=372?!E($)0		5+-I¤:

<"@L°D/CFMÀ1;8KÎ'JÖ#HÙG

.6�;
__CPAN_FILE__ src/widget/templates/images/dpHorizLine.gif
GIF89a€®Éñ„¤Ó!ù,
;
__CPAN_FILE__ src/widget/templates/images/dpVertLine.gif
GIF89a€y—Á°Çç!ù,D\;
__CPAN_FILE__ src/widget/templates/images/slider-bg.gif
GIF89a,æ\>Mc€“¯�ž·dx•q…£ds‹euŒ[n�`pˆy�ªYlŠBQis†¥HXrz�©� ¸q„¢€’®ižh}œ†˜³�¡¹]o‰k}˜EVoDTlr†¤J[v@PfWj„l�¡‰š±Xkˆ^n†}�¬Tfƒvˆ£\p�f{™Vj†v†žCSjn�žv‰¨fuŒ‚”°ŽŸ¸ŽŸ·_rŽ„–°FVoat‘Wg�k}šZm‹ey—hx’br‰oƒ et‹x‹§Zk„Pa|GXplœ?Nd?Ne„–±ƒ•°>Lbbv“x‹©fx“†—²Ug„‰›µ~‘­_s�=Lbtˆ§cw•Wj‡‹�¶Vi…j|˜�Ÿ·�“¯r…¤dx–?MdcsŠXk‰!ù\,,ÿ€\‚ƒ„…†‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉ‡,;ZÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæá9!=4’(./Uö÷øùúûüýþÿ
H° Áƒ*( ¡”%1HXˆ„ƒB’!DZXÙÈ±£Ç� CŠI²¤É“(Sª\É²¥Ë—(ÈŒÀD„@B’àÈŠ'4\J´¨Ñ£H“*]Ê´©Ó§P£J�JµªÕ«P	€ C�Td@:áAÂ7°¨]Ë¶­Û·p‘ãÊ�K·®Ý»xóêÝË·¯_¼@12£	Œ) mq Ä
¶HžL¹²åË˜3kÞÌ¹³çÏ C‹Mº´éÐ ¢LQâã‡$p$‹íÛ¸sëÞÍ»·ïßÀƒN¼¸ñãÈ“+' ¹“"”IŸN½ºõëØ³kßÎ½»÷ïàÃ‹O¾¼ùóèÓ«_Ï¾½{\�;
__CPAN_FILE__ src/widget/templates/images/soriaButton-l.gif
GIF89a6w÷…¨Ýƒ§ÛxœÒÃÚûµÌî³Êí­ÃæªÂåªÁå™ºí–¸ë“¶é¨Êý£ÆùžÁõœ¿ó§Éü�Àôr˜Ð©Ìþp–Îq—Ïo”Ío•Í¥Èû�³è‘µê�´é¢Åø¦ÉüŸÂöv›Ó›¾ò}¢Ù§Êýp•Îr—Ïq–Î¨Ëþn”Í”¸í Ã÷Š®ä‹¯å˜»ðŽ²çš½ñt™Ñ|¡Ø–ºî¥Çú”·ì˜¼ð™¼ñ—ºï¤Æú¡Äø£Åù�±ç¤Û•¸í•¹í“·ì’¶ë“¶ë{ ×wœÔ¡Ä÷–¹îzŸÖušÒ¦Èû~£Ú—»ï¤ÇúŒ°æŸÂõ Ãö�¦Ý„¨ßÍàþ®Ãä…©àŽ²èq–Ïˆ­ã€¥Ü‡¬â¡Ã÷�°æš¾ò›¿ó™½ñ¨Ëýs˜Ñw�Ô†ªá‚§ÞxžÕx�Ô…©ß�²èŠ¯äŽ±çx�Õ‰­ã€¤Û‡«âœ¿ô�¥Ü™¼ð†«á�³é¢Åù�±æ¦Èü…ªàš½òs™Ñs˜ÐzŸ×¥Çû’µê‚§Ýˆ¬â‘´êtšÒƒ§Þ¢ÄøyžÖ­Íþ·ÎðÁ×ø¾ÕõÇÜý«Ëü¡ÂóÁ×÷¯Æè¹Ïñ¶ÍïÈÝý»ÑòÅÛüÈÝþªËü¢Ãô¬Ìý¨Àã”·é®ÎÿÄÚû°ÇéÂÙú£Äõ¿Öö§Éù©Êû’´ç²Éê¦Èø®ÄçÀÖö•¸êÆÛü¼Òô§¿âÉÝþÃÙúÂØù£×·Îï™»îÇÝý Áò‹­áŒ®âž¿ñx›Ò�°ã¿Õõœ½ðŽ±äÇÛý«Âæ¼Ñó§¿ã†©ÞªËû{žÓw›Ñ‘³æ�¤Øˆ«à‚¥Ù²ÊëŸÁò­Îþ½Ôô¿Õö¥Æ÷¨¿ãºÏò¤Åõ¤Åö°Èé±Èê©Áä¨ÉúµËî˜¹ì¥Çø—¹ìš»î’µè�¿ñ»Ñó} Õ~¢Ö›½ïz�Ó½Óô§ÈùºÐò»Ðò¬Íý¤Æö¤Æ÷|ŸÔ¥Ç÷¾ÔõÇÛüÄÚüÅÚü¼Óô¸Îñ¸Ïñ¨Êú©Êúœ¾ð�¾ñš¼î›¼ï§¾â«Ìý®ÅèžÀòŸÀòvšÐv›Ð�²åÂÙù´Ëíp‹³©ËþªÌÿ!ù,6wÿû	H° Áƒ*üÇ°¡Ã‡#Jœ(±Å‹3F´¨±£Ç�C†ì7¡¤É“(Sª\Ére?0cÊœI³¦Í›6_âÜÉ³'M�>ƒ
ýi¢¨Ñ£H“*]Êti?P£F=¥ªÕ«X³jÝªõ©T©§,‰Û°Ÿˆ³hÑBKv¬Ù´i!kI·.Ë~òêÕÛHÐÐ¿5ñîÝÛ°á˜ý:(^¼¸•ßÃ†ûÍ™L™²¡p]2kÞÌ¹³çÏ�ûMš´¡I_S«^ÍZu?°cÇ>Ýº¶mÖýòèÞ½û=¸Àƒ¼ŸŒãÈ‘Ÿ;4¸¹óçÐ�÷SB½zuRÌ£kßþ¼ß�ïàÁ“ÿŠÄ¸¼ùóèÓ/î× ½{÷�È«ŸO=û÷ïñ*Í¿¿ÿÿ’ÖOX`:�È¦à‚6è`lýÄ!á„¢“àƒfØ`?tè¡‡—¸“Üˆ$–hâ‰ÈõÈŠ,²xI;ÖÅ(ãŒ4ÖX]?8ä¨£Ž@Þ�@)ä�àõ3Ä‘H"9'ø5éä“P:ÙO
TVY%*LF©å–OöÓÄ—`‚‰Š7–iæ™h¦Y`?´é¦›™€òáœtÖiç�²ùæ›qâéçŸwöÃÄ „ºÏ4;&ªè¢Œ6ªc?D*©¤©”“ä¥˜fªé¦HB:é¤© ƒÅ¨¤–jê©¨¦zj?´êª«„Œÿcå¬´Öjë­U²úê«„ˆæ¯À+ì°`öÃÆ±È"K3{6ëì³Ð:ÛÏÔV[m"Ëªí¶Üvë-¡ÓZkm"š|jî¹è¦{n? ´ë®»¢”«î¼ô¢Ëî»ïŠ"É®üöëï¿ýöSÇÀ¼É¾'¬°¿ý¸àðÃo‚ˆ¸WlñÅ÷SÃÆs|ÌÄ‡,²Åý¸aòÉ'Ó‚È,·ìòË0Ç,3ÌýÐ`óÍ7â
¾<÷ìóÏ=÷ÃÂÐD]1Z$­ôÒL7íôÓM÷“ÄÔTS]È=g­õÖ\wýp?6„-¶ØæØÃÅÙh§­öÚl·½v?1Ä-·ÜÆÄÒñÝxç­÷Þ÷ÿCÄß€ÞÍ58nøáˆ'~s?=4î¸ãêÀSôä”WnùåD÷ÃÃæœs^Ê;U‡.úè¤—Nu?(¤®ºê¥Ô2öë°Ç.ûìb÷3Ãí¸ãžË6s÷îûïÀ/w?>o¼ñØÈøòÌ7ïüó€÷ÄôÔSïH<�g¯ýöÜwïx??„/¾øŽTÓùùè§¯þúœ÷£ÇûðÃ+«×oÿýøç¯z?ôï¿ÿßH@îHÀð€¸ëGÈ@*#Ç‹ 'HÁ
¯È 5¸iTïƒ ¡GH½~Àá„(Dá"¨1¾ºð…0Œ¡øú‘�ÚÐ†ì ÆÿvÈÃúð‡þëGÿ†HD"®C@L¢Ø�8ñ‰OÄ(6HÅ*ZñŠXÔ`?ÎÀÅ.vQŠY£±Ø˜ñŒgD%nÈÆ6ºñ�p´a?ä@Ç:ÖqkŒ£÷øÆ~,á�€$#0…Bò�ˆL¤"™È~¬à‘�„ä ¡HÉJZò’˜|b?ÌÀÉNv’Ö@£(GIÊRšòŒýP�*W¹Jx"°Œ¥,gIËZÚ’–ýHƒ.w¹Ëhx"�À¦0‡IL@öƒÈLf2ùñ‹H:ó™ÐŒ¦4!Ù�5Xóš×,€>XÉÍnzó›à\e?Þ@Îr–³¶¨‚:×ÉÎvºó�ðtg?è@ÏzÖs³¸‚>÷ÉÿÏ~úóŸõg?È@Ð‚ô°ƒBÊÐ†:ô¡uh?ž@ÑŠVô¯�‚F7ÊÑŽzô£ õh?þ@Ò’–Ô¯°¨JWÊÒ–º´¢ýØƒLg:Óf#8Í©NwÊÓžú”§ýp‚P‡:TL€�¨HMªR—ÊÔ¡ö£
P�jT1±+XõªXÍªV·ÊU­öC
`
kX€˜õ¬hM«Z×ÊVµö£­dE‚\çJ×ºÚõ®xµk?òZ�„à¯€
¬`KØÂ¶†
E`ÀØÆ:ö±��¬d!‹ØÂ†BAÈ¬f7ËÙÎzö³�íÇd
Œ"˜ö´¨M­jWËZÕö´P…fKÛÚÿÚö¶¸Íímû�‡ÞúÖ·¸ÐÆ†KÜâ÷¸ÈMîqûÑÚà
á¹Ð�®t§KÝêN·�È®vµ{€l|à»à
¯xÇKÞòŽ·hH¯zÕ‹rá½ð�¯|çKßúÎ·cÈ¯~õ‹€^¼à¿°€Là¸Ö}7¼Àà;øÁŽ°„!ÜóR‚È°†7Ìá{øÃ®py)!€
˜øÄ(N±ŠWÌb÷Ã¾É�fLãÛøÆ8Îñ�ûá‡ûØÇºð†Lä"ùÈHNò‘ûa`SäãPŽ²”§Lå*[™Êý°ƒ–·¼eSàÃ`³˜ÇLæ2›™Ìý¸ƒš×¼æyDáyÍpŽ³œçLç:Ó¹ Î³ž÷¬ç~�àÏ€´ MèBºÐýh±¢ÍèE÷£�Ž´¤'MéJ[úÒ–î‡’7ÍéNsº#µ¨GMêR›úÔ¨>u?®ÌêV»ºÕý8³¬gMëY÷ã¸Îµ®wÍë^ûú×¾Vˆ°‡Ml„;
__CPAN_FILE__ src/widget/templates/images/soriaDisabled-r.gif
GIF89a3wÕÆÆÆ²²²ÂÂÂÉÉÉ±±±¯¯¯³³³ÙÙÙºººÐÐÐ¶¶¶¹¹¹»»»´´´¼¼¼···µµµÏÏÏ¸¸¸ÕÕÕ½½½ÒÒÒÖÖÖÔÔÔÓÓÓÑÑÑÃÃÃÊÊÊÇÇÇÁÁÁÄÄÄÈÈÈÅÅÅ°°°ËËËÀÀÀâââÎÎÎ¿¿¿¾¾¾ÍÍÍÌÌÌ!ù,3wÿ@’pH,�È¤rÉl:ŸÐ¨tJ­Z…¥¬vËíz¿à°xL.›Ïè´zÍngð¸|N¯Ûå–0jÏïûÿ€�|	y`‚‡ˆ‚„‰Œ�‡‹Ž‘’�’•‰”–™€˜š�{œžš	)¥¦§¡Ž£§¬)©�«­¦¯Œ±²®´ˆ¶²¹º¤·¸½�»­ÂŠ¿·ÆÃÈ¼ÊÄ¬Î"Ö×ØÒ~ÔØÝ"Ú}ÜÞ×à|âãßå(çãêëñòóÀõöÀ%ðóû÷ýþùûøùˆO_Àx¶*Qa€Ã‡J,Å¢Å%V¼ø0£Â�1z$ÈðƒÉ“(Ñ©\Éò[”0?´œIÅË˜'iê\igÎÿ�@»õôùá Ñ£HùeàÀ´©Ó¤P£ÊK±Ô©U©X‘Rµj5¤×¯`1VåÊ4¬Ù³"XË¶-Ñ·p‰¦mK@Ü»xçÖe‹·ï[½{�L¸ðUµ�^Ì˜éÄ�K.ü8±åË˜÷ˆ¢³çÏ™CcÞü¹´éÓ¨S«þÀYµë×°;³ŽM»ögÖrëÞÍ»·ïßÀwsˆ¼¸ñãº‡#_Î\8qà¢KŸN½ºõëÒ”ÀÎ½»wëÚ¿‹~;vèÓ«_Ï¾½ûô P¼ŸO¿~ûøó;èßÏ¿¿ÿÿî‡ß{h`€ºwà‚z�B�#D(á„Vhá…:!†vxÿ¡†z(âˆˆ0â‰(NX"‡&´èâ‹0Æ(ãŒ.j`"†4æ¨#�6²¸ã�?öˆ#�Dòxã…E&£�H*é¤	LZø¤“l0å•1
0À	\véå—`†)æ˜^jIæ™h¦ÙePàæ›pª)'™l:`ç�xÎ©'˜uâéçž€rÙjè¡�:è¡Œ2�èž€À¤”Vú¨ž‘Vª)—Î™é¦”v*g ,`ê©¨Šª&©¨¶º€ªiŽà�´Öj+¬hÊúÀ®¼öŠë™ºö*ì¯dŽ �È&«,±c«ì³
0+æ@`íµØJ&µØv�¶`ŽÐAä–k.¸_Šknîº
 ë¥¸Ä+ï¼îv	ï¼øÖËå½øÊkÛ¿¥uÐï¼lðÁ'¬ðÂ7ìðÃG,ñÄ`ñÅg¬ñÆwìñÇ ‡üq$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×s8ç¬óÎ<÷ìóÏ<;
__CPAN_FILE__ src/widget/templates/images/tab_left_r_curr.gif
GIF89a	–Õ#èïùúûþöùýâë÷íòúòõûýþþåíøßéöÚåõÝçöØãô¤¿åÖâô¨ÂæªÃç¢½åûüþÀÓîçîøãë÷“²à–µá¹ÍëÐÞòf“Óx ØŽ¯ßÜæö€¥ÚÇ×ïh”Ôd‘Ób�Òÿÿÿÿÿÿ!ù#,	–ÊÀ�hH
‹Ä#R¤D6‹ÏäÒ8eV£Ô)Öª½z»àåvü—�ghZF·Õo¶9ž�ÛÝwx^Žïëý|‚�„u€†ƒˆ…\{ŠŽŒ‡�‰’‹dt”�–�˜œš‘ž“ •k™¤�¦¢¥—©§«¨¯®±›¬´°³¶Ÿ¸¡ºI¾¿¾!ÃÄÃ!ÈÉÈ!ÍÎÍ!ÒÓÒ!×Ø×ÝÞãäéê 
ðñ#	ö÷#þ#^øABƒNpÐ!Dˆ ;
__CPAN_FILE__ src/widget/templates/images/treenode_expand_minus.gif
GIF89aæI�œÅ999üüüóôö��Åîðóéìðõö÷ïñôþþýúúúâæìÿÿþßäëÔÛåñòôûûûýþÿÒÙäùùùDDD�œÄ€œÅøùùÝâêÞãêòóõ÷øøÜáéÿÿÿþþþËÔàùùúêíñÚßèôõ÷äèí¿ÉÙÕÛå¾ÉÙëíñôõöÓÚäÌÔáÅÏÝðòôÍÕáìîòÖÜæíôþñóõþýýÊÓàüüûçêïºÆ×ùúúåèîãçííïòÛàèÄÍÜ}šÄåéîþþÿö÷øëîñ÷÷øæêïèëïÄÎÜìïòy–Á!ùI,€€I‚ƒ„…†‡ˆ‚H‹Œ�H‡H7%,.0
?(�'F+&9!)�=$¦†H4*:­C
±…H<Á
�"E;A8Ç²6G2 	¼„HD/5	�B-#3@1>�ŽŽ‰øùúûüýù�;
__CPAN_FILE__ src/widget/templates/images/no.svg
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
	<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg  version="1.1" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="15.433" height="15.433"
	 viewBox="0 0 15.433 15.433" overflow="visible" enable-background="new 0 0 15.433 15.433" xml:space="preserve">
<circle fill="none" stroke="#D02026" stroke-width="2" cx="7.716" cy="7.716" r="6.716"/>
<line fill="none" stroke="#D02026" stroke-width="2" x1="3.02" y1="12.352" x2="12.639" y2="2.732"/>
</svg>

__CPAN_FILE__ src/widget/templates/images/tab_top_right.gif
GIF89a�,Õ7b�Òåíøöùýèïùòõûýþþúûþíòúâë÷•¿ÿŸÆÿßéöÝçö­ÎÿØãô¸ÔÿÀÚÿÚåõÖâôÈÞÿÔáóÎâÿd‘Ó¨Âæh”Ô|¢Ù¹ÍëŽ¯ß�¦Ûûüþ£¾åçîø’²àãë÷k—ÕÓàóŽ´ìž½ëÊÚð¦ÀæŒ°å‹°æ½ÑìÆÖïÚæõ¸Òö•½ø“½ýÍáþ•´áºÓù¡½ä·Óþÿÿÿ”¾ÿÿÿÿ!ù7,�,ÿ@€pH,�È¤rÉl:ŸÐ¨tJ­Z¯Ø¬vë´p.Ÿ›øV)›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûã0-%c‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ –2(7¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁ¹)7ÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàØ4!
æçèéêëìíîïðñòóôõö÷øùúûüýþÿøHxP@° Áƒ*\È°¡Ã‡#JœH±¢Å‹3jÜÈ±£EˆI²¤É“(Sª\É²¥Ë—0cÊœI³¦Í›8sêÜIóÿ@ƒ
J´¨Ñ£H“*]Ê´©Ó§P£J�JµªÕ«X³N µ«×¯`ÃŠK¶¬Y²\Ïª]Ë¶­Û·pã&M+·®Ý»xóêUKw¯ß¿€¾Ûw°áÃˆ+fZx±ãÇ�#×m,¹²åË˜«RÎÌ¹³gÎ›?‹MzpèÒ¨S«v{zµë×°³¶ŽM»¶m¤³oëÞ;7ïßÀGûN¼xåáÆ“+?Œ|¹óçy›CŸN½­ôêØ³‡½®½»wÍßÃ‹ß>¾¼y«ÜÏ«Ÿ~½ûîíßË§¾ýåõïë'ž¿ÿÝýý' mhàj¨ i	.è`g
>(¡eNhác^¨!bnèÿa`~(¢^!Žhâd'¦èY‰*¶È—‹0JÆbŒ4~5c�8bucŽ<nÕã�~íä�J	Iä‘E‰ä’@)É$’N>Id”RIe•=^‰eŽZnYc—^Æf˜.ŽI¦ŠfžybšjŽÈf›¾	ç†rÎya�vNˆgžîÉç‚~þy` ‚Hh¡ÿŠè~Š.z_£ŽÎi¤ïMJéz–^z^¦š–Çi§â}
êw¢Ž
Ÿ©m–Š*vª®JŸ«d¶
ës²ÎŠŸ­[ÖŠ«qºîÊŸ¯Rö
ìoÂ ±K‹¬mÊ.K ³SB;d³ÒºFmµª]‹-jÚnË ·\‚‹c·â®X.�äž›ÿYºê^Æn»ÇÁÛâ»òBFo½ŽÝ‹¯búîË¡¿n,b¿FpÁ€Œp�k¨pÃÑAláÃÛEqÅr]Œ1\oÌšÇ€‚¬`Ç"¿X²¡'£œr¢+³Ü2£/Ãó£3Ó\³¤7ãœs¥;óÜ3¦?cÊÅÐDmôÑH'­ôÒL7íôÓPG-õÔTW
µ`Œq\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×�ö*Ì@Èôí÷ß€.øà„nøáˆ'®øâŒ7îøã�G.ùä”Wn9ã+€PÊ
tîùç ‡.úè¤—núé¨§®úê¬·îúë°Ç.ûì´×nÿ»ë1\pC¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWß¼ÀÀöÜwïý÷à‡/þøä—oþùè§¯þúì·ïþûðÇ/ÿüô·Âä¯ÿþü÷ïÿÿ HÀð€L ÈÀ:ð�Œ h‚ à‚Ì 7ÈÁzðƒ ¡GHÂšð„(L¡
WÈÂºð…0L!D€Úð†8Ì¡wÈÃúð‡@¢‡HÄ"ñˆHL¢—ÈÄ&:‰€§HÅ*ZñŠXÌ¢·ÈÅ.zñ‹`£ÇHÆ2šñŒhL£×XFà�pŒ£çHÇ:ÚÿñŽxÌ£÷ÈÇ>úñ�€¤ IÈBò�ˆ$ÀÈF:ò‘�Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“ ¥(GIÊR~H¥*WÉÊVºò•°Œ¥,gIËZÚò–¸Ì¥.wÉË^úò—À¦0y	ó˜ÈL¦2—ÉÌf:ó™ÐŒ¦4§IÍjZóšØÌ¦6·ÉÍnzó›Ù@ÆIÎršóœèL§:×ÉÎvºó�ðŒ§<çIÏzÚóžøÌ§>÷ÉO{ 
¨@JÐ‚ô M¨BÊÐ†:ô¡�¨D'JÑŠZô¢ÍèDÿ©ÑŽzô£ 
©HGJÒ’št¤=©JWÊÒ–ºô¥ÿ0�)BS*ÓšÚô¦8Í©NOJÓ�úô§@
ªPmÚÓ¡õ¨HMªRZÔ¥:õ©P�ªL›*ÕªZõªX¥(U³ÊÕ®z5«[ýªXÇJV¡†µ¬hM«Z[zÖµºõ­pÅh[ãJ×ºÚõ s½«^÷
×¼òõ¯€«_KØÂJu°†M¬b�ŠØÅ:ö±8m,d'KY–J¶²˜Í,H/«ÙÎzV«Ÿ
­hCÊÙÑšö´--jWZÕ²öµ™u-lgYÙÒö¶‰µ-nwXÝòö·wõ-p‡ÛWâ³Â=®rÇšÜå:—«Í}®t«ÝéZ×©Õ½®v�šÝíz¨Ýý®xsÞñšwªçMÿ¯WË«ÞöòÔ½ð=l|ç‹]úÚ©ì½¯~A»ßþî4¿þ
0SL`ôøÀlE°‚U
à¸Á&0„#à	S¸¿¾°~3¬aûr¸Ãóý0ˆá+â··Ä&N/ŠSlÞ³X¼.~±wc,cíÒ¸ÆÖ½1Ž¥«ã;·Ç>V.�ƒlÜ!y¸F>òo“¬äÝ2¹É·}2”g+å)¿¶ÊV^-–³|Ú-sy´^þrkÅ<â0“¹³f>slÕ¬á4³™²n~småá8Óy±v¾snõ¬à<ó™°~þso]à@z¯†>tp]aFû7ÑŽŽ+¤#ýÖISz­–¾tZ3­é²rºÓÌuˆoEßO“º«¦>5XU}bV«7Õ®¦n¬ÏëYCµÖ¶®o®¿‹ë]'µ×¾æn°·ìa›ÕØ×-6²ªìeÿ×Ù<†ös›-í›R»Ú5½6¶cªím¿´ÛÞNp¸‘<nr—{ÉçFwº�¼nv·;ÊïŽr;
__CPAN_FILE__ src/widget/templates/images/dpYearBg.png
‰PNG


IHDRÈ¢eÌŸtEXtSoftwareAdobe ImageReadyqÉe<0IDATHKc,�¸›GY£¬QÖ(k”5Êy¬kÂ.’Y;a¬~«˜kmXië_6Oh„IEND®B`‚
__CPAN_FILE__ src/widget/templates/images/soriaDisabled-c.gif
GIF89a3wÄÊÊÊ±±±ÉÉÉÆÆÆÂÂÂÙÙÙ¯¯¯ÇÇÇÄÄÄÁÁÁÈÈÈ²²²ÃÃÃËËËÅÅÅÀÀÀ°°°ÎÎÎâââ¿¿¿¾¾¾ÍÍÍÌÌÌ!ù,3wÿ $Ždižhª®lë¾p,Ïtm‹Q®ï|ïÿÀ pH,�È¤rÉlæ
Ð¨tJ­Z¯ÔŠvËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€�‚ƒ„…†‡…Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤Š
§¨©ª«¬­®¯°±²³´µ¶·¸³»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊÌÍÎÏÐÑÒÓÔÕÖ×Õ
ÚÛÜÝÞßàáâãäåæçèéëìíîïðñòóôõö÷øùúüýþÿ
H° Áƒ(\È°¡Ã‡#JœH±¢Å‹3"ØÈ±£Ç� CŠI²¤É“(SîªdÀ²¥Ë—0cÊœI³¦Í›8sêÜI §ÏŸ@ƒ
J´¨Ñ£H�&XÊ´©Ó§P£J�JµªÕ«X³j}Àµ«×¯`ÃŠK¶¬Ù³hÓª]Ë¶-Ú	pãÊ�K·®Ý»xóêÝË·¯ß¿€L¸°áÃˆ+†K¡±ãÇ�#KžL¹²åË˜3kÞÌ¹³çÏ C‹Mº´éÓ¨S«^Íºµë×°cËžM»¶íÛ¸sëÆ�±7ÆÀƒN¼¸ñãÈ“+_Î¼¹óç¢KŸN½ºõëØ³kßÎ];„ïàÃ‹O¾¼ùóèÓ«_Ï¾½û÷ð×˜O¿¾ýûøóë¿;
__CPAN_FILE__ src/widget/templates/images/dropdownButtonsArrow.gif
GIF89a€/?Zÿÿÿ!ù,„[;
__CPAN_FILE__ src/widget/templates/images/dpMonthBg.png
‰PNG


IHDRÈ@¹×ætEXtSoftwareAdobe ImageReadyqÉe<KIDATHÇíÔ+ ÐBvÿpn…+ŠdG:÷Òì£ÖÆ\8Õ‘*HŠ`sdOšT‰¾ .%q›”Ñ†aAÿQÃ0ŒlÿÅé¨A“žIEND®B`‚
__CPAN_FILE__ src/widget/templates/images/tab_close.gif
GIF89aÕá^^çccÚXXýóóÔTTÃEEê……åbbäaaÞ\\â__üóóûííúììÌVVüððà}}ÎXXáýôôÞ[[ÔSSÜddñkkàhhãkkÐPPÍNNÏOOÝ{{Ü{{ÎNNÑQQß\\ÇHHÈJJëppîiiËKKêeeíhhìggÅGGÙXXýððÆHHìrrèddïjjÄFF×__çƒƒëggè‚‚ÌMMÀÿÿÿ!ù,U@œpHÞŽÈ¤ðv�¡N t[–R®h&!¨ân4ËP{XÞÛë`L$Nú ˜
��)
À0 
"i2 -1i+6#*iI˜EšBA;
__CPAN_FILE__ src/widget/templates/images/slider-bg-vert.gif
GIF89a,÷ÿQb|„–±|Ž«wŠ©Oa|’®„–²xŠ¦’¢ºt‡¤xŒª^t–wˆ¢Vj‰l€žby˜N`{XmŒr… dx—|�­m~—n‚ g}žm‚¢ew’L]xVg€^t“k|–Yj‚z�ªŠ›µd{œr†¥zŒ§h}œf|��”¯av”yŠ¤r‡¦I[uq„¢j~�x‰£j|•l€¡x‹©vˆ¥l€œdzš[p‘l}–j~›pƒŸi~ by›|�¦ˆ™³gz˜{Œ¥Sd~i|šZj‚‰š´n~—}Ž¦zŽ¬br‰z‹¤u†¡f{šzŽ«kžw‰¥j dv‘r‚›|�¬� ¹|Ž©]p�Te~Ui‡bw•r…¢M_zwŒ©uˆ¤‹œ¶l�¡e|œh|™v‡¢c{�Žž·\m†~�¨t†£Zp�as�fx“bu�Wh€bt�hz”Wh�Rc}Uf`r�gy“€’¬h~Ÿi{•`s�cz›‚”°ƒ•°_u–‘«€“¯Pa|\r’‘­Xi‚`w—i ]s“nƒ£Vfo‚žuŠ¨{�¨ƒ•±o„¤cw–h{™Wi�iz”oƒ£s†£q…¤tˆ§�“°‡˜³n��n‚¢k€¡…—²y‹§Xi�bt�j{•s…¡v‡¡cu��“¯~�¬k�¡^s“q†¥ax˜uˆ§n—yŒ©dz™aw—cv‘pƒ¡q„Ÿbs�lœcu‘`u”�“¬h~ž~�«g|›p„¤p…¤t‰§j€¡k€ cy™q…¥g~žt‰¨i~�iz•}�ª�“­`v–~�ª€’®†˜²‡˜²~�­~‘®„•±o€™fy“‚”±‚•°~‘«wŠ¦ey—�’¬o„£€“®]r“‡™´t‡¦†˜³‡™³GXq‚“­m�Ÿn� fy˜s‡¦?Oedw–Sc~EUm@Of_u“arŒ€‘«Œ›´u…�v‰§i}šy�«ax—ƒ”±RfƒSg…}‘­�ž¸[q’u‰§[k„gy”hŸr…¥k€žnƒ¢\r“\s“�­p…¥fw“uˆ¦`p‰!ùÿ,,ÿÿ	H° Áƒ*\È°¡Ã‡#JtXÄ_˜5ÿiQn2I!@D˜‰æ¼ÓiÜD'P´L«ãï%˜ È�”ˆL¦	1òBj©†M�� ªýrT")•–6�ø4*S¤•^]u
UëTˆU½b+QÎg:¾>4­Z‡pÂÑáabÜsëJ¼›×®\º~ñÞûWoD¾ƒÜ—°`ÃC~Xa‡<=&ÃµŒYsÃÊ—3Ûå,z/iÏAwõBÕ¥Ÿ¶km³Ø‘kßv­°B¤:±ŒðNè¸p»¿ƒGX\¹]bu‚ß]úòƒªO?<Ì„u»Ý¿ïÿ
¿b�J�|¡è3ñ|úõíÑ«g/ÑýüøïéG<Ÿç~ýJýÁ÷_4ê]�(XŸÂDÑ‚‚û1è „æIø`{à "jØ‡zb„"v¸¡‰NÔÁ1|ÂF­Øâ‹*2#Œu`£‹8B¤ã�5ãŽ4)dŽëè3‚=>Ô�2Å,Ù¤COFÉ¤Šux2Â&h`©%—^nÙeŒYŠ&˜¹É–1fDj²éæDq¶ù&DuÎ™æšvÒÉ§žpæ!ç�¹ hŸe’‡h²ÁDŠ2ê(¤‹6úh¢•NŠ©¤—F$Ç¢Íhê)¨¢B$G,QêC§¦ºªC­ªÿÚ©©¨Ê:Q¬ÌÊj­¹ÞÊ«®°þ:Q/Æ”ƒ*‚[ì±ÉJÔ‹;¥d�ìD‹@+m³Uí´i{-µÖr›-0$p¶-B®¹è>¤Æº7´1Ñ»åÆ;/¼òJD¯¹ùF´¯½ú>1Àƒô‘7Rð¼	/ð
ìnÃ;„0ÄûKñDóqŽ’L1ÑI|òÈ%ƒ,²D$›¼rD-«Œ²Ë(Ç#3ËéŒ²‚/CôFÎ;÷üÐÏ:ó<2ÐFãÜÏ
2íP2é<Â´Ó
A-uÓ™¡5©°âCÖ[wýµDZsí5Øf�‘Xp#vÖm¿MvÛ7œ=77u«
‘0ˆÿ`�
z?Ä·ß€g=á�;dÆá'ÞÐâˆ9ÙŒ.?Ô£
:ßL”!Ždƒžƒ.:é}úè¥¯ŽzDªŸÞºì©ï2‹?¼Q¶ã®ûC¼ßž»çµÿ»Cï;ñÆ�=]ßP�0¢D"Ò3D½õØ{^ýõÙ/´=øÞs¾BãwŸú#÷�/QÜLÂL¿üôÛÿüõ¿¿þþÃ_ÿ"Ò„`€$ 8@ˆð€	t ¶@‚m4ð!M˜`/è�RÐ‚AE((è6D„$4!CPH‚†p„-TáBZ‘‹Èbz˜
mˆCÖð†9”H+ÿöA	 N„´¸…%‚D%ö�‰I\bDš(EˆpbL@‚7‚‘3"‹ˆ‰D¼F1vñ‹HãDÈ˜F3B„�j#ãØEh”q��øªàÆ‡œ!�{ì£Cþ¨G>â±�‚l!yHFŽ�†|$=fÉˆ¤q˜Á	É�Kfr“¹$,LJ‰ˆ’”œ\È)KiIŒ’•¹¤.PJÌ–‘%-M¹…àÂ©THzùË`&d˜¾f(‰©L‰`‚™ÆD&>q�ˆ#š™f5¯9mZ›ñ&7%²
J”@€ÀDÊyÎt®ÓœèT'9áéN‰”Á\ˆçDî™ÿÏzF„Ÿú´'>úO|ªÃŸ)Bp
PÈóŸmèCQ‡î³¢}Hþ?"£ÙhG?ºOŽz¤
éIK:R”2D¥$µ§IcúOÐÒpéBÊ`SœêT!sˆÃMññÓ„õ¦{(*BŽ
Œ¤N„©N•T•z�©>U¨M¥ªA¬*U¬F5"\�ˆ.�ƒ;Àã
kYÏšV²š­Që[ÛºV¸ŠÕ­l�+^í
¹æõ®u¥ë\õXÂ.€˜ˆ¾à‡| v"ÈÁa# ‚‰4à4ˆ*+vÀ#
hÇ5&¢‚4€
GFÀ¡t##°�­lgKÛÚÚö¶	;
__CPAN_FILE__ src/widget/templates/images/slider-button-vert.png
‰PNG


IHDR#»8—’gAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<¦IDATxÚÌ—mL[UÇÿ·/·¥/À/ƒò¢„&` ,Aç²ŒÄÄ˜8Ý�_Œ0QÌ>¸iÜD™„Ä£fÎL’Eq87æ·) Â
[GK¡£”²Û–ÒÛÞOá’�J»aä$ÿœ4÷œ{~÷žç<§”(ŠXjEáÿl2l ¶¡`±<ÐòS†BI7Q êÈ~¦Š¢0,ð¼•çÂ—§'ouòÃú;dÿ 0T,1ófëÏ&¹\q1=+7wgy†œ"Âì<Ø†a0ít„9.ô33õÁ‰Ã/þ)A‰ëÓxü’¢hÉ0æg>ùh&þ±yÉ@Ù¢D�ˆ‡H)áõÏÁ99�»WÛ”}ôí¯[nÆµfÌ�í8˜šž•¹s{aPœ“^®/Ó,öŠ$ˆ2%uZšBaqÙ¾lSiOÃûí�dº*ž¸ŒêqÅ@:Ç¾§jh‹Ã‡b£;VÿPŠ!Ã€ÀaÊí�Ãf½æ¸uã•Ó­¯ÅâRTjAà_JIM§ÇçQœ­E¯�‡y«</¬(Ž§À
48ÐH3lÆ#Åæê¼¢Š+/üòYò:z�÷~aHæ<­Ñ%¡Ì¨DÏX¥Y2ôÞfÉÂ|T…T€£¡Rka6—$šJ*¿Ùô»wÉ+¢­†¢Êi•ƒö¶e+Ñm
0Åš0K
„)p¢¹Æ—xã£5u/¤‘WËãŠ/dÅånCõÃ*\aQ™¯^Šû0#Ÿ¬Vˆ‘ãÀ2<4jéûmï÷ŸŽÄ·<ŽVuæHýã$g… Çs°Ï£<W…k#s=Çñq)âÁ†è´jdfåšòKªZÉú{Zõ^têˆqfc~í÷¡º@‹«Ã¾¸�Ñ'È QÉ0>é†cl¤ïìï’âgNr'†Ôþ¸Ë¿ÅX Ýš¢BÖf¿�š"ýBÛöPHÔÈ!—‰p8]¿9ÐqêØþ&?ãv‘ÇÓD¾å0Š5R»/ì(4'¡s`U&ºúgbIÔ*aHRa†ñÃ>fål–¿ZÈyÓFy$ù—ƒ¬	±ç‚ßŽ®�Ô–$áìÕ;x¢4…yV�£Q+°I¯†Š–Ã:>�kÂÝÝyæ­ÎöO#5+ò%³Dó+Õ¨0nçØI•Zs¨¬Â¨ì ®Ò@€&W«$)³e“ÉdjÆ›}ŒÛ~ùÇSMGn
^·K 1ý~
¥üµæsÍ	‰i
{ªó01+ × Àù?œ²qA	Z)Gj²†Ô&5¦gp¹¦2s ùÌ'�€GŠ�p´’°fÕÞý|ƒ¡¢ö™~Ðúô=U9r¡ÓÐPÓ
‚a„Hêz˜yx½DÖ'x¦N;n³ô:¥-a¤máÖã>#®þèö¼¢Ê”±«2{¦ÈDž”2‘%Ì³^�ëÒõ_Ú>ëéúv”ÌñJ~É
aÝ.W‘�Øµ÷Õóc»ßSkôµ2¹"9XÙ`À~×=ÑÝÕ~â¼ÃzcFZÜ'õl¼7¿Xa"”D:¢äHÒH§wd±�´
K
ýg7½{€dÒU@)ý¤…9I QéÓ¿ÄËw÷³å–ÙIEND®B`‚
__CPAN_FILE__ src/widget/templates/images/soriaButton-r.gif
GIF89a6w÷¤¼ã¯Îü¼Ôø•¶æŠ©Öœ¼ì¶Ïó´Ìñšºê©Áæ»Óö„£Ñr’ÂÀ×û¹Ðô©È÷…¦Ø¬Ëù ºázšÉªÂè� Î˜¸è­Ìú¦Æõ­Æë§Àåž¿î¥¿ä±Ðþ²Êï‹ª×}œË€ŸÍ‘±ãŠ«Ý†¨Ù«Êø¡Ó�Ì‚¤Ö€¢Ôx˜ÇÂÙüÁØüv–Å³Êð¯Èì¬Äé£Âò�¯àt”Ãu”Äp‹³�ÀôžÁõ§Éü£Æùœ¿ó¨Êýo”Íp–Îr˜Ðq—Ï©Ìþo•Í�³è¢Åø¥Èû‘µê¦Éü�´éŸÂö}¢Ù›¾òv›Ó§Êýn”Ír—Ïq–Î¨Ëþp•Î¡Äø“¶ë�¦ÝŒ°æ—»ï ÃöŸÂõŠ®ä‹¯å{ ×¤Û�±ç’¶ë”·ìušÒwœÔ“·ìt™Ñ˜»ðzŸÖ•¸í˜¼ð¡Ä÷—ºï¤Æú¥Çú¤Çú”¸í•¹í Ã÷¦Èû£ÅùŽ²ç„¨ßš½ñ|¡Ø~£Ú™¼ñ–ºî–¹îÍàþ®Ãäw�Ô…©àˆ­ã‡¬â™½ñ�°æš¾ò›¿ó¨Ëýs˜ÑŽ²è†ªá‚§Þ€¥Üq–ÏxžÕ¡Ã÷�³éˆ¬â¥Çû…©ß’µêœ¿ô†«á¢Äø¢Åùs™Ñ…ªà�¥Üs˜Ð�²è‡«â‚§Ý‰­ã€¤Ûx�ÕŽ±çƒ§Þ‘´êŠ¯ätšÒzŸ×yžÖ™¼ðx�Ôš½ò�±æ¦Èüƒ¢Ð~�Ë‰¨Õˆ§Ôp�À¥Åô‚¡ÏÂÚýÃÛþ¢»áµÎñ¤Äó°Ïýs“Ã Àïq‘Á|›Ê¼Ô÷ªÉ÷ÄÛþx—ÆÁØûŠ¨ÕÃÛý²Ñÿ…¤Ò‡¦Ó¡Áðˆ¦Ó‡¥Ó¾Öù¿Öù†¤Ò†¥Óˆ¦Ô®Íû¢Âñ¿×ú¤ÃòŒ­ßw—Æ ¹ßŸÀîp�¿p�¿£¼â~ŸÒ´ËðŽ°á¸Ðó’²ä“´å§Çöo�¿…£Ñ—·èµÎòr’Áq’Á·Ïó¿×ù¹ÑõºÑö™¹é‰§Õ�½í®ÇëˆªÛ‹¬Þ¯Çì¢Áñ‚¢Ï°Ðýv•Ä°Éí±Éîy™Èz™È¾Öø†¥Ò‰§ÔÂÛý©ËþªÌÿ!ù,6wÿkH° Áƒ&üÇ°¡Ã‡#Jœ(ñÅ‹3F´¨±£Ç�C†ü¤¤É“(Sª\Érå0cÊœI³¦Í›6	àÜÉ³gM�>ƒ
ý	¥¨Ñ£H“*]Êt)=P£J�JµªÕª¿vhÝº•€È¯
‰eåÊÕ+Ø¯Äh1YË–-�–pã²LÛ¶.Ð¡xgv†£¯_¿Âò
Ž¹÷¯áÀƒwèg¤±cÇ®IžL¹²åË˜-Ó›µª³gÏ®ÈŠMºôh\³à¨^½:´é×°I£&B»vmWusëÞÍ[7®�‚ÎÎ°ñãÈ“°b�óçÏù)ŸN=9s6Ø³gõ¸»÷ïàÃ;ÿÀB�ùóç¹‹_Ï|€`9âË—ÿŠµýûøóë_ýþüù¯Ø&à€h`mÏ4Ç‚2èÌ�Fh`‚•Th¡…Î@§á†vèás40Äˆ$’ˆŒv(¦¨âŠ,f"%0Æ#2èÕhã�8æx^ÑHáã�?óß�Di$‘ ƒÆ’L2)ä‘PFYdË¼aå•W&Óà–\véå—–°Ìd–Yf2%¦©æšl¶Ib	Ê !çœs6ãæ�x¶	'�|6äŸ€*è ?– ˆ&šè>M6êè£�FÊ¤/Ü`é¥—2ÃÈ¦œvêé§ †ú)¥˜–Ê–¨¦ªêª¬^ù€6Äÿ*«¬Å˜ië­¸æªk™¯Îêk1|+ì°Ä
ûª$È&›¬8Š6ëì³ÐF›è½è`íµ×ŠSê¶Üvë-·àT‹-¶Ú~kî¹Ý‚£€ì¶Ûî¾Æ+ï¼ôÊ‹Áºîºo½üö;/ê¤"ðÀ/0îÁ'¬0Â±¨CÇÃClðÂWœpÃwd¬±Æ¬âñÇ ‡,òÈ$‹Üð)(§œ2+ù¶ìòË0»|K:gÔl³Í¬¢óÎ<÷ìóÏ@û<3D]4+'­ôÒL7
±4éX!õÔSÏÈÕXg­õÖ\w½µ4¤!öØcË²ñÙh§­öÚÇÐ
pÇ·,7×m÷Ýxçm34çäÿá÷ßËbôà„nøáEËsŽŒ7Þ¸,TG.ùä”W>õ1ç˜¡ùæ›W@öç ‡.úècc@¨§žzr·îúë°Ç·.ä|aûí·Wøî¼÷îûïÓ.ÆðÄ_�ãÈ'¯üòÌ7n�-SD/½ô!pnýõØg¯ýæØâÅ÷àƒ‚êä—oþùè§Þ}$ì·ß~¸Ç/ÿüô×û¡ÿþû‡Püÿ H¼v@L`C0½:ð�Œ ôx„
ZÐ‚'Ÿ7ÈÁz|íØF#FHBž€(L¡
WÈÂý`Bˆ¡exÂÚð†+,€4ÁÃöð¢ÿ‡HÄ"Z°�ƒ—¸ÄVñ‰P,"AAÅ*V±3Ì¢·ÈÅ.Êè‚Ç8F,zñŒhä"UÁÆ6¶±†ˆ£çHÇ:ÚñŽu\Ç=ªÀÇ>öL¤ IÈB.qöÐ‚"¹H�ñ‘�Œ¤$'9FDŽâ’˜Ä$ÁÉNzò“ ¥(Ai�dá”¨D%/üÈÊVºò•°ìã8âÑ‰ZÚÒ–¼`¤.wÉË^úr‘ãp‡#†ILbò"•ÈL¦2—ÉLT ›ˆ¦4¥9?XóšØÌ¦6·ÉMm>sàg8'ð‡ršóœèL§:×™ÎodàðŒg<'pˆzÚóžøÌ§>÷™ÿOoÀ
h@óÑ‡‚ô M¨BšPÀ`�hDñ!ÑŠZô¢ÍhDŠŽzÔ£*@„HGJÒ’šô¤(5)7(À‰–ºÔ¥* ‚LgJÓšÚô¦8µ©(�S$â§@
ªP‡JÔ¢u§˜HªR•
.8õ©P�ªT§JU©N#žÈªVµ
;xõ«`
«XÇJV±Â#U¥FÖÊÖ¶ºõ­p�ë[G �²¶ xÍ«^÷Ê×¾ú•¯ïÐ€\[°…Âö°ˆM¬b›ØÀ¶��¬d'KÙÊZ–²$àÀ_ë±ˆÎzö³ 
­hGÚÌ2¶|H­jWËÚÖºöµ­…JAÛÚÿÖ–aÈ­nwËÛÞúö·½•íei°„â÷¸ÈM®r—›\ÀÐ�ntg†êZ÷ºØÍ®v·›]àà
oxs1†òš÷¼èM¯z×›^ï¢â½ð…o.
AßúÚ÷¾øÍ¯~ñ‹‚l7>°€LàøÀNA-˜›‹8øÁŽ°„'La	+˜ÁŠÈ°†7Ìá{øÃ6�¸Ë€˜øÄ(N±ŠWÌb‹˜0ŽqŒ„ÛøÆ8Î±ŽwœcmH€½åà��‡Lä"ùÈH6²�-Áä&7Ù{ˆ²”§Lå*[ùÊV®F&¶Ìe.ïÁ`³˜Ã¼'˜ùÌhN³š×Ìæ6³yXŽ³œç,ç]<áÎxÎ³ž÷Ìç>û¹Ï°h± MèAÃ"
ˆN´¢ÍèF;úÑŽ†�'MéJSúIÎ´¦7­il4áÓ µ¨GMêR›ºÔáPˆªWÍj„;
__CPAN_FILE__ src/widget/templates/images/tab_bot_left_curr.gif
GIF89a	–Õ#èïùúûþöùýâë÷íòúòõûýþþåíøßéöÚåõÝçöØãô¤¿åÖâô¨ÂæªÃç¢½åûüþÀÓîçîøãë÷“²à–µá¹ÍëÐÞòf“Óx ØŽ¯ßÜæö€¥ÚÇ×ïh”Ôd‘Ób�Òÿÿÿÿÿÿ!ù#,	–ÊÀ�hH
‹Ä#R¤D6‹ÏäÒ8eV£Ô)Öª½z»àåvü—�ghZF·Õo¶9ž�ÛÝwx^Žïëý|‚�„u€†ƒˆ…\{ŠŽŒ‡�‰’‹dt”�–�˜œš‘ž“ •k™¤�¦¢¥—©§«¨¯®±›¬´°³¶Ÿ¸¡ºI¾¿¾!ÃÄÃ!ÈÉÈ!ÍÎÍ!ÒÓÒ!×Ø×ÝÞãäéê 
ðñ#	ö÷#þ#^øABƒNpÐ!Dˆ ;
__CPAN_FILE__ src/widget/templates/images/soriaPressed-l.gif
GIF89a6w÷¸Ôý¶Óý´Ðú·Óý�ºæ¹Ôþ­Êô¯Ëõ³Ïù¹Õþ±ÎøµÒü«Èó¯Ìöo•Ír—Ï©Ìþr˜Ð¨Ëþq–Îq—Ïp–În”Ío”Íp•Î¢¿ëŸ¼ç°Í÷´Ïù´Ïú¦Âí«Çò¸Ôþ´Ñû£Àë¥Âì¬Éó¡½é¤Áë¨Åï¦Ãî²Ïø²Îø®Êôž»æ¶Òü´Ðû°Ì÷�¹å¬Éôž¼æ±Íø¯Ëö§ÄïµÑû¡½è®Ëô ½è©ÆðªÆð·Ôý¢¾ê«ÆñÁÚÿôøþ£Æù}¢ÙŸÂö¨ÊýžÁõ§Éü§Êý�Àô›¾òv›Óœ¿óó÷ýŠ¯ä˜»ð‚§Ý˜¼ð�¦Ý�¥Ü|¡Ø‘µêt™ÑŽ±çs™Ñx�ÔušÒzŸÖwœÔx�ÕyžÖ�³ès˜Ð£Åùƒ§Þ¤Û¥Çû–¹î¦Éüõùÿ…ªà�´é¡Äø…©ß‡«â¢Åù¥Çú�±ç¦Èü¢Åøïóú†«á—»ïš½ò”¸í{ ×•¹í¦Èû�±æŸÂõ¥Èû™¼ñ’¶ëˆ¬â¡Ä÷ Ã÷‰­ãzŸ×„¨ßtšÒ Ãö•¸íš½ñ‘´ê“·ì–ºî™¼ðŒ°æŠ®ä�²è¤Çú’µê—ºï¢Äø~£Ú�³éŽ²çœ¿ô¤Æú€¤Û“¶ë”·ì‹¯åòöüðôûòöýïôú¿Øýñõû½ÖûñõüµÎôÀÙýðõûñöüó÷þò÷ý¾×üÁÙþÁÚþ©Âé·Ðõ¸Ò÷ºÔùóøþ¸Ñö¼Õú¸ÑõµÍóïóù°Éï³Íò¹Óø­Æì¾ÖûÀÙþ¬ÅìºÓù©Áè»Ôù´Íòôùÿ°Éî«Åë¸Ðõ®Çí¹Òø­Çí¯Èí²ÌñªÄê±Ëñ¿×ü¬Åë¶Ïô½Õú©Ãé¶Ïõ½Õûðôú¿Ùý»Õù©Äé¸Ñ÷°Êðôøÿ©ËþªÌÿp‹³¹Õÿÿÿÿ!ù,6wÿ»	H° Áƒ*äÆ°¡Ã‡#Jœ(±Å‹3F´¨±£Ç�C†ì¡¤É“(Sª\Ére·m0cÊœI³¦Í›6_âÜÉ³'M�>ƒ
ý)¡¨Ñ£H“*]Êti7"P£F5ó­ªÕ«X³jÝªõ©T©f~ÁK¶¬Ù³hÓžív¤­[·fZ˜K·®Ý»xóÞeûöm\½€îf¤°aÃf¢±XÌ¸±ãÇ�#?&|ø°™k22kÞÌ¹³çÏ�»•Mš´™eR«^Íºµë×­»½™M›¶b9rëÞÍ»·ïß½»áNœ¸g7’+_Î¼¹óçÍ»í™N�º°^%²kßÎ½»÷ïÝ»�ÿOž¼6]=Ò«_Ï¾½û÷í»µ™OŸ>dòëßÏ¿¿ÿÿýuóÈ€„1"$¨à‚6èàƒ
vsÉ„RD2&d¨á†vèá‡vÄˆ$’Ä0#¤¨âŠ,¶èâ‹-ŠXb‰@ÜâÁ�8æ¨ãŽ<ö¸c7`)¤�@dƒÂ‘H&©ä’L6¹d7lD)¥”@0SÃ•Xf©å–\v¹e7p„)¦˜@(sÂ™h¦©æšl¶¹f7’Ä)§œ@à¢Ã�xæ©çž|ö¹g7i*¨ @³Ã¡ˆ&ªè¢Œ6ºh7D*©¤@ÔâÃ¥˜fªé¦œvºi7€„*ª¨@�òÁ©¨¦ªêª¬¶ºj7…Äÿ*«¬¥2`ë­¸æªë®¼êÚÍÀl­½k¬±¿
+,Ï�àì³ÐF+í´ÔJÛ�Øf›-ÒÄàí·à†+î¸äŠÛMè¦›.®àî»ðÆ+ï¼ôÊ{®ºê²[ï¾üöÛ
p,Å¬`ðÁ'¬ðÂ+ü¯ÀÇBWlñÅg¬1ÆÝXâñÇ£"Ë$—lòÉ(§¬2ÊÝ,áòË/‹¼òÌ4×Ü2Ì0£‚

<÷ìóÏ@-4ÐÝ$aôÑG3ñJL7íôÓPG-5ÔE#�´ÒSg­õÖÝÐáõ×_3qÌd—möÙh§­6ÚÝâöÛo3‘Ët×m÷Ýxç­7ÞÝðÿá÷ß3áË„nøáˆ'®8âÝ,âøã�3‹”Wnùå˜g®9æÝ@áùçŸK¾ùè¤—Þ�¨§ž:À¨àúë°Ç.ûì´ËÞÍ¸çž;Ö¤àûïÀ/üðÄßM$È'Ÿ<³ àüóÐG/ýôÔKß�"ØgŸ=óÕwïý÷Ý�!þøã3
è§¯þúì·ï>ûÝÜ!ÿüó31Møç¯ÿþü÷ï?ÿÝ0„8@&ˆBL ÈÀ:��Ý¨ƒ'8ÁTð�Ì`»¡‰zÐƒt�GHÂšð„(4a7ÁÂ¶Ð‚!ˆ¡gHÃÚð†5ìF&vÈCzb6¢ÿ‡HÄ"ñˆEìF–ÈD&zBˆ¢§HÅ*ZñŠUì$¶ÈE.>‹`£»A…2šÑŒžhFÖÈÆ6ºñ�pŒã»�ˆ:ÚÑŽžEöÈÇ>úñ�€ä»�†BÒ�œÐ£ ÉHFvƒ�Œd$9€JZò’˜Ì¤&7™Énxá“ %%9IÊR–²ŽH¥*UÉ‰jðà•°Œ¥,gIËZÎ²•È¥.uÉ‰Rà—À¦0‡IÌb³VH¦2•ÙKc:ó™Ðì†¦IMj6šØÌæ/»‘‡nzÓ›œàÆIÎršóœèLç9»ÁˆvºÓ�§XEæIÏzÚóžøÌç=»±ÿ‰~úÓŸñÔ§@JÐn4á Eè)X‘€†:ô¡�¨D'Ñn4â¢Åè(JÑŽzÔ£Ý„HG:ÒQüÀ(M©JWÊÒ–º”¥ÝðƒLg:S“¾ô¦8Íi7ÖÀÓžöÔ¦9
ªPQÚ
9õ¨G
ÅI‡ÊÔ›vãP�jT•ÚÔª¶´jÈªVµJU«z•¨ƒ«XÅÚÕ¯ZµaH«ZÕjŠ¥šµªÝx‚\ç:×¶¾õ¬QÈ«^õj×»6µR¬`Û	·úU¨ÝÀ„b»ØÂ–©Ýƒd';YÇ>±“È¬f5kÙËêT 
mh;ëY§Šö´¤-­K»1…ÖºÖµÔ0¬j¯j‡ÚÿÚÖ¶Ÿ�ílWÚ
Aøö·¿Íín_Ú
-÷¸Çîp¯Ú…æ:×¹Ê].o¹@ÝêV7º•n7°ÀÝîv»Ò…éÆK^ò‚7¼*í†ÖË^öž½Dm¯|ßßndá¾øÅ/}ÑÛ
Bø÷¿ÿÝox»Q…ØÀÖîÌ`'x¹Ýø‚„'<a[påÂÎð7º�{øÃ ±ˆGLâwã(N±ŠWÌâ»øÅ.îfLãÛøÆ8Î±ŽsÜ�	øøÇ@²�‡Lä"¹H²’—Ìä&;ùÉP~r70@å*[ùÊXÎ²–·¬ån8àË`³˜ÇLæ2›¹ÌÝ¸€š×Ìæ6»ùÍpŽ3œ»a�:ÛùÎxÎ³ž÷Ìç=+äÏ€4B;
__CPAN_FILE__ src/widget/templates/images/slider-button.png
‰PNG


IHDRÄé…cgAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<kIDATxÚ¼VKhQ½3I¦i“˜¤éÇÖT1~ª­¤P±UP,ˆ¨ˆÜ	"îtgýD¬HÛêB\¸SQ+.Ô¢R‚Ö
"~[R+‘Ø4i¾“Ìç�wâLœš’¦©4pxIÞ›{Þ½ç½s‡†9øÐsA¢ÏgQÛ•¥!›Ë”üŸÀs_.Ýþ¿Š)×óT®Éã�ÏÖÐ´îPÔf›½L§ÓÿÝS*ÉB4ç¹”çÇÐûöž®£¿ÂüHpçÅ’DºLfëGù|°9*�'{© ððûÀï‰FCc­Ý'÷ÞÀ¿yÑ®ÓME’ô¤¼Ò¹c¡«ŒÅ¦?’”š¢Ál±‚yž­ˆ1–l_æ^ŸxÓwàßf	�\wTT7WV/‚Uh Dšv\SkGÅÌ¸êÌ¾ÖîÝÆ¨­Ò¤LNtõo³ØJÏVÕ,w�Þ}ò!ÌSHÚìó~ôL|qU£I™`Ý;¬öòôƒƒ^nÆcS}8*�-{Âp&5~†äØå§n¬ëÊ¦:'¡,dÜØè«cþ.iA&•kÝÖýû-6GK�“u—À
†	$ba{8èïõ�~“O­QÜEë ŠdÖÐX¸´a9FedôAJ¸Hœµ�Px´
L‘Yq:C‚¶á¿� õ—b9Us½fÂ‹ŒHfM‚¾C^
«7?CÂÆÂ}Æ’yíE&û¬D�ƒó~è÷Ë|2QFxô�w—ü–dcÀcÙ
E2�1ßðCÙCrÉ$­Õ“x4xRÇ”x%úÂ´’ÀF�Ç·.ÜÆŸq•D{ã¥Î¶Ý½ÉXð—˜˜y¨''ŸŸwøG¿0^Tqä,&|Š}Z³¤¾-¦
O|Ú§…Èƒ$$àÇ·Á®;WÛîa™$¬h’mõhn©ØÄø}§k…Ë §W¼Å"&,�Ù @‰,P|$>ôþå9Oç‘… ¤h’³3Ê¢˜w<½qQmc«Ñdm"¸)½œJ·
Z>�b
{•¯¯¯çâµ‘ÏoâDP!HjW®ö«Sú‚¥nõ&§{í–
ÆhÇÛÌ"ãþÑ‘G7Ï¿Vv,‹AÄ¦êŒÔt¡dÅ(„ŒBN)��WHÔã*ò¶¢’ÁjT’ÏÛÊoûØ‡ZÕŽ¼£IEND®B`‚
__CPAN_FILE__ src/widget/templates/images/soriaDisabled-l.gif
GIF89a3wÕ²²²ÆÆÆÉÉÉÂÂÂ±±±¯¯¯ÙÙÙ³³³ººº´´´···µµµ¶¶¶¹¹¹¼¼¼×××»»»ØØØÐÐÐÑÑÑÖÖÖ½½½¸¸¸ÓÓÓÒÒÒÕÕÕÔÔÔÏÏÏÁÁÁÄÄÄÃÃÃÊÊÊÇÇÇÈÈÈÅÅÅ°°°ËËËÀÀÀÎÎÎ¿¿¿âââ¾¾¾ÍÍÍÌÌÌ!ù,3wÿ@”pH,�È¤rÉl:ŸÐ¨tJ­Z�¦¬vËíz¿`S1L.›Çæ´Z‹^»Éí·¼7Eø¼~Ïïûõu&*„…†‡ˆ‰Š…E‡‚‹�‘‹�†�’——”…–˜�Šš„œž£ŒDŽƒ¤©* *¢ª�E+²²¨¯ž±³+µ·£¹³¼½°Dº»¶Â’¿´ÇÈ�ÊÆÍ™ÄºÁÑÎÓÀÌÖˆÏÕÛ‰ÝÚß¥C$ææâã«DçèêãEî$éëàíîõö‡òùðßE>˜áß¶€?dPQ¬¡Ã‡u!¸0¢Å‹
'dˆ±£Å"B†ÔÀÑ£ÉŒDDŽ,y²å
�*Iºœ	S¤Ì™-‹„Ø¹óKÿœuòqaÅ¼£H“*u'”gÑ¥P£mÚÓ¨Ô«P©µŠµëT" Â†Å@"¡Ù³hÓª-"vlYµpã¦eÛ–¬Ü»xéŠÅðA¥ß¿€. pá	}+^˜°á�L¹²åËŽ
G¾Ì¹3f"�!KöLštæÃ!Úª^ÍºµëÓ�S»žM»5ì	²kë®]D„oß@„N¼¸ñÇ½‹~¼¹óáÉWN½ºõëØ£�½»÷ìD:ˆ?ý»yóEÆ“ ¾½û÷ðã§W/�}üûøáÏ_?¿ÿÿEx  €ˆ0à�&¨à‚	x`�F(!ƒá„bXÄrhÿB†(âˆ$–8â†!~hâŠ,šˆb‡&xÀÁŒ4Öhã�8æHã‹Ê¨ã�@æX„�*øä‘AY£
”àä“PF)å”T>©$�LV©å–Ue–\†¦—P‚)æ™T’ù¤
œàæ›pÆ)çœt¾©¦“lÖ©çžuÞYBž|¨Ÿ€
j(�„¶yè¢q&Êè£nç
ŠBºh)dš)	•Zj(¦š¦@B	¡–jê©¨¦ZD¬²ú©©Æ*+ªE8`«­¯Îªë®µÞê@®»«*[¬°
«l¨E{l²Ë.[ÔRÂ	Ñf;mµ\›m´ÛVëí·ÊÑÀ¹ç‚€Ó-¹Âš‹nê²Û.Ô[oëÊ«k
ôÛ/¾úòJ„¿ÿæp¬E0 °Â"|0­D,Ì°Ã›ZÄcÜÅ3KDÆsÜq¦E$`²Éˆ<rÉ''�òÈqÀÌ3¿³ÅDÐ\³Ê¡ó6ßì±Ì:{pÞÑÞÀÒL7íôÓPG-5JOmõÕWW�õÖ\/]`‡-öØd—möÙ|�öÚl³]ÄpÇ-÷Üt×m÷Ý#¼�÷Þ|ó­wß€÷ß‚Žw$®øâŒ7îøã�;
__CPAN_FILE__ src/widget/templates/images/dateIcon.gif
GIF89aÕ"Aqôôôðóöçìñòô÷âèîïòõáçíÞÞÞûûû÷ùúúûüóöøùúûìðôèìñõ÷ùô÷ù&J€ÁÉ×“®üüýÀÄËÐÙãòõ÷ÍÕà9aŸêêêJd‹p„£@[„:e� ¸ÈÈÈ9c+Iw2N{èíñ0S1TÛâéÚáéíñôèèè!ApOsªÚÚÚ2WÒÛäÓÓÓððð.Yšÿÿÿ!ù,¥À™pH,
	£’ˆ,Ÿ1ÙsmÑ®ØlvÅª`)Z6 Á`
˜ë‹Éf´:Å–Yµøk½µP	h*4**
~{_acegik]v(4(4((
•{y4$¦{”–˜š( ¦#Šn�ft’|~€‚„*%u.ÊËÌÊ!Q"/ÕÖ×Ö'&Q1ßàáâM	2çèéêHA;
__CPAN_FILE__ src/widget/templates/images/decrementMonth.png
‰PNG


IHDR5Y^gAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<„IDATxÚbÔ´òf@6y©1ê	´¬}Î‚˜PA×¤ÙK2‘�D±%7÷N÷¸vt‹1²�n˜Êåë¶fÞ}ðˆÄf•UÑ�@ì…dß›·ï·,›þ¤@(°¤Ùî{kÉHIìd²…VÎé;É€
$°"td=÷EIEND®B`‚
__CPAN_FILE__ src/widget/templates/images/floatingPaneMaximize.gif
GIF89aæÂÓì®ÍûªÉù¥Åõ§Ç÷œ¾ð¬ËúŸÀò¢Ãô™¼ïp‹³r�µ¢Åù�°å¬ÊøqŒ´yžÖ–ºî§Æõ‘´ê™¼ñÁÓë¦Éü}¢Ù Ã÷œ¾ïž¿ð‚¦Ý¨Êý¯ÎúžÁõ±Ïû³Ðümˆ°–¸ëŽ²ç¤Äô†ªá›¿óÃÕí‹¯ån‰±oŠ²®Ìùl‡¯“·ì¤Çú¡ÁòÄÕíÁÓìv›Ó™»í´Ñý©Èö„©àr�´qŒ³q�´o‹²lˆ°ÄÕîÃÔí‰®ä–¹í²Ðý°Ïü³Ñþ“¶ë€¦ßlˆ²©Ëþr˜ÐÆÖík…«):Kÿÿÿ!ù,ÿ€I‚ƒ„…†‚F‰Š‹ŒŒI<H“”•–H<�<4BŸ ¡¡4<�.< @«¬­­ <.7I<A¸¹ºº<9I<JÇÈÉÅ<I0+ÉÖJÔ+0Ï&'×Éá'&8I=5JKñòñJî5=
I=ðæÉSòOB�úZô �A@�K”4$Ñ£…¾	=^8ðP ’�/zLÐ‘dD

tœ§$¥†#T$AÑ#C‚ã�ÝÌÐ…ÌfüJ´hÑJ¤H²€ˆ!P£J•*À†¥4ðÁµ«W¯
\‘BDÒª]»ÖFdeT¸D—R;’ÙË·¯_¿,’L¸°aÃ,;
__CPAN_FILE__ src/widget/templates/images/scBackground.gif
GIF89a¶æt�ºw”¿z—Ãu‘»s�¹ƒ¢Ñ~œÉy–Á|šÇx•À†¦Ö„¤Ó� Îv’½sŽ¸€ŸÍ}›Ès�¸{™Å’µé—»ðy–Âu‘¼v“½� ÏžË…¥Õ…¥Ôx•Á|šÆ›À÷u’¼‰ªÛƒ£Òw“¾™½órŽ·�Ë–ºï‚¡Ðz˜Ä{˜Ä‡§×‚¡Ï€žÌ‚¢Ð”·ëš¿õœÁ÷ˆ©ÙžÌ˜¼ò‰©Ú}›Ç|™Æ�Ê�¯áŠ«Üx”À—»ñ•¹î–¹îŽ°ât�¹�±ãrŽ¸t‘»‡§Øš¾ôv“¾~œÊ~�Ê‹¬Þ‹­Þš¿ö�³æ“¶ê›¿ö’´è�±ä†§×€ŸÌv’¼†¦Õy—ÂŠ¬Ý…¤Ô{˜Å”·ìœÁøˆ¨ØŽ°ãw”¾}œÉ•¸í”¸ì“¶ë‘´ç˜½òŒ®àš¾õ�²åt�¹‘³ç„£Ó™¾ô›ÀöŒ­ß„£Ò�²å�®à˜¼ñ!ù,¶ÿ€YY00†jjMMJJ//ddDDii#—#bb33oo;;¢&¥&==<<^^__XX..``LL¸NNaaggKKmmeeOO@@[[>>88nncckkIIHHUU99 ß 4411ZZCC*ê*PP
ïðSSô÷VVüýhhlØ„¢€Áƒ-ZœXxb…Ã"b`@±âƒ‹£DaÁB†Œ 3”YâÆ�#GŒ1À²e—.bÊ¬Q�Í›rv°aC‚ÏŸW®¤š…Q’*MJ…J…§H�Ê¡*‡X³êÐ «×®\¸ˆ+¢H‘h/4XËVŠ”p(?X˜ka€Ý»v…À·¯_¾fÌüøA °áÂ+vÀ¸q� $"“;
__CPAN_FILE__ src/widget/templates/images/transparent.gif
GIF89a((÷ÀÀÀè×gÔˆ0ÿÿÿÔˆ*ç‘2¨!�æàé$ç0‘2H!º`çL‘2H!º`ç$‘ëéh�î‘8ÿÿÿ‘2‘«‘ëé¸éäéÜçdÝtuê¼�î�ûxÿÿÿ�ûqÝu!¨Ýu,!º`¨éÜ@ê$éä@ê(z
ì¨éÜ¨ÿÿÿè,Ý›‚çtHè(‚èŒÝ‚é@‡€–Hæ‚°é@‡Lèè@è�‘È!ˆé\‘Q¨‘mé´è¸‘È!ºXé„‘QHèÔ‘È!ºXé ‘QH‘méäæ„Dº«Í0!�Ôˆýð0ç�ûl !º`é@‘ÈGi ê‘Qá8‘mGn8Gi(�ûq�Õ†�ç¼é`�çÈê�î�ûxÿÿèäê�î‘pÿÿÿ‘m‘	¼È!º`éÄ‘	’!º`êÝíÝí b¦Èáb¦ÔéPGi(êD�î‘pÿÿÿ‘mÂÂÞáÂÂãGn8Gi(ÝhªGi(Gi(êPê ÿÿÿê¼Ã\”Á pÿÿÿÂÂãD•ÕGi(c c EµGGn8I¼�ê†Ôê†Ôê†Ôê†Ô¨ê Ýltê¨I¼�I¼�æà£æ‚°!ù,((CH° Áƒ*\È°¡Ã‡#JœH±¢Å‹3jÜÈ±£Ç� CŠI²¤É“(Sª\É²¥Ë—0cÊœI³¦Í›8	;
__CPAN_FILE__ src/widget/templates/images/incrementMonth.gif
GIF89aÄ¥Åô¤Ãó¡Àí—µà”·ëp�µrˆ¦�©Ð€™¼}�Ê²Æâ¤Âò^xš‰«Ü¥Äô—ºð‚¢Ð>Rj,=O5H]™½ó—»ñ¦¶Ï˜¼ò):K!ù,% d�¤ÒHXŠIÅ¨˜PÄ”Nu]EŠ8»Ë#Yì*ÈÄ!€;
__CPAN_FILE__ src/widget/templates/images/dpCurveTR.png
‰PNG


IHDRÈÜEtEXtSoftwareAdobe ImageReadyqÉe< IDAThÞíËË
a@Ñû¯Ô£ÑËè@/^c¡
o(@¢€ñ�È|‚Õ=û“†ëÇ“÷F@;kÔ
€T!ì�fÖ¨íR¾ºW	[ 	­”¯n‘°Iù2Ê4X^#�Â¢Œ…~8Ì/?½Ù9N±Ð�†Ã1:“p8ƒÁ`0ƒÁ`0ãÂ`0ƒÁ`0ƒáûá`–‘ò‹ã€IEND®B`‚
__CPAN_FILE__ src/widget/templates/images/dpCurveBR.png
‰PNG


IHDR	È:%ËtEXtSoftwareAdobe ImageReadyqÉe<IDATXÃíË¹	€@DÑÙî´c¯Ì¼Rñ*C°	0MLd7Aø?{cÒzÜe™�@ �@ �@ ý
%N¨þŠzT: økÔ½…ŠwÐæ‚&­
64JòŸÐ&©–”å¡·ÞÑ"i:kòÐ›¯Ça…37¥’ñÅIEND®B`‚
__CPAN_FILE__ src/widget/templates/images/treenode_grid_y.gif
GIF89a€rrr!ù,Œ�©Ëí£œt‚‹3X›v[}’‘�ù Žj;
__CPAN_FILE__ src/widget/templates/images/soriaPressed-r.gif
GIF89a6w÷„£ÑàéöÂØøäìùŠ©Ör’ÂÆÚú¾ÓôzšÉâê÷� ÎÄÚú¿Õö¶Ìíãëø´ÊìÈÞý‹ª×ãìù}œË€ŸÍ»Ðñ¸Îð�Ìx˜Çv–Å¼Óót”Ãu”Ä¸Ôýp‹³¯Ëõ¯Ìö³ÏùµÒü¶Óý·Óý�ºæ¹Õþ­Êô«Èó´Ðú¹Ôþ±Îøp•Îr—Ïr˜Ð©Ìþp–Îo”Í¨Ëþn”Íq—Ïo•Íq–Î¤ÁëªÆðž¼æ®Ëô�¹å´ÑûµÑû©Æð¬Éó ½è¡½è¨Åï°Í÷¬Éôž»æŸ¼ç«Æñ´Ïù°Ì÷´Ðû¶Òü§Äï¦Âí·Ôý²Îø¸Ôþ¥Âì¢¾ê£Àë¯Ëö¡½é±Íø¢¿ë«Çò´Ïú²Ïø®Êô¦ÃîÉßÿ›¾ò£Æùœ¿ó}¢Ù¨Êý§Éü�Àô§Êýv›ÓžÁõŸÂöêòþ”·ì‹¯å¥ÇûwœÔ�³éx�Õ�¦Ýƒ§Þ¤Çú¥Çú…©ß–ºî˜¼ð”¸í•¹í–¹î“·ìŽ²ç Ã÷¥Èû Ãö‘´êx�Ôs™Ñ•¸í¦Èû’µê¡Ä÷€¤Û¤Û�³èyžÖ‘µê—»ït™ÑŽ±ç™¼ð£ÅùušÒzŸÖ�¥Ü‚§Ý|¡Ø‰­ã~£Ús˜Ð…ªà†«á‡«â¤Æú¢Äø¢Åø¢Åù¦Èü¦Éü�±ç—ºïŒ°æ�±æŠ®äŠ¯ä�´é˜»ð{ ×™¼ñˆ¬âš½ñ„¨ßš½òœ¿ô’¶ëŸÂõ“¶ë�²èzŸ×tšÒ¡Äøéñýåíúçïûèðü~�Ëßèõƒ¢Ðáê÷‰¨ÕæîûÞçôˆ§Ôp�ÀåîúÉÞþèñýæïûçïü‚¡ÏÇÝýÀÖ÷†¥Óéñþéòþs“ÃßçõëóÿÈÝý|›ÊÃÚúŠ¨ÕÉßþx—Æèðýêóÿ…¤Òçðü‡¥Óˆ¦ÓÆÜüÆÝýÂ×÷†¤Ò‡¦Óˆ¦Ôq‘Á‰§Õ¸Íïp�¿o�¿p�¿‚¢Ï·ÍíàèõÆÛû»Ñòq’Ár’Á´ÉëæîúÃÙúÂ×øv•Äw—ÆµÌìßçô¹Ððy™Èz™È©ËþªÌÿ¹Õÿÿÿÿ!ù,6wÿ=H° Áƒ&ìÇ°¡Ã‡#Jœ(1Å‹3F´¨±£Ç�C†Œð¢¤É“(Sª\Ére~0cÊœI³¦Í›6	àÜÉ³gM�>ƒ
ý)£¨Ñ£H“*]Êt)�P£J�JµªÕªÑÄhÝº•ÀŽ¯`ÃŠK¶ìØxY¹r%P¢­Û·pãÊ�÷A¶2xóæeK·¯_¿võ
&P¤°áÃˆ+^œø^š1�#G®–£²åË˜3kÞœÙ±äÏÕŒˆMº´éÓ¨M7Hªµk×¿€ÈžM»¶íÛ¸m¯Kó©·oß¿‚N¼¸ñãÈ�ïÄ¼yó_U¢KŸN½ºõëÕw÷ÙÎ�û/)àÃ‹ÿO¾¼yòæÒ°YÏž}¹+ðãËŸO¿¾}úÒÌÙÏŸ¹)(à€h �ù¤!Ç‚2(Ì
F(á„Vh!…	n¢á†
Å‡ †(âˆ$–8b>Î|¡âŠ+
ÓÄ‹0Æ(ãŒ4Ö8c)²È¢0\ôèã�@)ä�AºÓÌ#H&™ä8L4éä“PF)å”QjÐŒ'Xf™å8Btéå—`†)æ˜ajpK'h¦™f7>´éæ›pÆ)çœqp'xæ™g78ôéçŸ€*è �ÚiË¡ˆ"*ÎŒ6êè£�F*)¤vbé¥—ŠƒÅ¦œvêé§ †ú)·ðaê©§rƒÂª¬¶êê«°Æÿú*©~Ôj«­ªÊªë®»2`À,3?kì±È&«ì²É.ó«°Â2CÄ´ÔVkíµØf{­³±të­·Ìœ î¸ä–kî¹èš»6g´ë®»á¤+ï¼ô®ûî½ál¡ï¾üöëï¿û»Œ.dl°ÁÚè ðÂ7ìðÃ;Á¬Íg¬ñÆwì1Ç¿"òÈ#ðñÉ(§<1,·Ü2TÄ,óÌ4×lóÍ5Ó£‹Ë<ÂÏ@-ôÐD=´Ûx¡ôÒKûlôÓPC�4ÓT�ÄÕXg­õÖ\w½µÈ¸"öØc0ÄÙh§­öÚl·½ö<È°"÷Üs`ÅÝxç­÷Þ|÷ÿ½7Üª.¸à½¬`øáˆ'®øâŒ+NM.ŽD.¹ä…7nùå—?nÇæœsÞË ‡.úè¤—n:éä‚Êê¬³Þ‹°Ç.ûì´×n;í©/¢ûî»«ÂïÀ/üðÄ?¼¹ˆ¢üòË'cüóÐGoÀ1uTo½õÉ ¡ýöÜwïý÷à{?}ä—_~2Y¤¯þúì·ïþûíO�ÇüôÓŸL
øç¯ÿþü÷ï?ÿí† H@*àL x‡:Ð�
P‚'HÁ
Zð‚´`ÕÀÁvP<¡GHÂšð„%ô0ôÀÂ¶P=ˆ¡gHÃÚð†5ô†<dÁÃö�"¢ÿ‡HÄ"ñˆEü1`ÁÄ&6ˆHŒ¢¥¨DBXñŠW¤À¶ÈÅ.zñ‹`ã•AE˜ñŒg¤ÀÖÈÆ6ºñ�pŒã•�‹?ØñŽwT£÷ÈG>Òñ€d /@‚Bò�ˆL¤"™HiàÂ
�Œd$	ÉÈJZÒ’ŽD„&7¹É8á“ ¥(GIÊRŽ¸˜…*W¹Êtà•°Œ¥,gIËZÎ²¸Øƒ.w¹Ë]Øò—À&.AÌbÓ—ÁL¦2_‰ËP8ó™ÏÜ¦IÍjZóšØÌæ5qIŠnzÓ›»P�8ÇIÎršóœè4g10ŠvºÓ�H§<çIÏu®ážøÄçLÀÿÏ~úóŸ
¨@j
	˜â Eè>ÊÐ†6´ ¥ˆ¨D%:
Xô¢Í¨F7ÊQ�vA•©HEZÑŽšô¤'í‚VÁÒ–¶´¤(�©Lý¡RMØô¦7EÀLwšRdâ§@ªNyJT�:HMjR‡ZÔ¦ÒÔtˆªT¥º§:U¥­ÈªVµª«6µ	ˆƒXÇ:Vxµ¨`�„Z×ºV³ž•§]ðæJWººõ­3�«$öÊW¾^¯;�«!KXÂþ°2�ë!ËXÆÚ±‰
€%&KYÊf²1íBÂÀÙÎvö²˜Méf=ëYÐ†¶£š¥„jW»ÚzœÖ¤šM…lg;[×ÿ¾–£]`-vË[Þrà¶¸eG$†K\âþ¸åE"–Ë\æn¹É}ƒt§;Ýg@7£]à ¶Ë]îZ÷ºÍnÆK^ò~¼4…†ÖË^öž¼]Po{ÛûÞëv�È¯~õ[ôZ´Á¨…€<àþúÀŒH°‚ÿÒ4�ˆ°„%üŽ«XøÂþG0.Ááw˜.±ˆGLâ›øÄ(>19ZÀâ»øÅ0Ž±Œg,crÐàÆ8Î±ŽwÌãû¸Çä°��‡Lä"ùÈHN2’‡ƒ&;ùÉPŽ²”§Lå)ƒXÎ²–·Ìå.{ùË^F
ÆLæ2›ùÌhN³šÓ|Ž¸ù$ÍpŽ³œçLç:Ó93È³ž÷Ìç>ûùÏ€þ3:BèB!;
__CPAN_FILE__ src/widget/templates/images/tab_bot_right_curr.gif
GIF89a�–Õ"b�ÒúûþýþþèïùíòúòõûöùýßéöåíøÚåõâë÷ÝçöØãôÖâô¦Àæh”Ôçîø“²à€¥Ú¹Íë¢½åÀÓî–µái•Ôãë÷¨ÂæûüþŽ¯ß|¢ÙÇ×ï©ÂæÍÜñd‘Óÿÿÿÿÿÿ!ù",�–ÿÀ�pH,�È¤rÉl:ŸÐ¨tJ­Z¯Ø¬v[p¿à°xL.›Ïh³7Ín»ßð¸|¾\Óïø¼~ÏgÛû€�‚ƒ„y…ˆ‰Š‹ŒN‡��‘’“w�”—˜™šW–›žŸ ž�¡¤¥¦…£§ª«¬p©­°±²[¯³¶·¸Jµ¹¼½³»¾ÁÂ¥ÀÃÆÇ—ÅÈËÌ‰ÊÍÐÑ{ÏÒÕÖoÔ×ÚÛcÙÜßàœáãäÝåçèXÞéìåëíðßïñôÖóõøÍ÷ùüÆûý{ýHÐÖÀ‚[LÈÐÔÂ†?=ŒHÓÄŠ#]ÌÈQÑÆŽ }I’ÏÈ’(+¥\	ê$Ë—~`Ê¤är¦Í05oêÔ’s§Ïÿ.?ƒê)´(¢F“Aª´©¦N•B�jt*U¡V¯þÌªu'×®7¿‚�)v,Ì²fY¢M›r-Û’nß†Œ+·#Ýºïâ­¨woÄ¾~œp0á‚†L¬¸ãÆùC®'yr¼Ê–ÛaÎœn3çsž?“-:éÒòP¿=­ZëÖö`›}-;íÚúpw½­ïÞþ€Sý-<ñâ‘7=®óæ¡W•^ô9uXÖ¯³Ê®]÷îÁ{¯ó;ù–çmšO¿i=ûLîß'“ÿ2>}IöïCÊ¯Ÿÿþ—€$ýG !(H‚
Õ G>8�„EH!^HG†ÊÁÿa‡®€(˜ˆ}HbL'"–¢Š+.Ö¢‹/:£Œ3FV£�7R&ÀŽ<öèã�@)ä�Diä‘H&©ä’L6éä“PF)å”T:	@Xf©å–\véå—`†)æ˜d–iæ™h¦©æšl¶éæ›pÆ¹&Ôiç�xæ©çž|öéçŸ€*è „jè¡ˆ&ªè¢Œ6ê(¢ é¤”Vjé¥˜fªé¦œvêé§ †*ê¨¤–jê©¨¦ªêª¥@À«°Æ*ë¬´Öjë­¸æªë®¼öêë¯À+ì°Äkì±È
ÀÌ6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–û-¤«ÿîºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ð¾\ ÀÁ'¬ðÂ7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ gü”lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÍ8°ÀÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\S�$ öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷Þs[à€.øà„nøáˆ'®øâŒ7îøã�G.ùä”Wnùå˜g®9äD°�"4 úè¤—núé¨§®úê¬·îúë°Ç.ûì´×n;ûí¸ç®ûî¯W@Áˆ <ÄoüñÈ'¯üòÌ7ïüóÐG/ýôÔWoýõØg¯ýöÜw½@ ¼ðA;
__CPAN_FILE__ src/widget/templates/images/whiteDownArrow.gif
GIF89a€ÿÿÿÿÿÿ!ù,„[;
__CPAN_FILE__ src/widget/templates/images/soriaButton-c.gif
GIF89a6wæo•Í¦Éü�´é�³è£Æùr˜Ðœ¿ó§ÉüžÁõ¢Åø�Àô‘µêo”Í¥Èû¨Êý©Ìþp–Îp‹³q—Ï�°æŒ°æ—ºï™½ñŽ²çt™Ñq–Ï›¿ó–¹î�±ç¡Ä÷—»ïr—Ï}¢Ùš¾ò‚§Þ|¡ØŠ®äˆ­ãš½ñ®Ãä§Êý¨Ëþ£Åù¤Û Ãö„¨ßŸÂõw�Ô¨Ëý•¹í•¸ís˜Ñ‹¯å Ã÷”·ì“¶ë–ºî¡ÄøŸÂö~£Úv›Ón”Í¤Çú¤Æú€¥Üq–Î˜»ð¡Ã÷zŸÖxžÕ¦Èûp•Î�¦Ý…©à’¶ë¥ÇúÍàþ™¼ñwœÔ{ ×Ž²è†ªá‡¬âušÒ”¸í˜¼ð›¾ò“·ì©ËþªÌÿ!ù,6wÿ€‚ƒ„…†‡ˆ‰‰YŒ�Ž��‘’“”•–—˜™š›œ�ž�¡¢£¤¥¦§¨¨X«¬­®¯°±²³´µ¶·¸¹º²)½¾¿ÀÁÂÃÄÄLÇÈÉÊËÌÍÎÎŸÑÒÓœ©Ö×Ø§»ÛÜÝÞßà¸0ãäåæçèéêêíîïðñòóôõö÷øùî(üýþÿ
8ð€Áƒ*\È°¡Ã‡#J< ¢Å‹3jÜÈ±£Ç� CZ4B²¤É“(Sª\¹²�Ë—0cÊœI³¦Í›8sê|¹¤§ÏŸ@ƒ
J”¨�£H“*]Ê´©S§?¢J�JµªÕ«X±ØÊµ«×¯`ÃŠK¶¬Ù³\U¨]Ë¶­Û·pÿãÆM@·®Ý»xóêÝË·¯ß¿€ëæL¸°áÃˆ+VÜ¡±ãÇ�#KžL™ò�Ë˜3kÞÌ¹³gÏ5B‹Mº´éÓ¨Q³XÍºµë×°cË–­£¶íÛ¸sëÞÍ›·‹ßÀƒN¼¸qã’+_Î¼¹óçÐ£KŸN½ºrØ³kßÎ½»÷ïàÃ‹O>»�óèÓ«_Ï¾½û÷ðãËŸ�^ƒýûøóëßÏ¿+(à€hà�† à‚6èàƒF¡	Vhá…f¨á†Zàá‡ †(âˆ$–Xb(¦¨âŠ,¶èâ‹/V!ãŒ4Öhã�8æ˜£<öèã�@)ä�Cz`ä‘H&©äÿ’L6ÙdPF)å”TViå•Wâ å–\véå—`†æd–iæ™h¦©æškÆàæ›pÆ)çœtÖY§xæ©çž|öéçŸR!è „jè¡ˆ&š¨
Œ6êè£�F*é¤“^aé¥˜fªé¦œvÚé
 †*ê¨¤–jê©§*¡êª¬¶êê«°Æë´Öjë­¸æªë®¼öêë¯ÀÖ*À°Äkì±È&«ì²Ì6ëì³Ä í´ÔVkíµØf«í¶Üvëí´P„+î¸ä–kî¹è¢{Áºì¶ëî»ðÆ+¯¼Ôkï½øæ«ï¾üò;Á¿,ðÀl°Á$¬ðÂ7ìðÃCLÃÄWlñÿÅg¬±Æ$tìñÇ ‡,òÈ$“\ÂÉ(§¬òÊ,·ì²ËRÄ,óÌ4×lóÍ8ãÅÎ<÷ìóÏ@-´ÐImôÑH'­ôÒL3ÝÂÓPG-õÔTWmµÕ"d­õÖ\wíõ×`ƒ�ÄØd—möÙh§­¶Ú@´íöÛpÇ-÷ÜtÓ½ÂÝxç­÷Þ|÷í·ß;.øà„nøáˆ#ÂâŒ7îøã�G.¹ä#Tnùå˜g®ùæœsþÄç ‡.úè¤—nºéD¤®úê¬·îúë°Ã^Äì´×nûí¸ç®»î/ôîûïÀ/üðÄïÄñÈ'¯üòÌ7ï¼ó<D/ýôÔWoýõØc?ÅöÜwïý÷à‡/¾Ûø”oþùè§¯þúì³?ÃûðÇ/ÿüô×o¿ýä¯ÿþü÷ïÿÿ HÀð€L ˜�:ð�Œ 'HA
Bà‚Ì 7ÈÁzÐƒ¡GHÂšð„(D!VÈÂºð…0Œ¡ex‚Úð†8Ì¡wÈCð‡@âÿ>@Ä"ñˆHL¢—¸Ä:ñ‰PL`¦HÅ*ZñŠXÌ¢µøÁ.zñ‹<‚ÇHÆ2šñŒhLcSÈÆ6ºñ„3Œ£çÃØñŽxÌ£÷ÈÇ>öQ€¤ ;
__CPAN_FILE__ src/widget/templates/images/treenode_grid_v.gif
GIF89a€rrr!ù,Œ€Ë¦
S„o®jÎ’kÿ�¸e¥uNi´Râèµ;
__CPAN_FILE__ src/widget/templates/images/submenu_off.gif
GIF89a	Äq|ˆ!/=ht€frp|‡8HX(8HTao*;L*6Zgt#1@,8DSb%4D#.AP_!/<",&6F$.'3)5(4ÿÿÿ!ù,	 ��0�‚ÒŒ„8Xa,Œ5…E•4&Ò…„	;
__CPAN_FILE__ src/widget/templates/images/incrementMonth.png
‰PNG


IHDR	Ú›g`gAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<�IDATxÚbÔ´ò6k®ÈËfÀäd$ÅçTÖ²Ùïj;&Ei645¿2#Ü@& ¾Ä}è¦èhªÎÍM‰yS­@üIÍÓ¢Œ„)ZÖ>‘}âJ˜
+SÃ~ý¯0>#Ðá063Ÿ1ŽlYlãs&Á‚dÅ_ Îõ÷t’ø‹ì>€.7"§öð|�IEND®B`‚
__CPAN_FILE__ src/widget/templates/images/dpMonthBg.gif
GIF89a³™¾ô•¹î›¿öš¾ô—»ñ–ºï›Àö—ºð–¹î—»ðš¿õ˜¼ò™½ó›À÷!ù,°ÉfŒ*«1` ³ŒA$Éq‚A;
__CPAN_FILE__ src/widget/templates/images/tab_right_r.gif
GIF89a�–Äb�Ò Æÿ–Àÿ­Îÿ¸ÔÿÀÚÿÈÞÿh”Ô€¥Ú³Ðùçîø£¾å‰«Ýš»ë¡¼äd‘Ó‰®å‡®æ|¢Ù�¸ø†°ì’¼ýûüþáê÷µÏ÷¨Âæ¬Íþ¹Íë”¾ÿÿÿÿ!ù,�–ÿ  Ždižhª®lë¾p,Ïtmßx®ï6çÿÀ pH,�È¤rÉl:ŸÐ¨tJ­Z¯QvËíz¿à°xLkËè´zÍn»ßÇ3|N¯Ûïx´<Ïïûÿ€u{�„…†‡ˆJƒ‰Œ�Ž�s‹�“”•–S’—š›œš™� ¡¢�Ÿ£¦§¨l¥©¬­®W«¯²³´F±µ¸¹¯·º½¾¡¼¿ÂÃ“ÁÄÇÈ…ÆÉÌÍwËÎÑÒkÐÓÖ×_ÕØÛÜ˜ÝßàÙáãäTÚåèáçéìÛëíðÒïñôÉóõøÂ÷ùü¹ûýeýH0ÕÀ‚ELÈpÓÂ†)=ŒH±ÑÄŠ
]ÌÈñÏÆŽ ñ|I2RÉ“œFÿ¢\©‡¥KH*_Êìs¦M+5oêÌ²³'Ÿœ>ƒ"*´è¢F“ú@ªÔ(Ó¦BŸBõ)uêÎªVobÍ:s+×—^¿²+%Ù²%Ï¢
©vmÇ¶n3Â�[q.Ýˆvï6Ì«7!ß¾ÿ(xp¿Â†ó!N\o1ãxŽ·‹,9åÊå.c§y3¸Îž»�íŽôÚÑ¦­¡N-�µØÕ®›ÁŽm�vÖÙ¶‰áÎ­�7ÔÝ¾{î�xÒáÆi!O.�yTçA—Cg%}:ªêÖMaÏ®�»Vï6·ƒO9^¦øò—Î£¯¤~}1÷+ÛÃw$>£úöáÏ¯‘?[ÿ í  èG�þ” ÿF.øŒƒ5!NG…º�a†ªpè—‡mbK#V¢‰'–¢Š+*Ö¢‹/6£Œ3BV£�7N–£Ž;ZÖ£�?’SÁiä‘H&©ä’L6éä“PF)å”TViå•Xf©å–\véå•HÀ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiç�xæ©çž|ÖIÁ*è „jè¡ˆ&ªè¢Œ6êè£�F*é¤”Vjé¥˜fª©¤<p †*ê¨¤–jê©¨¦ªêª¬¶êê«°Æ*ë¬´Öjë­¸æktPÀ¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíKµØ:›XÐ�à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæÛ.
°Aó ðÀlðÁ'¬ðÂ#��;
__CPAN_DIR__ src/widget/templates/images/Tree
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_loading.jpg
ÿØÿàJFIFddÿìDuckydÿî&AdobedÀ

E‡vlÿÛ„ÿÂÿÄ¿	!"#1AQR$2r3&!1AQBðaÁá#¡C$!1AQaq‘¡ð�±ÑÁáñÿÚë‹²Ó$2üÑ ƒ«ƒÈlÅt	M%9MÉ‰AèÿÚÏö\(L¾Söì]/fÜ6kŒâ�:W€ì^~Ç­|òú?ÿÚH°Ä-»W.qï%ñÆbña.ª¶§ÿÚ(¥L’u‘D¶ùiõ>—"ÙZ÷èH=ŒñÿÚ?mmfªg±”$i-Zò^®r:©)¶V
:³‚rÞç
îÚúêä
ü†¾î_ ö¸‘³ÿÚ?}=7ÖºŒÕ_1]ü¡Llw*J@¾èb»‡Uç¯¯|vÿÚ?]ƒ%â5jlN]&6¸]Áb(©â‚hŽ‚!¼LP<@IÔ�<®'B“÷
:IT¤›ôQÜÂd›¹)ÅÝ·p©¨›½î�6=2d®8ÞÜ²9~—qÔˆ¶P#çk¿ASC¦tÜ�y7˜Jž?´Å-ðR¦ü^šuOcd”h=^¨šItôH†ë¤uPM¨×”â*V¾�Ù9òâæÇ�y7K�FIlÙ}÷äÝZëÇôQ"Tl‘[îó��ä_Of´à;,~á^L©9kåfÌŸŽÿ§ÿÚ?!0“æaÇ–
¢1$P`,À�j†Ð€å7ÔX$©8P8(		+åRÐTa4bhz<”•â‹RæE}Ê÷ÅÓÿÚ?!>æ8V	ÕöTFD
Lî	Î¶Ãø[ôSÅCÌCkÍÆÑŠ™˜@$ï—$ª}†‚XVYI(¯ãnë9¯'Xù1ÓÿÚ?!ÜØz
*H	À Ù¾óÞ¯×x©hÐ{úï5§Á™˜Yd,ƒ¡uªó—x;¼7züËøÏjð«~>“ÓÿÚe;rÿÚ?Êæ¾Bª'‹MË)“Æ¸UFî�nËÜi%'Ä¬xvh©… ³ÎŸçÚAÒï#ü�èÄÚáüñ^¢†¸œ¿§ÿÚ?G–Õ§g•À$3'V*2$!�"
aFv‹îîô8¡!)`Uˆœ‚Ë@•‡É”bàE�‡®á¿Ú%Çócpµ®ÓS0v�êeéÿÚ?q�vDÀX‘$À‹Žƒð V€a,I™¦±‡—m�Ø{Q`Y¢IhlbFI$î€€S‚–	>áÕÆ±cQss\½¾w-ª?šþ'ÐÿÙ
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_grid_z.gif
GIF89a€999!ù,Œ�©Ëí£œt‚zi¶¸kÏ}M;
__CPAN_FILE__ src/widget/templates/images/Tree/document.gif
GIF89aÄøüþõùýüýþ÷ûþûýþúüþùüþüþÿ×Þâûüþïô÷õúýÛàãÚßãêîñØÞâôùýìòöçìðöúþöúýÙÞâöûþåëðíòöþÿÿýþÿóùý_€ŸF^uÿÿÿ!ù,mà'Ždivhª¦e·½p¼um„È1MvHwqÀ ' u0H`XP&–¢¨SéH„Á�ôÓQ4€Xl0l;ŒŽLœ
…x‚@šs¯ék2€g}€€††g‡ŠŠ‰‹‹�Ž‡�‘g+—[&š"!;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_grid_l.gif
GIF89a€rrr!ù,Œ€Ë¦
S„o®jÎ’k¯âH‚æ‰¦êÊz;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_grid_t.gif
GIF89a€rrr!ù,!Œ€Ë¦
S„o®jÎ’k¯âH6[vZé´F-:q¾;
__CPAN_FILE__ src/widget/templates/images/Tree/plus.gif
GIF89aæ999† ÇDDDîñõ�œÅCCDìïôçëñïòöûüýùúû…ŸÆþþþÒÙåØÞè÷ùû…ŸÇíîðãçï‡¡È„žÆ¾ÉÙûûýðòöËÔáÛáêßäìäèïüüýßâçôõøüýýåéðëïôýþþÐØäàæíCDDåêðrrrêîóÉÒàÄÎÝòôøôöùâçîÙßéëîóÞãìòô÷×ÞèÓÚåêìîøùûÚàéàåíÑÙäðóöóõøÃÍÜùúüßåíö÷úêíóèìñÊÓàöøúÞäì‡ Çâåêþþÿzzzy–Áÿÿÿ!ù,x€I‚ƒ„…†‡ˆ‰…HŒ�Ž‹ƒ"/‘I	5,!D‘œ9-‹F
4@0¬„H
¼C2'G¸<>1E%#‹B+=.8)‹:? 76
A;Ù¸(&$3*‹Žñ�ŠôõI�;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_expand_plus.gif
GIF89aæH999~šÃDDDCCDïòöçëñ€›ÄîñõùúûìïôûüýþþþÄÎÝãçïÙßéÛáêÚàéýþþßåíëïôùúüøùûÃÍÜÞäì~™Ãâåêðóöäèïö÷úÉÒà¾ÉÙàåíöøúåéðÓÚåðòö}™ÃšÃàæí}™ÂÑÙäüüýÐØäØÞèêìîûûýíîðÞãìÒÙåCDDòô÷ôõøåêðèìñêíóóõøâçîÊÓàËÔáòôøßâç›Äüýýôöù÷ùûßäìêîóëîóþþÿ×Þèy–Áÿÿÿ!ùH,{€H‚ƒ„…†‡ˆ‚F‹Œ�F‡FG’-@3C�’
?#š†‘�.	8=�D),	5
/%�>½E�21A+*Ã¥ ;<(�76!09$�B4&":'�ŽŽ‰óôõö÷øô�;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_blank.gif
GIF89a÷'ÿÿÿþþþýýýüüüûûûúúúùùùøøø÷÷÷öööõõõôôôòòòñññïïïîîîìììëëëêêêèèèçççæææäääãããâââáááàààÝÝÝÜÜÜÛÛÛÚÚÚÙÙÙÖÖÖÕÕÕÓÓÓÒÒÒ½½½___!ù',OH° Áƒ*\È°¡Ã‡#JœH±¢Å‹1;
__CPAN_FILE__ src/widget/templates/images/Tree/blank.gif
GIF89a€ÿÿÿ!ù,„�©Ëí£œ´Ú‹³>;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_loading.gif
GIF89a÷œ¿ó“·ì{ ×žÁõ¥Èû%g¸ŠªÚ�´é¡Ä÷–¹îv›Ó‰©Ù„¤Õçî÷´Ðù±Í÷îóú�®Ü£ÆùÄÔì�³è�°àøúý�°äŸÁóñõû•²ÝŒ¬ÜŠ­âµÑúûüþ|¡×…§Û¸Ìé’µè§Éüƒ¥×Š­á‚¥ØùûýˆªÛ®Îûõøüš½ï’³æ�¯âèïø�¯Þˆ©Ùþþÿ›¶ß˜´ÞÉØî±Íõ¨Êû€ Ï‚ Î†¨Ù�¿ð×âòˆ«á…§ØŒ­ÞŠ«ÜŠ«Ý�Ê‘¯Ü®Ë÷¤Æùˆ©ÛÈ×î�¾î¨Çô‹¬Ý´Éçˆ©ÚÜåô•·éŸÂô�£Ö~¡Ö�²ä‡©Ýêðø°Îø¬Ãå»Îêkkk¯Åæ›¾îœ·à„¦Ø¯Ìõ¯Íú–¸é} Õ£Åø}œÊ÷ùüÇÖí�¬Û™»íÅÕíááá°ÌõwœÓÁÒëžÀòëñùÒÞñ–·çô÷û¤Åöˆ¬áßçõÂÂÂœ¾ñãëö”±Ý�¼é˜»îŽ¯à‰«Ü·Ëè�±çˆ¬â™¼ñ�¦Ýÿÿÿ!ù,ÿ	(PEƒ&ô`FÃ�<I„X± �àMÀŒ(0‚ˆ
u*jc Œ�)¨$°
…L`¬éÒ¡C�#$èteÁv²Pq@ô 7’"XáÄÀ	,†<˜
§ 
²fe1aàh¸ Áà Ò¦Å£¥ 
?tüÈõ³Ð†¹s—Pt¤@‚¿	Dàd�a"
èa(Š�!·8gà™Š¼#… \¸q%ƒÓ9.Pˆ0pO	>°as�Â!6ì!B0À£�ïßÀûÄ1� ’+_þD×„!L|@½uL`9Æ”4
Â+ø²EM‘€ (!Câ	‰U\ 'è¡�œbæë¯;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_child.gif
GIF89a€!ù, Œ�©Ëí¢œ`ÑkïÌ:òþi!¦tÒH¡[iVÏÇòS;
__CPAN_FILE__ src/widget/templates/images/Tree/closed.gif
GIF89a÷¼ÐÙã³ÊåºÎæ°ÈäÎ×ã§Âá®ÇãÀÒçÁÒè¸ÍæºÎåØâîËÙêªÄâ¦Áà®Çä¹Íå·Ìæ±Çã¯Çä©Äâ¼ÏæÕàí×áîÂÓèÈ×éÄÕéÅÕéçíónˆ¨æìò«½ÏÁÓèÙãîÃÔèÜåï­Åâ­ÄâµËåÉÙìrˆ¢àèï†¡À´Êäg‡ªÌÚêÒÞì{–·Š¦ÆâéñÊØêw‘°u“³“­Ì¨»Ðr‘±±ÉäœµÒÛäî–®Ç–±ÑÓÛåˆ¢½Ì×âÉØê˜°ÉÜäï¿ÒéŸºØ~’ª­ÆãÆÔäpŽ¯£¿ÝÁÑã¼Ðçäêòj��ÎÛë‰¦Äy�«„žº«ÁÚ† »ßæðv’¯ÆÑßÖàí²Éå«Ãáãêðd…¨Œ¦Å}š¹ßçïl‚œz˜¹”«ÅâéðÊÕã¾Ðç¿ÑçÆÖéÞæïhˆ«s‰¢j‰ªž¿³Éã¸Ìå{˜·¬¾Ð¾Ðè®ÄÞáèð…¡ÁÀÒèÍÛëÓÞìµËäÊÙê¯Æã€™·«Åã°ÁÔ±ÁÔ·Ëäœ±Èaƒ§²ÃÕ¾Ñè¡¼Ú…Ÿ½eŸ��»yŽ©‚˜´vŠ¢ÐÝì‘¬Ìo†¢èíó²Èã«ÄáªÃá°ÆãÇ×émƒžd}œèîô—³Òv”µÔßí‰£¿x•µ¬Åã¶Ëäl‹«ÄÔè¯ÆßæëòÎÜìÒÝì±Èä¨ÃáÏÜëäêñ®Æâ¶Ëåt‘¯àèðåëñ¿Ñè«Äâm‚›oŒ¬¯ÀÓ»Íâ¶Ìær�±¨ÃâÝæï¥ÀßÍÚëÓßí®¿Ñqˆ¤©Ãâ!ù¼,ÿy	H° Áƒyeò1%ŠM4n ùC ¢•W×<	²#L >°r½ù dI�`~TjÄÁ¨U¦´ˆ‘“ÂË™=x]âÃ$†**µ„è±àÂ¸\Œá5ËFQ˜ìˆRTÊÉ-x€d8Â+•¡:-ÈÈ ÉÌO@ ³!¯*]D`@p ™
@P€@ƒ†Ñ(€ÐÆ§lÝ0Dœ%¬’é‰Y$D� AT&d)áÅ"Î#H­òX�Ç€ˆÅk‹”Q°eÙ´§…]¤
8øÄKMß´„ÛJ2ˆ�\éAÄ«ÓK‹`¨x1£C!JŒšLúâj ]‡P¤)’(¡û÷ð;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_grid_p.gif
GIF89a€rrr!ù,Œ�©Ëí£œ”�‹o»Sþy8ŠK;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_grid_c.gif
GIF89a€rrr!ù,Œ�©Ëí£œ”�‹oÝ¼û†L;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_grid_x.gif
GIF89a€rrr!ù,Œ�©Ëí£œt‚‹3¨¼û†`;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_expand_minus.gif
GIF89aæI�œÅ999üüüóôö��Åîðóéìðõö÷ïñôþþýúúúâæìÿÿþßäëÔÛåñòôûûûýþÿÒÙäùùùDDD�œÄ€œÅøùùÝâêÞãêòóõ÷øøÜáéÿÿÿþþþËÔàùùúêíñÚßèôõ÷äèí¿ÉÙÕÛå¾ÉÙëíñôõöÓÚäÌÔáÅÏÝðòôÍÕáìîòÖÜæíôþñóõþýýÊÓàüüûçêïºÆ×ùúúåèîãçííïòÛàèÄÍÜ}šÄåéîþþÿö÷øëîñ÷÷øæêïèëïÄÎÜìïòy–Á!ùI,€€I‚ƒ„…†‡ˆ‚H‹Œ�H‡H7%,.0
?(�'F+&9!)�=$¦†H4*:­C
±…H<Á
�"E;A8Ç²6G2 	¼„HD/5	�B-#3@1>�ŽŽ‰øùúûüýù�;
__CPAN_FILE__ src/widget/templates/images/Tree/Tree.css

.dojoTree {
	font: caption;
	font-size: 11px;
	font-weight: normal;
	overflow: auto;
}


.dojoTreeNodeLabelTitle {
	padding-left: 2px;
	color: WindowText;
}

.dojoTreeNodeLabel {
	cursor:hand;
	cursor:pointer;
}

.dojoTreeNodeLabelTitle:hover {
	text-decoration: underline;
}

.dojoTreeNodeLabelSelected {
	background-color: Highlight;
	color: HighlightText;
}

.dojoTree div {
	white-space: nowrap;
}

.dojoTree img, .dojoTreeNodeLabel img {
	vertical-align: middle;
}


__CPAN_FILE__ src/widget/templates/images/Tree/transparent.gif
GIF89a((÷ÀÀÀè×gÔˆ0ÿÿÿÔˆ*ç‘2¨!�æàé$ç0‘2H!º`çL‘2H!º`ç$‘ëéh�î‘8ÿÿÿ‘2‘«‘ëé¸éäéÜçdÝtuê¼�î�ûxÿÿÿ�ûqÝu!¨Ýu,!º`¨éÜ@ê$éä@ê(z
ì¨éÜ¨ÿÿÿè,Ý›‚çtHè(‚èŒÝ‚é@‡€–Hæ‚°é@‡Lèè@è�‘È!ˆé\‘Q¨‘mé´è¸‘È!ºXé„‘QHèÔ‘È!ºXé ‘QH‘méäæ„Dº«Í0!�Ôˆýð0ç�ûl !º`é@‘ÈGi ê‘Qá8‘mGn8Gi(�ûq�Õ†�ç¼é`�çÈê�î�ûxÿÿèäê�î‘pÿÿÿ‘m‘	¼È!º`éÄ‘	’!º`êÝíÝí b¦Èáb¦ÔéPGi(êD�î‘pÿÿÿ‘mÂÂÞáÂÂãGn8Gi(ÝhªGi(Gi(êPê ÿÿÿê¼Ã\”Á pÿÿÿÂÂãD•ÕGi(c c EµGGn8I¼�ê†Ôê†Ôê†Ôê†Ô¨ê Ýltê¨I¼�I¼�æà£æ‚°!ù,((CH° Áƒ*\È°¡Ã‡#JœH±¢Å‹3jÜÈ±£Ç� CŠI²¤É“(Sª\É²¥Ë—0cÊœI³¦Í›8	;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_grid_y.gif
GIF89a€rrr!ù,Œ�©Ëí£œt‚‹3X›v[}’‘�ù Žj;
__CPAN_FILE__ src/widget/templates/images/Tree/treenode_grid_v.gif
GIF89a€rrr!ù,Œ€Ë¦
S„o®jÎ’kÿ�¸e¥uNi´Râèµ;
__CPAN_FILE__ src/widget/templates/images/Tree/minus.gif
GIF89aæ999ˆ¢Èüüüïñôéìð�œÅóôöîðóÿÿþõö÷þþýúúúâæìˆ¡ÈìïòìîòñóõðòôûûûüüûÌÔá‡¡ÈÄÍÜèëïÛàèýþÿÕÛåÜáéþýýåèîËÔàÖÜæ÷øøÚßèßäëzzzºÆ×çêï¿ÉÙ¾ÉÙêíñÔÛå÷÷øÒÙäÄÎÜùùúæêïÓÚäãçíòóõÞãêÍÕáDDDrrrÊÓàÅÏÝÝâêåéîôõöíïòíôþþþþñòô„ŸÈëîñäèíþþÿôõ÷øùùùúúùùùö÷øëíñy–Áÿÿÿ!ù,~€J‚ƒ„…†‡ˆ‰…IŒ�Ž‹$&73"9H
‹',2(:›„I)8A ‹6/0®*²§+À45#§!;1GE=¼ƒI%	-
JÒ‚I.>	F
‹@CDB<?‹Ž÷�ŠúûJ�;
__CPAN_DIR__ src/widget/templates/buttons
__CPAN_FILE__ src/widget/templates/buttons/paste.gif
GIF89aÄüüüÊÃƒæææòòòÜÜÜÌÅ…¯¨h·°pÃ¼}«¤d»´t¿¸y³¬l¨¡b÷÷÷ìììáááïí%ÇÀ€TLIAn¾ÿÿÿ!ù,nà%Ždiž(*ER*Rð±0eRE!Ïln“”€PB$
¿eÂl:'ÉbZ©Z«ÑeÁ­X¾àJ–¢(Wè´¸D9¸+Žk|Ì¨WøühèWW€c	„‡ˆ{J
ŒW�c5•–Š&WW.œ!;
__CPAN_FILE__ src/widget/templates/buttons/justifyfull.gif
GIF89aÕ'2–16š5:ž9D¨CI­H-‘,?£>B¦AY¼XF©EWºVcÇbbÅaG«F8›7.’-5™4jÍiT·SmÐl1•09�8fÉeA¤@U¹TRµQ>¡=_Â^0”//“.< ;M°LP³O]Á\4˜3N²MK¯JZ¾Y,�+!ù',CÀ“pH,�È¤r‰œD,ŒB2"‚€Éíž›DJ\<§`òº“ŠÌ§qÐT ”‡iß~û‰VXZl|‡ˆnA;
__CPAN_FILE__ src/widget/templates/buttons/bg-fade.png
‰PNG


IHDR
d0®6ÀgAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<CIDATxÚb<sænÀÄ€°022MÝ”>tý=�5|Ð>RíÍþ£ºGuß
zÔcƒÎi£†:Ã	HGÃ&�(x}IEND®B`‚
__CPAN_FILE__ src/widget/templates/buttons/inserthorizontalrule.gif
GIF89a³I­HN²MY¼X:ž9jÍi]Á\6š5?£>T·SmÐl2–1fÉeD¨CbÅaççç!ù,"ðÉI«½8ëÍ»ÿ –KSH0Ç`(”#Ï4Þx®ï¼;
__CPAN_FILE__ src/widget/templates/buttons/createlink.gif
GIF89a÷´øùúðñô‹‹‹óôöccc666555—È˜[[[ßßß˜˜˜ÔÚìœÎžJJJ€€€]]]òóö÷øùGGGîîîAAAèèè®ºÝ—Ìœö÷ùq™ÇÞÞÞæçç—Å˜Þäñþþþm§o444¹Éëƒ¹…ÅÅÅÏÕèºÌîÌÙîkmk„…‡¸ÀÚŽÂŒ¼ÊÐÙÞë¨µÚllnŠ¼‡eee¯ºÚzzzdt¡…¶…“¶òÙàðblcššš€°�ˆ¶‰fv¡fik---£ÄçŒŒŒÀÁÀbbb™Ä›nqo¤·Ï�¸Õ™¿ÊHHHt¢…m¡ox«z‡°íäçí|§ív£ww¦zdƒºëëë•ªÜ§ÂÝ�‘–RSS…º‡NNN›ÁÉW�\•¼·Ößà§Ó®EEEZZZÈÔØööùïðókokííí„´†¼ÅÖáçó¨Ö°îñóÓÔÖ¹Ãß°×»‡‡‡ÌÌË777`bdùúûjŽ¬³³³f”—ÌÜØììì‰‰‰�¸’~˜Í—Ð™o¡ÃyŸ˜‰À‹y¯vq©t   «¬¬šºëiim‰­ð���ÅÖñ…ˆ‰°¼ß°½ÞìîòÖÖÖ“““·ÎññññËÑãfw¦{¨·×ØÙm•´œÕŸ‹Œ�ÎÜìÝáë¦´Ü–ÔMMMnqn\\\DDD¬¹ÞÂÊâåêö¬Î³}}}ÆÆÆPYP†”¾�±Ý”””�¼Ž­€x¨‰ÜÜÝ‚‚‚ëíòååå„„„ýýþÿÿÿ!ù´,ÿi	H° ÁY"Xaƒ´f€ÕEL‹3^(Z`VA	Nî¸Qƒ�¢©öCp#^ø08@‚Ô£*v¤Dò(€¦–fzXeH«(tP8ÀÄ(°b¢å+=~$
@Tš!xì@r£É¤%Jj�áÚG&@g¸2ô¤Ï(=Öp½€�Š2žRø¨´!Qh$ 5`Ó+‚(Lé àTHJÈ"àˆ€PTTá±ðÌ§,?’LhPJ�ˆ8)ˆ%çJ3¼RhP�3,"àªQ @(` ‚JÄ$Ž)!4„pÈ�€NyrxJDl(!ˆcàË¥ÅãËŸ/0 ;
__CPAN_FILE__ src/widget/templates/buttons/removeformat.gif
GIF89a‘ÿ±±ÐmmÿÌÌÿÿÿ!ù,6œ�©Ëí¢|AX\ ƒÌçEáè}ß"’]"m
+bª
ñ!õµ�ûèB—‹)ä;>–Ì¦£;
__CPAN_FILE__ src/widget/templates/buttons/undo.gif
GIF89aæBPìQìÍÚöOÙöùý[«ìãêúðôüPìýþÿ"UìœµîiŽý&Wî$VíQ›è²ÅïPyëPzåÅÔôEŠäŠ¨é|šâõ÷ýßèùÏÚø¼Îñ2hãz›ìô÷ý ¶êŠÜô:tÜ;içOí!TìÆÔó°ÅðÌÚölŽúöøþ¹ËòµÆíRƒàöøý„¤éèîûûüþs˜å:gïÚãøD‚á0`ïâêúTŸéiÀñT|× SìzÁíOì‚Îñ'[èOìïóüÐÝöLîÿÿÿ!ùB,z€B‚ƒ„…†‡ˆ‰Šƒ	‚�‹‚'41#0Š@
!
">†A‚9+=8-,…A¡3 .B²:6;%ƒ*…<?„)É„7„�ÕAááƒ2“‚/$(èB5&Åîîö÷ö�;
__CPAN_FILE__ src/widget/templates/buttons/outdent.gif
GIF89a‘1zè'Œ&!ù,%”�©Ëíÿ‚œ4¬Š/¦	@xÇfáé‘ h¨à§�“&Ó.ŒçM;
__CPAN_FILE__ src/widget/templates/buttons/backcolor.gif
GIF89aæb¼¼½ãããÐÐÐÏÐÐóóôóôó¬«¬ƒ¤êÿ{ããäïóéº}µ—¤ûWÌÉæ‡ÚDüöÎ–½~°]õï÷óÿÖEûýàÿÕ¾ÿ=qÛÐÏÐ¸Ÿ†�ÙÇ¶íÍÅÊÿOÅ¸ÿúåøýµèôôóTÿãÿ×•ÿ”˜ÿé´¾¶çÐ—ÁÍûvÆÍ´Íáýÿÿl°¶È¨.Ô€ÿƒ««¬õùú÷úùÿÚþö²{¯¬¬¬Å“»žâ•�Íu�³]ÉúïöÎ‰ÖôîöïÐã´Îf×õ½•Àíï÷·Ûö««­…®"?Á½j´\÷™ÿà§õ¨¨òÖ·ÿ¨ÿòæúÿÆŠ­ÉÖQ|öíë«¬­ÿŸÿóôôÉ™ÊùÚù÷ùp¨+”éª­“ÿZÍè–¦ÿ@@@ÿÿÿÿÿÿ!ùb,¦€b‚ƒ„…†‡ˆ‰Š…a>B7D,@a‡aX?LNM;E–…Z9VK&]'_R3†(S.+! P<ƒ`¿À¿ƒFC^*¾aÉÊ`ƒ-
¾W"Ì‚6YAI¾àà	Ùb\Q¾ë`1)¾ùú`O#%5$zÐðUÅŽ€Ñ�†%
F‰	É–/¨H\Ä±£ÇA�;
__CPAN_FILE__ src/widget/templates/buttons/wikiword.gif
GIF89aÕ2<\ÇZ…ßêïú›«âìïúc|ÒMnÐª¸ç´ÆïMsÕU~Ûèëø?_ÉÀÊí~”Û^xÑÉÓñúûþ¯¼èeÓJhË³Ãì¬¼èˆ�Þ_{ÓGeËC`ÉVqÏXuÑIhÍýýþ|’ÛMpÒWrÏA_ÈÍ×òCaÉ@bËFeÊ>^ÈRoÎ{‘Ú—«ãáæöÕÝôKkÍGhÍ¶ÄìsŠ×9YÆÿÿÿ!ù2,Ÿ@™pH,�È¤RAÅb‡âá‰Š)•Ñ 8U(Å‰Š+ÂXªIÑñ�dŠÈÇ!}¼4„!AózD‰$!
C
!$F""G0‘0G).&	¦.)G%	0
0	%G+'
0
'+G ÀÊH-2Ò-IÔÚÜFOáâã12A;
__CPAN_FILE__ src/widget/templates/buttons/superscript.gif
GIF89a‘QìKvø2–1ÿÿÿ!ù,œ�©Ëí^ŠQž`ØLãY^˜‘âx‚_Æ¶î·;
__CPAN_FILE__ src/widget/templates/buttons/subscript.gif
GIF89a‘QìKvø2–1ÿÿÿ!ù,œ�©Ëí£œNc£Í’ëýau”iNÁ	¤ä{;
__CPAN_FILE__ src/widget/templates/buttons/space.gif
GIF89a€!ù,D;
__CPAN_FILE__ src/widget/templates/buttons/indent.gif
GIF89a‘1zè'Œ&!ù,$”�©Ëíÿ‚œ4¬Š/¦
ÀxÂfáé‘�¨‚_BNZ<·ï�7;
__CPAN_FILE__ src/widget/templates/buttons/bold.gif
GIF89aÕ<ržëv’ÝÄÖõ±ÂíQqÑêîú´ÄíÃÐñ¡µéRqÑMlÎ|•ÜÒßöÞçö‹ Þx“Ý–¶î”¯èBbË”ªätŽÙk’âÿÿÿ¨ºè‰žÞÅÑñÈØõQyØ‰¦åVrÏ?_É²ÊóQqÐ\xÑ@`È§í�£ßƒ�ád†Úl…ÕIjÍ ²æ|¥ìÍ×ðEiÏ?_È\zÓ�²îtŸëMmÎUtÑµÄíHgË£¶é~Ÿäb€ÖsŒØ ½ði˜ê9YÆÿÿÿ!ù<,w@žpH,�È¤RHÚ9Ÿ»N
¹X­Fã49î> ƒx–Â­hÞÜ®èÀ¬�»×[h	]dÞQ…ÀO´81^„…*
‚p:Ž7("‹sB
%–E‹,¥6.‹:®¯0&	GPO•K»¼CA;
__CPAN_FILE__ src/widget/templates/buttons/underline.gif
GIF89aÕ+EiÏ¿ÓôZ„ßÀÓôi˜êHmÑ<]È?_ÈDhÏ™¸ðFjÐµËóq�ë±Âí`×HgÌ|¥ìW€Ü§ÂñŠ®îw“ÞAcÌq�ÜGgÌGhÎ¡µèInÒh…ØSqÐMoÐQxØ>`Êf”èMpÒMsÕCfÍLpÓGlÑ=]È?aË]{ÔKkÎ9YÆ!ù+,uÀ•pH,�È¤r¥j6‹Î§P¨Š‡�V5t.ÅÇÂ	•pŠ	×¨J Š©Ä:Ù;“9Q±Cz]E$‚S…D‰+"C#G' %

+
H&©JM¦K·]QºsA;
__CPAN_FILE__ src/widget/templates/buttons/redo.gif
GIF89aæBPìQìÍÚöOÙöùý[«ìãêúðôüPìýþÿ"UìœµîiŽý&Wî$VíQ›è²ÅïPyëPzåÅÔôEŠäŠ¨é|šâõ÷ýßèùÏÚø¼Îñ2hãz›ìô÷ý ¶êŠÜô:tÜ;içOí!TìÆÔó°ÅðÌÚölŽúöøþ¹ËòµÆíRƒàöøý„¤éèîûûüþs˜å:gïÚãøD‚á0`ïâêúTŸéiÀñT|× SìzÁíOì‚Îñ'[èOìïóüÐÝöLîÿÿÿ!ùB,|€B‚ƒ„…†‡ˆ‰Š„Ž‚	‰0#14'‹>"
!
@ˆ,-8=+9‚A…B. 3�°„*ƒ%;6:½ƒ)„?<…	„7Ô…2ƒAååß„($/‹„&5î„�ó÷øù†�;
__CPAN_FILE__ src/widget/templates/buttons/cut.gif
GIF89a¢êÀÀƒ…‚êˆˆ„…ƒÈÿÿÿ!ù,5XºÜþ0ª1¤«–��uD(LØC,!U6¡
jÌ€áYØt§œ8èæ;
;À äåk:	;
__CPAN_FILE__ src/widget/templates/buttons/justifyright.gif
GIF89aÄ.’-2•1>¢=5™4:�9C§BH¬GN±MS¶RX»WüüüfÉeiÍh„Íƒ]À\aÅ`,�+çççÿÿÿ!ù,; $Ždižhª®gÃ,�“ ‡QÄ£ýÀ`�EátˆR%Qµ[n§¬BHÍlä¹JZ­(í�K.—B;
__CPAN_FILE__ src/widget/templates/buttons/inserttable.gif
GIF89aÄ¤¡œ¥¢�¦£žÃÁÀº··ËÉÈÆÄÃª¤¨½º¹ÎÓÍ¨¥ ª¨£ª§£æææóóóêêêøøøÀ¾½ÉÇÆÍÒÌ?£>TLIÿÿÿ!ù,fà%Ždižhª^ŒÌ­°À$VTïÿ¾ŠîÂ)Â�ei)0�Ì$QB­Z«Ò
d1p½Ü¬cì�ÍäJbi»ßîìcþ@Ðíôlcß ðý|R„…†…C‹Œ�ŽC+‘’“"!;
__CPAN_FILE__ src/widget/templates/buttons/italic.gif
GIF89aÕ3›«â<\ÇÀÊísŠ×9YÆ´Æïêïúª¸çìïúU~Û¯¼è@bËáæöCaÉýýþ{‘ÚeÓXuÑÍ×òž®ä|’Û^xÑMsÕc|ÒÕÝôA_ÈGhÍèëø?_ÉVqÏ>^ÈMpÒ~”Û³Ãì¶ÄìRoÎZ…ßC`É¬¼èWrÏ—«ãJhËˆ�ÞGeËúûþMnÐIhÍ_{ÓKkÍÉÓñFeÊÿÿÿ!ù3,RÀ™pH,�È¤òx F¬¥ 	¥¤ÂÁÎV1
‹(‰*¬àdjl°€‹*ãD^¯¬¥y�9
j.	p$X0^^RA;
__CPAN_FILE__ src/widget/templates/buttons/insertorderedlist.gif
GIF89a‘KvøQì'Œ&ÿÿÿ!ù,&œ�©Ë½Âƒj�³¨’zj}Oè‡–qäÇ+d¾�…bJÜr¾;
__CPAN_FILE__ src/widget/templates/buttons/right_to_left.gif
GIF89a³
G«FD¨C@¤?=¡<I­H5™4.’-1•08œ7Qì!ù
,;PÉI«½8ëÍ»$ §#@RÉ(A‹¦– ô”Ü× ºtã„Bø‚U

dX9(œ#Å  Š®Ø,6;
__CPAN_FILE__ src/widget/templates/buttons/copy.gif
GIF89aÄýýýüüüðððëëëÁÁÁõõõÜÜÜÏÏÏ³³³ííí÷÷÷ÚÚÚ®®®ÄÄÄßßß§§§ÑÑÑÿÿÿAn¾!ù,Oà$Ždižè(­ìšNR$ÏÒÏr�Æm £·H«eâ­p¹" 0ÒŠ–�å+§"ñSµ¦«EWÉt@ã’$Êb¤I’+ñ@¼½Ãûkÿ
;
__CPAN_FILE__ src/widget/templates/buttons/list_bullet_outdent.gif
GIF89a¢G¦ðRè`†ï'Œ&ÿÿÿ!ù,(HºÜþ0J&‚˜,€ †ÿƒS]Xi>ã©qèzJzÎtl©[÷‚6Yÿ“;
__CPAN_FILE__ src/widget/templates/buttons/aggregate.gif
GIF89a¾÷ÿýä�£ÙËGhÌÑllQëÊ--«ºèÝÝÝ³Äíÿl@@@¸Îóöw’ÜêÿÖY„ß¯Ð®çççFªEt²]¶µµcíò•ÊE†ãjÍiN¥í	øÐË·ùÿÌÌúíìAn¾—­ämÊòöë÷�žØøùùÐHHºÅØZœì­ðÞþû…¥éÃÕô9YÆîíí¸Ÿ’ÈQüüü…ÍÉÂ‚ƒƒ‚”˜ÿêïúo«1|¨ë,�+V¹U˜Ê˜Lwõ‡·ˆÌ‘Ð«¹ÛõøýÓÓÔcedñññ·Ûö¹²rë¸»ÃÂÂèˆˆi˜ê111êêêÈÔØu¨zðôüoŽ³6fê?£>f†ÙçÁÁ«¤eK‚À†Õó|||ÚyyÌÙõ¥¢�[ª~¨ÒQqÑðñôöööå––ÍÓæÔÜìøÝÛb~ÔZ[Z$Wìóýs‹Øâáá˜¶ÙÌÌË¬¬¬¿ÊëðÑÑÆËÕñEüúLîƒÆ'‰Å‰:tÜÒÍn›š   Ê•¼ržë¶|²ûœÿÍÒÌ™™™ÔÞôQyÝìîõ©·©9�8

2–1^zÒ~»G µêMrÔ—¥ýk´5™4â¢¢‹‹‹tœËŠ³ÜLmÏ�²î>^È˜ÁÌœâ—¸ï›Ð�‘¤à¤Ãæ¨¥ ßåökŽüóôõM±Lev£XvÒ\À[âêúVrÏ7›6lnmSLI ¯ ÿ±±`†ïÈ1zè|’ßÿÊ#ŽÑŽwvoÉÇÆ½½¼A¥@ïí%åååOÙý÷÷Ø°-ª¤¨óóóÿ=Í´Í?Á½”éª€ÿƒWÌÉ­“ÿZÍèAaÊã´Î…®"¾žâ¨ÿ½•ÀúûþÁº{.ÔÍÅÊ]É¨¨ò³¬lïóé‹¯ËRoÎÐÐÐz›ì©ÁïûvÆããä©¨¥s˜åÖQ|¶çÐÏÚø÷÷ø ½ðûüþ×•ÿóôóÿl°U~Ú´±[*�)ÖŽŽÿÝÊäÊþº�‰®î.“.äçíáÍÍQ´PÔÙØ`”Ö’“”{¨·X‘™ÓÌ¦1m‡¿d†”¾G~'•¼·çëøbÆaW�\…‡ˆ'Œ&ÿÿÿÿÿÿ!ùÿ,¾ÿÿ	”!° Áƒ*\È°¡Ã‡#JœH±¢Å…þ2jÜ˜ñ¢@Ž ýyI²¤É“(Sª\É2¡-cÊDIp¦DS8sæüaòÅN\‚r!Ò¦Ñ£Crô¨T#Ò§P£J�JÕ «—0«jmYs«@S!Áò<è¡¬Ù²}: ¤D‰pÁŒx!QFW¯T›v<H`âÆ‚Kñ
±oCÃ3ÿÈúCØ#+W³6ž\·¢¿ÂîäÉsLWˆ¢/­Mz…¨CM½XÍúE Õczéa!·uî@È‘CÅšŽzt©œÐH6	‰ƒ³fÎžA¼œysçÏQÿ~Ô.�â†XÂcÿ¹–I¼øká÷DE•E££!£ü”½{Šö%z?ü]e©ÿŠÉ²Ø¥0¤Â6W\ÊG
ààƒ­€Ç„Rø�‘¤Bi¥¡ÆRqx�ˆI	J‚W¨�2ÑŒfÀAð­ ŸAwAä.<ðpÂ4³Š€HWÐ
*Yä}hÅ©ÖÚj°°Û?³qT[B/–X’Ã,P‚<M|A×Cv)DBmxq�œ™Ð�9îØã�A&…£Ž<ú¤�õ#è „ös‘yä™zX¨Wb…
jP)OTjé¥––âè?d`X¤†2ô� úè
�Hð„ ‹¨ÿsÃ¬7„©®ŠC;¸
+!�sk®»öúj¬µ
$®ªîÚj,Ç¢ŽG�~
ê Uh¤
AÊ-§]‹-BâJZJ1(àbè˜6d�á„›L4øâ;@„x¬âï¿«\˜áHid‚¦®ÔˆD)ÉA’¹ÂB›Ì/6		€€L4j©Õø7wX ‡ßü2C")@ÃMB+,°4#pˆn$\�)#ôìó°èdÐlg½p%B#X£I—¼í°&K,Ñ„=/£ÉÐlZQÖ$„Ä×`ƒ­2Ë.D²É(�ÝrÕ•jE®è¥‘+›zbB”bª÷š®ÿ×žEfôñ�
ù“Dˆ'®xâ½°øãŒä8ä�7NyåIÐ*Bùá÷waû-d·Enÿs.º¤ž:º1¸{Ð&v{ç}@t/§ä~Ê¾i.D®²o¼	ÌÊÄ#Å<3ÍP‚€:«¤Ì£-ý?,@ZB}ÈKv×{�ôaÆA�2EDdN5'„Â,7±ÌÝ _�"èÿU#(Àº@À� 
]0ÅÐ4r–³„_È‡ä°ƒ¨MâN«ƒ'8�#¤âƒFˆÈâ…¬ýcMÌñWØ\ a~õ»ŸAÚ÷¾øÁ0öKHé,7øð‡S€ÿÐ Ð­"¥ØÈ+4²D�ô­$pƒ¿èC’þôêw¿£âHJw:Öy±]ñü�‚ˆC^0®v
ÜéÎAÁb¯ø‚�à-àŽ0üg‘ä)£ƒ5¶p�-Pƒ�ÿX#§0;q”ÑðÁAü•³ƒDqŠ4Šˆ6ÉÉMD Æ$`	ÿù£ ¤AL�\0¢
$B
@pàB�²ñ‡Yhc.¬atÚ$"‘ŽxDÍ€@H*
òA»Œð Q`SÚ@„…„-a(E)�Nvò“¡åATÁ’š ,S˜‚qGLqSàzH)^AÏzÚ³žO	
‚�ÿT:äX²¢UBTµªv´ªR£@V²â,_-b"Ñ
èB»ó	Ä‹R¹ÛC4šr:¤ÉiÍâº‚ˆ‘šø
A€9\À;ŠLÈÚ¨»Ýí.Žÿ°h)ZÇ~
/Æ[ÅI²‚RJ„ÀúR²T¥&•!+¨D!RˆJ |¸Àpü#”ˆ$Œ
�€`xU ûìç‹2	€DAÁÞà˜¥à[Èë$‘H¨h•,¢I‚0"°,À¥@<ð‚.$¡J9Ú?¸P‚>€a	;ÀG%ÒaGìc	žàÂA>(Á™¨]HØD‚‡ ÁHH¡@äJ×nÿ¾5®s­ë8=z­‚«YÅrèSÿáŠÈCé|‡rñ`ƒæ¾óQñlH)~VŸU×gùìÜDÖ 
#¡\B.·8ƒ@n"â5H ÿa)ö2D»
�¯CB7ú6DÝ·@*RÚ”T bD@A˜€€¬1=ÈLÝ˜»ó® O`o¥eßù4�‚Ì„ŠÈˆâÃ ±ˆ?Œ¤6•©&~È
Ò…ƒ@!WA^Š&¤À’4H>‚aQ¬¡ Üõ.xÙú€ƒ¶Ä8à:[
h`0«Ð„lP	Hü°,È2Ø”å,+–JAØeÑ$Ë…\¡2 …š�ÐGðCÿÍc¨Â
âÁ.ówvH-ØÄ&F8	¯ˆ­APàd(ÿÃÈHnå’ãZè‚à÷Ñäìí?&G^Ä$n¨‡¦ëaƒG@ãZ¨Ãs2=ýjR­leR½êTçS[ÿ•¨Ä ‚‡i‘Zë�p„Eç)S�Ö;ìN¸Ê•­aÊÑ�Ž´¬K1„f3öIøï?| ƒ„	�Êh!Sš¾±�†°„)\áØÑfE6<T‹´âÝðŽ·¼ß��;ÄÞPµÁùb ’TÈÀ`ã‚,@#@H0DPˆÐ@4\­òÌ„(ÀÏ8“ÿÁ‹h 0;‚@òˆÿ0ë*“ÀrvÀ’$`y¾ì�H£�õ7X@æ¬v`Áá1 ¶2<âÁ(D¡Î©Å4pBj6	@:Òñ�w3ã/H×A¾[_�nþÈB
j`ˆ¶»À5¸=FÍ©rã
xÏ»ÞóžÝÏMÄŸ(„(PZ^ i(´~%Ñ‰2žâ2È³"zø‰Ö½?‚øGæ"_Îù}£vçG
‚_ƒô–ÙÎæÆYT/mL9îN@°m„Ì´¦6å@¸’ùÍ“»§Â³ºY�G—Dä%7¹R¾·ù)vˆ„p�´Û —ñw|€€iJ…ø„ÿ!†|^ð×¤4ÖÏ~8À½ÈE ��óQ�0%V9‹Yœ�Mý7V`
³@sg¡Kfq’5=p	ðÀ0X
H ÿQ|
±LyÆÓÔµ VÐ²å5×€æïóÝÄ~í·‚òG‘_)7Y�ƒŠ q`Šðv5@wQ
2—° sG(sùä	°
Qi‘#RhiQ…`^UÈ òPukaƒQ
ÎP†h˜†Ñ–Ûp)%p‡qÈmñ vè`
á…ÙÂ0>5ÂG<
`|+Ñ*`k%–Tøvˆ‘ˆutÔÿg
pÿ&‡qXšpÛ�«Ð„MˆNè„P¸>mµw° ÆP�ŠÌ�p�ÈGû´
�øg`
ÓÄgp0åp_64�•ð8g/«À³¥@Øü@ � mÿàAxæˆQB]£H`HPepŠ©È«ØM¤hŠ¨¨Š¬Ø6ÄÆCþP00�ôqp�B8z“¢8�8ý˜8Khû„<†q7Àò|G¡�¢3\$Î ÀsfÁsÔè Þð·WS÷²{‘�	Á‡ÂÓˆ×—„hˆeM	ò‡°Gp=á
*ÿ°±gÞ…’`â`Á@�kEd¡j�”J©ÅPÊ@À€bn5Y36³”P1ù¦pg`Œà•bÐ‹²ff¡’õÜÐ@pî _“:_£2ÀgËd�1‚m‚Œ@uÞŽt@Mù”QYH©”IÉ”N	•R©CïˆvrCwÓÃ�ÿp²™œY
·°)�çk â 	oÈ•gxa,Œwxäy
Ñx®éÓ2-œ÷y	š
‰™tÄ›fwl¥ Âé�³†	Á
Â‘ù’/p´µ	<ý‹‚—à(Ùa±S33I	ÁPÑåbÿG	5ó	 „ó'Rp¡	’ `ð¤išé×VÞ´IÃP‘rG0 ŠP J;s
º Z–
Qs7G×@ké#Ð@�¯P��:�`ÓØ	Á�˜ÓÔZÅ’ñ�H0ãÐŸÿ ‡¶Ÿ
£:•±6™¡™�Ù™Ÿ©^Ævj±DZ¤Fz¤uÓk9zl
ñˆð’ 'A^!…Uz9á…¥%lßÂ¥°)¥¶¤’fa*k¯yÁ9œgpkJ�¶ q‡r2!
€XÕi})ÙGÚ§x 	,éaJ’ à`¨¥yVå
;yÞ 	°õé¤P*¥a
À!£
À¨_—¢º î  f¹X#µ–q2 —H0?àcP—20g”
!Ôµ ¢Ñ�6)H:¬EJjá‰º)*€
	ÁZ¸éy÷ë:¾)ORs
jœTÜú‘ðÞúÜÚb$±©œC­'!Ÿ 	�
q'	+ 	^EîÊ¬ù‰:±¯BÓ¬þ:Õj4@3 ú¯Û©ªª»°S1°P¯›Ç°[±{±›±ŸÀ©¤q	Éã±û;
__CPAN_FILE__ src/widget/templates/buttons/-.gif
GIF89a€‚‚‚ÿÿÿ!ù,L`†¹š÷d±ÒëðÌ|{¹;
__CPAN_FILE__ src/widget/templates/buttons/insertunorderedlist.gif
GIF89a¢G¦ðRè`†ï'Œ&ÿÿÿ!ù,'HºÜþ0J„l5ºe]diŠ&‘mÄç…U*Ïj®œ66í_	;
__CPAN_FILE__ src/widget/templates/buttons/list_num_indent.gif
GIF89a‘KvøQì'Œ&ÿÿÿ!ù,&œ�©Ë½Âƒj�³NÒ:a7ŠÆ†U^ÉZàã~À�r‰³ºR;
__CPAN_FILE__ src/widget/templates/buttons/list_bullet_indent.gif
GIF89a¢G¦ðRè`†ï'Œ&ÿÿÿ!ù,'HºÜþ0J„l5ºÿƒBYWižÌˆfvŽŠÎ´X­÷ÆwíC	;
__CPAN_FILE__ src/widget/templates/buttons/save.gif
GIF89aÄ”¯èd†ÚïïïØ°-Ž¢àv’Ýö™Æ˜Ì—¹ÏõÿÊ#9YÆýãŽ{’áržëÿÿÿ!ù,p $ŽdyeJ*'ª–
Ãº‹cßwÌÈcÝüÀ†Ž×s4ˆ$b¨X�|‰h‚ép�If£ú4F™‰­Uìdˆ0÷š˜Rq÷Xp+
r¶áÁçã×dF
…c56„†ˆ6Š”–—”/›œ�!;
__CPAN_FILE__ src/widget/templates/buttons/forecolor.gif
GIF89aæ]   öõõöõöƒ¤êÿ{õùúÇÇÇ­“ÿ²{¯õööõöõj´\…®"öíëÿÝÎ‰Ö†�ÙÖÂÉ™Êúïöÿûòæú©©©u�³•�ÍÅ¸ÿÇ¶íÿÆèèèíï÷–¦ÿÿÚþö···ãEûýp¨+Î–½·Ûö£ÙË—ÁÍ€ÿƒ.Ôf×õ´±[ØØØÓÌ¦÷úùôîöÍÅÊTÿ~°]Í´Íº}µWÌÉÍØqÛ¶È¨]É”˜ÿÖ·ÿ½•À¨¨ò¾Š­Éÿ¸ŸþáÙÿ=õõö?Á½ZÍèõï÷ÿáåã´ÎïÐùÚà§õþº�”éª¨ÿçÿžâ—¤ûÿOàÿÕùÿ€áýÿDüöóÿÖïóé000ÿÿÿÿÿÿ!ù],›€]‚ƒ„…†‡ˆ‰Š…\J%5=40\‡\HM<>–‚[¥¦¦;@ƒ[
E	[S1¯¦§‚&+G(†[-[I„W#X6È[C„ LKFÈ![N„OBÈ[VYU)DT'È[QP2A":/ð[7R8TüX e¡-ñ\°`@bFŽ–ZD±¢¢@;
__CPAN_FILE__ src/widget/templates/buttons/hilitecolor.gif
GIF89aæb¼¼½ãããÐÐÐÏÐÐóóôóôó¬«¬ƒ¤êÿ{ããäïóéº}µ—¤ûWÌÉæ‡ÚDüöÎ–½~°]õï÷óÿÖEûýàÿÕ¾ÿ=qÛÐÏÐ¸Ÿ†�ÙÇ¶íÍÅÊÿOÅ¸ÿúåøýµèôôóTÿãÿ×•ÿ”˜ÿé´¾¶çÐ—ÁÍûvÆÍ´Íáýÿÿl°¶È¨.Ô€ÿƒ««¬õùú÷úùÿÚþö²{¯¬¬¬Å“»žâ•�Íu�³]ÉúïöÎ‰ÖôîöïÐã´Îf×õ½•Àíï÷·Ûö««­…®"?Á½j´\÷™ÿà§õ¨¨òÖ·ÿ¨ÿòæúÿÆŠ­ÉÖQ|öíë«¬­ÿŸÿóôôÉ™ÊùÚù÷ùp¨+”éª­“ÿZÍè–¦ÿ@@@ÿÿÿÿÿÿ!ùb,¦€b‚ƒ„…†‡ˆ‰Š…a>B7D,@a‡aX?LNM;E–…Z9VK&]'_R3†(S.+! P<ƒ`¿À¿ƒFC^*¾aÉÊ`ƒ-
¾W"Ì‚6YAI¾àà	Ùb\Q¾ë`1)¾ùú`O#%5$zÐðUÅŽ€Ñ�†%
F‰	É–/¨H\Ä±£ÇA�;
__CPAN_FILE__ src/widget/templates/buttons/cancel.gif
GIF89aÕ7ïïïéééåååâââóóóÓÓÓÌBBÅÍ@@ÒzzÌ>>¶Á¶ážžÐccÈ//Í;;¡°¡Ë66æ´´ÅåßßãÍÍÓTT×¡¡ÅÇ""éÑÑÖbbÔxxÉ,,¶Â¶æÅÅ©·©ÖŽŽÏPPÅÛ¾¾ÆÏ]]ßÍÍà¡¡¢±¢ðêêé½½Ç##ùùùööößßßìììýýýûûûÝÝÝÛÛÛ ¯ ÿÿÿÿÿÿ!ù7,”À›pH,kÈd²`ÖlÐ¨íÉ<Æ®ØèZ%Ödà°Ìî:[ètkI!‹5—ë±‘Ë-+W
N 0F*}{^‰%
(‰‡C50•0–0’NŸ"Ÿ�75,«&«¨5'¶
!´//	ÁÅ$/´3ÊËÌ3´4ÐÑÒ4´JÖIMÙEA;
__CPAN_FILE__ src/widget/templates/buttons/left_to_right.gif
GIF89a³
G«FD¨C@¤?=¡<I­H5™4.’-1•08œ7Qì!ù
,7PÉI«½8ëÍ»&à•T@©â8¬¤ª"Ì2ƒ’[I_!
 /6)(Œ¼ËA±ôO�tJíD;
__CPAN_FILE__ src/widget/templates/buttons/strikethrough.gif
GIF89aÕ!?_È±Âí´ÄíÈØõHgËµÄí@`ÈBbË�²îQyØ~Ÿä ½ðIjÍ‚›à£¶éQqÑÅÖõ”¯ètŸëqŒÚ­¾ëQqÐÆ×õb€Ö²ÊóEiÏ¡µév’Ýi˜êÄÖõŽÑŽ9�89YÆÿÿÿ!ù!,fÀ�pH,�È¤rØ9ŸNÇ±Ù©v –Á€pa*‚0¥Q˜p� hI!ÖË�|N¯ËCž¼~ÏÏ9	‚lC‰B‹�]”
‘E �žšDPOŽ«KA;
__CPAN_FILE__ src/widget/templates/buttons/justifyleft.gif
GIF89aÄ6š5O³ND©C?£>I­HJ®IU¸TVºU9�84˜3üüü/”/-’,eÉd*�)5™4[¾Y>¢=1–0:ž9oÒnP´PÊäÊaÄ_;Ÿ:jÎiC¨B,�+'Œ&çççÿÿÿ!ù,? 'Ždižhª®§EeÍ¡EH²l£ÒýÀ`�¥:T
‚Áä±þˆP a88Øl–äìv¢'­˜ƒò>Áè4*;
__CPAN_FILE__ src/widget/templates/buttons/delete.gif
GIF89a€Å!ù,(Œ�©Ëí@“)R™½ÙÙÐ=Ûƒ…âG~æ‚‚—Ò¯¼Êp
Í É÷N;
__CPAN_FILE__ src/widget/templates/buttons/list_num_outdent.gif
GIF89a‘KvøQì'Œ&ÿÿÿ!ù,&œ�©Ë½Âƒîˆ‹…“´Gp 1
Ùy‘âÈ¥÷¼`¡™*·:T;
__CPAN_FILE__ src/widget/templates/buttons/insertimage.gif
GIF89aæ\¤¡œ¥¢�xwp¦£žþÿþª¤¨^­€É†É!…Î¨¥ 5r³‚Ézªì[žÎÓÍ|¾2ŠÁkl�ŸXš~½F~¬ÖT–gšÜV˜4p¯zyrZ�Ðƒ½]d°q±9_“Õ’ÆYŠ°ßC}¿‚ËŠ´Ë~«ân¡C]®t¦èS¡q¸n â¶ÏíY‘¡W‡º!` ‡Ë$_¬G~'›¹Ùª§£}­î�®Ñy·CH�ÃqžÔ•ÌL#b¥V�‘P’„¾K†¿dr¶-‹ÄRI€¿}¤Î—ËM™·×‚É„Ê‰Àe�¶Û‘×ª¨£N†Ç¸Ðð `¡t«91mˆ³Ù‹Ó‚Â2†Êt°^bª'£ÃîTLIwvoÍÒÌÿÿÿÿÿÿ!ù\,°€\‚‚[…†‡…ƒƒˆŒ[Š\�‡�„†‹’‚4
Ÿ™KZ‚Y‘ˆY¦\¨=/N.6E3C[¬¨;B89!,MW[¼<-"L+(
5[«§U?H%I$QØ¼[)V7>A &2PÉ§[1'*S@:ˆ<9wO‰”#Œ`p„
[¥:¤LP,3jÌX€•–� CŠd5©¤É“�;
__CPAN_FILE__ src/widget/templates/buttons/justifycenter.gif
GIF89a³:�94˜3/“.@¤?N±M¬Ü¬GªF[¾ZüüüaÅ`T¸SgÊf,�+çççÿÿÿ!ù,1ÐÉI«½8ë}ËJ‡BLÊLHã¾0ÌÍå©®YüÎ\�Þ@ŠnØài€ÁÑel:5;
__CPAN_DIR__ src/widget/vml
__CPAN_FILE__ src/widget/vml/Chart.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.vml.Chart");

dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.Chart");
dojo.require("dojo.math");
dojo.require("dojo.html");
//dojo.require("dojo.vml");
dojo.require("dojo.graphics.color");

dojo.widget.vml.Chart=function(){
	dojo.widget.Chart.call(this);
	dojo.widget.HtmlWidget.call(this);
};
dojo.inherits(dojo.widget.vml.Chart, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.vml.Chart, {
	//	widget props
	templatePath:null,
	templateCssPath:null,

	//	state
	_isInitialized:false,
	hasData:false,

	//	chart props
	vectorNode:null,
	plotArea:null,
	dataGroup:null,
	axisGroup:null,

	properties:{
		height:400,	//	defaults, will resize to the domNode.
		width:600,
		plotType:null,
		padding:{
			top:10,
			bottom:2,
			left:60,
			right:30
		},
		axes:{
			x:{
				plotAt:0,
				label:"",
				unitLabel:"",
				unitType:Number,
				nUnitsToShow:10,
				range:{
					min:0,
					max:200
				}
			},
			y:{
				plotAt:0,
				label:"",
				unitLabel:"",
				unitType:Number,
				nUnitsToShow:10,
				range:{
					min:0,
					max:200
				}
			}
		}
	},
	
	fillInTemplate:function(args,frag){
		this.initialize();
		this.render();
	},
	parseData:function(){
	},
	initialize:function(){
		//	parse the data first.
		this.parseData();
	
		// render the body of the chart, not the chart data.
		if(this.vectorNode){ this.destroy(); }
		this.vectorNode=document.createElement("div");
		this.vectorNode.style.width=this.properties.width+"px";
		this.vectorNode.style.height=this.properties.height+"px";
		this.vectorNode.style.position="relative";
		this.domNode.appendChild(this.vectorNode);

		var plotWidth=this.properties.width-this.properties.padding.left-this.properties.padding.right;
		var plotHeight=this.properties.height-this.properties.padding.top-this.properties.padding.bottom;

		this.plotArea=document.createElement("div");
		this.plotArea.style.position="absolute";
		this.plotArea.style.backgroundColor="#fff";
		this.plotArea.style.top=(this.properties.padding.top)-2+"px";
		this.plotArea.style.left=(this.properties.padding.left-1)+"px";
		this.plotArea.style.width=plotWidth+"px";
		this.plotArea.style.height=plotHeight+"px";
		this.vectorNode.appendChild(this.plotArea);
		
		this.dataGroup=document.createElement("div");
		this.dataGroup.style.position="relative";
		this.plotArea.appendChild(this.dataGroup);

		//	clipping rects, what a fucking pain.
		var bg=this.domNode.style.backgroundColor;
		var r=document.createElement("v:rect");
		r.setAttribute("fillcolor", bg);
		r.setAttribute("stroked", "false");
		r.style.position="absolute";
		r.style.top=(-1*this.properties.padding.top)-1+"px";
		r.style.left=(-1*this.properties.padding.left)+"px";
		r.style.width=(this.properties.width-3)+"px";
		r.style.height=(this.properties.padding.top)-2+"px";
		this.vectorNode.appendChild(r);

		r=document.createElement("v:rect");
		r.setAttribute("fillcolor", bg);
		r.setAttribute("stroked", "false");
		r.style.position="absolute";
		r.style.top=plotHeight-2+"px";
		r.style.left=(-1*this.properties.padding.left)+"px";
		r.style.width=(this.properties.width-3)+"px";
		r.style.height=(this.properties.padding.bottom)-2+"px"; // fixme: check this.
		this.vectorNode.appendChild(r);

		r=document.createElement("v:rect");
		r.setAttribute("fillcolor", bg);
		r.setAttribute("stroked", "false");
		r.style.position="absolute";
		r.style.top="-2px";
		r.style.left=(-1*this.properties.padding.left)+"px";
		r.style.width=(this.properties.padding.left-1)+"px";
		r.style.height=plotHeight+"px";
		this.vectorNode.appendChild(r);
		
		r=document.createElement("v:rect");
		r.setAttribute("fillcolor", bg);
		r.setAttribute("stroked", "false");
		r.style.position="absolute";
		r.style.top="-2px";
		r.style.right=(-1*this.properties.padding.right)+1+"px";
		r.style.width=(this.properties.padding.right-1)+"px";
		r.style.height=plotHeight+"px";
		this.vectorNode.appendChild(r);
		//	end clipping rects.  god that sucks, i wish VML had clipping outside of that crap vmlframe...

		this.axisGroup=document.createElement("div");
		this.axisGroup.style.position="relative";
		this.plotArea.appendChild(this.axisGroup);

		var stroke=1;

		//	x axis
		var line=document.createElement("v:line");
		var y=dojo.widget.vml.Chart.Plotter.getY(this.properties.axes.x.plotAt, this);
		line.setAttribute("from", this.properties.padding.left-stroke + "," + y);
		line.setAttribute("to", plotWidth + "," + y);
		line.style.position="absolute";
		line.style.antialias="false";
		line.setAttribute("strokecolor", "#666");
		line.setAttribute("strokeweight", stroke*2+"px");
		this.axisGroup.appendChild(line);

		//	y axis
		var line=document.createElement("v:line");
		var y=dojo.widget.vml.Chart.Plotter.getX(this.properties.axes.y.plotAt, this);
		line.setAttribute("from", y+","+this.properties.padding.top);
		line.setAttribute("to", y+","+this.properties.height-this.properties.padding.bottom);
		line.style.position="absolute";
		line.style.antialias="false";
		line.setAttribute("strokecolor", "#666");
		line.setAttribute("strokeweight", stroke*2+"px");
		this.axisGroup.appendChild(line);
		
		//	labels
		var size=10;

		//	x axis labels.
		var t=document.createElement("div");
		t.style.position="absolute";
		t.style.top=(this.properties.height-this.properties.padding.bottom+size+2)+"px";
		t.style.left=this.properties.padding.left+"px";
		t.style.fontFamily="sans-serif";
		t.style.fontSize=size+"px";
		t.innerHTML=dojo.math.round(parseFloat(this.properties.axes.x.range.min),2);
		this.axisGroup.appendChild(t);

		t=document.createElement("div");
		t.style.position="absolute";
		t.style.top=(this.properties.height-this.properties.padding.bottom+size+2)+"px";
		t.style.left=(this.properties.width-this.properties.padding.right-(size/2))+"px";
		t.style.fontFamily="sans-serif";
		t.style.fontSize=size+"px";
		t.innerHTML=dojo.math.round(parseFloat(this.properties.axes.x.range.max),2);
		this.axisGroup.appendChild(t);

		//	y axis labels.
		t=document.createElement("div");
		t.style.position="absolute";
		t.style.top=-1*(size/2)+"px";
		t.style.right=(plotWidth+4)+"px";
		t.style.fontFamily="sans-serif";
		t.style.fontSize=size+"px";
		t.innerHTML=dojo.math.round(parseFloat(this.properties.axes.y.range.max),2);
		this.axisGroup.appendChild(t);
		
		t=document.createElement("div");
		t.style.position="absolute";
		t.style.top=(this.properties.height-this.properties.padding.bottom)+"px";
		t.style.right=(plotWidth+4)+"px";
		t.style.fontFamily="sans-serif";
		t.style.fontSize=size+"px";
		t.innerHTML=dojo.math.round(parseFloat(this.properties.axes.y.range.min),2);
		this.axisGroup.appendChild(t);
		
		//	this is last.
		this.assignColors();
		this._isInitialized=true;
	},
	destroy:function(){
		while(this.domNode.childNodes.length>0){
			this.domNode.removeChild(this.domNode.childNodes[0]);
		}
		this.vectorNode=this.plotArea=this.dataGroup=this.axisGroup=null;
	},
	render:function(){
		if (this.dataGroup){
			while(this.dataGroup.childNodes.length>0){
				this.dataGroup.removeChild(this.dataGroup.childNodes[0]);
			}
		} else {
			this.initialize();
		}
		for(var i=0; i<this.series.length; i++){
			dojo.widget.vml.Chart.Plotter.plot(this.series[i], this);
		}
	}
});

dojo.widget.vml.Chart.Plotter=new function(){
	var _this=this;
	var plotters = {};
	var types=dojo.widget.Chart.PlotTypes;
	
	this.getX=function(value, chart){
		var v=parseFloat(value);
		var min=chart.properties.axes.x.range.min;
		var max=chart.properties.axes.x.range.max;
		var ofst=0-min;
		min+=ofst; max+=ofst; v+=ofst;

		var xmin=chart.properties.padding.left;
		var xmax=chart.properties.width-chart.properties.padding.right;
		var x=(v*((xmax-xmin)/max))+xmin;
		return x;
	};
	this.getY=function(value, chart){
		var v=parseFloat(value);
		var max=chart.properties.axes.y.range.max;
		var min=chart.properties.axes.y.range.min;
		var ofst=0;
		if(min<0)ofst+=Math.abs(min);
		min+=ofst; max+=ofst; v+=ofst;
		
		var ymin=chart.properties.height-chart.properties.padding.bottom;
		var ymax=chart.properties.padding.top;
		var y=(((ymin-ymax)/(max-min))*(max-v))+ymax;
		return y;
	};

	this.addPlotter=function(name, func){
		plotters[name]=func;
	};
	this.plot=function(series, chart){
		if (series.values.length==0) return;
		if (series.plotType && plotters[series.plotType]){
			return plotters[series.plotType](series, chart);
		}
		else if (chart.plotType && plotters[chart.plotType]){
			return plotters[chart.plotType](series, chart);
		}
	};

	//	plotting
	plotters[types.Bar]=function(series, chart){
		var space=1;
		var lastW = 0;
		for (var i=0; i<series.values.length; i++){
			var x=_this.getX(series.values[i].x, chart);
			var w;
			if (i==series.values.length-1){
				w=lastW;
			} else{
				w=_this.getX(series.values[i+1].x, chart)-x-space;
				lastW=w;
			}
			x-=(w/2);

			var yA=_this.getY(chart.properties.axes.x.plotAt, chart);
			var y=_this.getY(series.values[i].value, chart);
			var h=Math.abs(yA-y);
			if (parseFloat(series.values[i].value)<chart.properties.axes.x.plotAt){
				var oy=yA;
				yA=y;
				y=oy;
			}

			var bar=document.createElement("v:rect");
			bar.style.position="absolute";
			bar.style.top=x+"px";
			bar.style.left=y+"px";
			bar.style.width=w+"px";
			bar.style.height=h+"px";
			bar.setAttribute("fillColor", series.color);
			bar.setAttribute("title", series.label + ": " + series.values[i].value);
			bar.setAttribute("coordsize", chart.properties.width + "," + chart.properties.height);
			var fill=document.createElement("v:fill");
			fill.setAttribute("opacity", "0.9");
			bar.appendChild(fill);
			chart.dataGroup.appendChild(bar);
		}
	};	
	plotters[types.Line]=function(series, chart){
		var tension=3;

		var line=document.createElement("v:shape");
		line.setAttribute("strokeweight", "2px");
		line.setAttribute("strokecolor", series.color);
		line.setAttribute("fillcolor", "none");
		line.setAttribute("filled", "false");
		line.setAttribute("title", series.label);
		line.setAttribute("coordsize", chart.properties.width + "," + chart.properties.height);
		line.style.position="absolute";
		line.style.top="0px";
		line.style.left="0px";
		line.style.width= chart.properties.width+"px";
		line.style.height=chart.properties.height+"px";
		var stroke=document.createElement("v:stroke");
		stroke.setAttribute("opacity", "0.85");
		line.appendChild(stroke);

		var path = [];
		for (var i=0; i<series.values.length; i++){
			var x = _this.getX(series.values[i].x, chart)
			var y = _this.getY(series.values[i].value, chart);

			if (i==0){
				path.push("m");
				path.push(x+","+y);
			}else{
				var lastx=_this.getX(series.values[i-1].x, chart);
				var lasty=_this.getY(series.values[i-1].value, chart);
				var dx=x-lastx;
				
				path.push("v");
				var cx=x-(tension-1)*(dx/tension);
				path.push(cx+",0");
				cx=x-(dx/tension);
				path.push(cx+","+y-lasty);
				path.push(dx, y-lasty);
			}
		}
		line.setAttribute("path", path.join(" ")+" e");
		chart.dataGroup.appendChild(line);
	};
	plotters[types.Scatter]=function(series, chart){
		var r=8;
		for (var i=0; i<series.values.length; i++){
			var x=_this.getX(series.values[i].x, chart);
			var y=_this.getY(series.values[i].value, chart);
			var mod=r/2;

			var point=document.createElement("v:rect");
			point.setAttribute("fillcolor", series.color);
			point.setAttribute("strokecolor", series.color);
			point.setAttribute("title", series.label + ": " + series.values[i].value);
			point.style.position="absolute";
			point.style.rotation="45";
			point.style.top=(y-mod)+"px";
			point.style.left=(x-mod)+"px";
			point.style.width=r+"px";
			point.style.height=r+"px";
			var fill=document.createElement("v:fill");
			fill.setAttribute("opacity", "0.5");
			point.appendChild(fill);
			chart.dataGroup.appendChild(point);
		}
	};	
	plotters[types.Bubble]=function(series, chart){
		//	added param for series[n].value: size
		var minR=1;
		
		//	do this off the x axis?
		var min=chart.properties.axes.x.range.min;
		var max=chart.properties.axes.x.range.max;
		var ofst=0-min;

		min+=ofst; max+=ofst;
		var xmin=chart.properties.padding.left;
		var xmax=chart.properties.width-chart.properties.padding.right;
		var factor=(max-min)/(xmax-xmin)*25;
		
		for (var i=0; i<series.values.length; i++){
			var size = series.values[i].size;
			if (isNaN(parseFloat(size))) size=minR;
			var mod=(parseFloat(size)*factor)/2;

			var point=document.createElement("v:oval");
			point.setAttribute("strokecolor", series.color);
			point.setAttribute("fillcolor", series.color);
			point.setAttribute("title", series.label + ": " + series.values[i].value + " (" + size + ")");
			point.style.position="absolute";
			point.style.top=(_this.getY(series.values[i].value, chart)-mod) + "px";
			point.style.left=(_this.getX(series.values[i].x, chart)-mod) + "px";
			point.style.width=mod+"px";
			point.style.height=mod+"px";
			chart.dataGroup.appendChild(point);
		}
	};
}();

__CPAN_DIR__ src/lfx
__CPAN_FILE__ src/lfx/Animation.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lfx.Animation");
dojo.provide("dojo.lfx.Line");

dojo.require("dojo.lang.func");

/*
	Animation package based on Dan Pupius' work: http://pupius.co.uk/js/Toolkit.Drawing.js
*/
dojo.lfx.Line = function(start, end){
	this.start = start;
	this.end = end;
	if(dojo.lang.isArray(start)){
		var diff = [];
		dojo.lang.forEach(this.start, function(s,i){
			diff[i] = this.end[i] - s;
		}, this);
		
		this.getValue = function(/*float*/ n){
			var res = [];
			dojo.lang.forEach(this.start, function(s, i){
				res[i] = (diff[i] * n) + s;
			}, this);
			return res;
		}
	}else{
		var diff = end - start;
			
		this.getValue = function(/*float*/ n){
			//	summary: returns the point on the line
			//	n: a floating point number greater than 0 and less than 1
			return (diff * n) + this.start;
		}
	}
}

dojo.lfx.easeIn = function(n){
	//	summary: returns the point on an easing curve
	//	n: a floating point number greater than 0 and less than 1
	return Math.pow(n, 3);
}

dojo.lfx.easeOut = function(n){
	//	summary: returns the point on the line
	//	n: a floating point number greater than 0 and less than 1
	return ( 1 - Math.pow(1 - n, 3) );
}

dojo.lfx.easeInOut = function(n){
	//	summary: returns the point on the line
	//	n: a floating point number greater than 0 and less than 1
	return ( (3 * Math.pow(n, 2)) - (2 * Math.pow(n, 3)) );
}

dojo.lfx.IAnimation = function(){}
dojo.lang.extend(dojo.lfx.IAnimation, {
	// public properties
	curve: null,
	duration: 1000,
	easing: null,
	repeatCount: 0,
	rate: 25,
	
	// events
	handler: null,
	beforeBegin: null,
	onBegin: null,
	onAnimate: null,
	onEnd: null,
	onPlay: null,
	onPause: null,
	onStop: null,
	
	// public methods
	play: null,
	pause: null,
	stop: null,
	
	fire: function(evt, args){
		if(this[evt]){
			this[evt].apply(this, (args||[]));
		}
	},
	
	// private properties
	_active: false,
	_paused: false
});

dojo.lfx.Animation = function(/*Object*/ handlers, /*int*/ duration, /*Array*/ curve, /*function*/ easing, /*int*/ repeatCount, /*int*/ rate){
	//	summary
	//		a generic animation object that fires callbacks into it's handlers
	//		object at various states
	//	handlers
	//		object { 
	//			handler: function(){}, 
	//			onstart: function(){}, 
	//			onstop: function(){}, 
	//			onanimate: function(){}
	//		}
	dojo.lfx.IAnimation.call(this);
	if(dojo.lang.isNumber(handlers)||(!handlers && duration.getValue)){
		// no handlers argument:
		rate = repeatCount;
		repeatCount = easing;
		easing = curve;
		curve = duration;
		duration = handlers;
		handlers = null;
	}else if(handlers.getValue||dojo.lang.isArray(handlers)){
		// no handlers or duration:
		rate = easing;
		repeatCount = curve;
		easing = duration;
		curve = handlers;
		duration = null;
		handlers = null;
	}
	if(dojo.lang.isArray(curve)){
		this.curve = new dojo.lfx.Line(curve[0], curve[1]);
	}else{
		this.curve = curve;
	}
	if(duration != null && duration > 0){ this.duration = duration; }
	if(repeatCount){ this.repeatCount = repeatCount; }
	if(rate){ this.rate = rate; }
	if(handlers){
		this.handler = handlers.handler;
		this.beforeBegin = handlers.beforeBegin;
		this.onBegin = handlers.onBegin;
		this.onEnd = handlers.onEnd;
		this.onPlay = handlers.onPlay;
		this.onPause = handlers.onPause;
		this.onStop = handlers.onStop;
		this.onAnimate = handlers.onAnimate;
	}
	if(easing && dojo.lang.isFunction(easing)){
		this.easing=easing;
	}
}
dojo.inherits(dojo.lfx.Animation, dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Animation, {
	// "private" properties
	_startTime: null,
	_endTime: null,
	_timer: null,
	_percent: 0,
	_startRepeatCount: 0,

	// public methods
	play: function(delay, gotoStart){
		if(gotoStart){
			clearTimeout(this._timer);
			this._active = false;
			this._paused = false;
			this._percent = 0;
		}else if(this._active && !this._paused){
			return this;
		}
		
		this.fire("handler", ["beforeBegin"]);
		this.fire("beforeBegin");

		if(delay > 0){
			setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
			return this;
		}
		
		this._startTime = new Date().valueOf();
		if(this._paused){
			this._startTime -= (this.duration * this._percent / 100);
		}
		this._endTime = this._startTime + this.duration;

		this._active = true;
		this._paused = false;
		
		var step = this._percent / 100;
		var value = this.curve.getValue(step);
		if( this._percent == 0 ) {
			if(!this._startRepeatCount) {
				this._startRepeatCount = this.repeatCount;
			}
			this.fire("handler", ["begin", value]);
			this.fire("onBegin", [value]);
		}

		this.fire("handler", ["play", value]);
		this.fire("onPlay", [value]);

		this._cycle();
		return this;
	},

	pause: function() {
		clearTimeout(this._timer);
		if(!this._active){ return this; }
		this._paused = true;
		var value = this.curve.getValue(this._percent / 100);
		this.fire("handler", ["pause", value]);
		this.fire("onPause", [value]);
		return this;
	},

	gotoPercent: function(pct, andPlay) {
		clearTimeout(this._timer);
		this._active = true;
		this._paused = true;
		this._percent = pct;
		if( andPlay ) { this.play(); }
	},

	stop: function(gotoEnd) {
		clearTimeout(this._timer);
		var step = this._percent / 100;
		if( gotoEnd ) {
			step = 1;
		}
		var value = this.curve.getValue(step);
		this.fire("handler", ["stop", value]);
		this.fire("onStop", [value]);
		this._active = false;
		this._paused = false;
		return this;
	},

	status: function() {
		if( this._active ) {
			return this._paused ? "paused" : "playing";
		} else {
			return "stopped";
		}
	},

	// "private" methods
	_cycle: function() {
		clearTimeout(this._timer);
		if(this._active){
			var curr = new Date().valueOf();
			var step = (curr - this._startTime) / (this._endTime - this._startTime);

			if(step >= 1){
				step = 1;
				this._percent = 100;
			}else{
				this._percent = step * 100;
			}
			
			// Perform easing
			if((this.easing)&&(dojo.lang.isFunction(this.easing))){
				step = this.easing(step);
			}

			var value = this.curve.getValue(step);
			this.fire("handler", ["animate", value]);
			this.fire("onAnimate", [value]);

			if( step < 1 ) {
				this._timer = setTimeout(dojo.lang.hitch(this, "_cycle"), this.rate);
			} else {
				this._active = false;
				this.fire("handler", ["end"]);
				this.fire("onEnd");

				if( this.repeatCount > 0 ) {
					this.repeatCount--;
					this.play(null, true);
				} else if( this.repeatCount == -1 ) {
					this.play(null, true);
				} else {
					if(this._startRepeatCount) {
						this.repeatCount = this._startRepeatCount;
						this._startRepeatCount = 0;
					}
				}
			}
		}
		return this;
	}
});

dojo.lfx.Combine = function(){
	dojo.lfx.IAnimation.call(this);
	this._anims = [];
	this._animsEnded = 0;
	
	var anims = arguments;
	if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){
		anims = anims[0];
	}
	
	var _this = this;
	dojo.lang.forEach(anims, function(anim){
		_this._anims.push(anim);
		var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
		anim.onEnd = function(){ oldOnEnd(); _this._onAnimsEnded(); };
	});
}
dojo.inherits(dojo.lfx.Combine, dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Combine, {
	// private members
	_animsEnded: 0,
	
	// public methods
	play: function(delay, gotoStart){
		if( !this._anims.length ){ return this; }

		this.fire("beforeBegin");

		if(delay > 0){
			setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
			return this;
		}
		
		if(gotoStart || this._anims[0].percent == 0){
			this.fire("onBegin");
		}
		this.fire("onPlay");
		this._animsCall("play", null, gotoStart);
		return this;
	},
	
	pause: function(){
		this.fire("onPause");
		this._animsCall("pause"); 
		return this;
	},
	
	stop: function(gotoEnd){
		this.fire("onStop");
		this._animsCall("stop", gotoEnd);
		return this;
	},
	
	// private methods
	_onAnimsEnded: function(){
		this._animsEnded++;
		if(this._animsEnded >= this._anims.length){
			this.fire("onEnd");
		}
		return this;
	},
	
	_animsCall: function(funcName){
		var args = [];
		if(arguments.length > 1){
			for(var i = 1 ; i < arguments.length ; i++){
				args.push(arguments[i]);
			}
		}
		var _this = this;
		dojo.lang.forEach(this._anims, function(anim){
			anim[funcName](args);
		}, _this);
		return this;
	}
});

dojo.lfx.Chain = function() {
	dojo.lfx.IAnimation.call(this);
	this._anims = [];
	this._currAnim = -1;
	
	var anims = arguments;
	if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){
		anims = anims[0];
	}
	
	var _this = this;
	dojo.lang.forEach(anims, function(anim, i, anims_arr){
		_this._anims.push(anim);
		var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
		if(i < anims_arr.length - 1){
			anim.onEnd = function(){ oldOnEnd(); _this._playNext(); };
		}else{
			anim.onEnd = function(){ oldOnEnd(); _this.fire("onEnd"); };
		}
	}, _this);
}
dojo.inherits(dojo.lfx.Chain, dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Chain, {
	// private members
	_currAnim: -1,
	
	// public methods
	play: function(delay, gotoStart){
		if( !this._anims.length ) { return this; }
		if( gotoStart || !this._anims[this._currAnim] ) {
			this._currAnim = 0;
		}

		var currentAnimation = this._anims[this._currAnim];

		this.fire("beforeBegin");
		if(delay > 0){
			setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
			return this;
		}
		
		if(currentAnimation){
			if(this._currAnim == 0){
				this.fire("handler", ["begin", this._currAnim]);
				this.fire("onBegin", [this._currAnim]);
			}
			this.fire("onPlay", [this._currAnim]);
			currentAnimation.play(null, gotoStart);
		}
		return this;
	},
	
	pause: function(){
		if( this._anims[this._currAnim] ) {
			this._anims[this._currAnim].pause();
			this.fire("onPause", [this._currAnim]);
		}
		return this;
	},
	
	playPause: function(){
		if(this._anims.length == 0){ return this; }
		if(this._currAnim == -1){ this._currAnim = 0; }
		var currAnim = this._anims[this._currAnim];
		if( currAnim ) {
			if( !currAnim._active || currAnim._paused ) {
				this.play();
			} else {
				this.pause();
			}
		}
		return this;
	},
	
	stop: function(){
		var currAnim = this._anims[this._currAnim];
		if(currAnim){
			currAnim.stop();
			this.fire("onStop", [this._currAnim]);
		}
		return currAnim;
	},
	
	// private methods
	_playNext: function(){
		if( this._currAnim == -1 || this._anims.length == 0 ) { return this; }
		this._currAnim++;
		if( this._anims[this._currAnim] ){
			this._anims[this._currAnim].play(null, true);
		}
		return this;
	}
});

dojo.lfx.combine = function(){
	var anims = arguments;
	if(dojo.lang.isArray(arguments[0])){
		anims = arguments[0];
	}
	return new dojo.lfx.Combine(anims);
}

dojo.lfx.chain = function(){
	var anims = arguments;
	if(dojo.lang.isArray(arguments[0])){
		anims = arguments[0];
	}
	return new dojo.lfx.Chain(anims);
}

__CPAN_FILE__ src/lfx/html.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lfx.html");
dojo.require("dojo.lfx.Animation");

dojo.require("dojo.html");

dojo.lfx.html._byId = function(nodes){
	if(!nodes){ return []; }
	if(dojo.lang.isArray(nodes)){
		if(!nodes.alreadyChecked){
			var n = [];
			dojo.lang.forEach(nodes, function(node){
				n.push(dojo.byId(node));
			});
			n.alreadyChecked = true;
			return n;
		}else{
			return nodes;
		}
	}else{
		var n = [];
		n.push(dojo.byId(nodes));
		n.alreadyChecked = true;
		return n;
	}
}

dojo.lfx.html.propertyAnimation = function(	/*DOMNode*/ nodes, 
											/*Array*/ propertyMap, 
											/*int*/ duration,
											/*function*/ easing){
	nodes = dojo.lfx.html._byId(nodes);
	
	if(nodes.length==1){
		// FIXME: we're only supporting start-value filling when one node is
		// passed
		
		dojo.lang.forEach(propertyMap, function(prop){
			if(typeof prop["start"] == "undefined"){
				if(prop.property != "opacity"){
					prop.start = parseInt(dojo.style.getComputedStyle(nodes[0], prop.property));
				}else{
					prop.start = dojo.style.getOpacity(nodes[0]);
				}
			}
		});
	}

	var coordsAsInts = function(coords){
		var cints = new Array(coords.length);
		for(var i = 0; i < coords.length; i++){
			cints[i] = Math.round(coords[i]);
		}
		return cints;
	}
	var setStyle = function(n, style){
		n = dojo.byId(n);
		if(!n || !n.style){ return; }
		for(var s in style){
			if(s == "opacity"){
				dojo.style.setOpacity(n, style[s]);
			}else{
				n.style[s] = style[s];
			}
		}
	}
	var propLine = function(properties){
		this._properties = properties;
		this.diffs = new Array(properties.length);
		dojo.lang.forEach(properties, function(prop, i){
			// calculate the end - start to optimize a bit
			if(dojo.lang.isArray(prop.start)){
				// don't loop through the arrays
				this.diffs[i] = null;
			}else if(prop.start instanceof dojo.graphics.color.Color){
				// save these so we don't have to call toRgb() every getValue() call
				prop.startRgb = prop.start.toRgb();
				prop.endRgb = prop.end.toRgb();
			}else{
				this.diffs[i] = prop.end - prop.start;
			}
		}, this);
		this.getValue = function(n){
			var ret = {};
			dojo.lang.forEach(this._properties, function(prop, i){
				var value = null;
				if(dojo.lang.isArray(prop.start)){
					// FIXME: what to do here?
				}else if(prop.start instanceof dojo.graphics.color.Color){
					value = (prop.units||"rgb") + "(";
					for(var j = 0 ; j < prop.startRgb.length ; j++){
						value += Math.round(((prop.endRgb[j] - prop.startRgb[j]) * n) + prop.startRgb[j]) + (j < prop.startRgb.length - 1 ? "," : "");
					}
					value += ")";
				}else{
					value = ((this.diffs[i]) * n) + prop.start + (prop.property != "opacity" ? prop.units||"px" : "");
				}
				ret[dojo.style.toCamelCase(prop.property)] = value;
			}, this);
			return ret;
		}
	}
	
	var anim = new dojo.lfx.Animation({
		onAnimate: function(propValues){
			dojo.lang.forEach(nodes, function(node){
				setStyle(node, propValues);
			});
		} }, duration, new propLine(propertyMap), easing);
	
	return anim;
}

dojo.lfx.html._makeFadeable = function(nodes){
	var makeFade = function(node){
		if(dojo.render.html.ie){
			// only set the zoom if the "tickle" value would be the same as the
			// default
			if( (node.style.zoom.length == 0) &&
				(dojo.style.getStyle(node, "zoom") == "normal") ){
				// make sure the node "hasLayout"
				// NOTE: this has been tested with larger and smaller user-set text
				// sizes and works fine
				node.style.zoom = "1";
				// node.style.zoom = "normal";
			}
			// don't set the width to auto if it didn't already cascade that way.
			// We don't want to f anyones designs
			if(	(node.style.width.length == 0) &&
				(dojo.style.getStyle(node, "width") == "auto") ){
				node.style.width = "auto";
			}
		}
	}
	if(dojo.lang.isArrayLike(nodes)){
		dojo.lang.forEach(nodes, makeFade);
	}else{
		makeFade(nodes);
	}
}

dojo.lfx.html.fadeIn = function(nodes, duration, easing, callback){
	nodes = dojo.lfx.html._byId(nodes);
	dojo.lfx.html._makeFadeable(nodes);
	var anim = dojo.lfx.propertyAnimation(nodes, [
		{	property: "opacity",
			start: dojo.style.getOpacity(nodes[0]),
			end: 1 } ], duration, easing);
	if(callback){
		var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
		anim.onEnd = function(){ oldOnEnd(); callback(nodes, anim); };
	}

	return anim;
}

dojo.lfx.html.fadeOut = function(nodes, duration, easing, callback){
	nodes = dojo.lfx.html._byId(nodes);
	dojo.lfx.html._makeFadeable(nodes);
	var anim = dojo.lfx.propertyAnimation(nodes, [
		{	property: "opacity",
			start: dojo.style.getOpacity(nodes[0]),
			end: 0 } ], duration, easing);
	if(callback){
		var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
		anim.onEnd = function(){ oldOnEnd(); callback(nodes, anim); };
	}

	return anim;
}

dojo.lfx.html.fadeShow = function(nodes, duration, easing, callback){
	var anim = dojo.lfx.html.fadeIn(nodes, duration, easing, callback);
	var oldBb = (anim["beforeBegin"]) ? dojo.lang.hitch(anim, "beforeBegin") : function(){};
	anim.beforeBegin = function(){ 
		oldBb();
		if(dojo.lang.isArrayLike(nodes)){
			dojo.lang.forEach(nodes, dojo.style.show);
		}else{
			dojo.style.show(nodes);
		}
	};
	
	return anim;
}

dojo.lfx.html.fadeHide = function(nodes, duration, easing, callback){
	var anim = dojo.lfx.html.fadeOut(nodes, duration, easing, function(){
		if(dojo.lang.isArrayLike(nodes)){
			dojo.lang.forEach(nodes, dojo.style.hide);
		}else{
			dojo.style.hide(nodes);
		}
		if(callback){ callback(nodes, anim); }
	});
	
	return anim;
}

dojo.lfx.html.wipeIn = function(nodes, duration, easing, callback){
	nodes = dojo.lfx.html._byId(nodes);
	var anims = [];

	dojo.lang.forEach(nodes, function(node){
		var overflow = dojo.style.getStyle(node, "overflow");
		if(overflow == "visible") {
			node.style.overflow = "hidden";
		}
		node.style.height = "0px";
		dojo.style.show(node);
		
		var anim = dojo.lfx.propertyAnimation(node,
			[{	property: "height",
				start: 0,
				end: node.scrollHeight }], duration, easing);
		
		var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
		anim.onEnd = function(){ 
			oldOnEnd(); 
			node.style.overflow = overflow;
			node.style.height = "auto";
			if(callback){ callback(node, anim); }
		};
		anims.push(anim);
	});
	
	if(nodes.length > 1){ return dojo.lfx.combine(anims); }
	else{ return anims[0]; }
}

dojo.lfx.html.wipeOut = function(nodes, duration, easing, callback){
	nodes = dojo.lfx.html._byId(nodes);
	var anims = [];
	
	dojo.lang.forEach(nodes, function(node){
		var overflow = dojo.style.getStyle(node, "overflow");
		if(overflow == "visible") {
			node.style.overflow = "hidden";
		}
		dojo.style.show(node);

		var anim = dojo.lfx.propertyAnimation(node,
			[{	property: "height",
				start: dojo.style.getContentBoxHeight(node),
				end: 0 } ], duration, easing);
		
		var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
		anim.onEnd = function(){ 
			oldOnEnd(); 
			dojo.style.hide(node);
			node.style.overflow = overflow;
			if(callback){ callback(node, anim); }
		};
		anims.push(anim);
	});

	if(nodes.length > 1){ return dojo.lfx.combine(anims); }
	else { return anims[0]; }
}

dojo.lfx.html.slideTo = function(nodes, coords, duration, easing, callback){
	nodes = dojo.lfx.html._byId(nodes);
	var anims = [];

	dojo.lang.forEach(nodes, function(node){
		var top = null;
		var left = null;
		
		var init = (function(){
			var innerNode = node;
			return function(){
				top = innerNode.offsetTop;
				left = innerNode.offsetLeft;

				if (!dojo.style.isPositionAbsolute(innerNode)) {
					var ret = dojo.style.abs(innerNode, true);
					dojo.style.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
					top = ret.y;
					left = ret.x;
				}
			}
		})();
		init();
		
		var anim = dojo.lfx.propertyAnimation(node,
			[{	property: "top",
				start: top,
				end: coords[0] },
			{	property: "left",
				start: left,
				end: coords[1] }], duration, easing);
		
		var oldBb = (anim["beforeBegin"]) ? dojo.lang.hitch(anim, "beforeBegin") : function(){};
		anim.beforeBegin = function(){ oldBb(); init(); };

		if(callback){
			var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
			anim.onEnd = function(){ oldOnEnd(); callback(nodes, anim); };
		}

		anims.push(anim);
	});
	
	if(nodes.length > 1){ return dojo.lfx.combine(anims); }
	else{ return anims[0]; }
}

dojo.lfx.html.slideBy = function(nodes, coords, duration, easing, callback){
	nodes = dojo.lfx.html._byId(nodes);
	var anims = [];

	dojo.lang.forEach(nodes, function(node){
		var top = null;
		var left = null;
		
		var init = (function(){
			var innerNode = node;
			return function(){
				top = node.offsetTop;
				left = node.offsetLeft;

				if (!dojo.style.isPositionAbsolute(innerNode)) {
					var ret = dojo.style.abs(innerNode);
					dojo.style.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
					top = ret.y;
					left = ret.x;
				}
			}
		})();
		init();
		
		var anim = dojo.lfx.propertyAnimation(node,
			[{	property: "top",
				start: top,
				end: top+coords[0] },
			{	property: "left",
				start: left,
				end: left+coords[1] }], duration, easing);

		var oldBb = (anim["beforeBegin"]) ? dojo.lang.hitch(anim, "beforeBegin") : function(){};
		anim.beforeBegin = function(){ oldBb(); init(); };

		if(callback){
			var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
			anim.onEnd = function(){ oldOnEnd(); callback(nodes, anim); };
		}

		anims.push(anim);
	});

	if(nodes.length > 1){ return dojo.lfx.combine(anims); }
	else{ return anims[0]; }
}

dojo.lfx.html.explode = function(start, endNode, duration, easing, callback){
	start = dojo.byId(start);
	endNode = dojo.byId(endNode);
	var startCoords = dojo.style.toCoordinateArray(start, true);
	var outline = document.createElement("div");
	dojo.html.copyStyle(outline, endNode);
	with(outline.style){
		position = "absolute";
		display = "none";
	}
	document.body.appendChild(outline);

	with(endNode.style){
		visibility = "hidden";
		display = "block";
	}
	var endCoords = dojo.style.toCoordinateArray(endNode, true);
	with(endNode.style){
		display = "none";
		visibility = "visible";
	}

	var anim = new dojo.lfx.propertyAnimation(outline, [
		{ property: "height", start: startCoords[3], end: endCoords[3] },
		{ property: "width", start: startCoords[2], end: endCoords[2] },
		{ property: "top", start: startCoords[1], end: endCoords[1] },
		{ property: "left", start: startCoords[0], end: endCoords[0] },
		{ property: "opacity", start: 0.3, end: 1.0 }
	], duration, easing);
	
	anim.beforeBegin = function(){
		dojo.style.setDisplay(outline, "block");
	};
	anim.onEnd = function(){
		dojo.style.setDisplay(endNode, "block");
		outline.parentNode.removeChild(outline);
	};
	if(callback){
		var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
		anim.onEnd = function(){ oldOnEnd(); callback(endNode, anim); };
	}
	return anim;
}

dojo.lfx.html.implode = function(startNode, end, duration, easing, callback){
	startNode = dojo.byId(startNode);
	end = dojo.byId(end);
	var startCoords = dojo.style.toCoordinateArray(startNode, true);
	var endCoords = dojo.style.toCoordinateArray(end, true);

	var outline = document.createElement("div");
	dojo.html.copyStyle(outline, startNode);
	dojo.style.setOpacity(outline, 0.3);
	with(outline.style){
		position = "absolute";
		display = "none";
	}
	document.body.appendChild(outline);

	var anim = new dojo.lfx.propertyAnimation(outline, [
		{ property: "height", start: startCoords[3], end: endCoords[3] },
		{ property: "width", start: startCoords[2], end: endCoords[2] },
		{ property: "top", start: startCoords[1], end: endCoords[1] },
		{ property: "left", start: startCoords[0], end: endCoords[0] },
		{ property: "opacity", start: 1.0, end: 0.3 }
	], duration, easing);
	
	anim.beforeBegin = function(){
		dojo.style.hide(startNode);
		dojo.style.show(outline);
	};
	anim.onEnd = function(){
		outline.parentNode.removeChild(outline);
	};
	if(callback){
		var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
		anim.onEnd = function(){ oldOnEnd(); callback(startNode, anim); };
	}
	return anim;
}

dojo.lfx.html.highlight = function(nodes, startColor, duration, easing, callback){
	nodes = dojo.lfx.html._byId(nodes);
	var anims = [];

	dojo.lang.forEach(nodes, function(node){
		var color = dojo.style.getBackgroundColor(node);
		var bg = dojo.style.getStyle(node, "background-color").toLowerCase();
		var bgImage = dojo.style.getStyle(node, "background-image");
		var wasTransparent = (bg == "transparent" || bg == "rgba(0, 0, 0, 0)");
		while(color.length > 3) { color.pop(); }

		var rgb = new dojo.graphics.color.Color(startColor);
		var endRgb = new dojo.graphics.color.Color(color);

		var anim = dojo.lfx.propertyAnimation(node, [{
			property: "background-color",
			start: rgb,
			end: endRgb
		}], duration, easing);

		var oldbb = (anim["beforeBegin"]) ? dojo.lang.hitch(anim, "beforeBegin") : function(){};
		anim.beforeBegin = function(){ 
			oldbb();
			if(bgImage){
				node.style.backgroundImage = "none";
			}
			node.style.backgroundColor = "rgb(" + rgb.toRgb().join(",") + ")";
		};

		var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
		anim.onEnd = function(){ 
			oldOnEnd();
			if(bgImage){
				node.style.backgroundImage = bgImage;
			}
			if(wasTransparent){
				node.style.backgroundColor = "transparent";
			}
			if(callback){
				callback(node, anim);
			}
		};

		anims.push(anim);
	});

	if(nodes.length > 1){ return dojo.lfx.combine(anims); }
	else{ return anims[0]; }
}

dojo.lfx.html.unhighlight = function(nodes, endColor, duration, easing, callback){
	nodes = dojo.lfx.html._byId(nodes);
	var anims = [];

	dojo.lang.forEach(nodes, function(node){
		var color = new dojo.graphics.color.Color(dojo.style.getBackgroundColor(node));
		var rgb = new dojo.graphics.color.Color(endColor);

		var bgImage = dojo.style.getStyle(node, "background-image");
		
		var anim = dojo.lfx.propertyAnimation(node, [{
			property: "background-color",
			start: color,
			end: rgb
		}], duration, easing);

		var oldbb = (anim["beforeBegin"]) ? dojo.lang.hitch(anim, "beforeBegin") : function(){};
		anim.beforeBegin = function(){ 
			oldbb();
			if(bgImage){
				node.style.backgroundImage = "none";
			}
			node.style.backgroundColor = "rgb(" + color.toRgb().join(",") + ")";
		};

		var oldOnEnd = (anim["onEnd"]) ? dojo.lang.hitch(anim, "onEnd") : function(){};
		anim.onEnd = function(){ 
			oldOnEnd();
			if(callback){
				callback(node, anim);
			}
		};

		anims.push(anim);
	});

	if(nodes.length > 1){ return dojo.lfx.combine(anims); }
	else{ return anims[0]; }
}

dojo.lang.mixin(dojo.lfx, dojo.lfx.html);

__CPAN_FILE__ src/lfx/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	browser: ["dojo.lfx.html"],
	dashboard: ["dojo.lfx.html"]
});
dojo.provide("dojo.lfx.*");
__CPAN_FILE__ src/lfx/toggle.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lfx.toggle");
dojo.require("dojo.lfx.*");

dojo.lfx.toggle.plain = {
	show: function(node, duration, easing, callback){
		dojo.style.show(node);
		if(dojo.lang.isFunction(callback)){ callback(); }
	},
	
	hide: function(node, duration, easing, callback){
		dojo.style.hide(node);
		if(dojo.lang.isFunction(callback)){ callback(); }
	}
}

dojo.lfx.toggle.fade = {
	show: function(node, duration, easing, callback){
		dojo.lfx.fadeShow(node, duration, easing, callback).play();
	},

	hide: function(node, duration, easing, callback){
		dojo.lfx.fadeHide(node, duration, easing, callback).play();
	}
}

dojo.lfx.toggle.wipe = {
	show: function(node, duration, easing, callback){
		dojo.lfx.wipeIn(node, duration, easing, callback).play();
	},

	hide: function(node, duration, easing, callback){
		dojo.lfx.wipeOut(node, duration, easing, callback).play();
	}
}

dojo.lfx.toggle.explode = {
	show: function(node, duration, easing, callback, explodeSrc){
		dojo.lfx.explode(explodeSrc||[0,0,0,0], node, duration, easing, callback).play();
	},

	hide: function(node, duration, easing, callback, explodeSrc){
		dojo.lfx.implode(node, explodeSrc||[0,0,0,0], duration, easing, callback).play();
	}
}

__CPAN_FILE__ src/lfx/extras.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lfx.extras");

dojo.require("dojo.lfx.html");
dojo.require("dojo.lfx.Animation");

dojo.lfx.html.fadeWipeIn = function(nodes, duration, easing, callback){
	nodes = dojo.lfx.html._byId(nodes);
	var anim = dojo.lfx.combine(
		dojo.lfx.wipeIn(nodes, duration, easing),
		dojo.lfx.fadeIn(nodes, duration, easing));
	
	if(callback){
		dojo.event.connect(anim, "onEnd", function(){
			callback(nodes, anim);
		});
	}
	
	return anim;
}

dojo.lfx.html.fadeWipeOut = function(nodes, duration, easing, callback){
	nodes = dojo.lfx.html._byId(nodes);
	var anim = dojo.lfx.combine(
		dojo.lfx.wipeOut(nodes, duration, easing),
		dojo.lfx.fadeOut(nodes, duration, easing));
	
	if(callback){
		dojo.event.connect(anim, "onEnd", function(){
			callback(nodes, anim);
		});
	}

	return anim;
}

dojo.lfx.html.scale = function(nodes, percentage, scaleContent, fromCenter, duration, easing, callback){
	nodes = dojo.lfx.html._byId(nodes);
	var anims = [];

	dojo.lang.forEach(nodes, function(node){
		var origWidth = dojo.style.getOuterWidth(node);
		var origHeight = dojo.style.getOuterHeight(node);

		var actualPct = percentage/100.0;
		var props = [
			{	property: "width",
				start: origWidth,
				end: origWidth * actualPct
			},
			{	property: "height",
				start: origHeight,
				end: origHeight * actualPct
			}];
		
		if(scaleContent){
			var fontSize = dojo.style.getStyle(node, 'font-size');
			var fontSizeType = null;
			if(!fontSize){
				fontSize = parseFloat('100%');
				fontSizeType = '%';
			}else{
				dojo.lang.some(['em','px','%'], function(item, index, arr){
					if(fontSize.indexOf(item)>0){
						fontSize = parseFloat(fontSize);
						fontSizeType = item;
						return true;
					}
				});
			}
			props.push({
				property: "font-size",
				start: fontSize,
				end: fontSize * actualPct,
				units: fontSizeType });
		}
		
		if(fromCenter){
			var positioning = dojo.style.getStyle(node, "position");
			var originalTop = node.offsetTop;
			var originalLeft = node.offsetLeft;
			var endTop = ((origHeight * actualPct) - origHeight)/2;
			var endLeft = ((origWidth * actualPct) - origWidth)/2;
			props.push({
				property: "top",
				start: originalTop,
				end: (positioning == "absolute" ? originalTop - endTop : (-1*endTop))
			});
			props.push({
				property: "left",
				start: originalLeft,
				end: (positioning == "absolute" ? originalLeft - endLeft : (-1*endLeft))
			});
		}
		
		var anim = dojo.lfx.propertyAnimation(node, props, duration, easing);
		if(callback){
			dojo.event.connect(anim, "onEnd", function(){
				callback(node, anim);
			});
		}

		anims.push(anim);
	});
	
	if(nodes.length > 1){ return dojo.lfx.combine(anims); }
	else{ return anims[0]; }
}

dojo.lang.mixin(dojo.lfx, dojo.lfx.html);

__CPAN_DIR__ src/i18n
__CPAN_FILE__ src/i18n/common.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.i18n.common");
dojo.require("dojo.lang");

dojo.require("dojo.experimental");
dojo.experimental("dojo.i18n.common");


/**
 * Gets a reference to a hash containing the localization for a given bundle in a package, matching the specified
 * locale.  Bundle must have already been loaded by dojo.requireLocalization() or by a build optimization step.
 *
 * @param modulename package in which the bundle is found
 * @param bundlename the filename in the directory structure without the ".js" suffix
 * @param locale the variant to load (optional).  By default, the locale defined by the
 *   host environment: dojo.locale
 * @return a hash containing name/value pairs.  Throws an exception if the bundle is not found.
 */
dojo.i18n.getLocalization = function(modulename, bundlename, locale /*optional*/){
	locale = dojo.normalizeLocale(locale);

	// look for nearest locale match
	var elements = locale.split('-');
	var bundle = dojo.hostenv.findModule([modulename,"_nls",bundlename].join('.'), true);

	for(var i = elements.length; i > 0; i--){
		var loc = elements.slice(0, i).join('-');
		if(bundle[loc]){
			return bundle[loc];
		}
	}

	if(bundle[dojo.fallback_locale]){
		return bundle[dojo.fallback_locale];
	}

	dojo.raise("Bundle not found " + [modulename,"_nls",bundlename,locale].join('.'));
};

/**
 * Is the language read left-to-right?  Most exceptions are for middle eastern languages.
 *
 * @param locale a string representing the locale.  By default, the locale defined by the
 *   host environment: dojo.locale
 * @return true if language is read left to right; false otherwise
 */
dojo.i18n.isLTR = function(locale /*optional*/){
	var lang = dojo.normalizeLocale(locale).split('-')[0];
	var RTL = {ar:true,fa:true,he:true,ur:true,yi:true};
	return !RTL[lang];
}

__CPAN_DIR__ src/crypto
__CPAN_FILE__ src/crypto/LICENSE
License Disclaimer:

All contents of this directory are Copyright (c) the Dojo Foundation, with the
following exceptions:
-------------------------------------------------------------------------------

MD5.js, SHA1.js:
	* Copyright 1998-2005, Paul Johnstone
	  Distributed under the terms of the BSD License



__CPAN_FILE__ src/crypto/SHA256.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.crypto.SHA256");
dojo.require("dojo.crypto");
dojo.require("dojo.experimental");

dojo.experimental("dojo.crypto.SHA256");

dojo.crypto.SHA256 = new function(){
	this.compute=function(s){
	};
}();

__CPAN_FILE__ src/crypto/Rijndael.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.crypto.Rijndael");
dojo.require("dojo.crypto");
dojo.require("dojo.experimental");

dojo.experimental("dojo.crypto.Rijndael");

dojo.crypto.Rijndael = new function(){
	this.encrypt=function(plaintext, key){
	};
	this.decrypt=function(ciphertext, key){
	};
}();

__CPAN_FILE__ src/crypto/MD5.js
dojo.require("dojo.crypto");
dojo.provide("dojo.crypto.MD5");

/*	Return to a port of Paul Johnstone's MD5 implementation
 *	http://pajhome.org.uk/crypt/md5/index.html
 *
 *	Copyright (C) Paul Johnston 1999 - 2002.
 *	Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * 	Distributed under the BSD License
 *
 *	Dojo port by Tom Trenka
 *
 *	2005-12-7
 *	All conversions are internalized (no dependencies)
 *	implemented getHMAC for message digest auth.
 */
dojo.crypto.MD5 = new function(){
	var chrsz=8;
	var mask=(1<<chrsz)-1;
	function toWord(s) {
	  var wa=[];
	  for(var i=0; i<s.length*chrsz; i+=chrsz)
		wa[i>>5]|=(s.charCodeAt(i/chrsz)&mask)<<(i%32);
	  return wa;
	}
	function toString(wa){
		var s=[];
		for(var i=0; i<wa.length*32; i+=chrsz)
			s.push(String.fromCharCode((wa[i>>5]>>>(i%32))&mask));
		return s.join("");
	}
	function toHex(wa) {
		var h="0123456789abcdef";
		var s=[];
		for(var i=0; i<wa.length*4; i++){
			s.push(h.charAt((wa[i>>2]>>((i%4)*8+4))&0xF)+h.charAt((wa[i>>2]>>((i%4)*8))&0xF));
		}
		return s.join("");
	}
	function toBase64(wa){
		var p="=";
		var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		var s=[];
		for(var i=0; i<wa.length*4; i+=3){
			var t=(((wa[i>>2]>>8*(i%4))&0xFF)<<16)|(((wa[i+1>>2]>>8*((i+1)%4))&0xFF)<<8)|((wa[i+2>>2]>>8*((i+2)%4))&0xFF);
			for(var j=0; j<4; j++){
				if(i*8+j*6>wa.length*32) s.push(p);
				else s.push(tab.charAt((t>>6*(3-j))&0x3F));
			}
		}
		return s.join("");
	}
	function add(x,y) {
		var l=(x&0xFFFF)+(y&0xFFFF);
		var m=(x>>16)+(y>>16)+(l>>16);
		return (m<<16)|(l&0xFFFF);
	}
	function R(n,c){ return (n<<c)|(n>>>(32-c)); }
	function C(q,a,b,x,s,t){ return add(R(add(add(a,q),add(x,t)),s),b); }
	function FF(a,b,c,d,x,s,t){ return C((b&c)|((~b)&d),a,b,x,s,t); }
	function GG(a,b,c,d,x,s,t){ return C((b&d)|(c&(~d)),a,b,x,s,t); }
	function HH(a,b,c,d,x,s,t){ return C(b^c^d,a,b,x,s,t); }
	function II(a,b,c,d,x,s,t){ return C(c^(b|(~d)),a,b,x,s,t); }
	function core(x,len){
		x[len>>5]|=0x80<<((len)%32);
		x[(((len+64)>>>9)<<4)+14]=len;
		var a= 1732584193;
		var b=-271733879;
		var c=-1732584194;
		var d= 271733878;
		for(var i=0; i<x.length; i+=16){
			var olda=a;
			var oldb=b;
			var oldc=c;
			var oldd=d;

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

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

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

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

			a = add(a,olda);
			b = add(b,oldb);
			c = add(c,oldc);
			d = add(d,oldd);
		}
		return [a,b,c,d];
	}
	function hmac(data,key){
		var wa=toWord(key);
		if(wa.length>16) wa=core(wa,key.length*chrsz);
		var l=[], r=[];
		for(var i=0; i<16; i++){
			l[i]=wa[i]^0x36363636;
			r[i]=wa[i]^0x5c5c5c5c;
		}
		var h=core(l.concat(toWord(data)),512+data.length*chrsz);
		return core(r.concat(h),640);
	}

	//	Public functions
	this.compute=function(data,outputType){
		var out=outputType||dojo.crypto.outputTypes.Base64;
		switch(out){
			case dojo.crypto.outputTypes.Hex:{
				return toHex(core(toWord(data),data.length*chrsz));
			}
			case dojo.crypto.outputTypes.String:{
				return toString(core(toWord(data),data.length*chrsz));
			}
			default:{
				return toBase64(core(toWord(data),data.length*chrsz));
			}
		}
	};
	this.getHMAC=function(data,key,outputType){
		var out=outputType||dojo.crypto.outputTypes.Base64;
		switch(out){
			case dojo.crypto.outputTypes.Hex:{
				return toHex(hmac(data,key));
			}
			case dojo.crypto.outputTypes.String:{
				return toString(hmac(data,key));
			}
			default:{
				return toBase64(hmac(data,key));
			}
		}
	};
}();

__CPAN_FILE__ src/crypto/Blowfish.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.crypto");
dojo.provide("dojo.crypto.Blowfish");

/*	Blowfish
 *	Created based on the C# implementation by Marcus Hahn (http://www.hotpixel.net/)
 *	Unsigned math functions derived from Joe Gregorio's SecureSyndication GM script
 *	http://bitworking.org/projects/securesyndication/
 *	(Note that this is *not* an adaption of the above script)
 *
 *	version 1.0 
 *	TRT 
 *	2005-12-08
 */
dojo.crypto.Blowfish = new function(){
	var POW2=Math.pow(2,2);
	var POW3=Math.pow(2,3);
	var POW4=Math.pow(2,4);
	var POW8=Math.pow(2,8);
	var POW16=Math.pow(2,16);
	var POW24=Math.pow(2,24);
	var iv=null;	//	CBC mode initialization vector
	var boxes={
		p:[
			0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 
			0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 
			0x9216d5d9, 0x8979fb1b
		],
		s0:[
			0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
			0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
			0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
			0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
			0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
			0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
			0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
			0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
			0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
			0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
			0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 
			0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 
			0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 
			0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
			0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
			0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
			0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 
			0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 
			0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 
			0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 
			0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
			0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 
			0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
			0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 
			0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
			0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
			0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
			0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
			0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
			0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
			0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
			0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
		],
		s1:[
			0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
			0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
			0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
			0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
			0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
			0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
			0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
			0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 
			0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 
			0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
			0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 
			0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
			0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 
			0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 
			0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
			0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 
			0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
			0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 
			0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
			0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 
			0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 
			0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 
			0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
			0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
			0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 
			0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
			0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
			0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
			0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
			0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
			0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
			0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
		],
		s2:[
			0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
			0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
			0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
			0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
			0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
			0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
			0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
			0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
			0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
			0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
			0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
			0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
			0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
			0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
			0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
			0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
			0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
			0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
			0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
			0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
			0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 
			0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
			0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
			0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 
			0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 
			0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 
			0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 
			0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
			0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
			0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 
			0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
			0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
		],
		s3:[
			0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
			0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
			0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 
			0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
			0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 
			0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 
			0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
			0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 
			0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 
			0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 
			0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
			0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 
			0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 
			0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 
			0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
			0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
			0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 
			0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
			0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 
			0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 
			0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 
			0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 
			0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
			0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 
			0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
			0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 
			0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 
			0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 
			0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 
			0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
			0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
			0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
		]
	}
////////////////////////////////////////////////////////////////////////////
	function add(x,y){
		var sum=(x+y)&0xffffffff;
		if (sum<0){
			sum=-sum;
			return (0x10000*((sum>>16)^0xffff))+(((sum&0xffff)^0xffff)+1);
		}
		return sum;
	}
	function split(x){
		var r=x&0xffffffff;
		if(r<0) {
			r=-r;
			return [((r&0xffff)^0xffff)+1,(r>>16)^0xffff];
		}
		return [r&0xffff,(r>>16)];
	}
	function xor(x,y){
		var xs=split(x);
		var ys=split(y);
		return (0x10000*(xs[1]^ys[1]))+(xs[0]^ys[0]);
	}
	function $(v, box){
		var d=v&0xff; v>>=8;
		var c=v&0xff; v>>=8;
		var b=v&0xff; v>>=8;
		var a=v&0xff;
		var r=add(box.s0[a],box.s1[b]);
		r=xor(r,box.s2[c]);
		return add(r,box.s3[d]);
	}
////////////////////////////////////////////////////////////////////////////
	function eb(o, box){
		var l=o.left;
		var r=o.right;
		l=xor(l,box.p[0]);
		r=xor(r,xor($(l,box),box.p[1]));
		l=xor(l,xor($(r,box),box.p[2]));
		r=xor(r,xor($(l,box),box.p[3]));
		l=xor(l,xor($(r,box),box.p[4]));
		r=xor(r,xor($(l,box),box.p[5]));
		l=xor(l,xor($(r,box),box.p[6]));
		r=xor(r,xor($(l,box),box.p[7]));
		l=xor(l,xor($(r,box),box.p[8]));
		r=xor(r,xor($(l,box),box.p[9]));
		l=xor(l,xor($(r,box),box.p[10]));
		r=xor(r,xor($(l,box),box.p[11]));
		l=xor(l,xor($(r,box),box.p[12]));
		r=xor(r,xor($(l,box),box.p[13]));
		l=xor(l,xor($(r,box),box.p[14]));
		r=xor(r,xor($(l,box),box.p[15]));
		l=xor(l,xor($(r,box),box.p[16]));
		o.right=l;
		o.left=xor(r,box.p[17]);
	}

	function db(o, box){
		var l=o.left;
		var r=o.right;
		l=xor(l,box.p[17]);
		r=xor(r,xor($(l,box),box.p[16]));
		l=xor(l,xor($(r,box),box.p[15]));
		r=xor(r,xor($(l,box),box.p[14]));
		l=xor(l,xor($(r,box),box.p[13]));
		r=xor(r,xor($(l,box),box.p[12]));
		l=xor(l,xor($(r,box),box.p[11]));
		r=xor(r,xor($(l,box),box.p[10]));
		l=xor(l,xor($(r,box),box.p[9]));
		r=xor(r,xor($(l,box),box.p[8]));
		l=xor(l,xor($(r,box),box.p[7]));
		r=xor(r,xor($(l,box),box.p[6]));
		l=xor(l,xor($(r,box),box.p[5]));
		r=xor(r,xor($(l,box),box.p[4]));
		l=xor(l,xor($(r,box),box.p[3]));
		r=xor(r,xor($(l,box),box.p[2]));
		l=xor(l,xor($(r,box),box.p[1]));
		o.right=l;
		o.left=xor(r,box.p[0]);
	}

	//	Note that we aren't caching contexts here; it might take a little longer
	//	but we should be more secure this way.
	function init(key){
		var k=key;
		if (typeof(k)=="string"){
			var a=[];
			for(var i=0; i<k.length; i++) 
				a.push(k.charCodeAt(i)&0xff);
			k=a;
		}
		//	init the boxes
		var box = { p:[], s0:[], s1:[], s2:[], s3:[] };
		for(var i=0; i<boxes.p.length; i++) box.p.push(boxes.p[i]);
		for(var i=0; i<boxes.s0.length; i++) box.s0.push(boxes.s0[i]);
		for(var i=0; i<boxes.s1.length; i++) box.s1.push(boxes.s1[i]);
		for(var i=0; i<boxes.s2.length; i++) box.s2.push(boxes.s2[i]);
		for(var i=0; i<boxes.s3.length; i++) box.s3.push(boxes.s3[i]);

		//	init p with the key
		var pos=0;
		var data=0;
		for(var i=0; i < box.p.length; i++){
			for (var j=0; j<4; j++){
				data = (data*POW8) | k[pos];
				if(++pos==k.length) pos=0;
			}
			box.p[i] = xor(box.p[i], data);
		}

		//	encrypt p and the s boxes
		var res={ left:0, right:0 };
		for(var i=0; i<box.p.length;){
			eb(res, box);
			box.p[i++]=res.left;
			box.p[i++]=res.right;
		}
		for (var i=0; i<4; i++){
			for(var j=0; j<box["s"+i].length;){
				eb(res, box);
				box["s"+i][j++]=res.left;
				box["s"+i][j++]=res.right;
			}
		}
		return box;
	}

////////////////////////////////////////////////////////////////////////////
//	CONVERSION FUNCTIONS
////////////////////////////////////////////////////////////////////////////
	//	these operate on byte arrays, NOT word arrays.
	function toBase64(ba){ 
		var p="=";
		var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		var s=[];
		var count=0;
		for (var i =0; i<ba.length;){
			var t=ba[i++]<<16|ba[i++]<<8|ba[i++];
			s.push(tab.charAt((t>>>18)&0x3f)); 
			s.push(tab.charAt((t>>>12)&0x3f));
			s.push(tab.charAt((t>>>6)&0x3f));
			s.push(tab.charAt(t&0x3f));
			count+=4;
		}
		var pa=i-ba.length;
		while((pa--)>0)	s.push(p);	
		return s.join("");
	}
	function fromBase64(str){
		var s=str.split("");
		var p="=";
		var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		var out=[];
		var l=s.length;
		while(s[--l]==p){ }
		for (var i=0; i<l;){
			var t=tab.indexOf(s[i++])<<18|tab.indexOf(s[i++])<<12|tab.indexOf(s[i++])<<6|tab.indexOf(s[i++]);
			out.push((t>>>16)&0xff);
			out.push((t>>>8)&0xff);
			out.push(t&0xff);
		}
		return out;
	}
////////////////////////////////////////////////////////////////////////////
//	PUBLIC FUNCTIONS
//	0.2: Only supporting ECB mode for now.
////////////////////////////////////////////////////////////////////////////
	this.getIV=function(outputType){
		var out=outputType||dojo.crypto.outputTypes.Base64;
		switch(out){
			case dojo.crypto.outputTypes.Hex:{
				var s=[];
				for(var i=0; i<iv.length; i++)
					s.push((iv[i]).toString(16));
				return s.join("");
			}
			case dojo.crypto.outputTypes.String:{
				return iv.join("");
			}
			case dojo.crypto.outputTypes.Raw:{
				return iv;
			}
			default:{
				return toBase64(iv);
			}
		}
	};
	this.setIV=function(data, inputType){
		var ip=inputType||dojo.crypto.outputTypes.Base64;
		var ba=null;
		switch(ip){
			case dojo.crypto.outputTypes.String:{
				ba=[];
				for (var i=0; i<data.length; i++){
					ba.push(data.charCodeAt(i));
				}
				break;
			}
			case dojo.crypto.outputTypes.Hex:{
				ba=[];
				var i=0;
				while (i+1<data.length){
					ba.push(parseInt(data.substr(i,2),16));
					i+=2;
				}
				break;
			}
			case dojo.crypto.outputTypes.Raw:{
				ba=data;
				break;
			}
			default:{
				ba=fromBase64(data);
				break;
			}
		}
		//	make it a pair of words now
		iv={};
		iv.left=ba[0]*POW24|ba[1]*POW16|ba[2]*POW8|ba[3];
		iv.right=ba[4]*POW24|ba[5]*POW16|ba[6]*POW8|ba[7];
	}
	this.encrypt = function(plaintext, key, ao){
		var out=dojo.crypto.outputTypes.Base64;
		var mode=dojo.crypto.cipherModes.EBC;
		if (ao){
			if (ao.outputType) out=ao.outputType;
			if (ao.cipherMode) mode=ao.cipherMode;
		}

		var bx = init(key);
		var padding = 8-(plaintext.length&7);
		for (var i=0; i<padding; i++) plaintext+=String.fromCharCode(padding);
		var cipher=[];
		var count=plaintext.length >> 3;
		var pos=0;
		var o={};
		var isCBC=(mode==dojo.crypto.cipherModes.CBC);
		var vector={left:iv.left||null, right:iv.right||null};
		for(var i=0; i<count; i++){
			o.left=plaintext.charCodeAt(pos)*POW24
				|plaintext.charCodeAt(pos+1)*POW16
				|plaintext.charCodeAt(pos+2)*POW8
				|plaintext.charCodeAt(pos+3);
			o.right=plaintext.charCodeAt(pos+4)*POW24
				|plaintext.charCodeAt(pos+5)*POW16
				|plaintext.charCodeAt(pos+6)*POW8
				|plaintext.charCodeAt(pos+7);

			if(isCBC){
				o.left=xor(o.left, vector.left);
				o.right=xor(o.right, vector.right);
			}

			eb(o, bx);	//	encrypt the block

			if(isCBC){
				vector.left=o.left;
				vector.right=o.right;dojo.crypto.outputTypes.Hex
			}

			cipher.push((o.left>>24)&0xff); 
			cipher.push((o.left>>16)&0xff); 
			cipher.push((o.left>>8)&0xff);
			cipher.push(o.left&0xff);
			cipher.push((o.right>>24)&0xff); 
			cipher.push((o.right>>16)&0xff); 
			cipher.push((o.right>>8)&0xff);
			cipher.push(o.right&0xff);
			pos+=8;
		}
		switch(out){
			case dojo.crypto.outputTypes.Hex:{
				var s=[];
				for(var i=0; i<cipher.length; i++)
					s.push((cipher[i]).toString(16));
				return s.join("");
			}
			case dojo.crypto.outputTypes.String:{
				return cipher.join("");
			}
			case dojo.crypto.outputTypes.Raw:{
				return cipher;
			}
			default:{
				return toBase64(cipher);
			}
		}
	};

	this.decrypt = function(ciphertext, key, ao){
		var ip=dojo.crypto.outputTypes.Base64;
		var mode=dojo.crypto.cipherModes.EBC;
		if (ao){
			if (ao.outputType) ip=ao.outputType;
			if (ao.cipherMode) mode=ao.cipherMode;
		}
		var bx = init(key);
		var pt=[];
	
		var c=null;
		switch(ip){
			case dojo.crypto.outputTypes.Hex:{
				c=[];
				var i=0;
				while (i+1<ciphertext.length){
					c.push(parseInt(ciphertext.substr(i,2),16));
					i+=2;
				}
				break;
			}
			case dojo.crypto.outputTypes.String:{
				c=[];
				for (var i=0; i<ciphertext.length; i++){
					c.push(ciphertext.charCodeAt(i));
				}
				break;
			}
			case dojo.crypto.outputTypes.Raw:{
				c=ciphertext;	//	should be a byte array
				break;
			}
			default:{
				c=fromBase64(ciphertext);
				break;
			}
		}

		var count=c.length >> 3;
		var pos=0;
		var o={};
		var isCBC=(mode==dojo.crypto.cipherModes.CBC);
		var vector={left:iv.left||null, right:iv.right||null};
		for(var i=0; i<count; i++){
			o.left=c[pos]*POW24|c[pos+1]*POW16|c[pos+2]*POW8|c[pos+3];
			o.right=c[pos+4]*POW24|c[pos+5]*POW16|c[pos+6]*POW8|c[pos+7];

			if(isCBC){
				var left=o.left;
				var right=o.right;
			}

			db(o, bx);	//	decrypt the block

			if(isCBC){
				o.left=xor(o.left, vector.left);
				o.right=xor(o.right, vector.right);
				vector.left=left;
				vector.right=right;
			}

			pt.push((o.left>>24)&0xff);
			pt.push((o.left>>16)&0xff);
			pt.push((o.left>>8)&0xff);
			pt.push(o.left&0xff);
			pt.push((o.right>>24)&0xff);
			pt.push((o.right>>16)&0xff);
			pt.push((o.right>>8)&0xff);
			pt.push(o.right&0xff);
			pos+=8;
		}

		//	check for padding, and remove.
		if(pt[pt.length-1]==pt[pt.length-2]||pt[pt.length-1]==0x01){
			var n=pt[pt.length-1];
			pt.splice(pt.length-n, n);
		}

		//	convert to string
		for(var i=0; i<pt.length; i++)
			pt[i]=String.fromCharCode(pt[i]);
		return pt.join("");
	};

	this.setIV("0000000000000000", dojo.crypto.outputTypes.Hex);
}();

__CPAN_FILE__ src/crypto/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: [
		"dojo.crypto",
		"dojo.crypto.MD5"
	]
});
dojo.provide("dojo.crypto.*");

__CPAN_FILE__ src/crypto/SHA1.js
dojo.require("dojo.crypto");
dojo.provide("dojo.crypto.SHA1");
dojo.require("dojo.experimental");

/*
 *	A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
 *	in FIPS PUB 180-1
 *
 * 	Version 2.1a Copyright Paul Johnston 2000 - 2002.
 * 	Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * 	Distributed under the BSD License
 * 	See http://pajhome.org.uk/crypt/md5 for details.
 *
 *	Dojo port by Tom Trenka
 */
dojo.experimental("dojo.crypto.SHA1");

dojo.crypto.SHA1 = new function(){
	var chrsz=8;
	var mask=(1<<chrsz)-1;
	function toWord(s) {
	  var wa=[];
	  for(var i=0; i<s.length*chrsz; i+=chrsz)
		wa[i>>5]|=(s.charCodeAt(i/chrsz)&mask)<<(i%32);
	  return wa;
	}
	function toString(wa){
		var s=[];
		for(var i=0; i<wa.length*32; i+=chrsz)
			s.push(String.fromCharCode((wa[i>>5]>>>(i%32))&mask));
		return s.join("");
	}
	function toHex(wa) {
		var h="0123456789abcdef";
		var s=[];
		for(var i=0; i<wa.length*4; i++){
			s.push(h.charAt((wa[i>>2]>>((i%4)*8+4))&0xF)+h.charAt((wa[i>>2]>>((i%4)*8))&0xF));
		}
		return s.join("");
	}
	function toBase64(wa){
		var p="=";
		var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		var s=[];
		for(var i=0; i<wa.length*4; i+=3){
			var t=(((wa[i>>2]>>8*(i%4))&0xFF)<<16)|(((wa[i+1>>2]>>8*((i+1)%4))&0xFF)<<8)|((wa[i+2>>2]>>8*((i+2)%4))&0xFF);
			for(var j=0; j<4; j++){
				if(i*8+j*6>wa.length*32) s.push(p);
				else s.push(tab.charAt((t>>6*(3-j))&0x3F));
			}
		}
		return s.join("");
	}

	//	math
	function add(x,y){
		var l=(x&0xffff)+(y&0xffff);
		var m=(x>>16)+(y>>16)+(l>>16);
		return (m<<16)|(l&0xffff);
	}
	function r(x,n){  return (x<<n)|(x>>>(32-n)); }
	
	//	SHA rounds
	function f(u,v,w){ return ((u&v)|(~u&w)); }
	function g(u,v,w){ return ((u&v)|(u&w)|(v&w)); }
	function h(u,v,w){ return (u^v^w); }
	
	function fn(i,u,v,w){
		if(i<20) return f(u,v,w);
		if(i<40) return h(u,v,w);
		if(i<60) return g(u,v,w);
		return h(u,v,w);
	}
	function cnst(i){
		if(i<20) return 1518500249;
		if(i<40) return 1859775393;
		if(i<60) return -1894007588;
		return -899497514;
	}

	function core(x,len){
		x[len>>5]|=0x80<<(24-len%32);
		x[((len+64>>9)<<4)+15]=len;

		var w=[];
		var a= 1732584193;		//	0x67452301
		var b=-271733879;		//	0xefcdab89
		var c=-1732584194;		//	0x98badcfe
		var d= 271733878;		//	0x10325476
		var e=-1009589776;		//	0xc3d2e1f0
		
		for(var i=0; i<x.length; i+=16){
			var olda=a;
			var oldb=b;
			var oldc=c;
			var oldd=d;
			var olde=e;

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

			a=add(a,olda);
			b=add(b,oldb);
			c=add(c,oldc);
			d=add(d,oldd);
			e=add(e,olde);
		}
		return [a,b,c,d,e];
	}
	function hmac(data,key){
		var wa=toWord(key);
		if(wa.length>16) wa=core(wa,key.length*chrsz);
		var l=[], r=[];
		for(var i=0; i<16; i++){
			l[i]=wa[i]^0x36363636;
			r[i]=wa[i]^0x5c5c5c5c;
		}
		var h=core(l.concat(toWord(data)),512+data.length*chrsz);
		return core(r.concat(h),640);
	}

	this.compute=function(data,outputType){
		var out=outputType||dojo.crypto.outputTypes.Base64;
		switch(out){
			case dojo.crypto.outputTypes.Hex:{
				return toHex(core(toWord(data),data.length*chrsz));
			}
			case dojo.crypto.outputTypes.String:{
				return toString(core(toWord(data),data.length*chrsz));
			}
			default:{
				return toBase64(core(toWord(data),data.length*chrsz));
			}
		}
	};
	this.getHMAC=function(data,key,outputType){
		var out=outputType||dojo.crypto.outputTypes.Base64;
		switch(out){
			case dojo.crypto.outputTypes.Hex:{
				return toHex(hmac(data,key));
			}
			case dojo.crypto.outputTypes.String:{
				return toString(hmac(data,key));
			}
			default:{
				return toBase64(hmac(data,key));
			}
		}
	};
}();

__CPAN_DIR__ src/reflect
__CPAN_FILE__ src/reflect/reflection.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.deprecated("dojo.reflect", "merged into dojo.lang (dojo.lang[type])", "0.4");
dojo.provide("dojo.reflect");

/*****************************************************************
	reflect.js
	v.1.5.0
	(c) 2003-2004 Thomas R. Trenka, Ph.D.

	Derived from the reflection functions of f(m).
	http://dojotoolkit.org
	http://fm.dept-z.com

	There is a dependency on the variable dJ_global, which
	should always refer to the global object.
******************************************************************/
if(!dj_global){ var dj_global = this; }

dojo.reflect = {} ;
dojo.reflect.$unknownType = function(){ } ;
dojo.reflect.ParameterInfo = function(name, type){ 
	this.name = name ;
	this.type = (type) ? type : dojo.reflect.$unknownType ;
} ;
dojo.reflect.PropertyInfo = function(name, type) { 
	this.name = name ;
	this.type = (type) ? type : dojo.reflect.$unknownType ;
} ;
dojo.reflect.MethodInfo = function(name, fn){
	var parse = function(f) {
		var o = {} ; 
		var s = f.toString() ;
		var param = ((s.substring(s.indexOf('(')+1, s.indexOf(')'))).replace(/\s+/g, "")).split(",") ;
		o.parameters = [] ;
		for (var i = 0; i < param.length; i++) {
			o.parameters.push(new dojo.reflect.ParameterInfo(param[i])) ;
		}
		o.body = (s.substring(s.indexOf('{')+1, s.lastIndexOf('}'))).replace(/(^\s*)|(\s*$)/g, "") ;
		return o ;
	} ;

	var tmp = parse(fn) ;
	var p = tmp.parameters ;
	var body = tmp.body ;
	
	this.name = (name) ? name : "anonymous" ;
	this.getParameters = function(){ return p ; } ;
	this.getNullArgumentsObject = function() {
		var a = [] ;
		for (var i = 0; i < p.length; i++){
			a.push(null);
		}
		return a ;
	} ;
	this.getBody = function() { return body ; } ;
	this.type = Function ;
	this.invoke = function(src, args){ return fn.apply(src, args) ; } ;
} ;

//	Static object that can activate instances of the passed type.
dojo.reflect.Activator = new (function(){
	this.createInstance = function(type, args) {
		switch (typeof(type)) {
			case "function" : { 
				var o = {} ;
				type.apply(o, args) ;
				return o ;
			} ;
			case "string" : {
				var o = {} ;
				(dojo.reflect.Reflector.getTypeFromString(type)).apply(o, args) ;
				return o ;
			} ;
		}
		throw new Error("dojo.reflect.Activator.createInstance(): no such type exists.");
	}
})() ;

dojo.reflect.Reflector = new (function(){
	this.getTypeFromString = function(s) {
		var parts = s.split("."), i = 0, obj = dj_global ; 
		do { obj = obj[parts[i++]] ; } while (i < parts.length && obj) ; 
		return (obj != dj_global) ? obj : null ;
	}; 

	this.typeExists = function(s) {
		var parts = s.split("."), i = 0, obj = dj_global ; 
		do { obj = obj[parts[i++]] ; } while (i < parts.length && obj) ; 
		return (obj && obj != dj_global) ;
	}; 

	this.getFieldsFromType = function(s) { 
		var type = s ;
		if (typeof(s) == "string") {
			type = this.getTypeFromString(s) ;
		}
		var nullArgs = (new dojo.reflect.MethodInfo(type)).getNullArgumentsObject() ;
		return this.getFields(dojo.reflect.Activator.createInstance(s, nullArgs)) ;
	};

	this.getPropertiesFromType = function(s) { 
		var type = s ;
		if (typeof(s) == "string") {
			type = this.getTypeFromString(s);
		}
		var nullArgs = (new dojo.reflect.MethodInfo(type)).getNullArgumentsObject() ;
		return this.getProperties(dojo.reflect.Activator.createInstance(s, nullArgs)) ;
	};

	this.getMethodsFromType = function(s) { 
		var type = s ;
		if (typeof(s) == "string") {
			type = this.getTypeFromString(s) ;
		}
		var nullArgs = (new dojo.reflect.MethodInfo(type)).getNullArgumentsObject() ;
		return this.getMethods(dojo.reflect.Activator.createInstance(s, nullArgs)) ;
	};

	this.getType = function(o) { return o.constructor ; } ;

	this.getFields = function(obj) {
		var arr = [] ;
		for (var p in obj) { 
			if(this.getType(obj[p]) != Function){
				arr.push(new dojo.reflect.PropertyInfo(p, this.getType(obj[p]))) ;
			}else{
				arr.push(new dojo.reflect.MethodInfo(p, obj[p]));
			}
		}
		return arr ;
	};

	this.getProperties = function(obj) {
		var arr = [] ;
		var fi = this.getFields(obj) ;
		for (var i = 0; i < fi.length; i++){
			if (this.isInstanceOf(fi[i], dojo.reflect.PropertyInfo)){
				arr.push(fi[i]) ;
			}
		}
		return arr ;
	};

	this.getMethods = function(obj) {
		var arr = [] ;
		var fi = this.getFields(obj) ;
		for (var i = 0; i < fi.length; i++){
			if (this.isInstanceOf(fi[i], dojo.reflect.MethodInfo)){
				arr.push(fi[i]) ;
			}
		}
		return arr ;
	};

	/*
	this.implements = function(o, type) {
		if (this.isSubTypeOf(o, type)) return false ;
		var f = this.getFieldsFromType(type) ;
		for (var i = 0; i < f.length; i++) {
			if (typeof(o[(f[i].name)]) == "undefined"){
				return false;
			}
		}
		return true ;
	};
	*/

	this.getBaseClass = function(o) {
		if (o.getType().prototype.prototype.constructor){
			return (o.getType()).prototype.prototype.constructor ;
		}
		return Object ;
	} ;

	this.isInstanceOf = function(o, type) { 
		return (this.getType(o) == type) ; 
	};

	this.isSubTypeOf = function(o, type) { 
		return (o instanceof type) ; 
	};

	this.isBaseTypeOf = function(o, type) { 
		return (type instanceof o); 
	};
})();

// back-compat
dojo.provide("dojo.reflect.reflection");

__CPAN_FILE__ src/reflect/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.deprecated("dojo.reflect", "merged into dojo.lang (dojo.lang[type]).", "0.4");
dojo.kwCompoundRequire({
	common: ["dojo.reflect.reflection"]
});
dojo.provide("dojo.reflect.*");

__CPAN_DIR__ src/undo
__CPAN_FILE__ src/undo/browser.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.undo.browser");
dojo.require("dojo.io");

try{
	if((!djConfig["preventBackButtonFix"])&&(!dojo.hostenv.post_load_)){
		document.write("<iframe style='border: 0px; width: 1px; height: 1px; position: absolute; bottom: 0px; right: 0px; visibility: visible;' name='djhistory' id='djhistory' src='"+(dojo.hostenv.getBaseScriptUri()+'iframe_history.html')+"'></iframe>");
	}
}catch(e){/* squelch */}

if(dojo.render.html.opera){
	dojo.debug("Opera is not supported with dojo.undo.browser, so back/forward detection will not work.");
}

/* NOTES:
 *  Safari 1.2: 
 *	back button "works" fine, however it's not possible to actually
 *	DETECT that you've moved backwards by inspecting window.location.
 *	Unless there is some other means of locating.
 *	FIXME: perhaps we can poll on history.length?
 *  Safari 2.0.3+ (and probably 1.3.2+):
 *	works fine, except when changeUrl is used. When changeUrl is used,
 *	Safari jumps all the way back to whatever page was shown before
 *	the page that uses dojo.undo.browser support.
 *  IE 5.5 SP2:
 *	back button behavior is macro. It does not move back to the
 *	previous hash value, but to the last full page load. This suggests
 *	that the iframe is the correct way to capture the back button in
 *	these cases.
 *	Don't test this page using local disk for MSIE. MSIE will not create 
 *	a history list for iframe_history.html if served from a file: URL. 
 *	The XML served back from the XHR tests will also not be properly 
 *	created if served from local disk. Serve the test pages from a web 
 *	server to test in that browser.
 *  IE 6.0:
 *	same behavior as IE 5.5 SP2
 * Firefox 1.0:
 *	the back button will return us to the previous hash on the same
 *	page, thereby not requiring an iframe hack, although we do then
 *	need to run a timer to detect inter-page movement.
 */
dojo.undo.browser = {
	initialHref: window.location.href,
	initialHash: window.location.hash,

	moveForward: false,
	historyStack: [],
	forwardStack: [],
	historyIframe: null,
	bookmarkAnchor: null,
	locationTimer: null,

	/**
	 * setInitialState sets the state object and back callback for the very first page that is loaded.
	 * It is recommended that you call this method as part of an event listener that is registered via
	 * dojo.addOnLoad().
	 */
	setInitialState: function(args){
		this.initialState = {"url": this.initialHref, "kwArgs": args, "urlHash": this.initialHash};
	},

	//FIXME: Would like to support arbitrary back/forward jumps. Have to rework iframeLoaded among other things.
	//FIXME: is there a slight race condition in moz using change URL with the timer check and when
	//       the hash gets set? I think I have seen a back/forward call in quick succession, but not consistent.
	/**
	 * addToHistory takes one argument, and it is an object that defines the following functions:
	 * - To support getting back button notifications, the object argument should implement a
	 *   function called either "back", "backButton", or "handle". The string "back" will be
	 *   passed as the first and only argument to this callback.
	 * - To support getting forward button notifications, the object argument should implement a
	 *   function called either "forward", "forwardButton", or "handle". The string "forward" will be
	 *   passed as the first and only argument to this callback.
	 * - If you want the browser location string to change, define "changeUrl" on the object. If the
	 *   value of "changeUrl" is true, then a unique number will be appended to the URL as a fragment
	 *   identifier (http://some.domain.com/path#uniquenumber). If it is any other value that does
	 *   not evaluate to false, that value will be used as the fragment identifier. For example,
	 *   if changeUrl: 'page1', then the URL will look like: http://some.domain.com/path#page1
	 *   
	 * Full example:
	 * 
	 * dojo.undo.browser.addToHistory({
	 *   back: function() { alert('back pressed'); },
	 *   forward: function() { alert('forward pressed'); },
	 *   changeUrl: true
	 * });
	 */
	addToHistory: function(args){
		var hash = null;
		if(!this.historyIframe){
			this.historyIframe = window.frames["djhistory"];
		}
		if(!this.bookmarkAnchor){
			this.bookmarkAnchor = document.createElement("a");
			(document.body||document.getElementsByTagName("body")[0]).appendChild(this.bookmarkAnchor);
			this.bookmarkAnchor.style.display = "none";
		}
		if((!args["changeUrl"])||(dojo.render.html.ie)){
			var url = dojo.hostenv.getBaseScriptUri()+"iframe_history.html?"+(new Date()).getTime();
			this.moveForward = true;
			dojo.io.setIFrameSrc(this.historyIframe, url, false);
		}
		if(args["changeUrl"]){
			this.changingUrl = true;
			hash = "#"+ ((args["changeUrl"]!==true) ? args["changeUrl"] : (new Date()).getTime());
			setTimeout("window.location.href = '"+hash+"'; dojo.undo.browser.changingUrl = false;", 1);
			this.bookmarkAnchor.href = hash;
			
			if(dojo.render.html.ie){
				var oldCB = args["back"]||args["backButton"]||args["handle"];

				//The function takes handleName as a parameter, in case the
				//callback we are overriding was "handle". In that case,
				//we will need to pass the handle name to handle.
				var tcb = function(handleName){
					if(window.location.hash != ""){
						setTimeout("window.location.href = '"+hash+"';", 1);
					}
					//Use apply to set "this" to args, and to try to avoid memory leaks.
					oldCB.apply(this, [handleName]);
				}
		
				//Set interceptor function in the right place.
				if(args["back"]){
					args.back = tcb;
				}else if(args["backButton"]){
					args.backButton = tcb;
				}else if(args["handle"]){
					args.handle = tcb;
				}
		
				//If addToHistory is called, then that means we prune the
				//forward stack -- the user went back, then wanted to
				//start a new forward path.
				this.forwardStack = []; 
				var oldFW = args["forward"]||args["forwardButton"]||args["handle"];
		
				//The function takes handleName as a parameter, in case the
				//callback we are overriding was "handle". In that case,
				//we will need to pass the handle name to handle.
				var tfw = function(handleName){
					if(window.location.hash != ""){
						window.location.href = hash;
					}
					if(oldFW){ // we might not actually have one
						//Use apply to set "this" to args, and to try to avoid memory leaks.
						oldFW.apply(this, [handleName]);
					}
				}

				//Set interceptor function in the right place.
				if(args["forward"]){
					args.forward = tfw;
				}else if(args["forwardButton"]){
					args.forwardButton = tfw;
				}else if(args["handle"]){
					args.handle = tfw;
				}

			}else if(dojo.render.html.moz){
				// start the timer
				if(!this.locationTimer){
					this.locationTimer = setInterval("dojo.undo.browser.checkLocation();", 200);
				}
			}
		}

		this.historyStack.push({"url": url, "kwArgs": args, "urlHash": hash});
	},

	checkLocation: function(){
		if (!this.changingUrl){
			var hsl = this.historyStack.length;

			if((window.location.hash == this.initialHash||window.location.href == this.initialHref)&&(hsl == 1)){
				// FIXME: could this ever be a forward button?
				// we can't clear it because we still need to check for forwards. Ugg.
				// clearInterval(this.locationTimer);
				this.handleBackButton();
				return;
			}
			// first check to see if we could have gone forward. We always halt on
			// a no-hash item.
			if(this.forwardStack.length > 0){
				if(this.forwardStack[this.forwardStack.length-1].urlHash == window.location.hash){
					this.handleForwardButton();
					return;
				}
			}
	
			// ok, that didn't work, try someplace back in the history stack
			if((hsl >= 2)&&(this.historyStack[hsl-2])){
				if(this.historyStack[hsl-2].urlHash==window.location.hash){
					this.handleBackButton();
					return;
				}
			}
		}
	},

	iframeLoaded: function(evt, ifrLoc){
		if(!dojo.render.html.opera){
			var query = this._getUrlQuery(ifrLoc.href);
			if(query == null){ 
				// alert("iframeLoaded");
				// we hit the end of the history, so we should go back
				if(this.historyStack.length == 1){
					this.handleBackButton();
				}
				return;
			}
			if(this.moveForward){
				// we were expecting it, so it's not either a forward or backward movement
				this.moveForward = false;
				return;
			}
	
			//Check the back stack first, since it is more likely.
			//Note that only one step back or forward is supported.
			if(this.historyStack.length >= 2 && query == this._getUrlQuery(this.historyStack[this.historyStack.length-2].url)){
				this.handleBackButton();
			}
			else if(this.forwardStack.length > 0 && query == this._getUrlQuery(this.forwardStack[this.forwardStack.length-1].url)){
				this.handleForwardButton();
			}
		}
	},

	handleBackButton: function(){
		//The "current" page is always at the top of the history stack.
		var current = this.historyStack.pop();
		if(!current){ return; }
		var last = this.historyStack[this.historyStack.length-1];
		if(!last && this.historyStack.length == 0){
			last = this.initialState;
		}
		if (last){
			if(last.kwArgs["back"]){
				last.kwArgs["back"]();
			}else if(last.kwArgs["backButton"]){
				last.kwArgs["backButton"]();
			}else if(last.kwArgs["handle"]){
				last.kwArgs.handle("back");
			}
		}
		this.forwardStack.push(current);
	},

	handleForwardButton: function(){
		var last = this.forwardStack.pop();
		if(!last){ return; }
		if(last.kwArgs["forward"]){
			last.kwArgs.forward();
		}else if(last.kwArgs["forwardButton"]){
			last.kwArgs.forwardButton();
		}else if(last.kwArgs["handle"]){
			last.kwArgs.handle("forward");
		}
		this.historyStack.push(last);
	},

	_getUrlQuery: function(url){
		var segments = url.split("?");
		if (segments.length < 2){
			return null;
		}
		else{
			return segments[1];
		}
	}
}

__CPAN_FILE__ src/undo/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.undo.Manager");
dojo.provide("dojo.undo.*");

__CPAN_FILE__ src/undo/Manager.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.undo.Manager");
dojo.require("dojo.lang");

dojo.undo.Manager = function(parent) {
	this.clear();
	this._parent = parent;
};
dojo.lang.extend(dojo.undo.Manager, {
	_parent: null,
	_undoStack: null,
	_redoStack: null,
	_currentManager: null,

	canUndo: false,
	canRedo: false,

	isUndoing: false,
	isRedoing: false,

	// these events allow you to hook in and update your code (UI?) as necessary
	onUndo: function(manager, item) {},
	onRedo: function(manager, item) {},

	// fired when you do *any* undo action, which means you'll have one for every item
	// in a transaction. this is usually only useful for debugging
	onUndoAny: function(manager, item) {},
	onRedoAny: function(manager, item) {},

	_updateStatus: function() {
		this.canUndo = this._undoStack.length > 0;
		this.canRedo = this._redoStack.length > 0;
	},

	clear: function() {
		this._undoStack = [];
		this._redoStack = [];
		this._currentManager = this;

		this.isUndoing = false;
		this.isRedoing = false;

		this._updateStatus();
	},

	undo: function() {
		if(!this.canUndo) { return false; }

		this.endAllTransactions();

		this.isUndoing = true;
		var top = this._undoStack.pop();
		if(top instanceof dojo.undo.Manager){
			top.undoAll();
		}else{
			top.undo();
		}
		if(top.redo){
			this._redoStack.push(top);
		}
		this.isUndoing = false;

		this._updateStatus();
		this.onUndo(this, top);
		if(!(top instanceof dojo.undo.Manager)){
			this.getTop().onUndoAny(this, top);
		}
		return true;
	},

	redo: function() {
		if(!this.canRedo){ return false; }

		this.isRedoing = true;
		var top = this._redoStack.pop();
		if(top instanceof dojo.undo.Manager){
			top.redoAll();
		}else{
			top.redo();
		}
		this._undoStack.push(top);
		this.isRedoing = false;

		this._updateStatus();
		this.onRedo(this, top);
		if(!(top instanceof dojo.undo.Manager)){
			this.getTop().onRedoAny(this, top);
		}
		return true;
	},

	undoAll: function() {
		while(this._undoStack.length > 0) {
			this.undo();
		}
	},

	redoAll: function() {
		while(this._redoStack.length > 0) {
			this.redo();
		}
	},

	push: function(undo, redo /* optional */, description /* optional */) {
		if(!undo) { return; }

		if(this._currentManager == this) {
			this._undoStack.push({
				undo: undo,
				redo: redo,
				description: description
			});
		} else {
			this._currentManager.push.apply(this._currentManager, arguments);
		}
		// adding a new undo-able item clears out the redo stack
		this._redoStack = [];
		this._updateStatus();
	},

	concat: function(manager) {
		if ( !manager ) { return; }

		if (this._currentManager == this ) {
			for(var x=0; x < manager._undoStack.length; x++) {
				this._undoStack.push(manager._undoStack[x]);
			}
			// adding a new undo-able item clears out the redo stack
			this._redoStack = [];
			this._updateStatus();
		} else {
			this._currentManager.concat.apply(this._currentManager, arguments);
		}
	},

	beginTransaction: function(description /* optional */) {
		if(this._currentManager == this) {
			var mgr = new dojo.undo.Manager(this);
			mgr.description = description ? description : "";
			this._undoStack.push(mgr);
			this._currentManager = mgr;
			return mgr;
		} else {
			//for nested transactions need to make sure the top level _currentManager is set
			this._currentManager = this._currentManager.beginTransaction.apply(this._currentManager, arguments);
		}
	},

	endTransaction: function(flatten /* optional */) {
		if(this._currentManager == this) {
			if(this._parent) {
				this._parent._currentManager = this._parent;
				// don't leave empty transactions hangin' around
				if(this._undoStack.length == 0 || flatten) {
					var idx = dojo.lang.find(this._parent._undoStack, this);
					if (idx >= 0) {
						this._parent._undoStack.splice(idx, 1);
						//add the current transaction to parents undo stack
						if (flatten) {
							for(var x=0; x < this._undoStack.length; x++){
								this._parent._undoStack.splice(idx++, 0, this._undoStack[x]);
							}
							this._updateStatus();
						}
					}
				}
				return this._parent;
			}
		} else {
			//for nested transactions need to make sure the top level _currentManager is set
			this._currentManager = this._currentManager.endTransaction.apply(this._currentManager, arguments);
		}
	},

	endAllTransactions: function() {
		while(this._currentManager != this) {
			this.endTransaction();
		}
	},

	// find the top parent of an undo manager
	getTop: function() {
		if(this._parent) {
			return this._parent.getTop();
		} else {
			return this;
		}
	}
});

__CPAN_DIR__ src/fx
__CPAN_FILE__ src/fx/svg.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.fx.svg");

dojo.require("dojo.svg");
dojo.require("dojo.animation.*");
dojo.require("dojo.event.*");

dojo.fx.svg.fadeOut = function(node, duration, callback){
	return dojo.fx.svg.fade(node, duration, dojo.svg.getOpacity(node), 0, callback);
};
dojo.fx.svg.fadeIn = function(node, duration, callback){
	return dojo.fx.svg.fade(node, duration, dojo.svg.getOpacity(node), 1, callback);
};
dojo.fx.svg.fadeHide = function(node, duration, callback){
	if(!duration) { duration = 150; } // why not have a default?
	return dojo.fx.svg.fadeOut(node, duration, function(node) {
		if(typeof callback == "function") { callback(node); }
	});
};
dojo.fx.svg.fadeShow = function(node, duration, callback){
	if(!duration) { duration = 150; } // why not have a default?
	return dojo.fx.svg.fade(node, duration, 0, 1, callback);
};
dojo.fx.svg.fade = function(node, duration, startOpac, endOpac, callback){
	var anim = new dojo.animation.Animation(
		new dojo.math.curves.Line([startOpac],[endOpac]),
		duration,
		0
	);
	dojo.event.connect(anim, "onAnimate", function(e){
		dojo.svg.setOpacity(node, e.x);
	});
	if (callback) {
		dojo.event.connect(anim, "onEnd", function(e){
			callback(node, anim);
		});
	};
	anim.play(true);
	return anim;
};

/////////////////////////////////////////////////////////////////////////////////////////
//	TODO
/////////////////////////////////////////////////////////////////////////////////////////

//	SLIDES
dojo.fx.svg.slideTo = function(node, endCoords, duration, callback) { };
dojo.fx.svg.slideBy = function(node, coords, duration, callback) { };
dojo.fx.svg.slide = function(node, startCoords, endCoords, duration, callback) { 
	var anim = new dojo.animation.Animation(
		new dojo.math.curves.Line([startCoords],[endCoords]),
		duration,
		0
	);
	dojo.event.connect(anim, "onAnimate", function(e){
		dojo.svg.setCoords(node, {x: e.x, y: e.y });
	});
	if (callback) {
		dojo.event.connect(anim, "onEnd", function(e){
			callback(node, anim);
		});
	};
	anim.play(true);
	return anim;
};

//	COLORS
dojo.fx.svg.colorFadeIn = function(node, startRGB, duration, delay, callback) { };
dojo.fx.svg.highlight = dojo.fx.svg.colorFadeIn;
dojo.fx.svg.colorFadeFrom = dojo.fx.svg.colorFadeIn;

dojo.fx.svg.colorFadeOut = function(node, endRGB, duration, delay, callback) { };
dojo.fx.svg.unhighlight = dojo.fx.svg.colorFadeOut;
dojo.fx.svg.colorFadeTo = dojo.fx.svg.colorFadeOut;

dojo.fx.svg.colorFade = function(node, startRGB, endRGB, duration, callback, dontPlay) { };

//	WIPES
dojo.fx.svg.wipeIn = function(node, duration, callback, dontPlay) { };
dojo.fx.svg.wipeInToHeight = function(node, duration, height, callback, dontPlay) { }
dojo.fx.svg.wipeOut = function(node, duration, callback, dontPlay) { };

//	Explode and Implode
dojo.fx.svg.explode = function(startNode, endNode, duration, callback) { };
dojo.fx.svg.explodeFromBox = function(startCoords, endNode, duration, callback) { };
dojo.fx.svg.implode = function(startNode, endNode, duration, callback) { };
dojo.fx.svg.implodeToBox = function(startNode, endCoords, duration, callback) { };
dojo.fx.svg.Exploder = function(triggerNode, boxNode) { };

//	html mixes in, we want SVG to remain separate

__CPAN_FILE__ src/fx/html.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.fx.html");

dojo.require("dojo.style");
dojo.require("dojo.math.curves");
dojo.require("dojo.lang.func");
dojo.require("dojo.animation");
dojo.require("dojo.event.*");
dojo.require("dojo.graphics.color");

dojo.deprecated("dojo.fx.html", "use dojo.lfx.html instead", "0.4");

dojo.fx.duration = 300;

dojo.fx.html._makeFadeable = function(node){
	if(dojo.render.html.ie){
		// only set the zoom if the "tickle" value would be the same as the
		// default
		if( (node.style.zoom.length == 0) &&
			(dojo.style.getStyle(node, "zoom") == "normal") ){
			// make sure the node "hasLayout"
			// NOTE: this has been tested with larger and smaller user-set text
			// sizes and works fine
			node.style.zoom = "1";
			// node.style.zoom = "normal";
		}
		// don't set the width to auto if it didn't already cascade that way.
		// We don't want to f anyones designs
		if(	(node.style.width.length == 0) &&
			(dojo.style.getStyle(node, "width") == "auto") ){
			node.style.width = "auto";
		}
	}
}

dojo.fx.html.fadeOut = function(node, duration, callback, dontPlay) {
	return dojo.fx.html.fade(node, duration, dojo.style.getOpacity(node), 0, callback, dontPlay);
};

dojo.fx.html.fadeIn = function(node, duration, callback, dontPlay) {
	return dojo.fx.html.fade(node, duration, dojo.style.getOpacity(node), 1, callback, dontPlay);
};

dojo.fx.html.fadeHide = function(node, duration, callback, dontPlay) {
	node = dojo.byId(node);
	if(!duration) { duration = 150; } // why not have a default?
	return dojo.fx.html.fadeOut(node, duration, function(node) {
		node.style.display = "none";
		if(typeof callback == "function") { callback(node); }
	});
};

dojo.fx.html.fadeShow = function(node, duration, callback, dontPlay) {
	node = dojo.byId(node);
	if(!duration) { duration = 150; } // why not have a default?
	node.style.display = "block";
	return dojo.fx.html.fade(node, duration, 0, 1, callback, dontPlay);
};

dojo.fx.html.fade = function(node, duration, startOpac, endOpac, callback, dontPlay) {
	node = dojo.byId(node);
	dojo.fx.html._makeFadeable(node);
	var anim = new dojo.animation.Animation(
		new dojo.math.curves.Line([startOpac],[endOpac]),
		duration||dojo.fx.duration, 0);
	dojo.event.connect(anim, "onAnimate", function(e) {
		dojo.style.setOpacity(node, e.x);
	});
	if(callback) {
		dojo.event.connect(anim, "onEnd", function(e) {
			callback(node, anim);
		});
	}
	if(!dontPlay) { anim.play(true); }
	return anim;
};

dojo.fx.html.slideTo = function(node, duration, endCoords, callback, dontPlay) {
	if(!dojo.lang.isNumber(duration)) {
		var tmp = duration;
		duration = endCoords;
		endCoords = tmp;
	}
	node = dojo.byId(node);

	var top = node.offsetTop;
	var left = node.offsetLeft;
	var pos = dojo.style.getComputedStyle(node, 'position');

	if (pos == 'relative' || pos == 'static') {
		top = parseInt(dojo.style.getComputedStyle(node, 'top')) || 0;
		left = parseInt(dojo.style.getComputedStyle(node, 'left')) || 0;
	}

	return dojo.fx.html.slide(node, duration, [left, top],
		endCoords, callback, dontPlay);
};

dojo.fx.html.slideBy = function(node, duration, coords, callback, dontPlay) {
	if(!dojo.lang.isNumber(duration)) {
		var tmp = duration;
		duration = coords;
		coords = tmp;
	}
	node = dojo.byId(node);

	var top = node.offsetTop;
	var left = node.offsetLeft;
	var pos = dojo.style.getComputedStyle(node, 'position');

	if (pos == 'relative' || pos == 'static') {
		top = parseInt(dojo.style.getComputedStyle(node, 'top')) || 0;
		left = parseInt(dojo.style.getComputedStyle(node, 'left')) || 0;
	}

	return dojo.fx.html.slideTo(node, duration, [left+coords[0], top+coords[1]],
		callback, dontPlay);
};

dojo.fx.html.slide = function(node, duration, startCoords, endCoords, callback, dontPlay) {
	if(!dojo.lang.isNumber(duration)) {
		var tmp = duration;
		duration = endCoords;
		endCoords = startCoords;
		startCoords = tmp;
	}
	node = dojo.byId(node);

	if (dojo.style.getComputedStyle(node, 'position') == 'static') {
		node.style.position = 'relative';
	}

	var anim = new dojo.animation.Animation(
		new dojo.math.curves.Line(startCoords, endCoords),
		duration||dojo.fx.duration, 0);
	dojo.event.connect(anim, "onAnimate", function(e) {
		with( node.style ) {
			left = e.x + "px";
			top = e.y + "px";
		}
	});
	if(callback) {
		dojo.event.connect(anim, "onEnd", function(e) {
			callback(node, anim);
		});
	}
	if(!dontPlay) { anim.play(true); }
	return anim;
};

// Fade from startColor to the node's background color
dojo.fx.html.colorFadeIn = function(node, duration, startColor, delay, callback, dontPlay) {
	if(!dojo.lang.isNumber(duration)) {
		var tmp = duration;
		duration = startColor;
		startColor = tmp;
	}
	node = dojo.byId(node);
	var color = dojo.style.getBackgroundColor(node);
	var bg = dojo.style.getStyle(node, "background-color").toLowerCase();
	var wasTransparent = bg == "transparent" || bg == "rgba(0, 0, 0, 0)";
	while(color.length > 3) { color.pop(); }

	var rgb = new dojo.graphics.color.Color(startColor).toRgb();
	var anim = dojo.fx.html.colorFade(node, duration||dojo.fx.duration, startColor, color, callback, true);
	dojo.event.connect(anim, "onEnd", function(e) {
		if( wasTransparent ) {
			node.style.backgroundColor = "transparent";
		}
	});
	if( delay > 0 ) {
		node.style.backgroundColor = "rgb(" + rgb.join(",") + ")";
		if(!dontPlay) { setTimeout(function(){anim.play(true)}, delay); }
	} else {
		if(!dontPlay) { anim.play(true); }
	}
	return anim;
};
// alias for (probably?) common use/terminology
dojo.fx.html.highlight = dojo.fx.html.colorFadeIn;
dojo.fx.html.colorFadeFrom = dojo.fx.html.colorFadeIn;

// Fade from node's background color to endColor
dojo.fx.html.colorFadeOut = function(node, duration, endColor, delay, callback, dontPlay) {
	if(!dojo.lang.isNumber(duration)) {
		var tmp = duration;
		duration = endColor;
		endColor = tmp;
	}
	node = dojo.byId(node);
	var color = new dojo.graphics.color.Color(dojo.style.getBackgroundColor(node)).toRgb();

	var rgb = new dojo.graphics.color.Color(endColor).toRgb();
	var anim = dojo.fx.html.colorFade(node, duration||dojo.fx.duration, color, rgb, callback, delay > 0 || dontPlay);
	if( delay > 0 ) {
		node.style.backgroundColor = "rgb(" + color.join(",") + ")";
		if(!dontPlay) { setTimeout(function(){anim.play(true)}, delay); }
	}
	return anim;
};
// FIXME: not sure which name is better. an alias here may be bad.
dojo.fx.html.unhighlight = dojo.fx.html.colorFadeOut;
dojo.fx.html.colorFadeTo = dojo.fx.html.colorFadeOut;

// Fade node background from startColor to endColor
dojo.fx.html.colorFade = function(node, duration, startColor, endColor, callback, dontPlay) {
	if(!dojo.lang.isNumber(duration)) {
		var tmp = duration;
		duration = endColor;
		endColor = startColor;
		startColor = tmp;
	}
	node = dojo.byId(node);
	var startRgb = new dojo.graphics.color.Color(startColor).toRgb();
	var endRgb = new dojo.graphics.color.Color(endColor).toRgb();
	var anim = new dojo.animation.Animation(
		new dojo.math.curves.Line(startRgb, endRgb),
		duration||dojo.fx.duration, 0);
	dojo.event.connect(anim, "onAnimate", function(e) {
		node.style.backgroundColor = "rgb(" + e.coordsAsInts().join(",") + ")";
	});
	if(callback) {
		dojo.event.connect(anim, "onEnd", function(e) {
			callback(node, anim);
		});
	}
	if( !dontPlay ) { anim.play(true); }
	return anim;
};

dojo.fx.html.wipeIn = function(node, duration, callback, dontPlay) {
	node = dojo.byId(node);
	var overflow = dojo.style.getStyle(node, "overflow");
	if(overflow == "visible") {
		node.style.overflow = "hidden";
	}
	node.style.height = 0;
	dojo.style.show(node);
	var anim = dojo.fx.html.wipe(node, duration, 0, node.scrollHeight, null, true);
	dojo.event.connect(anim, "onEnd", function() {
		node.style.overflow = overflow;
		node.style.visibility = "";
		node.style.height = "auto";
		if(callback) { callback(node, anim); }
	});
	if(!dontPlay) { anim.play(); }
	return anim;
}

dojo.fx.html.wipeOut = function(node, duration, callback, dontPlay) {
	node = dojo.byId(node);
	var overflow = dojo.style.getStyle(node, "overflow");
	if(overflow == "visible") {
		node.style.overflow = "hidden";
	}
	var anim = dojo.fx.html.wipe(node, duration, node.offsetHeight, 0, null, true);
	dojo.event.connect(anim, "onEnd", function() {
		dojo.style.hide(node);
		node.style.visibility = "hidden";
		node.style.overflow = overflow;
		if(callback) { callback(node, anim); }
	});
	if(!dontPlay) { anim.play(); }
	return anim;
}

dojo.fx.html.wipe = function(node, duration, startHeight, endHeight, callback, dontPlay) {
	node = dojo.byId(node);
	var anim = new dojo.animation.Animation([[startHeight], [endHeight]], duration||dojo.fx.duration, 0);
	dojo.event.connect(anim, "onAnimate", function(e) {
		node.style.height = e.x + "px";
	});
	dojo.event.connect(anim, "onEnd", function() {
		if(callback) { callback(node, anim); }
	});
	if(!dontPlay) { anim.play(); }
	return anim;
}

dojo.fx.html.wiper = function(node, controlNode) {
	this.node = dojo.byId(node);
	if(controlNode) {
		dojo.event.connect(dojo.byId(controlNode), "onclick", this, "toggle");
	}
}
dojo.lang.extend(dojo.fx.html.wiper, {
	duration: dojo.fx.duration,
	_anim: null,

	toggle: function() {
		if(!this._anim) {
			var type = "wipe" + (dojo.style.isVisible(this.node) ? "Out" : "In");
			this._anim = dojo.fx[type](this.node, this.duration, dojo.lang.hitch(this, "_callback"));
		}
	},

	_callback: function() {
		this._anim = null;
	}
});

dojo.fx.html.explode = function(start, endNode, duration, callback, dontPlay) {
	var startCoords = dojo.style.toCoordinateArray(start);

	var outline = document.createElement("div");
	with(outline.style) {
		position = "absolute";
		border = "1px solid black";
		display = "none";
	}
	document.body.appendChild(outline);

	endNode = dojo.byId(endNode);
	with(endNode.style) {
		visibility = "hidden";
		display = "block";
	}
	var endCoords = dojo.style.toCoordinateArray(endNode);

	with(endNode.style) {
		display = "none";
		visibility = "visible";
	}

	var anim = new dojo.animation.Animation(
		new dojo.math.curves.Line(startCoords, endCoords),
		duration||dojo.fx.duration, 0
	);
	dojo.event.connect(anim, "onBegin", function(e) {
		outline.style.display = "block";
	});
	dojo.event.connect(anim, "onAnimate", function(e) {
		with(outline.style) {
			left = e.x + "px";
			top = e.y + "px";
			width = e.coords[2] + "px";
			height = e.coords[3] + "px";
		}
	});

	dojo.event.connect(anim, "onEnd", function() {
		endNode.style.display = "block";
		outline.parentNode.removeChild(outline);
		if(callback) { callback(endNode, anim); }
	});
	if(!dontPlay) { anim.play(); }
	return anim;
};

dojo.fx.html.implode = function(startNode, end, duration, callback, dontPlay) {
	var startCoords = dojo.style.toCoordinateArray(startNode);
	var endCoords = dojo.style.toCoordinateArray(end);

	startNode = dojo.byId(startNode);
	var outline = document.createElement("div");
	with(outline.style) {
		position = "absolute";
		border = "1px solid black";
		display = "none";
	}
	document.body.appendChild(outline);

	var anim = new dojo.animation.Animation(
		new dojo.math.curves.Line(startCoords, endCoords),
		duration||dojo.fx.duration, 0
	);
	dojo.event.connect(anim, "onBegin", function(e) {
		startNode.style.display = "none";
		outline.style.display = "block";
	});
	dojo.event.connect(anim, "onAnimate", function(e) {
		with(outline.style) {
			left = e.x + "px";
			top = e.y + "px";
			width = e.coords[2] + "px";
			height = e.coords[3] + "px";
		}
	});

	dojo.event.connect(anim, "onEnd", function() {
		outline.parentNode.removeChild(outline);
		if(callback) { callback(startNode, anim); }
	});
	if(!dontPlay) { anim.play(); }
	return anim;
};

dojo.fx.html.Exploder = function(triggerNode, boxNode) {
	triggerNode = dojo.byId(triggerNode);
	boxNode = dojo.byId(boxNode);
	var _this = this;

	// custom options
	this.waitToHide = 500;
	this.timeToShow = 100;
	this.waitToShow = 200;
	this.timeToHide = 70;
	this.autoShow = false;
	this.autoHide = false;

	var animShow = null;
	var animHide = null;

	var showTimer = null;
	var hideTimer = null;

	var startCoords = null;
	var endCoords = null;

	this.showing = false;

	this.onBeforeExplode = null;
	this.onAfterExplode = null;
	this.onBeforeImplode = null;
	this.onAfterImplode = null;
	this.onExploding = null;
	this.onImploding = null;

	this.timeShow = function() {
		clearTimeout(showTimer);
		showTimer = setTimeout(_this.show, _this.waitToShow);
	}

	this.show = function() {
		clearTimeout(showTimer);
		clearTimeout(hideTimer);
		//triggerNode.blur();

		if( (animHide && animHide.status() == "playing")
			|| (animShow && animShow.status() == "playing")
			|| _this.showing ) { return; }

		if(typeof _this.onBeforeExplode == "function") { _this.onBeforeExplode(triggerNode, boxNode); }
		animShow = dojo.fx.html.explode(triggerNode, boxNode, _this.timeToShow, function(e) {
			_this.showing = true;
			if(typeof _this.onAfterExplode == "function") { _this.onAfterExplode(triggerNode, boxNode); }
		});
		if(typeof _this.onExploding == "function") {
			dojo.event.connect(animShow, "onAnimate", this, "onExploding");
		}
	}

	this.timeHide = function() {
		clearTimeout(showTimer);
		clearTimeout(hideTimer);
		if(_this.showing) {
			hideTimer = setTimeout(_this.hide, _this.waitToHide);
		}
	}

	this.hide = function() {
		clearTimeout(showTimer);
		clearTimeout(hideTimer);
		if( animShow && animShow.status() == "playing" ) {
			return;
		}

		_this.showing = false;
		if(typeof _this.onBeforeImplode == "function") { _this.onBeforeImplode(triggerNode, boxNode); }
		animHide = dojo.fx.html.implode(boxNode, triggerNode, _this.timeToHide, function(e){
			if(typeof _this.onAfterImplode == "function") { _this.onAfterImplode(triggerNode, boxNode); }
		});
		if(typeof _this.onImploding == "function") {
			dojo.event.connect(animHide, "onAnimate", this, "onImploding");
		}
	}

	// trigger events
	dojo.event.connect(triggerNode, "onclick", function(e) {
		if(_this.showing) {
			_this.hide();
		} else {
			_this.show();
		}
	});
	dojo.event.connect(triggerNode, "onmouseover", function(e) {
		if(_this.autoShow) {
			_this.timeShow();
		}
	});
	dojo.event.connect(triggerNode, "onmouseout", function(e) {
		if(_this.autoHide) {
			_this.timeHide();
		}
	});

	// box events
	dojo.event.connect(boxNode, "onmouseover", function(e) {
		clearTimeout(hideTimer);
	});
	dojo.event.connect(boxNode, "onmouseout", function(e) {
		if(_this.autoHide) {
			_this.timeHide();
		}
	});

	// document events
	dojo.event.connect(document.documentElement || document.body, "onclick", function(e) {
		function isDesc(node, ancestor) {
			while(node) {
				if(node == ancestor){ return true; }
				node = node.parentNode;
			}
			return false;
		}
		if(_this.autoHide && _this.showing
			&& !isDesc(e.target, boxNode)
			&& !isDesc(e.target, triggerNode) ) {
			_this.hide();
		}
	});

	return this;
};

/**** 
	Strategies for displaying/hiding objects
	This presents a standard interface for each of the effects
*****/
dojo.fx.html.toggle={}

dojo.fx.html.toggle.plain = {
	show: function(node, duration, explodeSrc, callback){
		dojo.style.show(node);
		if(dojo.lang.isFunction(callback)){ callback(); }
	},

	hide: function(node, duration, explodeSrc, callback){
		dojo.style.hide(node);
		if(dojo.lang.isFunction(callback)){ callback(); }
	}
}

dojo.fx.html.toggle.fade = {
	show: function(node, duration, explodeSrc, callback){
		dojo.fx.html.fadeShow(node, duration, callback);
	},

	hide: function(node, duration, explodeSrc, callback){
		dojo.fx.html.fadeHide(node, duration, callback);
	}
}

dojo.fx.html.toggle.wipe = {
	show: function(node, duration, explodeSrc, callback){
		dojo.fx.html.wipeIn(node, duration, callback);
	},

	hide: function(node, duration, explodeSrc, callback){
		dojo.fx.html.wipeOut(node, duration, callback);
	}
}

dojo.fx.html.toggle.explode = {
	show: function(node, duration, explodeSrc, callback){
		dojo.fx.html.explode(explodeSrc||[0,0,0,0], node, duration, callback);
	},

	hide: function(node, duration, explodeSrc, callback){
		dojo.fx.html.implode(node, explodeSrc||[0,0,0,0], duration, callback);
	}
}

dojo.lang.mixin(dojo.fx, dojo.fx.html);

__CPAN_FILE__ src/fx/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	browser: ["dojo.fx.html"],
	dashboard: ["dojo.fx.html"]
});
dojo.provide("dojo.fx.*");

__CPAN_DIR__ src/flash
__CPAN_DIR__ src/flash/flash8
__CPAN_FILE__ src/flash/flash8/ExpressInstall.as
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/**
 * Based on the expressinstall.as class created by Geoff Stearns as part
 * of the FlashObject library.
 *
 * Use this file to invoke the Macromedia Flash Player Express Install functionality
 * This file is intended for use with the FlashObject embed script. You can download FlashObject 
 * and this file at the following URL: http://blog.deconcept.com/flashobject/
 *
 * Usage: 
 *          var ExpressInstall = new ExpressInstall();
 *          
 *          // test to see if install is needed:
 *          if (ExpressInstall.needsUpdate) { // returns true if update is needed
 *              ExpressInstall.init(); // starts the update
 *          }
 *
 *	NOTE: Your Flash movie must be at least 214px by 137px in order to use ExpressInstall.
 *
 */

class ExpressInstall {
	public var needsUpdate:Boolean;
	private var updater:MovieClip;
	private var hold:MovieClip;
	
	public function ExpressInstall(){
		// does the user need to update?
		this.needsUpdate = (_root.MMplayerType == undefined) ? false : true;	
	}

	public function init():Void{
		this.loadUpdater();
	}

	public function loadUpdater():Void {
		System.security.allowDomain("fpdownload.macromedia.com");

		// hope that nothing is at a depth of 10000000, you can change this depth if needed, but you want
		// it to be on top of your content if you have any stuff on the first frame
		this.updater = _root.createEmptyMovieClip("expressInstallHolder", 10000000);

		// register the callback so we know if they cancel or there is an error
		var _self = this;
		this.updater.installStatus = _self.onInstallStatus;
		this.hold = this.updater.createEmptyMovieClip("hold", 1);

		// can't use movieClipLoader because it has to work in 6.0.65
		this.updater.onEnterFrame = function():Void {
			if(typeof this.hold.startUpdate == 'function'){
				_self.initUpdater();
				this.onEnterFrame = null;
			}
		}

		var cacheBuster:Number = Math.random();

		this.hold.loadMovie("http://fpdownload.macromedia.com/pub/flashplayer/"
												+"update/current/swf/autoUpdater.swf?"+ cacheBuster);
	}

	private function initUpdater():Void{
		this.hold.redirectURL = _root.MMredirectURL;
		this.hold.MMplayerType = _root.MMplayerType;
		this.hold.MMdoctitle = _root.MMdoctitle;
		this.hold.startUpdate();
	}

	public function onInstallStatus(msg):Void{
		getURL("javascript:dojo.flash.install._onInstallStatus('"+msg+"')");
	}
}

__CPAN_FILE__ src/flash/flash8/DojoExternalInterface.as
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/**
	A wrapper around Flash 8's ExternalInterface; DojoExternalInterface is needed so that we
	can do a Flash 6 implementation of ExternalInterface, and be able
	to support having a single codebase that uses DojoExternalInterface
	across Flash versions rather than having two seperate source bases,
	where one uses ExternalInterface and the other uses DojoExternalInterface.
	
	DojoExternalInterface class does a variety of optimizations to bypass ExternalInterface's
	unbelievably bad performance so that we can have good performance
	on Safari; see the blog post
	http://codinginparadise.org/weblog/2006/02/how-to-speed-up-flash-8s.html
	for details.
	
	@author Brad Neuberg, bkn3@columbia.edu
*/
import flash.external.ExternalInterface;

class DojoExternalInterface{
	public static var available:Boolean;
	public static var dojoPath = "";
	
	private static var flashMethods:Array = new Array();
	private static var numArgs:Number;
	private static var argData:Array;
	private static var resultData = null;
	
	public static function initialize(){
		// extract the dojo base path
		DojoExternalInterface.dojoPath = DojoExternalInterface.getDojoPath();
		
		// see if we need to do an express install
		var install:ExpressInstall = new ExpressInstall();
		if(install.needsUpdate){
			install.init();
		}
		
		// register our callback functions
		ExternalInterface.addCallback("startExec", DojoExternalInterface, startExec);
		ExternalInterface.addCallback("setNumberArguments", DojoExternalInterface,
																	setNumberArguments);
		ExternalInterface.addCallback("chunkArgumentData", DojoExternalInterface,
																	chunkArgumentData);
		ExternalInterface.addCallback("exec", DojoExternalInterface, exec);
		ExternalInterface.addCallback("getReturnLength", DojoExternalInterface,
																	getReturnLength);
		ExternalInterface.addCallback("chunkReturnData", DojoExternalInterface,
																	chunkReturnData);
		ExternalInterface.addCallback("endExec", DojoExternalInterface, endExec);
		
		// set whether communication is available
		DojoExternalInterface.available = ExternalInterface.available;
		DojoExternalInterface.call("loaded");
	}
	
	public static function addCallback(methodName:String, instance:Object, 
										 								 method:Function) : Boolean{
		// register DojoExternalInterface methodName with it's instance
		DojoExternalInterface.flashMethods[methodName] = instance;
		
		// tell JavaScript about DojoExternalInterface new method so we can create a proxy
		ExternalInterface.call("dojo.flash.comm._addExternalInterfaceCallback", 
													 methodName);
													 
		return true;
	}
	
	public static function call(methodName:String,
								resultsCallback:Function) : Void{
		// we might have any number of optional arguments, so we have to 
		// pass them in dynamically; strip out the results callback
		var parameters = new Array();
		for(var i = 0; i < arguments.length; i++){
			if(i != 1){ // skip the callback
				parameters.push(arguments[i]);
			}
		}
		
		var results = ExternalInterface.call.apply(ExternalInterface, parameters);
		
		// immediately give the results back, since ExternalInterface is
		// synchronous
		if(resultsCallback != null && typeof resultsCallback != "undefined"){
			resultsCallback.call(null, results);
		}
	}
	
	/** 
			Called by Flash to indicate to JavaScript that we are ready to have
			our Flash functions called. Calling loaded()
			will fire the dojo.flash.loaded() event, so that JavaScript can know that
			Flash has finished loading and adding its callbacks, and can begin to
			interact with the Flash file.
	*/
	public static function loaded(){
		DojoExternalInterface.call("dojo.flash.loaded");
	}
	
	public static function startExec():Void{
		DojoExternalInterface.numArgs = null;
		DojoExternalInterface.argData = null;
		DojoExternalInterface.resultData = null;
	}
	
	public static function setNumberArguments(numArgs):Void{
		DojoExternalInterface.numArgs = numArgs;
		DojoExternalInterface.argData = new Array(DojoExternalInterface.numArgs);
	}
	
	public static function chunkArgumentData(value, argIndex:Number):Void{
		//getURL("javascript:dojo.debug('FLASH: chunkArgumentData, value="+value+", argIndex="+argIndex+"')");
		var currentValue = DojoExternalInterface.argData[argIndex];
		if(currentValue == null || typeof currentValue == "undefined"){
			DojoExternalInterface.argData[argIndex] = value;
		}else{
			DojoExternalInterface.argData[argIndex] += value;
		}
	}
	
	public static function exec(methodName):Void{
		// decode all of the arguments that were passed in
		for(var i = 0; i < DojoExternalInterface.argData.length; i++){
			DojoExternalInterface.argData[i] = 
				DojoExternalInterface.decodeData(DojoExternalInterface.argData[i]);
		}
		
		var instance = DojoExternalInterface.flashMethods[methodName];
		DojoExternalInterface.resultData = instance[methodName].apply(
																			instance, DojoExternalInterface.argData);
		// encode the result data
		DojoExternalInterface.resultData = 
			DojoExternalInterface.encodeData(DojoExternalInterface.resultData);
			
		//getURL("javascript:dojo.debug('FLASH: encoded result data="+DojoExternalInterface.resultData+"')");
	}
	
	public static function getReturnLength():Number{
	 if(DojoExternalInterface.resultData == null || 
	 					typeof DojoExternalInterface.resultData == "undefined"){
	 	return 0;
	 }
	 var segments = Math.ceil(DojoExternalInterface.resultData.length / 1024);
	 return segments;
	}
	
	public static function chunkReturnData(segment:Number):String{
		var numSegments = DojoExternalInterface.getReturnLength();
		var startCut = segment * 1024;
		var endCut = segment * 1024 + 1024;
		if(segment == (numSegments - 1)){
			endCut = segment * 1024 + DojoExternalInterface.resultData.length;
		}
			
		var piece = DojoExternalInterface.resultData.substring(startCut, endCut);
		
		//getURL("javascript:dojo.debug('FLASH: chunking return piece="+piece+"')");
		
		return piece;
	}
	
	public static function endExec():Void{
	}
	
	private static function decodeData(data):String{
		// we have to use custom encodings for certain characters when passing
		// them over; for example, passing a backslash over as //// from JavaScript
		// to Flash doesn't work
		data = DojoExternalInterface.replaceStr(data, "&custom_backslash;", "\\");
		
		data = DojoExternalInterface.replaceStr(data, "\\\'", "\'");
		data = DojoExternalInterface.replaceStr(data, "\\\"", "\"");
		
		return data;
	}
	
	private static function encodeData(data){
		//getURL("javascript:dojo.debug('inside flash, data before="+data+"')");

		// double encode all entity values, or they will be mis-decoded
		// by Flash when returned
		data = DojoExternalInterface.replaceStr(data, "&", "&amp;");
		
		// certain XMLish characters break Flash's wire serialization for
		// ExternalInterface; encode these into a custom encoding, rather than
		// the standard entity encoding, because otherwise we won't be able to
		// differentiate between our own encoding and any entity characters
		// that are being used in the string itself
		data = DojoExternalInterface.replaceStr(data, '<', '&custom_lt;');
		data = DojoExternalInterface.replaceStr(data, '>', '&custom_gt;');
		
		// encode control characters and JavaScript delimiters
		data = DojoExternalInterface.replaceStr(data, "\n", "\\n");
		data = DojoExternalInterface.replaceStr(data, "\r", "\\r");
		data = DojoExternalInterface.replaceStr(data, "\f", "\\f");
		data = DojoExternalInterface.replaceStr(data, "'", "\\'");
		data = DojoExternalInterface.replaceStr(data, '"', '\"');
		
		//getURL("javascript:dojo.debug('inside flash, data after="+data+"')");
		return data;
	}
	
	/** 
			Flash ActionScript has no String.replace method or support for
			Regular Expressions! We roll our own very simple one.
	*/
	private static function replaceStr(inputStr:String, replaceThis:String, 
																		 withThis:String):String {
		var splitStr = inputStr.split(replaceThis)
		inputStr = splitStr.join(withThis)
		return inputStr;
	}
	
	private static function getDojoPath(){
		var url = _root._url;
		var start = url.indexOf("baseRelativePath=") + "baseRelativePath=".length;
		var path = url.substring(start);
		var end = path.indexOf("&");
		if(end != -1){
			path = path.substring(0, end);
		}
		return path;
	}
}

// vim:ts=4:noet:tw=0:

__CPAN_DIR__ src/flash/flash6
__CPAN_FILE__ src/flash/flash6/DojoExternalInterface.as
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/** 
		An implementation of Flash 8's ExternalInterface that works with Flash 6
		and which is source-compatible with Flash 8. 
		
		@author Brad Neuberg, bkn3@columbia.edu 
*/

class DojoExternalInterface{
	public static var available:Boolean;
	public static var dojoPath = "";
	
	public static var _fscommandReady = false;
	public static var _callbacks = new Array();

	public static function initialize(){ 
		//getURL("javascript:dojo.debug('FLASH:DojoExternalInterface initialize')");
		// FIXME: Set available variable by testing for capabilities
		DojoExternalInterface.available = true;
		
		// extract the dojo base path
		DojoExternalInterface.dojoPath = DojoExternalInterface.getDojoPath();
		//getURL("javascript:dojo.debug('FLASH:dojoPath="+DojoExternalInterface.dojoPath+"')");
		
		// Sometimes, on IE, the fscommand infrastructure can take a few hundred
		// milliseconds the first time a page loads. Set a timer to keep checking
		// to make sure we can issue fscommands; otherwise, our calls to fscommand
		// for setCallback() and loaded() will just "disappear"
		_root.fscommandReady = false;
		var fsChecker = function(){
			// issue a test fscommand
			fscommand("fscommandReady");
			
			// JavaScript should set _root.fscommandReady if it got the call
			if(_root.fscommandReady == "true"){
				DojoExternalInterface._fscommandReady = true;
				clearInterval(_root.fsTimer);
			}
		};
		_root.fsTimer = setInterval(fsChecker, 100);
	}
	
	public static function addCallback(methodName:String, instance:Object, 
											method:Function) : Boolean{
		// A variable that indicates whether the call below succeeded
		_root._succeeded = null;
		
		// Callbacks are registered with the JavaScript side as follows.
		// On the Flash side, we maintain a lookup table that associates
		// the methodName with the actual instance and method that are
		// associated with this method.
		// Using fscommand, we send over the action "addCallback", with the
		// argument being the methodName to add, such as "foobar".
		// The JavaScript takes these values and registers the existence of
		// this callback point.
		
		// precede the method name with a _ character in case it starts
		// with a number
		_callbacks["_" + methodName] = {_instance: instance, _method: method};
		_callbacks[_callbacks.length] = methodName;
		
		// The API for ExternalInterface says we have to make sure the call
		// succeeded; check to see if there is a value 
		// for _succeeded, which is set by the JavaScript side
		if(_root._succeeded == null){
			return false;
		}else{
			return true;
		}
	}
	
	public static function call(methodName:String, 
								resultsCallback:Function) : Void{
		// FIXME: support full JSON serialization
		
		// First, we pack up all of the arguments to this call and set them
		// as Flash variables, which the JavaScript side will unpack using
		// plugin.GetVariable(). We set the number of arguments as "_numArgs",
		// and add each argument as a variable, such as "_1", "_2", etc., starting
		// from 0.
		// We then execute an fscommand with the action "call" and the
		// argument being the method name. JavaScript takes the method name,
		// retrieves the arguments using GetVariable, executes the method,
		// and then places the return result in a Flash variable
		// named "_returnResult".
		_root._numArgs = arguments.length - 2;
		for(var i = 2; i < arguments.length; i++){
			var argIndex = i - 2;
			_root["_" + argIndex] = arguments[i];
		}
		
		_root._returnResult = undefined;
		fscommand("call", methodName);
		
		// immediately return if the caller is not waiting for return results
		if(resultsCallback == undefined || resultsCallback == null){
			return;
		}
		
		// check at regular intervals for return results	
		var resultsChecker = function(){
			if(_root._returnResult != undefined){
				clearInterval(_root._callbackID);
				resultsCallback.call(null, _root._returnResult);
			}
		};	
		_root._callbackID = setInterval(resultsChecker, 100);
	}
	
	/** 
			Called by Flash to indicate to JavaScript that we are ready to have
			our Flash functions called. Calling loaded()
			will fire the dojo.flash.loaded() event, so that JavaScript can know that
			Flash has finished loading and adding its callbacks, and can begin to
			interact with the Flash file.
	*/
	public static function loaded(){
		//getURL("javascript:dojo.debug('FLASH:loaded')");
		
		// one more step: see if fscommands are ready to be executed; if not,
		// set an interval that will keep running until fscommands are ready;
		// make sure the gateway is loaded as well
		var execLoaded = function(){
			if(DojoExternalInterface._fscommandReady == true){
				clearInterval(_root.loadedInterval);
				
				// initialize the small Flash file that helps gateway JS to Flash
				// calls
				DojoExternalInterface._initializeFlashRunner();
			}	
		};
		
		if(_fscommandReady == true){
			execLoaded();
		}else{
			_root.loadedInterval = setInterval(execLoaded, 50);
		}
	}
	
	/** 
			Handles and executes a JavaScript to Flash method call. Used by
			initializeFlashRunner. 
	*/
	public static function _handleJSCall(){
		// get our parameters
		var numArgs = parseInt(_root._numArgs);
		var jsArgs = new Array();
		for(var i = 0; i < numArgs; i++){
			var currentValue = _root["_" + i];
			jsArgs.push(currentValue);
		}
		
		// get our function name
		var functionName = _root._functionName;
		
		// now get the actual instance and method object to execute on,
		// using our lookup table that was constructed by calls to
		// addCallback on initialization
		var instance = _callbacks["_" + functionName]._instance;
		var method = _callbacks["_" + functionName]._method;
		
		// execute it
		var results = method.apply(instance, jsArgs);
		
		// return the results
		_root._returnResult = results;
	}
	
	/** Called by the flash6_gateway.swf to indicate that it is loaded. */
	public static function _gatewayReady(){
		for(var i = 0; i < _callbacks.length; i++){
			fscommand("addCallback", _callbacks[i]);
		}
		call("dojo.flash.loaded");
	}
	
	/** 
			When JavaScript wants to communicate with Flash it simply sets
			the Flash variable "_execute" to true; this method creates the
			internal Movie Clip, called the Flash Runner, that makes this
			magic happen.
	*/
	public static function _initializeFlashRunner(){
		// figure out where our Flash movie is
		var swfLoc = DojoExternalInterface.dojoPath + "flash6_gateway.swf";
		
		// load our gateway helper file
		_root.createEmptyMovieClip("_flashRunner", 5000);
		_root._flashRunner._lockroot = true;
		_root._flashRunner.loadMovie(swfLoc);
	}
	
	private static function getDojoPath(){
		var url = _root._url;
		var start = url.indexOf("baseRelativePath=") + "baseRelativePath=".length;
		var path = url.substring(start);
		var end = path.indexOf("&");
		if(end != -1){
			path = path.substring(0, end);
		}
		return path;
	}
}

// vim:ts=4:noet:tw=0:

__CPAN_FILE__ src/flash/flash6/flash6_gateway.fla
ÐÏà¡±á>þÿ	þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot Entryÿÿÿÿÿÿÿÿpª|YªrÏƒRASH€fUajbÆÀContentsÿÿÿÿÿÿÿÿ(¾APage 1ÿÿÿÿÿÿÿÿÿÿÿÿ§ÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿýÿÿÿÿÿÿÿÿÿÿÿþÿÿÿ'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿ)*+,-./0123456789:;<=>?@ABCDEFGMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot Entryÿÿÿÿÿÿÿÿpª|YªrÏƒRASHppÚ«žZÆ	ÀContentsÿÿÿÿÿÿÿÿ¾APage 1ÿÿÿÿÿÿÿÿÿÿÿÿ§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿ

 !"#$%&HÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿIJKLþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ	

þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿCPicPageÿÿ	CPicLayerÿÿ	CPicFrame€€ÿÿÿ?ÿÿÿþÿstart2ÿþÿÿÓ/** 

	Very simple two frame Flash file; frame 1 says we are all loaded, while frame 2

	says to execute a JavaScript call. This small file is necessary because ActionScript

	2.0 has no way to know when a specific frame has been called, which we use for all

	of our code. However, the Flash 6 communication we use kicks off a call by jumping

	to a specific frame and then calling Play() on the Flash player.

*/



DojoExternalIn	

þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿterface._gatewayReady();

stop();

ÿþÿ€€€ÿÿÿ?ÿÿÿþÿexecute}vÿþÿ/DojoExternalInterface._handleJSCall();

stop();ÿþÿ€€ÿþÿLayer 1ÿÿÿÿOÿOÿ€€("javascript:alert('TCallLabel')");

DojoExteÿÿCPicPageÿÿ	CPicLayerÿÿ	CPicFrame€€ÿÿÿ?ÿÿÿþÿstartZzÿþÿÿÓ/** 

	Very simple two frame Flash file; frame 1 says we are all loaded, while frame 2

	says to execute a JavaScript call. This small file is necessary because ActionScript

	2.0 has no way to know when a specific frame has been called, which we use for all

	of our code. However, the Flash 6 communication we use kicks off a call by jumping

	to a specific frame and then calling Play() on the Flash player.

*/



DojoExternalIn8ÿÿ
CDocumentPagePage 1ÿþÿScene 1ÿþÿsêËC ÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÏû6Dÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿø*@h�hhhhÿÿÿÿÀÀÀÿ´ÿþÿPropSheet::ActiveTabÿþÿ7628”ÿþÿ%PublishFormatProperties::htmlFileNameÿþÿflash6_gateway.htmlÿþÿ"PublishHtmlProperties::StartPausedÿþÿ0ÿþÿ PublishRNWKProperties::speed256Kÿþÿ0ÿþÿ!PublishGifProperties::PaletteNameÿþÿÿþÿPublishFormatProperties::jpegÿþÿ0ÿþÿPublishHtmlProperties::Loopÿþÿ1ÿþÿPublishProfileProperties::nameÿþÿDefaultÿþÿVector::Debugging Permittedÿþÿ0ÿþÿ"PublishQTProperties::MatchMovieDimÿþÿ1ÿþÿ PublishQTProperties::AlphaOptionÿþÿÿþÿ PublishQTProperties::LayerOptionÿþÿÿþÿ4PublishHtmlProperties::UsingDefaultAlternateFilenameÿþÿ1ÿþÿPublishHtmlProperties::Unitsÿþÿ0ÿþÿ%PublishHtmlProperties::showTagWarnMsgÿþÿ1ÿþÿVector::External Playerÿþÿÿþÿ&PublishRNWKProperties::singleRateAudioÿþÿ0ÿþÿ&PublishRNWKProperties::speedSingleISDNÿþÿ0ÿþÿ$PublishPNGProperties::OptimizeColorsÿþÿ1ÿþÿPublishQTProperties::Widthÿþÿ550ÿþÿ%PublishFormatProperties::projectorMacÿþÿ0ÿþÿ'PublishFormatProperties::gifDefaultNameÿþÿ1ÿþÿ&PublishFormatProperties::flashFileNameÿþÿ..\..\..\flash6_gateway.swfÿþÿVector::Package PathsÿþÿÿþÿVector::Compress Movieÿþÿ1ÿþÿ#PublishRNWKProperties::flashBitRateÿþÿ1200ÿþÿ%PublishRNWKProperties::mediaCopyrightÿþÿ(c) 2000ÿþÿPublishGifProperties::Smoothÿþÿ1ÿþÿPublishFormatProperties::htmlÿþÿ0ÿþÿ$PublishFormatProperties::pngFileNameÿþÿflash6_gateway.pngÿþÿ(PublishHtmlProperties::VerticalAlignmentÿþÿ1ÿþÿPublishHtmlProperties::Qualityÿþÿ4ÿþÿVector::FireFoxÿþÿ0ÿþÿ"PublishRNWKProperties::exportAudioÿþÿ1ÿþÿ PublishRNWKProperties::speed384Kÿþÿ0ÿþÿ!PublishRNWKProperties::exportSMILÿþÿ1ÿþÿ"PublishGifProperties::DitherOptionÿþÿÿþÿ-PublishFormatProperties::generatorDefaultNameÿþÿ1ÿþÿ!PublishHtmlProperties::DeviceFontÿþÿ0ÿþÿVector::Override Soundsÿþÿ0ÿþÿ'PublishRNWKProperties::mediaDescriptionÿþÿÿþÿ"PublishPNGProperties::FilterOptionÿþÿÿþÿPublishFormatProperties::gifÿþÿ0ÿþÿ(PublishFormatProperties::jpegDefaultNameÿþÿ1ÿþÿ(PublishFormatProperties::rnwkDefaultNameÿþÿ1ÿþÿ*PublishFormatProperties::generatorFileNameÿþÿflash6_gateway.swtÿþÿVector::Templateÿþÿ0ÿþÿ2PublishHtmlProperties::VersionDetectionIfAvailableÿþÿ0ÿþÿ*PublishHtmlProperties::HorizontalAlignmentÿþÿ1ÿþÿ"PublishHtmlProperties::DisplayMenuÿþÿ1ÿþÿVector::Protectÿþÿ0ÿþÿVector::Qualityÿþÿ80ÿþÿPublishJpegProperties::DPIÿþÿ4718592ÿþÿPublishGifProperties::Interlaceÿþÿ0ÿþÿ"PublishGifProperties::DitherSolidsÿþÿ0ÿþÿPublishPNGProperties::Smoothÿþÿ1ÿþÿPublishPNGProperties::BitDepthÿþÿ24-bit with AlphaÿþÿPublishQTProperties::Flattenÿþÿ1ÿþÿ#PublishFormatProperties::qtFileNameÿþÿflash6_gateway.movÿþÿPublishRNWKProperties::speed28Kÿþÿ1ÿþÿ!PublishRNWKProperties::mediaTitleÿþÿÿþÿ$PublishRNWKProperties::mediaKeywordsÿþÿÿþÿPublishGifProperties::Widthÿþÿ550ÿþÿPublishGifProperties::Loopÿþÿ1ÿþÿPublishFormatProperties::flashÿþÿ1ÿþÿPublishJpegProperties::Qualityÿþÿ80ÿþÿ$PublishRNWKProperties::realVideoRateÿþÿ100000ÿþÿ$PublishRNWKProperties::speedDualISDNÿþÿ0ÿþÿ#PublishGifProperties::MatchMovieDimÿþÿ1ÿþÿ#PublishGifProperties::PaletteOptionÿþÿÿþÿ"PublishPNGProperties::DitherOptionÿþÿÿþÿ0PublishFormatProperties::projectorMacDefaultNameÿþÿ1ÿþÿ'PublishFormatProperties::pngDefaultNameÿþÿ1ÿþÿ-PublishFormatProperties::projectorWinFileNameÿþÿflash6_gateway.exeÿþÿPublishHtmlProperties::Alignÿþÿ0ÿþÿ!PublishProfileProperties::versionÿþÿ1ÿþÿVector::Package Export Frameÿþÿ1ÿþÿ$PublishJpegProperties::MatchMovieDimÿþÿ1ÿþÿ#PublishPNGProperties::MatchMovieDimÿþÿ1ÿþÿ#PublishPNGProperties::PaletteOptionÿþÿÿþÿ)PublishFormatProperties::flashDefaultNameÿþÿ0ÿþÿ%PublishFormatProperties::jpegFileNameÿþÿflash6_gateway.jpgÿþÿPublishHtmlProperties::Widthÿþÿ550ÿþÿPublishHtmlProperties::Heightÿþÿ400ÿþÿVector::Omit Trace Actionsÿþÿ0ÿþÿVector::Debugging Passwordÿþÿÿþÿ"PublishJpegProperties::Progressiveÿþÿ0ÿþÿ"PublishPNGProperties::DitherSolidsÿþÿ0ÿþÿ#PublishQTProperties::PlayEveryFrameÿþÿ0ÿþÿPublishFormatProperties::pngÿþÿ0ÿþÿPublishFormatProperties::rnwkÿþÿ0ÿþÿ(PublishFormatProperties::htmlDefaultNameÿþÿ1ÿþÿ-PublishFormatProperties::projectorMacFileNameÿþÿflash6_gateway.hqxÿþÿ2PublishHtmlProperties::UsingDefaultContentFilenameÿþÿ1ÿþÿ!PublishHtmlProperties::WindowModeÿþÿ0ÿþÿ'PublishHtmlProperties::TemplateFileNameÿþÿ�C:\Documents and Settings\bradneuberg\Local Settings\Application Data\Macromedia\Flash MX 2004\en\Configuration\Html\Default.htmlÿþÿVector::TopDownÿþÿ0ÿþÿVector::DeviceSoundÿþÿ0ÿþÿPublishJpegProperties::Sizeÿþÿ0ÿþÿPublishGifProperties::Heightÿþÿ400ÿþÿPublishPNGProperties::Interlaceÿþÿ0ÿþÿ"PublishFormatProperties::generatorÿþÿ0ÿþÿ&PublishHtmlProperties::ContentFilenameÿþÿÿþÿ(PublishHtmlProperties::AlternateFilenameÿþÿÿþÿ+PublishHtmlProperties::OwnAlternateFilenameÿþÿÿþÿVector::Reportÿþÿ0ÿþÿPublishRNWKProperties::speed56Kÿþÿ1ÿþÿPublishGifProperties::LoopCountÿþÿÿþÿ'PublishGifProperties::TransparentOptionÿþÿÿþÿPublishGifProperties::MaxColorsÿþÿ255ÿþÿ%PublishPNGProperties::RemoveGradientsÿþÿ0ÿþÿPublishQTProperties::Heightÿþÿ400ÿþÿPublishFormatProperties::qtÿþÿ0ÿþÿVector::Stream Compressÿþÿ7ÿþÿVector::Event Formatÿþÿ0ÿþÿVector::Versionÿþÿ6ÿþÿ"PublishRNWKProperties::audioFormatÿþÿ0ÿþÿ$PublishGifProperties::OptimizeColorsÿþÿ1ÿþÿ0PublishFormatProperties::projectorWinDefaultNameÿþÿ1ÿþÿPublishHtmlProperties::Scaleÿþÿ0ÿþÿVector::Event Compressÿþÿ7ÿþÿVector::ActionScriptVersionÿþÿ2ÿþÿPublishJpegProperties::Heightÿþÿ400ÿþÿ PublishRNWKProperties::speed512Kÿþÿ0ÿþÿ%PublishGifProperties::RemoveGradientsÿþÿ0ÿþÿPublishPNGProperties::Widthÿþÿ550ÿþÿPublishPNGProperties::Heightÿþÿ400ÿþÿ&PublishFormatProperties::qtDefaultNameÿþÿ1ÿþÿ$PublishFormatProperties::gifFileNameÿþÿflash6_gateway.gifÿþÿ"PublishHtmlProperties::VersionInfoÿþÿÿþÿVector::Stream Formatÿþÿ0ÿþÿPublishJpegProperties::Widthÿþÿ550ÿþÿ"PublishRNWKProperties::exportFlashÿþÿ1ÿþÿ&PublishRNWKProperties::showBitrateDlogÿþÿ1ÿþÿ(PublishRNWKProperties::speedCorporateLANÿþÿ0ÿþÿ"PublishRNWKProperties::mediaAuthorÿþÿÿþÿPublishGifProperties::Animatedÿþÿ0ÿþÿ&PublishGifProperties::TransparentAlphaÿþÿ128ÿþÿ!PublishPNGProperties::Transparentÿþÿ0ÿþÿ!PublishPNGProperties::PaletteNameÿþÿÿþÿ*PublishQTProperties::UseQTSoundCompressionÿþÿ0ÿþÿPublishQTProperties::Loopingÿþÿ0ÿþÿ%PublishFormatProperties::defaultNamesÿþÿ0ÿþÿ%PublishFormatProperties::projectorWinÿþÿ0ÿþÿ%PublishFormatProperties::rnwkFileNameÿþÿflash6_gateway.smilÿþÿ,PublishHtmlProperties::UsingOwnAlternateFileÿþÿ0ÿþÿPublishPNGProperties::MaxColorsÿþÿ255ÿþÿ%PublishQTProperties::ControllerOptionÿþÿ0ÿþÿ"PublishQTProperties::PausedAtStartÿþÿ0ÿÿÿÿÿþÿÿþÿüÿÿ	CColorDefÿ€ÿ€ÿ€3ÿPï€fÿPï0€™ÿPïH€ÌÿPï`€ÿÿPïx€3ÿï€33ÿ(ï€3fÿ<ï0€3™ÿCïH€3ÌÿFï`€3ÿÿHïx€fÿï0€f3ÿï0€ffÿ(ï0€f™ÿ5ïH€fÌÿ<ï`€fÿÿ@ïx€ÿ€333ÿ0€ÿ€3ÿ ï€33ÿxï€f3ÿdï0€™3ÿ]ïH€Ì3ÿZï`€ÿ3ÿXïx€33ÿÈï€333ÿ0€3f3ÿPPH€3™3ÿPx`€3Ì3ÿP�x€3ÿ3ÿPï�€f3ÿÜï0€f33ÿPH€ff3ÿ(PH€f™3ÿ<x`€fÌ3ÿC�x€fÿ3ÿFï�€ÿ€fffÿ`€ÿ€fÿ ï0€3fÿŒï0€ffÿxï0€™fÿkïH€Ìfÿdï`€ÿfÿ`ïx€3fÿ´ï0€33fÿ PH€3ffÿxPH€3™fÿdx`€3Ìfÿ]�x€3ÿfÿZï�€ffÿÈï0€f3fÿÈPH€fffÿ`€f™fÿP0x€fÌfÿPx�€fÿfÿPï¨€ÿ€™™™ÿ�€ÿ€™ÿ ïH€3™ÿ“ïH€f™ÿ…ïH€™™ÿxïH€Ì™ÿnï`€ÿ™ÿhïx€3™ÿ­ïH€33™ÿ x`€3f™ÿŒx`€3™™ÿxx`€3Ì™ÿk�x€3ÿ™ÿdï�€f™ÿ»ïH€f3™ÿ´x`€ff™ÿ 0x€f™™ÿx0x€fÌ™ÿdx�€fÿ™ÿ]ï¨€ÿ€ÌÌÌÿÀ€ÿ€Ìÿ ï`€3Ìÿ–ï`€fÌÿŒï`€™Ìÿ‚ï`€ÌÌÿxï`€ÿÌÿpïx€3Ìÿªï`€33Ìÿ �x€3fÌÿ“�x€3™Ìÿ…�x€3ÌÌÿx�x€3ÿÌÿnï�€fÌÿ´ï`€f3Ìÿ­�x€ffÌÿ x�€f™ÌÿŒx�€fÌÌÿxx�€fÿÌÿkï¨€ÿ€ÿÿÿÿð€ÿ€ÿÿ ïx€3ÿÿ˜ïx€fÿÿ�ïx€™ÿÿˆïx€Ìÿÿ€ïx€ÿÿÿxïx€3ÿÿ¨ïx€33ÿÿ ï�€3fÿÿ–ï�€3™ÿÿŒï�€3Ìÿÿ‚ï�€3ÿÿÿxï�€fÿÿ°ïx€f3ÿÿªï�€ffÿÿ ï¨€f™ÿÿ“ï¨€fÌÿÿ…ï¨€fÿÿÿxï¨€ÿ€ÿÿïx€ÿ€™ÿïH€™3ÿ
ïH€™fterface._gatewayReady();

stop();

ÿþÿ€€€ÿÿÿ?ÿÿÿþÿexecute ÿþÿ/DojoExternalInterface._handleJSCall();

stop();ÿþÿ€€ÿþÿLayer 1ÿÿÿÿOÿOÿ€€("javascript:alert('TCallLabel')");

DojoExte8ÿÿ
CDocumentPagePage 1ÿþÿScene 1ÿþÿsêËC ÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿDDÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÌÈ
h�hhhhÿÿÿÿÀÀÀÿ´ÿþÿPropSheet::ActiveTabÿþÿ7628”ÿþÿ!PublishGifProperties::PaletteNameÿþÿÿþÿ PublishRNWKProperties::speed256Kÿþÿ0ÿþÿ"PublishHtmlProperties::StartPausedÿþÿ0ÿþÿ%PublishFormatProperties::htmlFileNameÿþÿflash6_gateway.htmlÿþÿ PublishQTProperties::LayerOptionÿþÿÿþÿ PublishQTProperties::AlphaOptionÿþÿÿþÿ"PublishQTProperties::MatchMovieDimÿþÿ1ÿþÿVector::Debugging Permittedÿþÿ0ÿþÿPublishProfileProperties::nameÿþÿDefaultÿþÿPublishHtmlProperties::Loopÿþÿ1ÿþÿPublishFormatProperties::jpegÿþÿ0ÿþÿPublishQTProperties::Widthÿþÿ550ÿþÿ$PublishPNGProperties::OptimizeColorsÿþÿ1ÿþÿ&PublishRNWKProperties::speedSingleISDNÿþÿ0ÿþÿ&PublishRNWKProperties::singleRateAudioÿþÿ0ÿþÿVector::External Playerÿþÿÿþÿ%PublishHtmlProperties::showTagWarnMsgÿþÿ1ÿþÿPublishHtmlProperties::Unitsÿþÿ0ÿþÿ4PublishHtmlProperties::UsingDefaultAlternateFilenameÿþÿ1ÿþÿPublishGifProperties::Smoothÿþÿ1ÿþÿ%PublishRNWKProperties::mediaCopyrightÿþÿ(c) 2000ÿþÿ#PublishRNWKProperties::flashBitRateÿþÿ1200ÿþÿVector::Compress Movieÿþÿ1ÿþÿVector::Package Pathsÿþÿÿþÿ&PublishFormatProperties::flashFileNameÿþÿ..\..\..\flash6_gateway.swfÿþÿ'PublishFormatProperties::gifDefaultNameÿþÿ1ÿþÿ%PublishFormatProperties::projectorMacÿþÿ0ÿþÿ"PublishGifProperties::DitherOptionÿþÿÿþÿ!PublishRNWKProperties::exportSMILÿþÿ1ÿþÿ PublishRNWKProperties::speed384Kÿþÿ0ÿþÿ"PublishRNWKProperties::exportAudioÿþÿ1ÿþÿVector::FireFoxÿþÿ0ÿþÿPublishHtmlProperties::Qualityÿþÿ4ÿþÿ(PublishHtmlProperties::VerticalAlignmentÿþÿ1ÿþÿ$PublishFormatProperties::pngFileNameÿþÿflash6_gateway.pngÿþÿPublishFormatProperties::htmlÿþÿ0ÿþÿ"PublishPNGProperties::FilterOptionÿþÿÿþÿ'PublishRNWKProperties::mediaDescriptionÿþÿÿþÿVector::Override Soundsÿþÿ0ÿþÿ!PublishHtmlProperties::DeviceFontÿþÿ0ÿþÿ-PublishFormatProperties::generatorDefaultNameÿþÿ1ÿþÿPublishQTProperties::Flattenÿþÿ1ÿþÿPublishPNGProperties::BitDepthÿþÿ24-bit with AlphaÿþÿPublishPNGProperties::Smoothÿþÿ1ÿþÿ"PublishGifProperties::DitherSolidsÿþÿ0ÿþÿPublishGifProperties::Interlaceÿþÿ0ÿþÿPublishJpegProperties::DPIÿþÿ4718592ÿþÿVector::Qualityÿþÿ80ÿþÿVector::Protectÿþÿ0ÿþÿ"PublishHtmlProperties::DisplayMenuÿþÿ1ÿþÿ*PublishHtmlProperties::HorizontalAlignmentÿþÿ1ÿþÿ2PublishHtmlProperties::VersionDetectionIfAvailableÿþÿ0ÿþÿVector::Templateÿþÿ0ÿþÿ*PublishFormatProperties::generatorFileNameÿþÿflash6_gateway.swtÿþÿ(PublishFormatProperties::rnwkDefaultNameÿþÿ1ÿþÿ(PublishFormatProperties::jpegDefaultNameÿþÿ1ÿþÿPublishFormatProperties::gifÿþÿ0ÿþÿPublishGifProperties::Loopÿþÿ1ÿþÿPublishGifProperties::Widthÿþÿ550ÿþÿ$PublishRNWKProperties::mediaKeywordsÿþÿÿþÿ!PublishRNWKProperties::mediaTitleÿþÿÿþÿPublishRNWKProperties::speed28Kÿþÿ1ÿþÿ#PublishFormatProperties::qtFileNameÿþÿflash6_gateway.movÿþÿ"PublishPNGProperties::DitherOptionÿþÿÿþÿ#PublishGifProperties::PaletteOptionÿþÿÿþÿ#PublishGifProperties::MatchMovieDimÿþÿ1ÿþÿ$PublishRNWKProperties::speedDualISDNÿþÿ0ÿþÿ$PublishRNWKProperties::realVideoRateÿþÿ100000ÿþÿPublishJpegProperties::Qualityÿþÿ80ÿþÿPublishFormatProperties::flashÿþÿ1ÿþÿ#PublishPNGProperties::PaletteOptionÿþÿÿþÿ#PublishPNGProperties::MatchMovieDimÿþÿ1ÿþÿ$PublishJpegProperties::MatchMovieDimÿþÿ1ÿþÿVector::Package Export Frameÿþÿ1ÿþÿ!PublishProfileProperties::versionÿþÿ1ÿþÿPublishHtmlProperties::Alignÿþÿ0ÿþÿ-PublishFormatProperties::projectorWinFileNameÿþÿflash6_gateway.exeÿþÿ'PublishFormatProperties::pngDefaultNameÿþÿ1ÿþÿ0PublishFormatProperties::projectorMacDefaultNameÿþÿ1ÿþÿ#PublishQTProperties::PlayEveryFrameÿþÿ0ÿþÿ"PublishPNGProperties::DitherSolidsÿþÿ0ÿþÿ"PublishJpegProperties::Progressiveÿþÿ0ÿþÿVector::Debugging PasswordÿþÿÿþÿVector::Omit Trace Actionsÿþÿ0ÿþÿPublishHtmlProperties::Heightÿþÿ400ÿþÿPublishHtmlProperties::Widthÿþÿ550ÿþÿ%PublishFormatProperties::jpegFileNameÿþÿflash6_gateway.jpgÿþÿ)PublishFormatProperties::flashDefaultNameÿþÿ0ÿþÿPublishPNGProperties::Interlaceÿþÿ0ÿþÿPublishGifProperties::Heightÿþÿ400ÿþÿPublishJpegProperties::Sizeÿþÿ0ÿþÿVector::DeviceSoundÿþÿ0ÿþÿVector::TopDownÿþÿ0ÿþÿ'PublishHtmlProperties::TemplateFileNameÿþÿ�C:\Documents and Settings\bradneuberg\Local Settings\Application Data\Macromedia\Flash MX 2004\en\Configuration\Html\Default.htmlÿþÿ!PublishHtmlProperties::WindowModeÿþÿ0ÿþÿ2PublishHtmlProperties::UsingDefaultContentFilenameÿþÿ1ÿþÿ-PublishFormatProperties::projectorMacFileNameÿþÿflash6_gateway.hqxÿþÿ(PublishFormatProperties::htmlDefaultNameÿþÿ1ÿþÿPublishFormatProperties::rnwkÿþÿ0ÿþÿPublishFormatProperties::pngÿþÿ0ÿþÿPublishQTProperties::Heightÿþÿ400ÿþÿ%PublishPNGProperties::RemoveGradientsÿþÿ0ÿþÿPublishGifProperties::MaxColorsÿþÿ255ÿþÿ'PublishGifProperties::TransparentOptionÿþÿÿþÿPublishGifProperties::LoopCountÿþÿÿþÿPublishRNWKProperties::speed56Kÿþÿ1ÿþÿVector::Reportÿþÿ0ÿþÿ+PublishHtmlProperties::OwnAlternateFilenameÿþÿÿþÿ(PublishHtmlProperties::AlternateFilenameÿþÿÿþÿ&PublishHtmlProperties::ContentFilenameÿþÿÿþÿ"PublishFormatProperties::generatorÿþÿ0ÿþÿ$PublishGifProperties::OptimizeColorsÿþÿ1ÿþÿ"PublishRNWKProperties::audioFormatÿþÿ0ÿþÿVector::Versionÿþÿ6ÿþÿVector::Event Formatÿþÿ0ÿþÿVector::Stream Compressÿþÿ7ÿþÿPublishFormatProperties::qtÿþÿ0ÿþÿPublishPNGProperties::Heightÿþÿ400ÿþÿPublishPNGProperties::Widthÿþÿ550ÿþÿ%PublishGifProperties::RemoveGradientsÿþÿ0ÿþÿ PublishRNWKProperties::speed512Kÿþÿ0ÿþÿPublishJpegProperties::Heightÿþÿ400ÿþÿVector::ActionScriptVersionÿþÿ2ÿþÿVector::Event Compressÿþÿ7ÿþÿPublishHtmlProperties::Scaleÿþÿ0ÿþÿ0PublishFormatProperties::projectorWinDefaultNameÿþÿ1ÿþÿPublishQTProperties::Loopingÿþÿ0ÿþÿ*PublishQTProperties::UseQTSoundCompressionÿþÿ0ÿþÿ!PublishPNGProperties::PaletteNameÿþÿÿþÿ!PublishPNGProperties::Transparentÿþÿ0ÿþÿ&PublishGifProperties::TransparentAlphaÿþÿ128ÿþÿPublishGifProperties::Animatedÿþÿ0ÿþÿ"PublishRNWKProperties::mediaAuthorÿþÿÿþÿ(PublishRNWKProperties::speedCorporateLANÿþÿ0ÿþÿ&PublishRNWKProperties::showBitrateDlogÿþÿ1ÿþÿ"PublishRNWKProperties::exportFlashÿþÿ1ÿþÿPublishJpegProperties::Widthÿþÿ550ÿþÿVector::Stream Formatÿþÿ0ÿþÿ"PublishHtmlProperties::VersionInfoÿþÿÿþÿ$PublishFormatProperties::gifFileNameÿþÿflash6_gateway.gifÿþÿ&PublishFormatProperties::qtDefaultNameÿþÿ1ÿþÿ"PublishQTProperties::PausedAtStartÿþÿ0ÿþÿ%PublishQTProperties::ControllerOptionÿþÿ0ÿþÿPublishPNGProperties::MaxColorsÿþÿ255ÿþÿ,PublishHtmlProperties::UsingOwnAlternateFileÿþÿ0ÿþÿ%PublishFormatProperties::rnwkFileNameÿþÿflash6_gateway.smilÿþÿ%PublishFormatProperties::projectorWinÿþÿ0ÿþÿ%PublishFormatProperties::defaultNamesÿþÿ0ÿÿÿÿÿþÿÿþÿüÿÿ	CColorDefÿ€ÿ€ÿ€3ÿPï€fÿPï0€™ÿPïH€ÌÿPï`€ÿÿPïx€3ÿï€33ÿ(ï€3fÿ<ï0€3™ÿCïH€3ÌÿFï`€3ÿÿHïx€fÿï0€f3ÿï0€ffÿ(ï0€f™ÿ5ïH€fÌÿ<ï`€fÿÿ@ïx€ÿ€333ÿ0€ÿ€3ÿ ï€33ÿxï€f3ÿdï0€™3ÿ]ïH€Ì3ÿZï`€ÿ3ÿXïx€33ÿÈï€333ÿ0€3f3ÿPPH€3™3ÿPx`€3Ì3ÿP�x€3ÿ3ÿPï�€f3ÿÜï0€f33ÿPH€ff3ÿ(PH€f™3ÿ<x`€fÌ3ÿC�x€fÿ3ÿFï�€ÿ€fffÿ`€ÿ€fÿ ï0€3fÿŒï0€ffÿxï0€™fÿkïH€Ìfÿdï`€ÿfÿ`ïx€3fÿ´ï0€33fÿ PH€3ffÿxPH€3™fÿdx`€3Ìfÿ]�x€3ÿfÿZï�€ffÿÈï0€f3fÿÈPH€fffÿ`€f™fÿP0x€fÌfÿPx�€fÿfÿPï¨€ÿ€™™™ÿ�€ÿ€™ÿ ïH€3™ÿ“ïH€f™ÿ…ïH€™™ÿxïH€Ì™ÿnï`€ÿ™ÿhïx€3™ÿ­ïH€33™ÿ x`€3f™ÿŒx`€3™™ÿxx`€3Ì™ÿk�x€3ÿ™ÿdï�€f™ÿ»ïH€f3™ÿ´x`€ff™ÿ 0x€f™™ÿx0x€fÌ™ÿdx�€fÿ™ÿ]ï¨€ÿ€ÌÌÌÿÀ€ÿ€Ìÿ ï`€3Ìÿ–ï`€fÌÿŒï`€™Ìÿ‚ï`€ÌÌÿxï`€ÿÌÿpïx€3Ìÿªï`€33Ìÿ �x€3fÌÿ“�x€3™Ìÿ…�x€3ÌÌÿx�x€3ÿÌÿnï�€fÌÿ´ï`€f3Ìÿ­�x€ffÌÿ x�€f™ÌÿŒx�€fÌÌÿxx�€fÿÌÿkï¨€ÿ€ÿÿÿÿð€ÿ€ÿÿ ïx€3ÿÿ˜ïx€fÿÿ�ïx€™ÿÿˆïx€Ìÿÿ€ïx€ÿÿÿxïx€3ÿÿ¨ïx€33ÿÿ ï�€3fÿÿ–ï�€3™ÿÿŒï�€3Ìÿÿ‚ï�€3ÿÿÿxï�€fÿÿ°ïx€f3ÿÿªï�€ffÿÿ ï¨€f™ÿÿ“ï¨€fÌÿÿ…ï¨€fÿÿÿxï¨€ÿ€ÿÿïx€ÿ€™ÿïH€™3ÿ
ïH€™fÿïH€™™ÿ(ïH€™Ìÿ2ï`€™ÿÿ8ïx€Ìÿï`€Ì3ÿ
ï`€Ìfÿï`€Ì™ÿï`€ÌÌÿ(ï`€Ìÿÿ0ïx€ÿÿïx€ÿ3ÿïx€ÿfÿïx€ÿ™ÿïx€ÿÌÿ ïx€ÿÿÿ(ïx€ÿ€ÿÿPïx€ÿ€™3ÿãïH€™33ÿx`€™f3ÿx`€™™3ÿ(x`€™Ì3ÿ5�x€™ÿ3ÿ<ï�€Ì3ÿæï`€Ì33ÿ�x€Ìf3ÿ
�x€Ì™3ÿ�x€ÌÌ3ÿ(�x€Ìÿ3ÿ2ï�€ÿ3ÿèïx€ÿ33ÿï�€ÿf3ÿ
ï�€ÿ™3ÿï�€ÿÌ3ÿï�€ÿÿ3ÿ(ï�€ÿ€ÿÿ ïx€ÿ€™fÿÕïH€™3fÿÜx`€™ffÿ0x€™™fÿ(0x€™Ìfÿ<x�€™ÿfÿCï¨€ÌfÿÜï`€Ì3fÿã�x€Ìffÿx�€Ì™fÿx�€ÌÌfÿ(x�€Ìÿfÿ5ï¨€ÿfÿàïx€ÿ3fÿæï�€ÿffÿï¨€ÿ™fÿ
ï¨€ÿÌfÿï¨€ÿÿfÿ(ï¨€ÿ€ÿÿÿ(ïx€ÿ€™™ÿÈïH€™3™ÿÈx`€™f™ÿÈ0x€™™™ÿ�€™Ì™ÿPP¨€™ÿ™ÿPïÀ€Ì™ÿÒï`€Ì3™ÿÕ�x€Ìf™ÿÜx�€Ì™™ÿP¨€ÌÌ™ÿ(P¨€Ìÿ™ÿ<ïÀ€ÿ™ÿØïx€ÿ3™ÿÜï�€ÿf™ÿãï¨€ÿ™™ÿïÀ€ÿÌ™ÿïÀ€ÿÿ™ÿ(ïÀ€ÿ€ÿÿÿxïx€ÿ€™Ìÿ¾ï`€™3Ìÿ»�x€™fÌÿ´x�€™™Ìÿ P¨€™ÌÌÿxP¨€™ÿÌÿdïÀ€ÌÌÿÈï`€Ì3ÌÿÈ�x€ÌfÌÿÈx�€Ì™ÌÿÈP¨€ÌÌÌÿÀ€ÌÿÌÿPïØ€ÿÌÿÐïx€ÿ3ÌÿÒï�€ÿfÌÿÕï¨€ÿ™ÌÿÜïÀ€ÿÌÌÿïØ€ÿÿÌÿ(ïØ€ÿ€ÿÿÿÈïx€ÿ€™ÿÿ¸ïx€™3ÿÿ´ï�€™fÿÿ­ï¨€™™ÿÿ ïÀ€™ÌÿÿŒïÀ€™ÿÿÿxïÀ€ÌÿÿÀïx€Ì3ÿÿ¾ï�€Ìfÿÿ»ï¨€Ì™ÿÿ´ïÀ€ÌÌÿÿ ïØ€ÌÿÿÿxïØ€ÿÿÿÈïx€ÿ3ÿÿÈï�€ÿfÿÿÈï¨€ÿ™ÿÿÈïÀ€ÿÌÿÿÈïØ€ÿÿÿÿð€ÿ€ÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿïH€™™ÿ(ïH€™Ìÿ2ï`€™ÿÿ8ïx€Ìÿï`€Ì3ÿ
ï`€Ìfÿï`€Ì™ÿï`€ÌÌÿ(ï`€Ìÿÿ0ïx€ÿÿïx€ÿ3ÿïx€ÿfÿïx€ÿ™ÿïx€ÿÌÿ ïx€ÿÿÿ(ïx€ÿ€ÿÿPïx€ÿ€™3ÿãïH€™33ÿx`€™f3ÿx`€™™3ÿ(x`€™Ì3ÿ5�x€™ÿ3ÿ<ï�€Ì3ÿæï`€Ì33ÿ�x€Ìf3ÿ
�x€Ì™3ÿ�x€ÌÌ3ÿ(�x€Ìÿ3ÿ2ï�€ÿ3ÿèïx€ÿ33ÿï�€ÿf3ÿ
ï�€ÿ™3ÿï�€ÿÌ3ÿï�€ÿÿ3ÿ(ï�€ÿ€ÿÿ ïx€ÿ€™fÿÕïH€™3fÿÜx`€™ffÿ0x€™™fÿ(0x€™Ìfÿ<x�€™ÿfÿCï¨€ÌfÿÜï`€Ì3fÿã�x€Ìffÿx�€Ì™fÿx�€ÌÌfÿ(x�€Ìÿfÿ5ï¨€ÿfÿàïx€ÿ3fÿæï�€ÿffÿï¨€ÿ™fÿ
ï¨€ÿÌfÿï¨€ÿÿfÿ(ï¨€ÿ€ÿÿÿ(ïx€ÿ€™™ÿÈïH€™3™ÿÈx`€™f™ÿÈ0x€™™™ÿ�€™Ì™ÿPP¨€™ÿ™ÿPïÀ€Ì™ÿÒï`€Ì3™ÿÕ�x€Ìf™ÿÜx�€Ì™™ÿP¨€ÌÌ™ÿ(P¨€Ìÿ™ÿ<ïÀ€ÿ™ÿØïx€ÿ3™ÿÜï�€ÿf™ÿãï¨€ÿ™™ÿïÀ€ÿÌ™ÿïÀ€ÿÿ™ÿ(ïÀ€ÿ€ÿÿÿxïx€ÿ€™Ìÿ¾ï`€™3Ìÿ»�x€™fÌÿ´x�€™™Ìÿ P¨€™ÌÌÿxP¨€™ÿÌÿdïÀ€ÌÌÿÈï`€Ì3ÌÿÈ�x€ÌfÌÿÈx�€Ì™ÌÿÈP¨€ÌÌÌÿÀ€ÌÿÌÿPïØ€ÿÌÿÐïx€ÿ3ÌÿÒï�€ÿfÌÿÕï¨€ÿ™ÌÿÜïÀ€ÿÌÌÿïØ€ÿÿÌÿ(ïØ€ÿ€ÿÿÿÈïx€ÿ€™ÿÿ¸ïx€™3ÿÿ´ï�€™fÿÿ­ï¨€™™ÿÿ ïÀ€™ÌÿÿŒïÀ€™ÿÿÿxïÀ€ÌÿÿÀïx€Ì3ÿÿ¾ï�€Ìfÿÿ»ï¨€Ì™ÿÿ´ïÀ€ÌÌÿÿ ïØ€ÌÿÿÿxïØ€ÿÿÿÈïx€ÿ3ÿÿÈï�€ÿfÿÿÈï¨€ÿ™ÿÿÈïÀ€ÿÌÿÿÈïØ€ÿÿÿÿð€ÿ€ÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿfýÿ`ÿÿÿÿzÿÿÿÿ€™fÿªÿÌÿÿÿÿÿÿ€ÿÿÿ*ÿÿÿ]ÿÿÿÿÿªÿÿÔÿÿÿÿÿÿÿþÿ"PublishQTProperties::QTSndSettingsÿÿCQTAudioSettingsÿÿÿþÿhÿþÿÿþÿ

ÿÿÿÿÿþÿÿþÿÿÿÿÿ€ÿfýÿ`ÿÿÿÿzÿÿÿÿ€™fÿªÿÌÿÿÿÿÿÿ€ÿÿÿ*ÿÿÿ]ÿÿÿÿÿªÿÿÔÿÿÿÿÿÿÿþÿ"PublishQTProperties::QTSndSettingsÿÿCQTAudioSettingsÿÿÿþÿhÿþÿÿþÿ

ÿÿÿÿÿþÿÿþÿ
__CPAN_DIR__ src/lang
__CPAN_FILE__ src/lang/array.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lang.array");

dojo.require("dojo.lang.common");

// FIXME: Is this worthless since you can do: if(name in obj)
// is this the right place for this?
dojo.lang.has = function(obj, name){
	try{
		return (typeof obj[name] != "undefined");
	}catch(e){ return false; }
}

dojo.lang.isEmpty = function(obj) {
	if(dojo.lang.isObject(obj)) {
		var tmp = {};
		var count = 0;
		for(var x in obj){
			if(obj[x] && (!tmp[x])){
				count++;
				break;
			} 
		}
		return (count == 0);
	} else if(dojo.lang.isArrayLike(obj) || dojo.lang.isString(obj)) {
		return obj.length == 0;
	}
}

dojo.lang.map = function(arr, obj, unary_func){
	var isString = dojo.lang.isString(arr);
	if(isString){
		arr = arr.split("");
	}
	if(dojo.lang.isFunction(obj)&&(!unary_func)){
		unary_func = obj;
		obj = dj_global;
	}else if(dojo.lang.isFunction(obj) && unary_func){
		// ff 1.5 compat
		var tmpObj = obj;
		obj = unary_func;
		unary_func = tmpObj;
	}
	if(Array.map){
	 	var outArr = Array.map(arr, unary_func, obj);
	}else{
		var outArr = [];
		for(var i=0;i<arr.length;++i){
			outArr.push(unary_func.call(obj, arr[i]));
		}
	}
	if(isString) {
		return outArr.join("");
	} else {
		return outArr;
	}
}

// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach
dojo.lang.forEach = function(anArray /* Array */, callback /* Function */, thisObject /* Object */){
	if(dojo.lang.isString(anArray)){ 
		anArray = anArray.split(""); 
	}
	if(Array.forEach){
		Array.forEach(anArray, callback, thisObject);
	}else{
		// FIXME: there are several ways of handilng thisObject. Is dj_global always the default context?
		if(!thisObject){
			thisObject=dj_global;
		}
		for(var i=0,l=anArray.length; i<l; i++){ 
			callback.call(thisObject, anArray[i], i, anArray);
		}
	}
}

dojo.lang._everyOrSome = function(every, arr, callback, thisObject){
	if(dojo.lang.isString(arr)){ 
		arr = arr.split(""); 
	}
	if(Array.every){
		return Array[ (every) ? "every" : "some" ](arr, callback, thisObject);
	}else{
		if(!thisObject){
			thisObject = dj_global;
		}
		for(var i=0,l=arr.length; i<l; i++){
			var result = callback.call(thisObject, arr[i], i, arr);
			if((every)&&(!result)){
				return false;
			}else if((!every)&&(result)){
				return true;
			}
		}
		return (every) ? true : false;
	}
}

dojo.lang.every = function(arr, callback, thisObject){
	return this._everyOrSome(true, arr, callback, thisObject);
}

dojo.lang.some = function(arr, callback, thisObject){
	return this._everyOrSome(false, arr, callback, thisObject);
}

dojo.lang.filter = function(arr, callback, thisObject) {
	var isString = dojo.lang.isString(arr);
	if(isString) { arr = arr.split(""); }
	if(Array.filter) {
		var outArr = Array.filter(arr, callback, thisObject);
	} else {
		if(!thisObject) {
			if(arguments.length >= 3) { dojo.raise("thisObject doesn't exist!"); }
			thisObject = dj_global;
		}

		var outArr = [];
		for(var i = 0; i < arr.length; i++) {
			if(callback.call(thisObject, arr[i], i, arr)) {
				outArr.push(arr[i]);
			}
		}
	}
	if(isString) {
		return outArr.join("");
	} else {
		return outArr;
	}
}

/**
 * Creates a 1-D array out of all the arguments passed,
 * unravelling any array-like objects in the process
 *
 * Ex:
 * unnest(1, 2, 3) ==> [1, 2, 3]
 * unnest(1, [2, [3], [[[4]]]]) ==> [1, 2, 3, 4]
 */
dojo.lang.unnest = function(/* ... */) {
	var out = [];
	for(var i = 0; i < arguments.length; i++) {
		if(dojo.lang.isArrayLike(arguments[i])) {
			var add = dojo.lang.unnest.apply(this, arguments[i]);
			out = out.concat(add);
		} else {
			out.push(arguments[i]);
		}
	}
	return out;
}

/**
 * Converts an array-like object (i.e. arguments, DOMCollection)
 * to an array
**/
dojo.lang.toArray = function(arrayLike, startOffset) {
	var array = [];
	for(var i = startOffset||0; i < arrayLike.length; i++) {
		array.push(arrayLike[i]);
	}
	return array;
}

__CPAN_FILE__ src/lang/assert.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lang.assert");

dojo.require("dojo.lang.common");
dojo.require("dojo.lang.array");
dojo.require("dojo.lang.type");

// -------------------------------------------------------------------
// Assertion methods
// -------------------------------------------------------------------

/**
 * Throws an exception if the assertion fails.
 *
 * If the asserted condition is true, this method does nothing. If the
 * condition is false, we throw an error with a error message.  
 *
 * @param	booleanValue	A boolean value, which needs to be true for the assertion to succeed.
 * @param	message	Optional. A string describing the assertion.
 * @throws	Throws an Error if 'booleanValue' is false.
 */
dojo.lang.assert = function(booleanValue, message){
	if(!booleanValue){
		var errorMessage = "An assert statement failed.\n" +
			"The method dojo.lang.assert() was called with a 'false' value.\n";
		if(message){
			errorMessage += "Here's the assert message:\n" + message + "\n";
		}
		// Use throw instead of dojo.raise, until bug #264 is fixed:
		// dojo.raise(errorMessage);
		throw new Error(errorMessage);
	}
}

/**
 * Given a value and a data type, this method checks the type of the value
 * to make sure it matches the data type, and throws an exception if there
 * is a mismatch.
 *
 * Examples:
 * <pre>
 *   dojo.lang.assertType("foo", String);
 *   dojo.lang.assertType(12345, Number);
 *   dojo.lang.assertType(false, Boolean);
 *   dojo.lang.assertType([6, 8], Array);
 *   dojo.lang.assertType(dojo.lang.assertType, Function);
 *   dojo.lang.assertType({foo: "bar"}, Object);
 *   dojo.lang.assertType(new Date(), Date);
 * </pre>
 *
 * @scope	public function
 * @param	value	Any literal value or object instance.
 * @param	type	A class of object, or a literal type, or the string name of a type, or an array with a list of types.
 * @param	message	Optional. A string describing the assertion.
 * @throws	Throws an Error if 'value' is not of type 'type'.
 */
dojo.lang.assertType = function(value, type, message){
	if(!dojo.lang.isOfType(value, type)){
		if(!message){
			if(!dojo.lang.assertType._errorMessage){
				dojo.lang.assertType._errorMessage = "Type mismatch: dojo.lang.assertType() failed.";
			}
			message = dojo.lang.assertType._errorMessage;
		}
		dojo.lang.assert(false, message);
	}
}

/**
 * Given an anonymous object and a list of expected property names, this
 * method check to make sure the object does not have any properties
 * that aren't on the list of expected properties, and throws an Error
 * if there are unexpected properties. This is useful for doing error
 * checking on keyword arguments, to make sure there aren't typos.
 *
 * Examples:
 * <pre>
 *   dojo.lang.assertValidKeywords({a: 1, b: 2}, ["a", "b"]);
 *   dojo.lang.assertValidKeywords({a: 1, b: 2}, ["a", "b", "c"]);
 *   dojo.lang.assertValidKeywords({foo: "iggy"}, ["foo"]);
 *   dojo.lang.assertValidKeywords({foo: "iggy"}, ["foo", "bar"]);
 *   dojo.lang.assertValidKeywords({foo: "iggy"}, {foo: null, bar: null});
 * </pre>
 *
 * @scope	public function
 * @param	object	An anonymous object.
 * @param	expectedProperties	An array of strings (or an object with all the expected properties).
 * @param	message	Optional. A string describing the assertion.
 * @throws	Throws an Error if 'value' is not of type 'type'.
 */
dojo.lang.assertValidKeywords = function(object, expectedProperties, message){
	var key;
	if(!message){
		if(!dojo.lang.assertValidKeywords._errorMessage){
			dojo.lang.assertValidKeywords._errorMessage = "In dojo.lang.assertValidKeywords(), found invalid keyword:";
		}
		message = dojo.lang.assertValidKeywords._errorMessage;
	}
	if(dojo.lang.isArray(expectedProperties)){
		for(key in object){
			if(!dojo.lang.inArray(expectedProperties, key)){
				dojo.lang.assert(false, message + " " + key);
			}
		}
	}else{
		for(key in object){
			if(!(key in expectedProperties)){
				dojo.lang.assert(false, message + " " + key);
			}
		}
	}
}

__CPAN_FILE__ src/lang/common.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lang.common");
dojo.require("dojo.lang");

/*
 * Adds the given properties/methods to the specified object
 */
dojo.lang._mixin = function(obj, props){
	var tobj = {};
	for(var x in props){
		// the "tobj" condition avoid copying properties in "props"
		// inherited from Object.prototype.  For example, if obj has a custom
		// toString() method, don't overwrite it with the toString() method
		// that props inherited from Object.protoype
		if(typeof tobj[x] == "undefined" || tobj[x] != props[x]) {
			obj[x] = props[x];
		}
	}
	// IE doesn't recognize custom toStrings in for..in
	if(dojo.render.html.ie && dojo.lang.isFunction(props["toString"]) && props["toString"] != obj["toString"]) {
		obj.toString = props.toString;
	}
	return obj;
}

/*
 * Adds the properties/methods of argument Objects to obj
 */
dojo.lang.mixin = function(obj, props /*, props, ..., props */){
	for(var i=1, l=arguments.length; i<l; i++){
		dojo.lang._mixin(obj, arguments[i]);
	}
	return obj;
}

/*
 * Adds the properties/methods of argument Objects to ctor's prototype
 */
dojo.lang.extend = function(ctor /*function*/, props /*, props, ..., props */){
	for(var i=1, l=arguments.length; i<l; i++){
		dojo.lang._mixin(ctor.prototype, arguments[i]);
	}
	return ctor;
}

/**
 * See if val is in arr. Call signatures:
 *  find(array, value, identity) // recommended
 *  find(value, array, identity)
**/
dojo.lang.find = function(	/*Array*/	arr, 
							/*Object*/	val,
							/*boolean*/	identity,
							/*boolean*/	findLast){
	// support both (arr, val) and (val, arr)
	if(!dojo.lang.isArrayLike(arr) && dojo.lang.isArrayLike(val)) {
		var a = arr;
		arr = val;
		val = a;
	}
	var isString = dojo.lang.isString(arr);
	if(isString) { arr = arr.split(""); }

	if(findLast) {
		var step = -1;
		var i = arr.length - 1;
		var end = -1;
	} else {
		var step = 1;
		var i = 0;
		var end = arr.length;
	}
	if(identity){
		while(i != end) {
			if(arr[i] === val){ return i; }
			i += step;
		}
	}else{
		while(i != end) {
			if(arr[i] == val){ return i; }
			i += step;
		}
	}
	return -1;
}

dojo.lang.indexOf = dojo.lang.find;

dojo.lang.findLast = function(/*Array*/ arr, /*Object*/ val, /*boolean*/ identity){
	return dojo.lang.find(arr, val, identity, true);
}

dojo.lang.lastIndexOf = dojo.lang.findLast;

dojo.lang.inArray = function(arr /*Array*/, val /*Object*/){
	return dojo.lang.find(arr, val) > -1; // return: boolean
}

/**
 * Partial implmentation of is* functions from
 * http://www.crockford.com/javascript/recommend.html
 * NOTE: some of these may not be the best thing to use in all situations
 * as they aren't part of core JS and therefore can't work in every case.
 * See WARNING messages inline for tips.
 *
 * The following is* functions are fairly "safe"
 */

dojo.lang.isObject = function(wh){
	if(typeof wh == "undefined"){ return false; }
	return (typeof wh == "object" || wh === null || dojo.lang.isArray(wh) || dojo.lang.isFunction(wh));
}

dojo.lang.isArray = function(wh){
	return (wh instanceof Array || typeof wh == "array");
}

dojo.lang.isArrayLike = function(wh){
	if(dojo.lang.isString(wh)){ return false; }
	if(dojo.lang.isFunction(wh)){ return false; } // keeps out built-in ctors (Number, String, ...) which have length properties
	if(dojo.lang.isArray(wh)){ return true; }
	if(typeof wh != "undefined" && wh
		&& dojo.lang.isNumber(wh.length) && isFinite(wh.length)){ return true; }
	return false;
}

dojo.lang.isFunction = function(wh){
	if(!wh){ return false; }
	return (wh instanceof Function || typeof wh == "function");
}

dojo.lang.isString = function(wh){
	return (wh instanceof String || typeof wh == "string");
}

dojo.lang.isAlien = function(wh){
	if(!wh){ return false; }
	return !dojo.lang.isFunction() && /\{\s*\[native code\]\s*\}/.test(String(wh));
}

dojo.lang.isBoolean = function(wh){
	return (wh instanceof Boolean || typeof wh == "boolean");
}

/**
 * The following is***() functions are somewhat "unsafe". Fortunately,
 * there are workarounds the the language provides and are mentioned
 * in the WARNING messages.
 *
 * WARNING: In most cases, isNaN(wh) is sufficient to determine whether or not
 * something is a number or can be used as such. For example, a number or string
 * can be used interchangably when accessing array items (arr["1"] is the same as
 * arr[1]) and isNaN will return false for both values ("1" and 1). Should you
 * use isNumber("1"), that will return false, which is generally not too useful.
 * Also, isNumber(NaN) returns true, again, this isn't generally useful, but there
 * are corner cases (like when you want to make sure that two things are really
 * the same type of thing). That is really where isNumber "shines".
 *
 * RECOMMENDATION: Use isNaN(wh) when possible
 */
dojo.lang.isNumber = function(wh){
	return (wh instanceof Number || typeof wh == "number");
}

/**
 * WARNING: In some cases, isUndefined will not behave as you
 * might expect. If you do isUndefined(foo) and there is no earlier
 * reference to foo, an error will be thrown before isUndefined is
 * called. It behaves correctly if you scope yor object first, i.e.
 * isUndefined(foo.bar) where foo is an object and bar isn't a
 * property of the object.
 *
 * RECOMMENDATION: Use `typeof foo == "undefined"` when possible
 *
 * FIXME: Should isUndefined go away since it is error prone?
 */
dojo.lang.isUndefined = function(wh){
	return ((wh == undefined)&&(typeof wh == "undefined"));
}

// end Crockford functions

__CPAN_FILE__ src/lang/func.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lang.func");

dojo.require("dojo.lang.common");

/**
 * Runs a function in a given scope (thisObject), can
 * also be used to preserve scope.
 *
 * hitch(foo, "bar"); // runs foo.bar() in the scope of foo
 * hitch(foo, myFunction); // runs myFunction in the scope of foo
 */
dojo.lang.hitch = function(thisObject, method) {
	if(dojo.lang.isString(method)) {
		var fcn = thisObject[method];
	} else {
		var fcn = method;
	}

	return function() {
		return fcn.apply(thisObject, arguments);
	}
}

dojo.lang.anonCtr = 0;
dojo.lang.anon = {};
dojo.lang.nameAnonFunc = function(anonFuncPtr, namespaceObj, searchForNames){
	var nso = (namespaceObj || dojo.lang.anon);
	if( (searchForNames) ||
		((dj_global["djConfig"])&&(djConfig["slowAnonFuncLookups"] == true)) ){
		for(var x in nso){
			if(nso[x] === anonFuncPtr){
				return x;
			}
		}
	}
	var ret = "__"+dojo.lang.anonCtr++;
	while(typeof nso[ret] != "undefined"){
		ret = "__"+dojo.lang.anonCtr++;
	}
	nso[ret] = anonFuncPtr;
	return ret;
}

dojo.lang.forward = function(funcName){
	// Returns a function that forwards a method call to this.func(...)
	return function(){
		return this[funcName].apply(this, arguments);
	};
}

dojo.lang.curry = function(ns, func /* args ... */){
	var outerArgs = [];
	ns = ns||dj_global;
	if(dojo.lang.isString(func)){
		func = ns[func];
	}
	for(var x=2; x<arguments.length; x++){
		outerArgs.push(arguments[x]);
	}
	// since the event system replaces the original function with a new
	// join-point runner with an arity of 0, we check to see if it's left us
	// any clues about the original arity in lieu of the function's actual
	// length property
	var ecount = (func["__preJoinArity"]||func.length) - outerArgs.length;
	// borrowed from svend tofte
	function gather(nextArgs, innerArgs, expected){
		var texpected = expected;
		var totalArgs = innerArgs.slice(0); // copy
		for(var x=0; x<nextArgs.length; x++){
			totalArgs.push(nextArgs[x]);
		}
		// check the list of provided nextArgs to see if it, plus the
		// number of innerArgs already supplied, meets the total
		// expected.
		expected = expected-nextArgs.length;
		if(expected<=0){
			var res = func.apply(ns, totalArgs);
			expected = texpected;
			return res;
		}else{
			return function(){
				return gather(arguments,// check to see if we've been run
										// with enough args
							totalArgs,	// a copy
							expected);	// how many more do we need to run?;
			}
		}
	}
	return gather([], outerArgs, ecount);
}

dojo.lang.curryArguments = function(ns, func, args, offset){
	var targs = [];
	var x = offset||0;
	for(x=offset; x<args.length; x++){
		targs.push(args[x]); // ensure that it's an arr
	}
	return dojo.lang.curry.apply(dojo.lang, [ns, func].concat(targs));
}

dojo.lang.tryThese = function(){
	for(var x=0; x<arguments.length; x++){
		try{
			if(typeof arguments[x] == "function"){
				var ret = (arguments[x]());
				if(ret){
					return ret;
				}
			}
		}catch(e){
			dojo.debug(e);
		}
	}
}

dojo.lang.delayThese = function(farr, cb, delay, onend){
	/**
	 * alternate: (array funcArray, function callback, function onend)
	 * alternate: (array funcArray, function callback)
	 * alternate: (array funcArray)
	 */
	if(!farr.length){ 
		if(typeof onend == "function"){
			onend();
		}
		return;
	}
	if((typeof delay == "undefined")&&(typeof cb == "number")){
		delay = cb;
		cb = function(){};
	}else if(!cb){
		cb = function(){};
		if(!delay){ delay = 0; }
	}
	setTimeout(function(){
		(farr.shift())();
		cb();
		dojo.lang.delayThese(farr, cb, delay, onend);
	}, delay);
}

__CPAN_FILE__ src/lang/Lang.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.lang");
dojo.deprecated("dojo.lang.Lang", "use dojo.lang instead", "0.4");

__CPAN_FILE__ src/lang/type.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lang.type");

dojo.require("dojo.lang.common");

dojo.lang.whatAmI = function(wh) {
	try {
		if(dojo.lang.isArray(wh)) { return "array"; }
		if(dojo.lang.isFunction(wh)) { return "function"; }
		if(dojo.lang.isString(wh)) { return "string"; }
		if(dojo.lang.isNumber(wh)) { return "number"; }
		if(dojo.lang.isBoolean(wh)) { return "boolean"; }
		if(dojo.lang.isAlien(wh)) { return "alien"; }
		if(dojo.lang.isUndefined(wh)) { return "undefined"; }
		// FIXME: should this go first?
		for(var name in dojo.lang.whatAmI.custom) {
			if(dojo.lang.whatAmI.custom[name](wh)) {
				return name;
			}
		}
		if(dojo.lang.isObject(wh)) { return "object"; }
	} catch(E) {}
	return "unknown";
}
/*
 * dojo.lang.whatAmI.custom[typeName] = someFunction
 * will return typeName is someFunction(wh) returns true
 */
dojo.lang.whatAmI.custom = {};

/**
 * Returns true for values that commonly represent numbers.
 *
 * Examples:
 * <pre>
 *   dojo.lang.isNumeric(3);                 // returns true
 *   dojo.lang.isNumeric("3");               // returns true
 *   dojo.lang.isNumeric(new Number(3));     // returns true
 *   dojo.lang.isNumeric(new String("3"));   // returns true
 *
 *   dojo.lang.isNumeric(3/0);               // returns false
 *   dojo.lang.isNumeric("foo");             // returns false
 *   dojo.lang.isNumeric(new Number("foo")); // returns false
 *   dojo.lang.isNumeric(false);             // returns false
 *   dojo.lang.isNumeric(true);              // returns false
 * </pre>
 */
dojo.lang.isNumeric = function(wh){
	return (!isNaN(wh) && isFinite(wh) && (wh != null) &&
			!dojo.lang.isBoolean(wh) && !dojo.lang.isArray(wh));
}

/**
 * Returns true for any literal, and for any object that is an 
 * instance of a built-in type like String, Number, Boolean, 
 * Array, Function, or Error.
 */
dojo.lang.isBuiltIn = function(wh){
	return (dojo.lang.isArray(wh)		|| 
			dojo.lang.isFunction(wh)	|| 
			dojo.lang.isString(wh)		|| 
			dojo.lang.isNumber(wh)		|| 
			dojo.lang.isBoolean(wh)		|| 
			(wh == null)				|| 
			(wh instanceof Error)		|| 
			(typeof wh == "error") );
}

/**
 * Returns true for any object where the value of the 
 * property 'constructor' is 'Object'.  
 * 
 * Examples:
 * <pre>
 *   dojo.lang.isPureObject(new Object()); // returns true
 *   dojo.lang.isPureObject({a: 1, b: 2}); // returns true
 * 
 *   dojo.lang.isPureObject(new Date());   // returns false
 *   dojo.lang.isPureObject([11, 2, 3]);   // returns false
 * </pre>
 */
dojo.lang.isPureObject = function(wh){
	return ((wh != null) && dojo.lang.isObject(wh) && wh.constructor == Object);
}

/**
 * Given a value and a datatype, this method returns true if the
 * type of the value matches the datatype. The datatype parameter
 * can be an array of datatypes, in which case the method returns
 * true if the type of the value matches any of the datatypes.
 *
 * Examples:
 * <pre>
 *   dojo.lang.isOfType("foo", String);                // returns true
 *   dojo.lang.isOfType(12345, Number);                // returns true
 *   dojo.lang.isOfType(false, Boolean);               // returns true
 *   dojo.lang.isOfType([6, 8], Array);                // returns true
 *   dojo.lang.isOfType(dojo.lang.isOfType, Function); // returns true
 *   dojo.lang.isOfType({foo: "bar"}, Object);         // returns true
 *   dojo.lang.isOfType(new Date(), Date);             // returns true
 *   dojo.lang.isOfType(xxxxx, Date);                  // returns true
 *
 *   dojo.lang.isOfType("foo", "string");                // returns true
 *   dojo.lang.isOfType(12345, "number");                // returns true
 *   dojo.lang.isOfType(false, "boolean");               // returns true
 *   dojo.lang.isOfType([6, 8], "array");                // returns true
 *   dojo.lang.isOfType(dojo.lang.isOfType, "function"); // returns true
 *   dojo.lang.isOfType({foo: "bar"}, "object");         // returns true
 *   dojo.lang.isOfType(xxxxx, "undefined");             // returns true
 *   dojo.lang.isOfType(null, "null");                   // returns true

 *   dojo.lang.isOfType("foo", [Number, String, Boolean]); // returns true
 *   dojo.lang.isOfType(12345, [Number, String, Boolean]); // returns true
 *   dojo.lang.isOfType(false, [Number, String, Boolean]); // returns true
 *   dojo.lang.isOfType(xxxxx, "undefined");               // returns true
 * </pre>
 *
 * @param	value	Any literal value or object instance.
 * @param	type	A class of object, or a literal type, or the string name of a type, or an array with a list of types.
 * @return	Returns a boolean
 */
dojo.lang.isOfType = function(value, type) {
	if(dojo.lang.isArray(type)){
		var arrayOfTypes = type;
		for(var i in arrayOfTypes){
			var aType = arrayOfTypes[i];
			if(dojo.lang.isOfType(value, aType)) {
				return true;
			}
		}
		return false;
	}else{
		if(dojo.lang.isString(type)){
			type = type.toLowerCase();
		}
		switch (type) {
			case Array:
			case "array":
				return dojo.lang.isArray(value);
				break;
			case Function:
			case "function":
				return dojo.lang.isFunction(value);
				break;
			case String:
			case "string":
				return dojo.lang.isString(value);
				break;
			case Number:
			case "number":
				return dojo.lang.isNumber(value);
				break;
			case "numeric":
				return dojo.lang.isNumeric(value);
				break;
			case Boolean:
			case "boolean":
				return dojo.lang.isBoolean(value);
				break;
			case Object:
			case "object":
				return dojo.lang.isObject(value);
				break;
			case "pureobject":
				return dojo.lang.isPureObject(value);
				break;
			case "builtin":
				return dojo.lang.isBuiltIn(value);
				break;
			case "alien":
				return dojo.lang.isAlien(value);
				break;
			case "undefined":
				return dojo.lang.isUndefined(value);
				break;
			case null:
			case "null":
				return (value === null);
				break;
			case "optional":
				return ((value === null) || dojo.lang.isUndefined(value));
				break;
			default:
				if (dojo.lang.isFunction(type)) {
					return (value instanceof type);
				} else {
					dojo.raise("dojo.lang.isOfType() was passed an invalid type");
				}
				break;
		}
	}
	dojo.raise("If we get here, it means a bug was introduced above.");
}

/*
 * 	From reflection code, part of merge.
 *	TRT 2006-02-01
 */
dojo.lang.getObject=function(/* String */ str){
	//	summary
	//	Will return an object, if it exists, based on the name in the passed string.
	var parts=str.split("."), i=0, obj=dj_global; 
	do{ 
		obj=obj[parts[i++]]; 
	}while(i<parts.length&&obj); 
	return (obj!=dj_global)?obj:null;	//	Object
}

dojo.lang.doesObjectExist=function(/* String */ str){
	//	summary
	//	Check to see if object [str] exists, based on the passed string.
	var parts=str.split("."), i=0, obj=dj_global; 
	do{ 
		obj=obj[parts[i++]]; 
	}while(i<parts.length&&obj); 
	return (obj&&obj!=dj_global);	//	boolean
}

__CPAN_FILE__ src/lang/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: [
		"dojo.lang",
		"dojo.lang.common",
		"dojo.lang.assert",
		"dojo.lang.array",
		"dojo.lang.type",
		"dojo.lang.func",
		"dojo.lang.extras",
		"dojo.lang.repr",
		"dojo.lang.declare"
	]
});
dojo.provide("dojo.lang.*");

__CPAN_FILE__ src/lang/repr.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lang.repr");

dojo.require("dojo.lang.common");
dojo.require("dojo.AdapterRegistry");
dojo.require("dojo.string.extras");

dojo.lang.reprRegistry = new dojo.AdapterRegistry();
dojo.lang.registerRepr = function(name, check, wrap, /*optional*/ override){
        /***
			Register a repr function.  repr functions should take
			one argument and return a string representation of it
			suitable for developers, primarily used when debugging.

			If override is given, it is used as the highest priority
			repr, otherwise it will be used as the lowest.
        ***/
        dojo.lang.reprRegistry.register(name, check, wrap, override);
    };

dojo.lang.repr = function(obj){
	/***
		Return a "programmer representation" for an object
	***/
	if(typeof(obj) == "undefined"){
		return "undefined";
	}else if(obj === null){
		return "null";
	}

	try{
		if(typeof(obj["__repr__"]) == 'function'){
			return obj["__repr__"]();
		}else if((typeof(obj["repr"]) == 'function')&&(obj.repr != arguments.callee)){
			return obj["repr"]();
		}
		return dojo.lang.reprRegistry.match(obj);
	}catch(e){
		if(typeof(obj.NAME) == 'string' && (
				obj.toString == Function.prototype.toString ||
				obj.toString == Object.prototype.toString
			)){
			return o.NAME;
		}
	}

	if(typeof(obj) == "function"){
		obj = (obj + "").replace(/^\s+/, "");
		var idx = obj.indexOf("{");
		if(idx != -1){
			obj = obj.substr(0, idx) + "{...}";
		}
	}
	return obj + "";
}

dojo.lang.reprArrayLike = function(arr){
	try{
		var na = dojo.lang.map(arr, dojo.lang.repr);
		return "[" + na.join(", ") + "]";
	}catch(e){ }
};

dojo.lang.reprString = function(str){ 
	dojo.deprecated("dojo.lang.reprNumber", "use `String(num)` instead", "0.4");
	return dojo.string.escapeString(str);
};

dojo.lang.reprNumber = function(num){
	dojo.deprecated("dojo.lang.reprNumber", "use `String(num)` instead", "0.4");
	return num + "";
};

(function(){
	var m = dojo.lang;
	m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike);
	m.registerRepr("string", m.isString, m.reprString);
	m.registerRepr("numbers", m.isNumber, m.reprNumber);
	m.registerRepr("boolean", m.isBoolean, m.reprNumber);
	// m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber);
})();

__CPAN_FILE__ src/lang/extras.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lang.extras");

dojo.require("dojo.lang.common");

/**
 * Sets a timeout in milliseconds to execute a function in a given context
 * with optional arguments.
 *
 * setTimeout (Object context, function func, number delay[, arg1[, ...]]);
 * setTimeout (function func, number delay[, arg1[, ...]]);
 */
dojo.lang.setTimeout = function(func, delay){
	var context = window, argsStart = 2;
	if(!dojo.lang.isFunction(func)){
		context = func;
		func = delay;
		delay = arguments[2];
		argsStart++;
	}

	if(dojo.lang.isString(func)){
		func = context[func];
	}
	
	var args = [];
	for (var i = argsStart; i < arguments.length; i++) {
		args.push(arguments[i]);
	}
	return setTimeout(function () { func.apply(context, args); }, delay);
}

dojo.lang.getNameInObj = function(ns, item){
	if(!ns){ ns = dj_global; }

	for(var x in ns){
		if(ns[x] === item){
			return new String(x);
		}
	}
	return null;
}

dojo.lang.shallowCopy = function(obj) {
	var ret = {}, key;
	for(key in obj) {
		if(dojo.lang.isUndefined(ret[key])) {
			ret[key] = obj[key];
		}
	}
	return ret;
}

/**
 * Return the first argument that isn't undefined
 */
dojo.lang.firstValued = function(/* ... */) {
	for(var i = 0; i < arguments.length; i++) {
		if(typeof arguments[i] != "undefined") {
			return arguments[i];
		}
	}
	return undefined;
}

/**
 * Get a value from a reference specified as a string descriptor,
 * (e.g. "A.B") in the given context.
 * 
 * getObjPathValue(String objpath [, Object context, Boolean create])
 *
 * If context is not specified, dj_global is used
 * If create is true, undefined objects in the path are created.
 */
dojo.lang.getObjPathValue = function(objpath, context, create){
	with(dojo.parseObjPath(objpath, context, create)){
		return dojo.evalProp(prop, obj, create);
	}
}

/**
 * Set a value on a reference specified as a string descriptor. 
 * (e.g. "A.B") in the given context.
 * 
 * setObjPathValue(String objpath, value [, Object context, Boolean create])
 *
 * If context is not specified, dj_global is used
 * If create is true, undefined objects in the path are created.
 */
dojo.lang.setObjPathValue = function(objpath, value, context, create){
	if(arguments.length < 4){
		create = true;
	}
	with(dojo.parseObjPath(objpath, context, create)){
		if(obj && (create || (prop in obj))){
			obj[prop] = value;
		}
	}
}

__CPAN_FILE__ src/lang/declare.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.lang.declare");

dojo.require("dojo.lang.common");
dojo.require("dojo.lang.extras");

/*
 * Creates a constructor: inherit and extend
 *
 * - inherits from "superclass(es)" 
 *
 *   "superclass" argument may be a Function, or an array of 
 *   Functions. 
 *
 *   If "superclass" is an array, the first element is used 
 *   as the prototypical ancestor and any following Functions 
 *   become mixin ancestors. 
 * 
 *   All "superclass(es)" must be Functions (not mere Objects).
 *
 *   Using mixin ancestors provides a type of multiple
 *   inheritance. Mixin ancestors prototypical 
 *   properties are copied to the subclass, and any 
 *   inializater/constructor is invoked. 
 *
 * - "props" are copied to the constructor prototype
 *
 * - name of the class ("className" argument) is stored in 
 *   "declaredClass" property
 * 
 * - An initializer function can be specified in the "init" 
 *   argument, or by including a function called "initializer" 
 *   in "props".
 * 
 * - Superclass methods (inherited methods) can be invoked using "inherited" method:
 *
 * this.inherited(<method name>[, <argument array>]);
 * 
 * - inherited will continue up the prototype chain until it finds an implementation of method
 * - nested calls to inherited are supported (i.e. inherited method "A" can succesfully call inherited("A"), and so on)
 *
 * Aliased as "dojo.declare"
 *
 * Usage:
 *
 * dojo.declare("my.classes.bar", my.classes.foo, {
 *	initializer: function() {
 *		this.myComplicatedObject = new ReallyComplicatedObject(); 
 *	},
 *	someValue: 2,
 *	aMethod: function() { doStuff(); }
 * });
 *
 */
dojo.lang.declare = function(className /*string*/, superclass /*function || array*/, init /*function*/, props /*object*/){
	// FIXME: parameter juggling for backward compat ... deprecate and remove after 0.3.*
	// new sig: (className (string)[, superclass (function || array)[, init (function)][, props (object)]])
	// old sig: (className (string)[, superclass (function || array), props (object), init (function)])
	if ((dojo.lang.isFunction(props))||((!props)&&(!dojo.lang.isFunction(init)))){ 
		var temp = props;
		props = init;
		init = temp;
	}	
	var mixins = [ ];
	if (dojo.lang.isArray(superclass)) {
		mixins = superclass;
		superclass = mixins.shift();
	}
	if(!init){
		init = dojo.evalObjPath(className, false);
		if ((init)&&(!dojo.lang.isFunction(init))){ init = null };
	}
	var ctor = dojo.lang.declare._makeConstructor();
	var scp = (superclass ? superclass.prototype : null);
	if(scp){
		scp.prototyping = true;
		ctor.prototype = new superclass();
		scp.prototyping = false; 
	}
	ctor.superclass = scp;
	ctor.mixins = mixins;
	for(var i=0,l=mixins.length; i<l; i++){
		dojo.lang.extend(ctor, mixins[i].prototype);
	}
	ctor.prototype.initializer = null;
	ctor.prototype.declaredClass = className;
	if(dojo.lang.isArray(props)){
		dojo.lang.extend.apply(dojo.lang, [ctor].concat(props));
	}else{
		dojo.lang.extend(ctor, (props)||{});
	}
	dojo.lang.extend(ctor, dojo.lang.declare.base);
	ctor.prototype.constructor = ctor;
	ctor.prototype.initializer=(ctor.prototype.initializer)||(init)||(function(){});
	dojo.lang.setObjPathValue(className, ctor, null, true);
}

dojo.lang.declare._makeConstructor = function() {
	return function(){ 
		// get the generational context (which object [or prototype] should be constructed)
		var self = this._getPropContext();
		var s = self.constructor.superclass;
		if((s)&&(s.constructor)){
			if(s.constructor==arguments.callee){
				// if this constructor is invoked directly (my.ancestor.call(this))
				this.inherited("constructor", arguments);
			}else{
				this._inherited(s, "constructor", arguments);
			}
		}
		var m = (self.constructor.mixins)||([]);
		for(var i=0,l=m.length; i<l; i++) {
			(((m[i].prototype)&&(m[i].prototype.initializer))||(m[i])).apply(this, arguments);
		}
		if((!this.prototyping)&&(self.initializer)){
			self.initializer.apply(this, arguments);
		}
	}
}

dojo.lang.declare.base = {
	_getPropContext: function() { return (this.___proto||this); },
	// caches ptype context and calls method on it
	_inherited: function(ptype, method, args){
		var stack = this.___proto;
		this.___proto = ptype;
		var result = ptype[method].apply(this,(args||[]));
		this.___proto = stack;
		return result;
	},
	// invokes ctor.prototype.method, with args, in our context 
	inheritedFrom: function(ctor, prop, args){
		var p = ((ctor)&&(ctor.prototype)&&(ctor.prototype[prop]));
		return (dojo.lang.isFunction(p) ? p.apply(this, (args||[])) : p);
	},
	// searches backward thru prototype chain to find nearest ancestral instance of prop
	inherited: function(prop, args){
		var p = this._getPropContext();
		do{
			if((!p.constructor)||(!p.constructor.superclass)){return;}
			p = p.constructor.superclass;
		}while(!(prop in p));
		return (dojo.lang.isFunction(p[prop]) ? this._inherited(p, prop, args) : p[prop]);
	}
}

dojo.declare = dojo.lang.declare;
__CPAN_DIR__ src/data
__CPAN_FILE__ src/data/to_do.txt
Existing Features
 * can import data from .json or .csv format files
 * can import data from del.icio.us
 * can create and modify data programmatically
 * can bind data to dojo.widget.Chart
 * can bind data to dojo.widget.SortableTable
 * can bind one data set to multiple widgets
 * notifications: widgets are notified when data changes
 * notification available per-item or per-resultSet
 * can create ad-hoc attributes
 * attributes can be loosely-typed 
 * attributes can have meta-data like type and display name
 * half-implemented support for sorting
 * half-implemented support for export to .json
 * API for getting data in simple arrays 
 * API for getting ResultSets with iterators (precursor to support for something like the openrico.org live grid)
 
~~~~~~~~~~~~~~~~~~~~~~~~
To-Do List
 * be able to import data from an html <table></table>
 * think about being able to import data from some type of XML 
 * think about integration with dojo.undo.Manager
 * think more about how to represent the notion of different data types
 * think about what problems we'll run into when we have a MySQL data provider
 * in TableBindingHack, improve support for data types in the SortableTable binding
 * deal with ids (including MySQL multi-field keys)
 * add support for item-references:  employeeItem.set('department', departmentItem);
 * deal with Attributes as instances of Items, not just subclasses of Items
 * unit tests for compare/sort code
 * unit tests for everything
 * implement item.toString('json') and item.toString('xml')
 * implement dataProvider.newItem({name: 'foo', age: 26})
 * deal better with transactions
 * add support for deleting items
 * don't send out multiple notifications to the same observer
 * deal with item versions
 * prototype a Yahoo data provider -- http://developer.yahoo.net/common/json.html
 * prototype a data provider that enforces strong typing
 * prototype a data provider that prevents ad-hoc attributes
 * prototype a data provider that enforces single-kind item
 * prototype a data provider that allows for login/authentication
 * have loosely typed result sets play nicely with widgets that expect strong typing
 * prototype an example of spreadsheet-style formulas or derivation rules
 * experiment with some sort of fetch() that returns only a subset of a data provider's items


__CPAN_FILE__ src/data/Item.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.Item");
dojo.require("dojo.data.Observable");
dojo.require("dojo.data.Value");
dojo.require("dojo.lang.common");
dojo.require("dojo.lang.assert");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.Item = function(/* dojo.data.provider.Base */ dataProvider) {
	/**
	 * summary:
	 * An Item has attributes and attribute values, sort of like 
	 * a record in a database, or a 'struct' in C.  Instances of
	 * the Item class know how to store and retrieve their
	 * attribute values.
	 */
	dojo.lang.assertType(dataProvider, [dojo.data.provider.Base, "optional"]);
	dojo.data.Observable.call(this);
	this._dataProvider = dataProvider;
	this._dictionaryOfAttributeValues = {};
};
dojo.inherits(dojo.data.Item, dojo.data.Observable);

// -------------------------------------------------------------------
// Public class methods
// -------------------------------------------------------------------
dojo.data.Item.compare = function(/* dojo.data.Item */ itemOne, /* dojo.data.Item */ itemTwo) {
	/**
	 * summary:
	 * Given two Items to compare, this method returns 0, 1, or -1.
	 * This method is designed to be used by sorting routines, like
	 * the JavaScript built-in Array sort() method.
	 * 
	 * Example:
	 * <pre>
	 *   var a = dataProvider.newItem("kermit");
	 *   var b = dataProvider.newItem("elmo");
	 *   var c = dataProvider.newItem("grover");
	 *   var array = new Array(a, b, c);
	 *   array.sort(dojo.data.Item.compare);
	 * </pre>
	 */
	dojo.lang.assertType(itemOne, dojo.data.Item);
	if (!dojo.lang.isOfType(itemTwo, dojo.data.Item)) {
		return -1;
	}
	var nameOne = itemOne.getName();
	var nameTwo = itemTwo.getName();
	if (nameOne == nameTwo) {
		var attributeArrayOne = itemOne.getAttributes();
		var attributeArrayTwo = itemTwo.getAttributes();
		if (attributeArrayOne.length != attributeArrayTwo.length) {
			if (attributeArrayOne.length > attributeArrayTwo.length) {
				return 1; 
			} else {
				return -1;
			}
		}
		for (var i in attributeArrayOne) {
			var attribute = attributeArrayOne[i];
			var arrayOfValuesOne = itemOne.getValues(attribute);
			var arrayOfValuesTwo = itemTwo.getValues(attribute);
			dojo.lang.assert(arrayOfValuesOne && (arrayOfValuesOne.length > 0));
			if (!arrayOfValuesTwo) {
				return 1;
			}
			if (arrayOfValuesOne.length != arrayOfValuesTwo.length) {
				if (arrayOfValuesOne.length > arrayOfValuesTwo.length) {
					return 1; 
				} else {
					return -1;
				}
			}
			for (var j in arrayOfValuesOne) {
				var value = arrayOfValuesOne[j];
				if (!itemTwo.hasAttributeValue(value)) {
					return 1;
				}
			}
			return 0;
		}
	} else {
		if (nameOne > nameTwo) {
			return 1; 
		} else {
			return -1;  // 0, 1, or -1
		}
	}
};

// -------------------------------------------------------------------
// Public instance methods
// -------------------------------------------------------------------
dojo.data.Item.prototype.toString = function() {
	/**
	 * Returns a simple string representation of the item.
	 */
	var arrayOfStrings = [];
	var attributes = this.getAttributes();
	for (var i in attributes) {
		var attribute = attributes[i];
		var arrayOfValues = this.getValues(attribute);
		var valueString;
		if (arrayOfValues.length == 1) {
			valueString = arrayOfValues[0];
		} else {
			valueString = '[';
			valueString += arrayOfValues.join(', ');
			valueString += ']';
		}
		arrayOfStrings.push('  ' + attribute + ': ' + valueString);
	}
	var returnString = '{ ';
	returnString += arrayOfStrings.join(',\n');
	returnString += ' }';
	return returnString; // string
};

dojo.data.Item.prototype.compare = function(/* dojo.data.Item */ otherItem) {
	/**
	 * summary: Compares this Item to another Item, and returns 0, 1, or -1.
	 */ 
	return dojo.data.Item.compare(this, otherItem); // 0, 1, or -1
};

dojo.data.Item.prototype.isEqual = function(/* dojo.data.Item */ otherItem) {
	/**
	 * summary: Returns true if this Item is equal to the otherItem, or false otherwise.
	 */
	return (this.compare(otherItem) == 0); // boolean
};

dojo.data.Item.prototype.getName = function() {
	return this.get('name');
};

dojo.data.Item.prototype.get = function(/* string or dojo.data.Attribute */ attributeId) {
	/**
	 * summary: Returns a single literal value, like "foo" or 33.
	 */ 
	// dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
	var literalOrValueOrArray = this._dictionaryOfAttributeValues[attributeId];
	if (dojo.lang.isUndefined(literalOrValueOrArray)) {
		return null; // null
	}
	if (literalOrValueOrArray instanceof dojo.data.Value) {
		return literalOrValueOrArray.getValue(); // literal
	}
	if (dojo.lang.isArray(literalOrValueOrArray)) {
		var dojoDataValue = literalOrValueOrArray[0];
		return dojoDataValue.getValue(); // literal
	}
	return literalOrValueOrArray; // literal
};

dojo.data.Item.prototype.getValue = function(/* string or dojo.data.Attribute */ attributeId) {
	/**
	 * summary: Returns a single instance of dojo.data.Value.
	 */ 
	// dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
	var literalOrValueOrArray = this._dictionaryOfAttributeValues[attributeId];
	if (dojo.lang.isUndefined(literalOrValueOrArray)) {
		return null; // null
	}
	if (literalOrValueOrArray instanceof dojo.data.Value) {
		return literalOrValueOrArray; // dojo.data.Value
	}
	if (dojo.lang.isArray(literalOrValueOrArray)) {
		var dojoDataValue = literalOrValueOrArray[0];
		return dojoDataValue; // dojo.data.Value
	}
	var literal = literalOrValueOrArray;
	dojoDataValue = new dojo.data.Value(literal);
	this._dictionaryOfAttributeValues[attributeId] = dojoDataValue;
	return dojoDataValue; // dojo.data.Value
};

dojo.data.Item.prototype.getValues = function(/* string or dojo.data.Attribute */ attributeId) {
	/**
	 * summary: Returns an array of dojo.data.Value objects.
	 */ 
	// dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
	var literalOrValueOrArray = this._dictionaryOfAttributeValues[attributeId];
	if (dojo.lang.isUndefined(literalOrValueOrArray)) {
		return null; // null
	}
	if (literalOrValueOrArray instanceof dojo.data.Value) {
		var array = [literalOrValueOrArray];
		this._dictionaryOfAttributeValues[attributeId] = array;
		return array; // Array
	}
	if (dojo.lang.isArray(literalOrValueOrArray)) {
		return literalOrValueOrArray; // Array
	}
	var literal = literalOrValueOrArray;
	var dojoDataValue = new dojo.data.Value(literal);
	array = [dojoDataValue];
	this._dictionaryOfAttributeValues[attributeId] = array;
	return array; // Array
};

dojo.data.Item.prototype.load = function(/* string or dojo.data.Attribute */ attributeId, /* anything */ value) {
	/**
	 * summary: 
	 * Used for loading an attribute value into an item when
	 * the item is first being loaded into memory from some
	 * data store (such as a file).
	 */ 
	// dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
	this._dataProvider.registerAttribute(attributeId);
	var literalOrValueOrArray = this._dictionaryOfAttributeValues[attributeId];
	if (dojo.lang.isUndefined(literalOrValueOrArray)) {
		this._dictionaryOfAttributeValues[attributeId] = value;
		return;
	}
	if (!(value instanceof dojo.data.Value)) {
		value = new dojo.data.Value(value);
	}
	if (literalOrValueOrArray instanceof dojo.data.Value) {
		var array = [literalOrValueOrArray, value];
		this._dictionaryOfAttributeValues[attributeId] = array;
		return;
	}
	if (dojo.lang.isArray(literalOrValueOrArray)) {
		literalOrValueOrArray.push(value);
		return;
	}
	var literal = literalOrValueOrArray;
	var dojoDataValue = new dojo.data.Value(literal);
	array = [dojoDataValue, value];
	this._dictionaryOfAttributeValues[attributeId] = array;
};

dojo.data.Item.prototype.set = function(/* string or dojo.data.Attribute */ attributeId, /* anything */ value) {
	/**
	 * summary: 
	 * Used for setting an attribute value as a result of a
	 * user action.
	 */ 
	// dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
	this._dataProvider.registerAttribute(attributeId);
	this._dictionaryOfAttributeValues[attributeId] = value;
	this._dataProvider.noteChange(this, attributeId, value);
};

dojo.data.Item.prototype.setValue = function(/* string or dojo.data.Attribute */ attributeId, /* dojo.data.Value */ value) {
	this.set(attributeId, value);
};

dojo.data.Item.prototype.addValue = function(/* string or dojo.data.Attribute */ attributeId, /* anything */ value) {
	/**
	 * summary: 
	 * Used for adding an attribute value as a result of a
	 * user action.
	 */ 
	this.load(attributeId, value);
	this._dataProvider.noteChange(this, attributeId, value);
};

dojo.data.Item.prototype.setValues = function(/* string or dojo.data.Attribute */ attributeId, /* Array */ arrayOfValues) {
	/**
	 * summary: 
	 * Used for setting an array of attribute values as a result of a
	 * user action.
	 */
	// dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
	dojo.lang.assertType(arrayOfValues, Array);
	this._dataProvider.registerAttribute(attributeId);
	var finalArray = [];
	this._dictionaryOfAttributeValues[attributeId] = finalArray;
	for (var i in arrayOfValues) {
		var value = arrayOfValues[i];
		if (!(value instanceof dojo.data.Value)) {
			value = new dojo.data.Value(value);
		}
		finalArray.push(value);
		this._dataProvider.noteChange(this, attributeId, value);
	}
};

dojo.data.Item.prototype.getAttributes = function() {
	/**
	 * summary: 
	 * Returns an array containing all of the attributes for which
	 * this item has attribute values.
	 */ 
	var arrayOfAttributes = [];
	for (var key in this._dictionaryOfAttributeValues) {
		arrayOfAttributes.push(this._dataProvider.getAttribute(key));
	}
	return arrayOfAttributes; // Array
};

dojo.data.Item.prototype.hasAttribute = function(/* string or dojo.data.Attribute */ attributeId) {
	/**
	 * summary: Returns true if the given attribute of the item has been assigned any value.
	 */ 
	// dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
	for (var key in this._dictionaryOfAttributeValues) {
		if (key == attributeId) {
			return true; // boolean
		}
	}
	return false; // boolean
};

dojo.data.Item.prototype.hasAttributeValue = function(/* string or dojo.data.Attribute */ attributeId, /* anything */ value) {
	/**
	 * summary: Returns true if the given attribute of the item has been assigned the given value.
	 */ 
	var arrayOfValues = this.getValues(attributeId);
	for (var i in arrayOfValues) {
		var candidateValue = arrayOfValues[i];
		if (candidateValue.isEqual(value)) {
			return true; // boolean
		}
	}
	return false; // boolean
};



__CPAN_FILE__ src/data/Type.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.Type");
dojo.require("dojo.data.Item");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.Type = function(/* dojo.data.provider.Base */ dataProvider) {
	/**
	 * summary:
	 * A Type represents a type of value, like Text, Number, Picture,
	 * or Varchar.
	 */
	dojo.data.Item.call(this, dataProvider);
};
dojo.inherits(dojo.data.Type, dojo.data.Item);

__CPAN_FILE__ src/data/ResultSet.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.ResultSet");
dojo.require("dojo.lang.assert");
dojo.require("dojo.collections.Collections");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.ResultSet = function(/* dojo.data.provider.Base */ dataProvider, /* Array */ arrayOfItems) {
	/**
	 * summary:
	 * A ResultSet holds a collection of Items.  A data provider
	 * returns a ResultSet in reponse to a query.
	 * (The name "Result Set" comes from the MySQL terminology.)
	 */
	dojo.lang.assertType(dataProvider, [dojo.data.provider.Base, "optional"]);
	dojo.lang.assertType(arrayOfItems, [Array, "optional"]);
	dojo.data.Observable.call(this);
	this._dataProvider = dataProvider;
	this._arrayOfItems = [];
	if (arrayOfItems) {
		this._arrayOfItems = arrayOfItems;
	}
};
dojo.inherits(dojo.data.ResultSet, dojo.data.Observable);

// -------------------------------------------------------------------
// Public instance methods
// -------------------------------------------------------------------
dojo.data.ResultSet.prototype.toString = function() {
	var returnString = this._arrayOfItems.join(', ');
	return returnString; // string
};

dojo.data.ResultSet.prototype.toArray = function() {
	return this._arrayOfItems; // Array
};

dojo.data.ResultSet.prototype.getIterator = function() {
	return new dojo.collections.Iterator(this._arrayOfItems);
};

dojo.data.ResultSet.prototype.getLength = function() {
	return this._arrayOfItems.length; // integer
};

dojo.data.ResultSet.prototype.getItemAt = function(/* numeric */ index) {
	return this._arrayOfItems[index];
};

dojo.data.ResultSet.prototype.indexOf = function(/* dojo.data.Item */ item) {
	return dojo.lang.indexOf(this._arrayOfItems, item); // integer
};

dojo.data.ResultSet.prototype.contains = function(/* dojo.data.Item */ item) {
	return dojo.lang.inArray(this._arrayOfItems, item); // boolean
};

dojo.data.ResultSet.prototype.getDataProvider = function() {
	return this._dataProvider; // dojo.data.provider.Base
};
__CPAN_FILE__ src/data/Attribute.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.Attribute");
dojo.require("dojo.data.Item");
dojo.require("dojo.lang.assert");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.Attribute = function(/* dojo.data.provider.Base */ dataProvider, /* string */ attributeId) {
	/**
	 * summary:
	 * An Attribute object represents something like a column in 
	 * a relational database.
	 */
	dojo.lang.assertType(dataProvider, [dojo.data.provider.Base, "optional"]);
	dojo.lang.assertType(attributeId, String);
	dojo.data.Item.call(this, dataProvider);
	this._attributeId = attributeId;
};
dojo.inherits(dojo.data.Attribute, dojo.data.Item);

// -------------------------------------------------------------------
// Public instance methods
// -------------------------------------------------------------------
dojo.data.Attribute.prototype.toString = function() {
	return this._attributeId; // string
};

dojo.data.Attribute.prototype.getAttributeId = function() {
	/**
	 * summary: 
	 * Returns the string token that uniquely identifies this
	 * attribute within the context of a data provider.
	 * For a data provider that accesses relational databases,
	 * typical attributeIds might be tokens like "name", "age", 
	 * "ssn", or "dept_key".
	 */ 
	return this._attributeId; // string
};

dojo.data.Attribute.prototype.getType = function() {
	/**
	 * summary: Returns the data type of the values of this attribute.
	 */ 
	return this.get('type'); // dojo.data.Type or null
};

dojo.data.Attribute.prototype.setType = function(/* dojo.data.Type or null */ type) {
	/**
	 * summary: Sets the data type for this attribute.
	 */ 
	this.set('type', type);
};

__CPAN_FILE__ src/data/Kind.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.Kind");
dojo.require("dojo.data.Item");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.Kind = function(/* dojo.data.provider.Base */ dataProvider) {
	/**
	 * summary:
	 * A Kind represents a kind of item.  In the dojo data model
	 * the item Snoopy might belong to the 'kind' Dog, where in
	 * a Java program the object Snoopy would belong to the 'class'
	 * Dog, and in MySQL the record for Snoopy would be in the 
	 * table Dog.
	 */
	dojo.data.Item.call(this, dataProvider);
};
dojo.inherits(dojo.data.Kind, dojo.data.Item);

__CPAN_FILE__ src/data/Observable.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.Observable");
dojo.require("dojo.lang.common");
dojo.require("dojo.lang.assert");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.Observable = function() {
};

// -------------------------------------------------------------------
// Public instance methods
// -------------------------------------------------------------------
dojo.data.Observable.prototype.addObserver = function(/* object */ observer) {
	/**
	 * summary: Registers an object as an observer of this item,
	 * so that the object will be notified when the item changes.
	 */ 
	dojo.lang.assertType(observer, Object);
	dojo.lang.assertType(observer.observedObjectHasChanged, Function);
	if (!this._arrayOfObservers) {
		this._arrayOfObservers = [];
	}
	if (!dojo.lang.inArray(this._arrayOfObservers, observer)) {
		this._arrayOfObservers.push(observer);
	}
};

dojo.data.Observable.prototype.removeObserver = function(/* object */ observer) {
	/**
	 * summary: Removes the observer registration for a previously
	 * registered object.
	 */ 
	if (!this._arrayOfObservers) {
		return;
	}
	var index = dojo.lang.indexOf(this._arrayOfObservers, observer);
	if (index != -1) {
		this._arrayOfObservers.splice(index, 1);
	}
};

dojo.data.Observable.prototype.getObservers = function() {
	/**
	 * summary: Returns an array with all the observers of this item.
	 */ 
	return this._arrayOfObservers; // Array or undefined
};


__CPAN_FILE__ src/data/Value.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.Value");
dojo.require("dojo.lang.assert");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.Value = function(/* anything */ value) {
	/**
	 * summary:
	 * A Value represents a simple literal value (like "foo" or 334),
	 * or a reference value (a pointer to an Item).
	 */
	this._value = value;
	this._type = null;
};

// -------------------------------------------------------------------
// Public instance methods
// -------------------------------------------------------------------
dojo.data.Value.prototype.toString = function() {
	return this._value.toString(); // string
};

dojo.data.Value.prototype.getValue = function() {
	/**
	 * summary: Returns the value itself.
	 */ 
	return this._value; // anything
};

dojo.data.Value.prototype.getType = function() {
	/**
	 * summary: Returns the data type of the value.
	 */ 
	dojo.unimplemented('dojo.data.Value.prototype.getType');
	return this._type; // dojo.data.Type
};

dojo.data.Value.prototype.compare = function() {
	dojo.unimplemented('dojo.data.Value.prototype.compare');
};

dojo.data.Value.prototype.isEqual = function() {
	dojo.unimplemented('dojo.data.Value.prototype.isEqual');
};

__CPAN_FILE__ src/data/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.experimental");

dojo.experimental("dojo.data.*");
dojo.kwCompoundRequire({
	common: [
		"dojo.data.Item",
		"dojo.data.ResultSet",
		"dojo.data.provider.FlatFile"
	]
});
dojo.provide("dojo.data.*");


__CPAN_DIR__ src/data/provider
__CPAN_FILE__ src/data/provider/MySql.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.provider.MySql");
dojo.require("dojo.data.provider.Base");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.provider.MySql = function() {
	/**
	 * summary:
	 * A MySql Data Provider knows how to connect to a MySQL database
	 * on a server and and make the content records available as 
	 * dojo.data.Items.
	 */
	dojo.unimplemented('dojo.data.provider.MySql');
};

dojo.inherits(dojo.data.provider.MySql, dojo.data.provider.Base);

__CPAN_FILE__ src/data/provider/Delicious.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.provider.Delicious");
dojo.require("dojo.data.provider.FlatFile");
dojo.require("dojo.data.format.Json");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.provider.Delicious = function() {
	/**
	 * summary:
	 * The Delicious Data Provider can be used to take data from
	 * del.icio.us and make it available as dojo.data.Items
	 * In order to use the Delicious Data Provider, you need 
	 * to have loaded a script tag that looks like this:
	 * <script type="text/javascript" src="http://del.icio.us/feeds/json/gumption?count=8"></script>
	 */
	dojo.data.provider.FlatFile.call(this);
	// Delicious = null;
	if (Delicious && Delicious.posts) {
		dojo.data.format.Json.loadDataProviderFromArrayOfJsonData(this, Delicious.posts);
	} else {
		// document.write("<script type='text/javascript'>dojo.data.provider.Delicious._fetchComplete()</script>");		
		/*
		document.write("<script type='text/javascript'>alert('boo!');</script>");		
		document.write("<script type='text/javascript'>var foo = 'not dojo'; alert('dojo == ' + foo);</script>");		
		document.write("<script type='text/javascript'>var foo = fetchComplete; alert('dojo == ' + foo);</script>");		
		fetchComplete();
		*/
		// dojo.debug("Delicious line 29: constructor");
	}
	var u = this.registerAttribute('u');
	var d = this.registerAttribute('d');
	var t = this.registerAttribute('t');
	
	u.load('name', 'Bookmark');
	d.load('name', 'Description');
	t.load('name', 'Tags');
	
	u.load('type', 'String');
	d.load('type', 'String');
	t.load('type', 'String');
};
dojo.inherits(dojo.data.provider.Delicious, dojo.data.provider.FlatFile);

/********************************************************************
 * FIXME: the rest of this is work in progress
 *
 
dojo.data.provider.Delicious.prototype.getNewItemToLoad = function() {
	var newItem = this._newItem();
	this._currentArray.push(newItem);
	return newItem; // dojo.data.Item
};

dojo.data.provider.Delicious.prototype.fetchArray = function(query) {
	if (!query) {	
		query = "gumption";
	}
	this._currentArray = [];
	alert("Delicious line 60: loadDataProviderFromArrayOfJsonData");
	alert("Delicious line 61: " + dojo);
		var sourceUrl = "http://del.icio.us/feeds/json/" + query + "?count=8";
		document.write("<script type='text/javascript' src='" + sourceUrl + "'></script>");
		document.write("<script type='text/javascript'>alert('line 63: ' + Delicious.posts[0].u);</script>");		
		document.write("<script type='text/javascript'>callMe();</script>");		
	alert("line 66");
	dojo.data.format.Json.loadDataProviderFromArrayOfJsonData(this, Delicious.posts);
	return this._currentArray; // Array
};

callMe = function() {
	alert("callMe!");
};

*/

__CPAN_FILE__ src/data/provider/FlatFile.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.provider.FlatFile");
dojo.require("dojo.data.provider.Base");
dojo.require("dojo.data.Item");
dojo.require("dojo.data.Attribute");
dojo.require("dojo.data.ResultSet");
dojo.require("dojo.data.format.Json");
dojo.require("dojo.data.format.Csv");
dojo.require("dojo.lang.assert");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.provider.FlatFile = function(/* keywords */ keywordParameters) {
	/**
	 * summary:
	 * A Json Data Provider knows how to read in simple JSON data
	 * tables and make their contents accessable as Items.
	 */
	dojo.lang.assertType(keywordParameters, ["pureobject", "optional"]);
	dojo.data.provider.Base.call(this);
	this._arrayOfItems = [];
	this._resultSet = null;
	this._dictionaryOfAttributes = {};

	if (keywordParameters) {
		var jsonObjects = keywordParameters["jsonObjects"];
		var jsonString  = keywordParameters["jsonString"];
		var fileUrl     = keywordParameters["url"];
		if (jsonObjects) {
			dojo.data.format.Json.loadDataProviderFromArrayOfJsonData(this, jsonObjects);
		}
		if (jsonString) {
			dojo.data.format.Json.loadDataProviderFromFileContents(this, jsonString);
		}
		if (fileUrl) {
			var arrayOfParts = fileUrl.split('.');
			var lastPart = arrayOfParts[(arrayOfParts.length - 1)];
			var formatParser = null;
			if (lastPart == "json") {
				formatParser = dojo.data.format.Json;
			}
			if (lastPart == "csv") {
				formatParser = dojo.data.format.Csv;
			}
			if (formatParser) {
				var fileContents = dojo.hostenv.getText(fileUrl);
				formatParser.loadDataProviderFromFileContents(this, fileContents);
			} else {
				dojo.lang.assert(false, "new dojo.data.provider.FlatFile({url: }) was passed a file without a .csv or .json suffix");
			}
		}
	}
};
dojo.inherits(dojo.data.provider.FlatFile, dojo.data.provider.Base);

// -------------------------------------------------------------------
// Public instance methods
// -------------------------------------------------------------------
dojo.data.provider.FlatFile.prototype.getProviderCapabilities = function(/* string */ keyword) {
	dojo.lang.assertType(keyword, [String, "optional"]);
	if (!this._ourCapabilities) {
		this._ourCapabilities = {
			transactions: false,
			undo: false,
			login: false,
			versioning: false,
			anonymousRead: true,
			anonymousWrite: false,
			permissions: false,
			queries: false,
			strongTyping: false,
			datatypes: [String, Date, Number]
		};
	}
	if (keyword) {
		return this._ourCapabilities[keyword];
	} else {
		return this._ourCapabilities;
	}
};

dojo.data.provider.FlatFile.prototype.registerAttribute = function(/* string or dojo.data.Attribute */ attributeId) {
	var registeredAttribute = this.getAttribute(attributeId);
	if (!registeredAttribute) {
		var newAttribute = new dojo.data.Attribute(this, attributeId);
		this._dictionaryOfAttributes[attributeId] = newAttribute;
		registeredAttribute = newAttribute;
	}
	return registeredAttribute; // dojo.data.Attribute
};

dojo.data.provider.FlatFile.prototype.getAttribute = function(/* string or dojo.data.Attribute */ attributeId) {
	var attribute = (this._dictionaryOfAttributes[attributeId] || null);
	return attribute; // dojo.data.Attribute or null
};

dojo.data.provider.FlatFile.prototype.getAttributes = function() {
	var arrayOfAttributes = [];
	for (var key in this._dictionaryOfAttributes) {
		var attribute = this._dictionaryOfAttributes[key];
		arrayOfAttributes.push(attribute);
	}
	return arrayOfAttributes; // Array
};

dojo.data.provider.FlatFile.prototype.fetchArray = function(query) {
	/**
	 * summary: Returns an Array containing all of the Items.
	 */ 
	return this._arrayOfItems; // Array
};

dojo.data.provider.FlatFile.prototype.fetchResultSet = function(query) {
	/**
	 * summary: Returns a ResultSet containing all of the Items.
	 */ 
	if (!this._resultSet) {
		this._resultSet = new dojo.data.ResultSet(this, this.fetchArray(query));
	}
	return this._resultSet; // dojo.data.ResultSet
};

// -------------------------------------------------------------------
// Private instance methods
// -------------------------------------------------------------------
dojo.data.provider.FlatFile.prototype._newItem = function() {
	var item = new dojo.data.Item(this);
	this._arrayOfItems.push(item);
	return item; // dojo.data.Item
};

dojo.data.provider.FlatFile.prototype._newAttribute = function(/* String */ attributeId) {
	dojo.lang.assertType(attributeId, String);
	dojo.lang.assert(this.getAttribute(attributeId) === null);
	var attribute = new dojo.data.Attribute(this, attributeId);
	this._dictionaryOfAttributes[attributeId] = attribute;
	return attribute; // dojo.data.Attribute
};

dojo.data.provider.Base.prototype._getResultSets = function() {
	return [this._resultSet]; // Array
};


__CPAN_FILE__ src/data/provider/JotSpot.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.provider.JotSpot");
dojo.require("dojo.data.provider.Base");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.provider.JotSpot = function() {
	/**
	 * summary:
	 * A JotSpot Data Provider knows how to read data from a JotSpot data 
	 * store and make the contents accessable as dojo.data.Items.
	 */
	dojo.unimplemented('dojo.data.provider.JotSpot');
};

dojo.inherits(dojo.data.provider.JotSpot, dojo.data.provider.Base);


__CPAN_FILE__ src/data/provider/Base.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.provider.Base");
dojo.require("dojo.lang.assert");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
dojo.data.provider.Base = function() {
	/**
	 * summary:
	 * A Data Provider serves as a connection to some data source,
	 * like a relational database.  This data provider Base class
	 * serves as an abstract superclass for other data provider
	 * classes.
	 */
	this._countOfNestedTransactions = 0;
	this._changesInCurrentTransaction = null;
};

// -------------------------------------------------------------------
// Public instance methods
// -------------------------------------------------------------------
dojo.data.provider.Base.prototype.beginTransaction = function() {
	/**
	 * Marks the beginning of a transaction.
	 *
	 * Each time you call beginTransaction() you open a new transaction, 
	 * which you need to close later using endTransaction().  Transactions
	 * may be nested, but the beginTransaction and endTransaction calls
	 * always need to come in pairs.
	 */
	if (this._countOfNestedTransactions === 0) {
		this._changesInCurrentTransaction = [];
	}
	this._countOfNestedTransactions += 1;
};

dojo.data.provider.Base.prototype.endTransaction = function() {
	/**
	 * Marks the end of a transaction.
	 */
	this._countOfNestedTransactions -= 1;
	dojo.lang.assert(this._countOfNestedTransactions >= 0);

	if (this._countOfNestedTransactions === 0) {
		var listOfChangesMade = this._saveChanges();
		this._changesInCurrentTransaction = null;
		if (listOfChangesMade.length > 0) {
			// dojo.debug("endTransaction: " + listOfChangesMade.length + " changes made");
			this._notifyObserversOfChanges(listOfChangesMade);
		}
	}
};

dojo.data.provider.Base.prototype.getNewItemToLoad = function() {
	return this._newItem(); // dojo.data.Item
};

dojo.data.provider.Base.prototype.newItem = function(/* string */ itemName) {
	/**
	 * Creates a new item.
	 */
	dojo.lang.assertType(itemName, [String, "optional"]);
	var item = this._newItem();
	if (itemName) {
		item.set('name', itemName);
	}
	return item; // dojo.data.Item
};

dojo.data.provider.Base.prototype.newAttribute = function(/* string */ attributeId) {
	/**
	 * Creates a new attribute.
	 */
	dojo.lang.assertType(attributeId, String); // FIXME: should be optional
	var attribute = this._newAttribute(attributeId);
	return attribute; // dojo.data.Attribute
};

dojo.data.provider.Base.prototype.getAttribute = function(/* string */ attributeId) {
	dojo.unimplemented('dojo.data.provider.Base');
	var attribute;
	return attribute; // dojo.data.Attribute
};

dojo.data.provider.Base.prototype.getAttributes = function() {
	dojo.unimplemented('dojo.data.provider.Base');
	return this._arrayOfAttributes; // Array
};

dojo.data.provider.Base.prototype.fetchArray = function() {
	dojo.unimplemented('dojo.data.provider.Base');
	return []; // Array
};

dojo.data.provider.Base.prototype.fetchResultSet = function() {
	dojo.unimplemented('dojo.data.provider.Base');
	var resultSet;
	return resultSet; // dojo.data.ResultSet
};

dojo.data.provider.Base.prototype.noteChange = function(/* dojo.data.Item */ item, /* string or dojo.data.Attribute */ attribute, /* anything */ value) {
	var change = {item: item, attribute: attribute, value: value};
	if (this._countOfNestedTransactions === 0) {
		this.beginTransaction();
		this._changesInCurrentTransaction.push(change);
		this.endTransaction();
	} else {
		this._changesInCurrentTransaction.push(change);
	}
};

dojo.data.provider.Base.prototype.addItemObserver = function(/* dojo.data.Item */ item, /* object */ observer) {
	/**
	 * summary: Registers an object as an observer of an item,
	 * so that the object will be notified when the item changes.
	 */
	dojo.lang.assertType(item, dojo.data.Item);
	item.addObserver(observer);
};

dojo.data.provider.Base.prototype.removeItemObserver = function(/* dojo.data.Item */ item, /* object */ observer) {
	/**
	 * summary: Removes the observer registration for a previously
	 * registered object.
	 */ 
	dojo.lang.assertType(item, dojo.data.Item);
	item.removeObserver(observer);
};

// -------------------------------------------------------------------
// Private instance methods
// -------------------------------------------------------------------
dojo.data.provider.Base.prototype._newItem = function() {
	var item = new dojo.data.Item(this);
	return item; // dojo.data.Item
};

dojo.data.provider.Base.prototype._newAttribute = function(/* String */ attributeId) {
	var attribute = new dojo.data.Attribute(this);
	return attribute; // dojo.data.Attribute
};

dojo.data.provider.Base.prototype._saveChanges = function() {
	var arrayOfChangesMade = this._changesInCurrentTransaction;
	return arrayOfChangesMade; // Array
};

dojo.data.provider.Base.prototype._notifyObserversOfChanges = function(/* Array */ arrayOfChanges) {
	var arrayOfResultSets = this._getResultSets();
	for (var i in arrayOfChanges) {
		var change = arrayOfChanges[i];
		var changedItem = change.item;
		var arrayOfItemObservers = changedItem.getObservers();
		for (var j in arrayOfItemObservers) {
			var observer = arrayOfItemObservers[j];
			observer.observedObjectHasChanged(changedItem, change);
		}
		for (var k in arrayOfResultSets) {
			var resultSet = arrayOfResultSets[k];
			var arrayOfResultSetObservers = resultSet.getObservers();
			for (var m in arrayOfResultSetObservers) {
				observer = arrayOfResultSetObservers[m];
				observer.observedObjectHasChanged(resultSet, change);
			}
		}
	}
};

dojo.data.provider.Base.prototype._getResultSets = function() {
	dojo.unimplemented('dojo.data.provider.Base');
	return []; // Array
};


__CPAN_DIR__ src/data/format
__CPAN_FILE__ src/data/format/Json.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.format.Json");
dojo.require("dojo.lang.assert");

dojo.data.format.Json = new function() {

	// -------------------------------------------------------------------
	// Public functions
	// -------------------------------------------------------------------
	this.loadDataProviderFromFileContents = function(/* dojo.data.provider.Base */ dataProvider, /* string */ jsonFileContents) {
		dojo.lang.assertType(dataProvider, dojo.data.provider.Base);
		dojo.lang.assertType(jsonFileContents, String);
		var arrayOfJsonData = eval("(" + jsonFileContents + ")");
		this.loadDataProviderFromArrayOfJsonData(dataProvider, arrayOfJsonData);
	};
	
	this.loadDataProviderFromArrayOfJsonData = function(/* dojo.data.provider.Base */ dataProvider, /* Array */ arrayOfJsonData) {
		dojo.lang.assertType(arrayOfJsonData, [Array, "optional"]);
		if (arrayOfJsonData && (arrayOfJsonData.length > 0)) {
			var firstRow = arrayOfJsonData[0];
			dojo.lang.assertType(firstRow, [Array, "pureobject"]);
			if (dojo.lang.isArray(firstRow)) {
				_loadDataProviderFromArrayOfArrays(dataProvider, arrayOfJsonData);
			} else {
				dojo.lang.assertType(firstRow, "pureobject");
				_loadDataProviderFromArrayOfObjects(dataProvider, arrayOfJsonData);
			}
		}
	};

	this.getJsonStringFromResultSet = function(/* dojo.data.ResultSet */ resultSet) {
		dojo.unimplemented('dojo.data.format.Json.getJsonStringFromResultSet');
		var jsonString = null;
		return jsonString; // String
	};

	// -------------------------------------------------------------------
	// Private functions
	// -------------------------------------------------------------------
	function _loadDataProviderFromArrayOfArrays(/* dojo.data.provider.Base */ dataProvider, /* Array */ arrayOfJsonData) {
		/** 
		 * Example: 
		 * var arrayOfJsonStates = [
		 * 	 [ "abbr",  "population",  "name" ]
		 * 	 [  "WA",     5894121,      "Washington"    ],
		 * 	 [  "WV",     1808344,      "West Virginia" ],
		 * 	 [  "WI",     5453896,      "Wisconsin"     ],
		 *   [  "WY",      493782,      "Wyoming"       ] ];
		 * this._loadFromArrayOfArrays(arrayOfJsonStates);
		 */
		var arrayOfKeys = arrayOfJsonData[0];
		for (var i = 1; i < arrayOfJsonData.length; ++i) {
			var row = arrayOfJsonData[i];
			var item = dataProvider.getNewItemToLoad();
			for (var j in row) {
				var value = row[j];
				var key = arrayOfKeys[j];
				item.load(key, value);
			}
		}
	}

	function _loadDataProviderFromArrayOfObjects(/* dojo.data.provider.Base */ dataProvider, /* Array */ arrayOfJsonData) {
		/** 
		 * Example: 
		 * var arrayOfJsonStates = [
		 * 	 { abbr: "WA", name: "Washington" },
		 * 	 { abbr: "WV", name: "West Virginia" },
		 * 	 { abbr: "WI", name: "Wisconsin", song: "On, Wisconsin!" },
		 * 	 { abbr: "WY", name: "Wyoming", cities: ["Lander", "Cheyenne", "Laramie"] } ];
		 * this._loadFromArrayOfArrays(arrayOfJsonStates);
		 */
		// dojo.debug("_loadDataProviderFromArrayOfObjects");
		for (var i in arrayOfJsonData) {
			var row = arrayOfJsonData[i];
			var item = dataProvider.getNewItemToLoad();
			for (var key in row) {
				var value = row[key];
				if (dojo.lang.isArray(value)) {
					var arrayOfValues = value;
					for (var j in arrayOfValues) {
						value = arrayOfValues[j];
						item.load(key, value);
						// dojo.debug("loaded: " + key + " = " + value); 
					}
				} else {
					item.load(key, value);
				}
			}
		}
	}
	
}();


__CPAN_FILE__ src/data/format/Csv.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.data.format.Csv");
dojo.require("dojo.lang.assert");


dojo.data.format.Csv = new function() {

	// -------------------------------------------------------------------
	// Public functions
	// -------------------------------------------------------------------
	this.getArrayStructureFromCsvFileContents = function(/* string */ csvFileContents) {
		/**
		 * Given a string containing CSV records, this method parses
		 * the string and returns a data structure containing the parsed
		 * content.  The data structure we return is an array of length
		 * R, where R is the number of rows (lines) in the CSV data.  The 
		 * return array contains one sub-array for each CSV line, and each 
		 * sub-array contains C string values, where C is the number of 
		 * columns in the CSV data.
		 * 
		 * For example, given this CSV string as input:
		 * <pre>
		 *   "Title, Year, Producer \n Alien, 1979, Ridley Scott \n Blade Runner, 1982, Ridley Scott"
		 * </pre>
		 * We will return this data structure:
		 * <pre>
		 *   [["Title", "Year", "Producer"]
		 *    ["Alien", "1979", "Ridley Scott"],  
		 *    ["Blade Runner", "1982", "Ridley Scott"]]
		 * </pre>
		 */
		dojo.lang.assertType(csvFileContents, String);
		
		var lineEndingCharacters = new RegExp("\r\n|\n|\r");
		var leadingWhiteSpaceCharacters = new RegExp("^\\s+",'g');
		var trailingWhiteSpaceCharacters = new RegExp("\\s+$",'g');
		var doubleQuotes = new RegExp('""','g');
		var arrayOfOutputRecords = [];
		
		var arrayOfInputLines = csvFileContents.split(lineEndingCharacters);
		for (var i in arrayOfInputLines) {
			var singleLine = arrayOfInputLines[i];
			if (singleLine.length > 0) {
				var listOfFields = singleLine.split(',');
				var j = 0;
				while (j < listOfFields.length) {
					var space_field_space = listOfFields[j];
					var field_space = space_field_space.replace(leadingWhiteSpaceCharacters, ''); // trim leading whitespace
					var field = field_space.replace(trailingWhiteSpaceCharacters, ''); // trim trailing whitespace
					var firstChar = field.charAt(0);
					var lastChar = field.charAt(field.length - 1);
					var secondToLastChar = field.charAt(field.length - 2);
					var thirdToLastChar = field.charAt(field.length - 3);
					if ((firstChar == '"') && 
							((lastChar != '"') || 
							 ((lastChar == '"') && (secondToLastChar == '"') && (thirdToLastChar != '"')) )) {
						if (j+1 === listOfFields.length) {
							// alert("The last field in record " + i + " is corrupted:\n" + field);
							return null;
						}
						var nextField = listOfFields[j+1];
						listOfFields[j] = field_space + ',' + nextField;
						listOfFields.splice(j+1, 1); // delete element [j+1] from the list
					} else {
						if ((firstChar == '"') && (lastChar == '"')) {
							field = field.slice(1, (field.length - 1)); // trim the " characters off the ends
							field = field.replace(doubleQuotes, '"');   // replace "" with "
						}
						listOfFields[j] = field;
						j += 1;
					}
				}
				arrayOfOutputRecords.push(listOfFields);
			}
		}
		return arrayOfOutputRecords; // Array
	};

	this.loadDataProviderFromFileContents = function(/* dojo.data.provider.Base */ dataProvider, /* string */ csvFileContents) {
		dojo.lang.assertType(dataProvider, dojo.data.provider.Base);
		dojo.lang.assertType(csvFileContents, String);
		var arrayOfArrays = this.getArrayStructureFromCsvFileContents(csvFileContents);
		if (arrayOfArrays) {
			var arrayOfKeys = arrayOfArrays[0];
			for (var i = 1; i < arrayOfArrays.length; ++i) {
				var row = arrayOfArrays[i];
				var item = dataProvider.getNewItemToLoad();
				for (var j in row) {
					var value = row[j];
					var key = arrayOfKeys[j];
					item.load(key, value);
				}
			}
		}
	};
	
	this.getCsvStringFromResultSet = function(/* dojo.data.ResultSet */ resultSet) {
		dojo.unimplemented('dojo.data.format.Csv.getCsvStringFromResultSet');
		var csvString = null;
		return csvString; // String
	};
	
}();

__CPAN_DIR__ src/storage
__CPAN_FILE__ src/storage/browser.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.storage.browser");
dojo.provide("dojo.storage.browser.FlashStorageProvider");

dojo.require("dojo.storage");
dojo.require("dojo.flash");
dojo.require("dojo.json");
dojo.require("dojo.uri.*");

/** 
		Storage provider that uses features in Flash to achieve permanent storage.
		
		@author Alex Russel, alex@dojotoolkit.org
		@author Brad Neuberg, bkn3@columbia.edu 
*/
dojo.storage.browser.FlashStorageProvider = function(){
}

dojo.inherits(dojo.storage.browser.FlashStorageProvider, dojo.storage);

// instance methods and properties
dojo.lang.extend(dojo.storage.browser.FlashStorageProvider, {
	namespace: "default",
	initialized: false,
	_available: null,
	_statusHandler: null,
	
	initialize: function(){
		if(djConfig["disableFlashStorage"] == true){
			return;
		}
		
		// initialize our Flash
		var loadedListener = function(){
			dojo.storage._flashLoaded();
		}
		dojo.flash.addLoadedListener(loadedListener);
		var swfloc6 = dojo.uri.dojoUri("Storage_version6.swf").toString();
		var swfloc8 = dojo.uri.dojoUri("Storage_version8.swf").toString();
		dojo.flash.setSwf({flash6: swfloc6, flash8: swfloc8, visible: false});
	},
	
	isAvailable: function(){
		if(djConfig["disableFlashStorage"] == true){
			this._available = false;
		}
		
		return this._available;
	},
	
	setNamespace: function(namespace){
		this.namespace = namespace;
	},

	put: function(key, value, resultsHandler){
		if(this.isValidKey(key) == false){
			dojo.raise("Invalid key given: " + key);
		}
			
		this._statusHandler = resultsHandler;
		
		// serialize the value
		// Handle strings differently so they have better performance
		if(dojo.lang.isString(value)){
			value = "string:" + value;
		}else{
			value = dojo.json.serialize(value);
		}
		
		dojo.flash.comm.put(key, value, this.namespace);
	},

	get: function(key){
		if(this.isValidKey(key) == false){
			dojo.raise("Invalid key given: " + key);
		}
		
		var results = dojo.flash.comm.get(key, this.namespace);

		if(results == ""){
			return null;
		}
    
		// destringify the content back into a 
		// real JavaScript object
		// Handle strings differently so they have better performance
		if(!dojo.lang.isUndefined(results) && results != null 
			 && /^string:/.test(results)){
			results = results.substring("string:".length);
		}else{
			results = dojo.json.evalJson(results);
		}
    
		return results;
	},

	getKeys: function(){
		var results = dojo.flash.comm.getKeys(this.namespace);
		
		if(results == ""){
			return new Array();
		}

		// the results are returned comma seperated; split them
		results = results.split(",");
		
		return results;
	},

	clear: function(){
		dojo.flash.comm.clear(this.namespace);
	},
	
	remove: function(key){
	},
	
	isPermanent: function(){
		return true;
	},

	getMaximumSize: function(){
		return dojo.storage.SIZE_NO_LIMIT;
	},

	hasSettingsUI: function(){
		return true;
	},

	showSettingsUI: function(){
		dojo.flash.comm.showSettings();
		dojo.flash.obj.setVisible(true);
		dojo.flash.obj.center();
	},

	hideSettingsUI: function(){
		// hide the dialog
		dojo.flash.obj.setVisible(false);
		
		// call anyone who wants to know the dialog is
		// now hidden
		if(dojo.storage.onHideSettingsUI != null &&
			!dojo.lang.isUndefined(dojo.storage.onHideSettingsUI)){
			dojo.storage.onHideSettingsUI.call(null);	
		}
	},
	
	/** 
			The provider name as a string, such as 
			"dojo.storage.FlashStorageProvider". 
	*/
	getType: function(){
		return "dojo.storage.FlashStorageProvider";
	},
	
	/** Called when the Flash is finished loading. */
	_flashLoaded: function(){
		this.initialized = true;

		// indicate that this storage provider is now loaded
		dojo.storage.manager.loaded();
	},
	
	/** 
			Called if the storage system needs to tell us about the status
			of a put() request. 
	*/
	_onStatus: function(statusResult, key){
		//dojo.debug("_onStatus, statusResult="+statusResult+", key="+key);
		if(statusResult == dojo.storage.PENDING){
			dojo.flash.obj.center();
			dojo.flash.obj.setVisible(true);
		}else{
			dojo.flash.obj.setVisible(false);
		}
		
		if(!dojo.lang.isUndefined(dojo.storage._statusHandler) 
				&& dojo.storage._statusHandler != null){
			dojo.storage._statusHandler.call(null, statusResult, key);		
		}
	}
});

// register the existence of our storage providers
dojo.storage.manager.register("dojo.storage.browser.FlashStorageProvider",
                              new dojo.storage.browser.FlashStorageProvider());

// now that we are loaded and registered tell the storage manager to initialize
// itself
dojo.storage.manager.initialize();
															

__CPAN_FILE__ src/storage/dashboard.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.storage");
dojo.require("dojo.json");
dojo.provide("dojo.storage.dashboard");

dojo.storage.dashboard.StorageProvider = function(){
	this.initialized = false;
}

dojo.inherits(dojo.storage.dashboard.StorageProvider, dojo.storage.StorageProvider);

dojo.lang.extend(dojo.storage.dashboard.StorageProvider, {
	storageOnLoad: function(){
		this.initialized = true;
	},

	set: function(key, value, ns){
		if (ns && widget.system){
			widget.system("/bin/mkdir " + ns);
			var system = widget.system("/bin/echo " + value + " >" + ns + "/" + key);
			if(system.errorString){
				return false;
			}
			return true;
		}

		return widget.setPreferenceForKey(dojo.json.serialize(value), key);
	},

	get: function(key, ns){
		if (ns && widget.system) {
			var system = widget.system("/bin/cat " + ns + "/" + key);
			if(system.errorString){
				return "";
			}
			return system.outputString;
		}

		return dojo.json.evalJson(widget.preferenceForKey(key));
	}
});

dojo.storage.setProvider(new dojo.storage.dashboard.StorageProvider());

__CPAN_FILE__ src/storage/storage_dialog.fla
ÐÏà¡±á>þÿ	þÿÿÿ	
�ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot Entryÿÿÿÿÿÿÿÿpª|YªrÏƒRASH°™ !eÆÀContentsÿÿÿÿÿÿÿÿÿÿÿÿ{jPage 1ÿÿÿÿÿÿÿÿÿÿÿÿ¿Media 1ÿÿÿÿþÿÿÿþÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿýÿÿÿýÿÿÿýÿÿÿ
BþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot Entryÿÿÿÿÿÿÿÿpª|YªrÏƒRASH°:73ºdÆÀContentsÿÿÿÿÿÿÿÿÿÿÿÿ{jPage 1ÿÿÿÿÿÿÿÿÿÿÿÿ¿Media 1ÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿýÿÿÿýÿÿÿýÿÿÿýÿÿÿýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€	

 !"#$%&'()*+,-./0123456789:;<=>?@A…ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ†‡ˆ‰‹ÿÿÿÿ�ÿÿÿÿŽ��‘’“”þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ	

 !"#$%&'()*+,-./0123456789:þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ8ÿÿ
CDocumentPagePage 1ÿþÿScene 1ÿþÿ8">D¼ÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿöðGDÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿCSwfPageMedia 1ÿþÿButtonÿþÿ	ëW?·Ô±CÿþÿButtonÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿþÿButtonÿþÿmx.controls.Buttonÿþÿ‚C:\Documents and Settings\bradneuberg\Local Settings\Application Data\Macromedia\Flash MX 2004\en\Configuration\TMP3yjbts6p08..swf]oCWSç’xœÌ;	l\×q³ÿÿ].)’")R«ƒÔE¦,Ëº,É‡¨ƒ‡DYÚ•—ò!_ëÏÝOî—þÞýÉ&i”Ä‰
§¥#a";NU
œIÑºpÚ&­Ü´5ê¶ìê¢hÔ…Ñ´Hš44ÝÎÌ{ï»+Å(£´üoÞ¼y3ófæÍ{oò_‚ŽW¡=#Z­V»
{ '"×`ÿ^¾|ºÚÿ"²X{ë_õ…ïn~lâ�Õ‹Ÿ)î<±ü‹ÿ¼ø¯?N=`ÿñ×^¿µÖ.¨á�OÅbüG°}¸s9“ÓàØ¬ë–ŠÙR®Â~ê8Çg`aÖº:Ú?~9ý±ýN~rtðó?q.oyýÙoü×…Èk•‡ŸüèW?;öWÏýÆ�¯ÜúCœæqkà¨ÃúCøµÔàæ­‚5RrJú¶«Ð¿Ô
-öBa-Õv±
É¥^F´r“sp`ÑE8rYµ\îštÒ	!‡®äèc9H›9»tÖ›q�”&êiŒ¥é»UíL{ñÅ¥¸ýšõÂÿüÛ;ÅGôáÌ�Ÿ}äs¯±²?Û4qÏ‹ðgRšØ&M4,M¬^šÝ(Íìj�3ð;»¦¤9ùÀ�Ÿýû7·¿òèÁ¡_}g›ÖºýÊ¶¤d>þ�1ß¢˜ïeæã0éZå0ïýØÓZ¿-OV6~³ëoç‹ß’,·}`,·†õÝ#y+{!Èóaýô›§úµ	À9\³˜µ&Fa¶˜³¦í¢•CÍò–=“waÎÎ¹y@rqÞ*”¦ÎÓ¼“ö/YPu+8hž> ›7+G]Ø€ówà¤ŽUœÁqvu²lfuv
‘ìâ­ywqIÀ2wVá(›•ªåÙjvÀGàd	§¦¶ÁÃð!ÑŸš:oe]xH´ŽV*æ‚øœ¤ñ· )Â®ylÏZ0m:HYÉé}ÜÏb©Ö	!kÆ±/Zg*ÖEÛš;mV/@¶b™®5V(»§Kqì2‰/:Å˜²fìâ¸í8P(]´Î–ÀAâ«˜chæ¢]µ§p}2ó�YÙB}Ïgó€Ï@n¶ìØYœÇŸbÚ1«yÇrqQ¬jÖ,[P*Þ[Î!Ž÷qzÖqm0{¦gOb9H gA±4IßÈG—¤ÒÌ\î¬
dfœÒ”éàâœòåEÂi«JËš©”J.,v"äTÉÌQ„=c°d€‰CrtIƒxd¢ç
v}kýô«'ýo#‰Ìæ�2 Æ�-éÄó¾¬âñq²÷–a·2v[zxq…g:È·C•µ_²°lâÎÝ
	Ñl7;ÂÍÎ‰áÅ¾ e`<ÝZ¾KiŸÄ]#!?ô:aä¢'†4-¾<y‚äE–!€yEh[Úc¼ëP!Dá²]$•9Ã°ý{5b…ˆˆI�„îM3CÃö2t&µŒ"Á�'àŸoÔ–:pr£	änÔZOÐ«€w0 æ2_ºxÏ¡ i¤¼œ´ÇÿúÏ ù·jH,àg@jû	5tL‰ãS]q¨a\Ï^6–®À¤ }x‰DÁž/À
‰ôÂ‰4Ö›&4£ÇW¦ÞÄBd¶1�€ƒÒš¾bëP­	>Ñƒñ7Ïí`G‚ªÁÙ¢ï�#”BG)tf(ÆvÖ±ª©’¢ž’~Ô¨$á;­_-|MxÏš´½…,³«Ú„'ß×¥ÌÂãcºiŒAö�Kû>>Ð¸:;DÔ0=õž„
HÖTýÚ�ÔoÔ„”úe”Ç,n;ü;GŽµbÏÀ=…ô7*d)
R4ß‡AèGx\}ø¡ßæú$Y¼¡y˜^¸
)ïx@Ú~Ù©òrÐsï¯‘µæëÐl4©A^ì�»$»âw"ïÝþ×±(k‚¦Ä]hXàm¸1ÞF…×c¼M‡†…ž„(Ò~g„&ÃŠL¢KDôpØ^nö†›‰‰º`«�á¹°ýŒ¶MTë-ó ´ebßÐ0!ó˜WñEØÀæ‰S4Q�˜WÇNV„É0ëa©â[ÀE(Öå2êrÔVßÛ£‘aÛ€Á0‡™“dè¥"eVboGRça¹†Æ¿‰w^IT“»ª¡'…†ã¤“!ú—<™­íô�Z¬Ü�YoCÉ‰Rä
�ÆªËŽíIá¿Qm5@å¥ˆŒÛ·us0À=±ƒ�B·7Ç¡ÿ¸7(ß‘N©A��í$Õák]t#É�O@åþ’hAŒ[c­ßy¬]uôë$H»Ó‰HÛˆÓs½Ùv¿'žv_Gæ=iŽÿÿCPicPageÿÿ	CPicLayerÿÿ	CPicFrameÿÿCPicSwf%	I}vÿþÿÿþÿcloseButton	ÿþÿiconÿþÿÿþÿiconöƒFôÈÿ¾L“ì¡sÎ¶ÿþÿÿþÿlabelÿþÿFinishedÿþÿlabelE»b[cF•EÀ\G½ŒÿþÿÿþÿlabelPlacementÿþÿleftÿþÿrightÿþÿtopÿþÿbottomÿþÿlabelPlacementå•¢T åIŸÄß^æãD©ÿþÿÿþÿselectedÿþÿfalseÿþÿselectedî/Ï?ëZJ�ñ…ƒ|úìgÿþÿÿþÿtoggleÿþÿfalseÿþÿtoggleg¿¥íY˜D¾ê±Ìœ²ÿþÿÿþÿenabledÿþÿtrueÿþÿenabled!º—À­RG¸5S8ìêbmÿþÿOtherÿþÿvisibleÿþÿtrueÿþÿvisibleD*Lc³XTC¦$úv±¢ÿþÿOtherÿþÿ	minHeightÿþÿ0ÿþÿ	minHeightÃP¬»¸K¨‰u@•&ÓjÿþÿSizeÿþÿminWidthÿþÿ0ÿþÿminWidth!7“C2«I”»¼ú l/›ÿþÿSizeÿþÿÿ<component metaDataFetched='true' schemaUrl='' schemaOperation='' sceneRootLabel='Scene 1' oldCopiedComponentPath='1'>
	<eventMap>
		<property name="selected" value="click" />
	</eventMap>
	<property name="selected">
<schema name="Boolean" base="Boolean" class="mx.data.types.Bool" required="true" readonly="false" writeonly="false" category="simple" original="true">
			<properties>
				<property name="defaultLabel" value="" />
				<property name="defaultUIControl" value="" />
			</properties>
		</schema>
	</property>
</component>
ÿÿCPicText€€/Xÿþÿ
ð_sansÿ(Press Finished when doneÿþÿÿþÿÿþÿ€€îîîÿÿó_!l¡Þ0”ê0_!0lÿÿÿ?ÿÿÿþÿZzÿþÿÿV// know when the close button is pressed; this is needed as a workaround when

// showing the storage configuration dialog, since there is no way we can

// know when that panel's close button is pressed

closeButton.onMouseDown = function(){

	// some versions of Flash don't have access to containing parents 

	// objects, like DojoExternalInterface; only Flash 8 seems to have access

	if(typeof DojoExternalInterface != "undefined"){ // flash 8

		DojoExternalInterface.call("dojo.storage.hideSettingsUI", null);

	}else{ // flash 6

		fscommand("call", "dojo.storage.hideSettingsUI");

	}

};ÿþÿ€€ÿþÿLayer 1ÿÿÿÿOÿOÿ€€", "dojo.storage.hideSettingsUI");

};ÿþÿ€€ÿþÿLayer 1ÿÿÿÿOÿOÿ€€ÿþÿrightÿþÿtopÿþÿbottomÿþÿlabelPlacementå•¢T åIŸÄß^æãD©ÿþÿÿþÿselectedÿþÿ8ÿÿ
CDocumentPagePage 1ÿþÿScene 1ÿþÿ8">D¼ÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿöðGDÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿCSwfPageMedia 1ÿþÿButtonÿþÿ	ëW?·Ô±CÿþÿButtonÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿþÿButtonÿþÿmx.controls.Buttonÿþÿ‚C:\Documents and Settings\bradneuberg\Local Settings\Application Data\Macromedia\Flash MX 2004\en\Configuration\TMP3yjbts6p08..swf]oCWSç’xœÌ;	l\×q³ÿÿ].)’")R«ƒÔE¦,Ëº,É‡¨ƒ‡DYÚ•—ò!_ëÏÝOî—þÞýÉ&i”Ä‰
§¥#a";NU
œIÑºpÚ&­Ü´5ê¶ìê¢hÔ…Ñ´Hš44ÝÎÌ{ï»+Å(£´üoÞ¼y3ófæÍ{oò_‚ŽW¡=#Z­V»
{ '"×`ÿ^¾|ºÚÿ"²X{ë_õ…ïn~lâ�Õ‹Ÿ)î<±ü‹ÿ¼ø¯?N=`ÿñ×^¿µÖ.¨á�OÅbüG°}¸s9“ÓàØ¬ë–ŠÙR®Â~ê8Çg`aÖº:Ú?~9ý±ýN~rtðó?q.oyýÙoü×…Èk•‡ŸüèW?;öWÏýÆ�¯ÜúCœæqkà¨ÃúCøµÔàæ­‚5RrJú¶«Ð¿Ô
-öBa-Õv±
É¥^F´r“sp`ÑE8rYµ\îštÒ	!‡®äèc9H›9»tÖ›q�”&êiŒ¥é»UíL{ñÅ¥¸ýšõÂÿüÛ;ÅGôáÌ�Ÿ}äs¯±²?Û4qÏ‹ðgRšØ&M4,M¬^šÝ(Íìj�3ð;»¦¤9ùÀ�Ÿýû7·¿òèÁ¡_}g›ÖºýÊ¶¤d>þ�1ß¢˜ïeæã0éZå0ïýØÓZ¿-OV6~³ëoç‹ß’,·}`,·†õÝ#y+{!Èóaýô›§úµ	À9\³˜µ&Fa¶˜³¦í¢•CÍò–=“waÎÎ¹y@rqÞ*”¦ÎÓ¼“ö/YPu+8hž> ›7+G]Ø€ówà¤ŽUœÁqvu²lfuv
‘ìâ­ywqIÀ2wVá(›•ªåÙjvÀGàd	§¦¶ÁÃð!ÑŸš:oe]xH´ŽV*æ‚øœ¤ñ· )Â®ylÏZ0m:HYÉé}ÜÏb©Ö	!kÆ±/Zg*ÖEÛš;mV/@¶b™®5V(»§Kqì2‰/:Å˜²fìâ¸í8P(]´Î–ÀAâ«˜chæ¢]µ§p}2ó�YÙB}Ïgó€Ï@n¶ìØYœÇŸbÚ1«yÇrqQ¬jÖ,[P*Þ[Î!Ž÷qzÖqm0{¦gOb9H gA±4IßÈG—¤ÒÌ\î¬
dfœÒ”éàâœòåEÂi«JËš©”J.,v"äTÉÌQ„=c°d€‰CrtIƒxd¢ç
v}kýô«'ýo#‰Ìæ�2 Æ�-éÄó¾¬âñq²÷–a·2v[zxq…g:È·C•µ_²°lâÎÝ
	Ñl7;ÂÍÎ‰áÅ¾ e`<ÝZ¾KiŸÄ]#!?ô:aä¢'†4-¾<y‚äE–!€yEh[Úc¼ëP!Dá²]$•9Ã°ý{5b…ˆˆI�„îM3CÃö2t&µŒ"Á�'àŸoÔ–:pr£	änÔZOÐ«€w0 æ2_ºxÏ¡ i¤¼œ´ÇÿúÏ ù·jH,àg@jû	5tL‰ãS]q¨a\Ï^6–®À¤ }x‰DÁž/À
‰ôÂ‰4Ö›&4£ÇW¦ÞÄBd¶1�€ƒÒš¾bëP­	>Ñƒñ7Ïí`G‚ªÁÙ¢ï�#”BG)tf(ÆvÖ±ª©’¢ž’~Ô¨$á;­_-|MxÏš´½…,³«Ú„'ß×¥ÌÂãcºiŒAö�Kû>>Ð¸:;DÔ0=õž„
HÖTýÚ�ÔoÔ„”úe”Ç,n;ü;GŽµbÏÀ=…ô7*d)
R4ß‡AèGx\}ø¡ßæú$Y¼¡y˜^¸
)ïx@Ú~Ù©òrÐsï¯‘µæëÐl4©A^ì�»$»âw"ïÝþ×±(k‚¦Ä]hXàm¸1ÞF…×c¼M‡†…ž„(Ò~g„&ÃŠL¢KDôpØ^nö†›‰‰º`«�á¹°ýŒ¶MTë-ó ´ebßÐ0!ó˜WñEØÀæ‰S4Q�˜WÇNV„É0ëa©â[ÀE(Öå2êrÔVßÛ£‘aÛ€Á0‡™“dè¥"eVboGRça¹†Æ¿‰w^IT“»ª¡'…†ã¤“!ú—<™­íô�Z¬Ü�YoCÉ‰Rä
�ÆªËŽíIá¿Qm5@å¥ˆŒÛ·us0À=±ƒ�B·7Ç¡ÿ¸7(ß‘N©A��í$Õák]t#É�O@åþ’hAŒ[c­ßy¬]uôë$H»Ó‰HÛˆÓs½Ùv¿'žv_Gæ=iŽªZ|o4’ºÜçaIÀm>€�d´bÎ)#Áäì2®ïOª$M,çðŒ…R0´÷½QH)\µˆÒ™¦4¶ýÉã>~¨¼žˆ´µýMašÎMñXtV×ÙoKÀ~[’<÷ß@“­‘ôß‹ß”¿hˆV`O§¼,NÝFünaý½�ÐsP©|M:H“
5K�ÐbxN®‰]O“{š†ó1Ùd
ÃÈ'kJl“Ï“E’Y--:Ô¥µ·§C2)µ!•þH°ÃóÞR0½Q0^þ;’4ÔZ�Vn{áñÎCÏãqo–&™€Áœ!9ú=9b“t#†™BŒ§ýn-dûzü®tb±Ë?Õ ×œ‡T¤þŒ!S¢àô‡ÄîR§Ã9on¶#ú¾é0ì@ž6£,Ö‡BÚ¬þ_µÉfaè!‰¶za&pQ1ÿ2fà/k!jA³¼K˜%žÈÐ ‡ã‡S~ëHü(–ø1äÈJ3âÇü³˜8Ê�
*c<nœ|^`áïñÅ8Àûy8dÚ'&Z·ôwJÈ»¢eðÝ!_Š¦t‘LOOwßöÌ•Ÿ®]åþÑ“#ïºxIÞ¶«ÛÁeê^„ „+Ís˜Q+Í_zO¨°«
®Dà‰'ž€®ÞW‡Þzùèé¾};�>�a;ùbçaüZZPÍ›¹ÒÜ/èf§CIÐÁ¼vÂ±J®2™ÏÍIF—KFðý £>ôæËãoD÷�•Œv…�â«Ñ_£ËÃŒv1£ãt˜¯µÞ† n^�uâ×Vãº\E–¶‚`:ŽxûUXcõLÓ0AM\huÃ¤](;–¸Ü-Í¥ø=R|úÅ�¼5yì�µûz¥ø+Ââ—*9«ò¿G‰ßÎ¯`ñ�9�Ï
é
/tõ=sÖ}þÍw?Ñù…]ï~�_:n÷1¿âw%@ÞžÉ;tGõþ³ü4±Ü_;þÒC×ç}Ìö	Û¡›±&6×tu§´2¸º+à¯kµ?‘«Û-V·Þ¾)\]ÛE0¹ÞÖ(Ò~ûjíëžQ¦ÐB¦ðkµ_©ý÷À±KSXÁS¯™ÂD±‰Ê›pÙT–È�–&Á.WJó-M) Ûï5ò(9Jl–ïUüa±=m´�6®�kØQr·‰KŽ ™Ü‰�Ü÷–‘/
Å«°+èw«`Ôš61«J„ÕB‚VÃ½âRclÞµŠU»T$ÔØ¹44?2®òéØJ"×óÎ.4Zlè8´·ÿ•+áùÖxäÐÒ7"h-dþsô{ï�ëB/ÝŽwïý§‘/¾T}öG•¿;‚h›±£¿­¶·Ö}[¾xÉÑƒp5~ˆöNŠúZB4Úûù
ÙŒ†ímÊ7Pw®9uÂ,æ«B†Þ<Æ×ZºŽ—´O,i;Å#SÈJ);yø:/eg«i³‰äµÖq­¨O®t„¸GŽFÌ²;[¡¥Ã0kv¬úÊÇº"èŠ¨Ù5Ðõ\E)¶›É¯Sž6‹æÊ"sƒ·˜kiò0R*”KEôõÐzÞŽý×s
ôüVR¬g§èýÙ¥kÜhER+wß“�„öË�AòH”òûM!)×(íýÁñß~æ±F’¸OÓÄÝÐýÐOå¼+!qæ£ïr£íº÷[µ+ÜHà„+ÿcä¥°"6…¿¹ú×!h0$íÓBÚ®ÊsŠÚ26ˆ†@Û@#@PÙÜHeçÛ‘PœÜd
Þ@Zš-FÙ"_")#Ê÷IQÍU÷:&½—šªîjì)àôpò°‰]Eÿ‚·Shw�+QL2ÛÐØJ33ã£œr‚U4§êŒpS=KP³`å#H Q]ÁpñTâƒù—h5j£÷µ�oàõZ‹zè}í«¢1€‹FPÝ[¥Po=ì�LßÆ¯/S¿,ù2}™dB]ÚôxK¼ &sÊBY%•�¥„�q0@òaàƒÖ‰éíÛÀ.«µæMŒt¸ófÖÃM�Éœ1³Ð—«;ó;yÓÞÙd¿®u&tüÔ‹è2êÑ·ziêb³o2®\)¹%w¡ly›½À¢fúø1ÈUÌ9Èd4c¹"(Ç�çÊxÅ,Ð+ÙEÓ±éd&:ÃICÁž§™�NNZî™J©<î˜3UÎö�“÷ˆ8×¯R <iDü,^;’JqÅù€G¬¡qúÏ'N<ú_ø´	8Œç£b0¬øÞÏÉÀÍhlq¿°�ž¥‹Ž§0];7ñ}¥¸‚�·ñž tu@ŒÓ�…©´.vr½ÁÀ}%;;äq¨Í¿òŠÄ—¥�žª¢üx¥§$‘Ž:" nWÚi‚dJrß¹˜ ÷Ð·C¤ZÖ_“ý9ñ<É°6àç«x›¡¥ÄW,¬þ]žg0‰Òq]”…Òz]ä3ðJÓ(s
½…Xî/jˆÒ$](1ºÖdŠ(Ÿùö¥‚Â³†¤gm`Ïªó¬,zÆNkè|y�F<õû-¿ÛÄ�ÙßGÐƒ«ne6ëÊ¶ïSþ+m&ƒÞ“ÉˆrõGÀäã¹÷W@kÚåw`Ñô>ÜR™Þ†eËûÁ,S6+äÕ!úS%Œ�õF� Ó^ÄÊøÁ«‚‹‘… 2"Àe¼PW
B=ª]
µ±uŸzîV!••–·sT¬‹ª<gWË¦›Í�]$±$Iï•\Pô›ÜË¯Û êøC!)hçê±çäJ§0˜U `¹ùRî,Å~›´íLEéA(Ê!£’[ìGEŠx(RYéPÍÛ¸¸Yª&pŽ:Î¨]
jˆªî4=É‹pLÅxZÈ=@?ç¼Ïº”%ñ}E<Ô#¦P;~È%$Zœ™†‹DÃ)Þ?Å÷YkÞ·-'§6—žåé‹yB›Ä6T‰Ï$iCŒRÅ®kfóì²cÄ1«Uµ/-¦J�Ÿ©9ª:¨X3T€PaÔ`e…–³ÐáJª…K:j•Q¶©YÛÉñ§XµÙ2LÛÅ\Ù;zÑ´
ÌêœYæ¯*ÎEòûžJ»n�£Ì•�£?UV2ed´‘¦™»Ê‚ÜUƒÛ©b\µë<R
ŸGÑGQ•ávV~Œ0U]›«­ˆÍf­*ZºíØîÂe¶4ƒébâ«˜› Te4ÉÒ�¯”
$Õ“ì”�,næÍ*êœ¶f«â.ˆ*)!6Êž5Ñ3(ÇdS¬Š•ÎâªZ¤,^#îµ²fŽ²œ)b´lŽU3™™ŒŸ„°£²á•*ÓEû­Î5~ƒ‰[¤ƒXÓ˜NñÏ¸Y°�þd÷¦Kaõ´Y™Á)ðŸSg9z†ÀivÛE}f
vC´Ð7ï>$jjÈþ�ò•"áü˜ŸT*U!×b 
_’²[…)+7^¢ÌO–;±6 NðÀ§ÊC1(òÇH8+S¬uÕÁã3»:QÄ¸d»jLÓ¬ÊŒUg(ñ‡Ý³sþoï�!D¡/1=žRÇ$_*û»„ìæ¼™óT®XÓV£ìðÚ¢[îZf.çÙ¦ã-Èp.#6í‰ó°ðÿ.Ë,­mÈ2Å=¸Nç!<x^øô†gÈh:!rÑzÌGÌçƒ3ÎˆÌ
ãò¦}Zeš×š–}m
}Ë¼¾ö†¾¯¯ó}Ëúº¼¾îôõx}Ûeß
–®7©f¨SG<}|™Üw�Á+“jšºÁm�Á‰ºìYñ¶ÊãmµHõõ!Ðò^j¼
ScÙ¿Æ›¾ê&J¤‘µA"ƒJvW7,öšô°:"ô_‡¿�¿u>é9�¿Ÿ¿õ×ç¯ßãoC�Hëø[ïó·q±—ÎQ8F±$r³G@Uªl’/ÊwKÆ6Ñ™GQùJ·‡«A
M<¨x‚ë]èk½ #�ãÀVïø´­Á¢6yZ¹Éh¶�àQIlli›/ÒPÙíÙ›ƒd¤LÛI¦ºªŸÜŽr·xävúä<r·4’Ûá“»u±›Ž'O�2PSÐs’î.ÿ×tbB�vá§»=T0€‡Q­N­»Øgö¥eUÈmü–¯lh¿°BCYáoÊo»Cž‡$E½KßUÄ.ùˆÝŒ)®k¹=|Z�‘%T¢@KKÔ½ßÁO¬BXÂÜu{ä“ëÞdšj{®Ö¤wÖyÓ@@Ž&¬ÉQwÕ�JÈ…:àU2„µu¨¿A-wy&|�V3BîcLuæÌ…*|	”JOq¥�x0'1ŸðæÅ}ÀS
#'CoÀ·xoÀZ½¡'¹î‰Wû0kçOku(¦:²Áøá8ßáçÛˆsTmÈºeÐ!>-ó[€¨
�y[…WßD�Ù«6À£E^t1&U!ãQ7±s$~ÿº±~]¶F|æ –÷9¨HF“µ�%½âDìñ8#Â:–ÜÀÓñø	´³	t¨ëó4^gkä
M+³#Mh³£Lèäâ*z¢ˆ
�>¿ƒÃnˆÎïca<(Ê¦¤#êÝËU�Sb4�èu-‘“Ÿ^\K:¤ÉùÜÍñ1Éà“Ý÷`iw“’¥Æ#Š´c‚vRÆ¯òŒë–RM.kÎˆË"-¾‰Œœ¿î1Œ”²ò†7ÊÀ<4ƒXRuaáPCØ¿KÕP¥
®P04š'‡ä
˜ßÒÍ§Ò®ŸÔ‡N'#ŠÁ+Ép¾(ªÓàZÖÛ[ï]ÜF”Ð$5ÿ E:-‚NLÑù’,m½Oˆé×wÈkEÞRµøý¬¨ûüjQñŠÒF9ˆ±ZA±4™ö
p˜äMr¾û“Þßë¦¤ä9·¸Bí@(„.„Øªh¨nM[ÅÕéÁÓÈƒ‹íä-C({žžiÄ’�ñJ‹?ª¹ájúT}<}X
¶â�†_F''~4í—÷ø•ôê:6ÓP^÷˜²ÖØÊ%ÌÅµQ»æŒ(8Fð”¦J°ìâ ðœˆAhzÐr¢´Ì)\æ¢T{Žë¾Mï?»·XÓ¤?é¢õø;“æm‹êª
vÌ´�Î[sÅ[^ˆ@WÖÄÛ­Ð
SÊ§ET1áœÒ„/¢Ý,îŸ¯‹pýõ+d§e�½€{¦­ô9©TÇ×H”S€á:b…7>ß)6@J*)s®ÒGòG#Jþƒ¼Þ`§~\pUÜ¾!Jp…á…7ãJx3>ÜŒƒ‰u5Ý£êµ¢AˆuäÚq¥ö”ü¸ƒØ{©æåIh:×�à\1¹Ë)ä9�â?Uƒ}S%H!¥>$Wø—åV5jðc‚hŒÑv%9‹Ïú«•¨×ÞãÍ•:«ê�/&YôP@Ÿt9É¼R¾dëSâÿ)#tÆÿÛÞ›@Çu]‚¿ª~UýÂ¾‘ @�àN‚ûN‘wˆ $ª@�”dI¶ÀP  ‚(ˆ¤¼È²%“^ÂX^˜flyë8Þí8Nœ3Ó9™¤“žvÔîé%�ÌØŸô™Lwr<Óé>>í8‹#Ì»Ë[ÿÿ…‚D¹™±uTàÛ—ûÞï¾»^Ï±À zÖýÎzø|›•¡t
Œºöƒ·çUO¾ìILì%	µw|Ñx"*©�â�7[àœ¬…Ã`ÌË
ünÒÛœ¦¼+øý>—'ÙM1è€Gð1O+©Ã‡¼ÿ>o/ø�Zpº+²gP¾<¶2Í‹‘fQ
b��` ’ac|dþ–4O³€f5£úoÉ×:ªo$C£úd’`ön.F‡¹€YZ¯Ë6¦aÌSIzR¼‡„ð¥ðÿÆB·¨™B:Ôº‡k�rj½SëE¬•äZïuj½7¦Ö{Iø2Aµ®;µnÄÔº�µnq­÷9µÞSëýXë×ú€SëƒF­eF­”û¡î:®ûNÝ›1uouÿÒ£º¿èÔýPÌh?„£ýu®õ’SëÃ1µ>ŒµÞÎµ>âÔúhÌ8?jŒó×ý˜S÷c1=~{¬Q‡vN‚ä?@ƒ(û>>uaŸæpŸæ¸™)üVs(êz‹’VÐ©—Nˆ±•\ðÎAÙêë4ÊZçV3
‰Æ¹	5¦ûÜø*¨ÁÁÕhøØMÖ„š‘ãy&Ïbº’Ø¦ÆÕÅ„_"­‘ãYþ/…
J„ãŸ8´‰&G¨ÖŽÓêqÉ#–ðíc¿½*üæ�'¸‚Ò÷Ï1q*ü2ÞL$â½0…àãòÖþÄ z3&ƒ÷‚B›ùlxY^ <ÚçÍí`�s'�ÓÜí.!ãåÁ#·�…¾Â]Y8Ucì‰Gö	@ÛÅu#®£²ä’xK“úº	 ÃOÂ/–ÑßèŠ©W"íˆ1¥N)ÃeÎá@3æ”:Ïdô4#¡'F·ÑÚÝˆügÛ�²YiãN'H„0BÜÏY,™å’õØ|V7¾c7ÿJmP×WÔ§Ïà•Ù^±Ô§¡û„Ú ¡›ŠèMé¸¦5\Íõí6¡'WWÃ°•aˆ_�9UÙ!áy¬xI“f@¼WK±ÔÈg`7'Qñ¹‚#û	ïŠÑÞà=Ç$£‚èCâ¾äÅÓ2ð9ô˜óLääÏÿtàV;„Îï%(ÓwGäÊƒþ26Á¯`&ê:%‚ÏÊOXîW¡Ü!Ä’ƒÏSk_ ¾Hÿ|‰þù2ýóúç«Ôa;”r@´2Kòp|M¾+¿>hg×`öÒ¸ì:Ìþ5�MÉË™MÑ‰Ù_p³Wqv7f1®ñÌþ†[{‹ÖPÙ¿îfoçì­˜ýÍ¸Æ1û7ÜÚ›¸öFÌþ|\í³Ûâ²0û7ã²›1û[FßD}2ZÔç·”¨ÏflíhH'D,JˆÎ–žûrjÝøšøBâ¤ç¢Åæ´à€Ëû·…,ÁWrEqNA²ƒŒ?(©ê`™Ž»�ÅYÒ1ó£Ók¶Yœ‰TE†fZ÷šÑM/ÈÞì )‘DÒdJSÔÎH)<ÉHòSôøw�“¬ ¦p
È%LÓ(jˆ>t¹,’ÅV«Ylu|Lµ89mž¤i§ø(jÐ…uá+À
”…›Táf,\�D[‹Úæ[x›oÄm¾ÅÝæ(\±ýä¹s CÀ²ó
ŸÎBÅ=‰UQ;�JÙuôf/ŒŽé naˆ'¸²&ëå&¦JSESx‚Ï®ÀFX„"$…±8!”Rb ÕÈcÜmÙI‡vteiUñ	iŠmÉK
“¬ÆÛÒ&/ó·Ù0‰=«H;i«æÄFUÜÍFÝJtþÔHü¾v°ÝìîÐ¢»ËxA�h§®_÷x¿Õc�n*‡ˆïm$š[%�¹^ñ˜ëpœ
Æ8oIúxÉ{ÝjŒ‡P#A¨1B¯©»¦øîš¨»æ;Ù]K|w-Ô]ë�\ÿ6ÑN[ìú·-¸þmQëß†ã\r'Á²4,K	,íw²»eñÝ-£î:îdw�ñÝuRwËïä¢w�i”ØEïZpÑ»¢½Ç¹âN‚ee<XVXVÝU{½w«ë}+_ïÛðzß{½‡Ä*ç¾�‚ê7þR C•.ùPM}Õ»˜CUI`šÂˆxç�@0`l'¥”¼ƒ]Ø8…]´8jî-N'¹ûdýM.òŽ�äd{<àd�[ð_�)ÝnoIèä÷ù§·€ï`ë¡þA“7$—QÞ®Œ4'$Ž<Ä¬‚¤þ ™;\d„ˆ,’(Ï&M0MáblÞI»…›ÖÝ*¥b4©ê!EºÎ–Ž¤Q ðàk-Ê‘õ H3-�× ŽÖI›éDìÇ˜tû©Ç¿
ˆ- �£¢‚
¡ƒLåhrZªö0hV‡Á6>6àa°-ú0°>Ðù†Ïd¡Þ�RÆŸVýùËÇkHjØŽ—#‹Õ»W‹kå£²-wl•¥³B†TI)Ïì”ñF'fÄ<àÔŠ÷Ö¯ãÅ¡'Æób¸ÀÊý³3¢4uþMó [ºXPy,MN<£R,áì±‰ÉI
9Zùå‘Qí¼îQª ö‚R¥ö!@Ýá’LGE‰¢æÅPþŒNíµÆáæž�)–Ëv¦¶+HgK£…kn`ƒ²4c�³0m�NFÇ@™s&EÿÞ•ñ‰YXøQïâL±8%RçŠâ½v”¼kÅÉÉÒoäZaÊ/L–ú°„N@1Ì¦.£¯|Kâ{Ïx"šïB~Jâs´`Jìëg¡ñTÏC…iyW2ìêÑi>4�åÝvC}$õÚ^‘dTS«÷¬Š¢¯ˆ¿Y¢
JJŠ8˜£j¯�¯
tf�gun1¨qP»˜ÔD îf7+Q&ÕÉä%0øh¶dÜ`ê‰®ä'´:¦Œn)n0õr0xùÊÁ4F5Ñ½@¢rÒÑ‚&qÛ5‹_‹øµŠ_›ø-¿¥â×žNd•=9pkJ×ËDj‡øuŠßrñƒÚ]â·BüVŠ_·ø­¿Õâ·FüÖŠß:ñ[/~Äo£øm¿ñÛ,~[Äo«øm¿í¢·eÔÛÐ[}°Coä�`{ÑveÁD°;f’ƒ=ÙyÈÛ+þ‰ûD¢øg¿()dšØlúÑ�¶xÁÁ¬÷Ïç½l-5¿š?Ü+:½�'q8íGÄï¨¿ãâwBüNŠ´Þ´ªyjÞ�ÀYÂ5[P¸Sâ×'~§˜ýâ×+¦UGµ«»ÞP×ûv¾Þ×âõ¾=Z9Õ°©ÐÐ\•ndR§âõSuy}±+­U[#5Z%Uij]MVB:9§ð(äHõC{ÑÐ˜­hmRÀG�sxÙ¡˜Ì“…$*2fF¤^kiêAq¡R…KÅkhÐ‡ô÷PâWY-y�L“6)¶307ë¨’‚ò#µSš:'Ç ž"v;X¹_ÜQ½ª8(ž¢d¥»‡Å´–¤¡¥Jƒ"ìzÈšÓpSÃ3&…r‘"å³4c¼ÌPP)´J¥UìP oŽ«¡6§Ô»“U³ÆÃŠ� ðŒ‘B‘8mÌ°"Ø¥s³3EhÇ '[7-Ù¶`TÏ@­CÔ7=‘è¤ñ4iÉ´Sï¶Ûõùlè~ýŒ33sÎÐòÊ†4L%®™åÕ¨¼ZÒÝñ;‘m!å[\óZ%Ywsˆ·‚pH
¼‰®½äTñ
…ØªCõ!)ÌÉj!Åÿ¦Cí·Lñ‰zâ·€L¨Üº!ñÁ5žfBYB‰ ECª•
·Þÿ´tÁxL¬J�Gñ.°ŒÏbÙm›‚R›i½�ÚiSý±¦™˜ÿ%€hËtì`–úÒƒ?‰´?´ÓVŒâ÷çM	�e@ ÙPúöQÖYäuÈÕè$Á}q
›)`º8XR×X‰Ö®Ó*Þ­¦²J÷%–‘Od·¯Õ¡¾VË¾ÖDöe/Ô´…»VŠÒ(Ã|ZêV�gà›)�¼&®‹Ÿˆ4“Ø`�’DGâˆ	Í�š¤Wò¾Âk *A­—¤)é°À±Lã7ûiñÜ|È3ËnÊ³Ð†LÓàY7(«tFeoTV#õÇÀŠh~�÷Ó~<N¹à–†'}á¦)özÆú'Þ‹\£”±F›Õö?1ž$Ê¢'í)ù9[¬IR[ÌU:ä™ßÒ�‘æ�ds¾ÃªRÛN¾b8¾�aØ‘x›;ˆm¸—A
"K¢ìÙÁ”tÞ)æ¿‹a#Ï@”GØ-?ˆ=ò<ÛmHŒ5yÖWW¯f»÷f#Ë²%é’íÆ£«+Øìg–´óI1Éè€’œ¹'Zræ`p'à÷fo´*˜û@E
C Ô¡ÃÁÄ¦éfá™£ÚŽ.·xÌ¾p$¶*þÍG?2TnÁŒ8>èˆÔäœ'¤xÇIGú#‹Ù½:»J\ú~…KïÀÖŽ6€)¥„ˆ¹¸ôÔìLi²¼Ý26ßpß¨ycsö[‘5U²mŠi¬:„p#ÊØ]qÖµn¦Å>lÑ�Å�º“s3e@˜lóÒÅLqŒ
R\š˜BL
�–ý	­L°… .•dÚ ­²z8’Ù››ÀáNìýY°C04TžE,ˆù"ðhÍAaaicGL�—3lØŠÓø0ë"·ÀÅ±&þ/"Ô™>*^ž/¶;êÝ¯ƒ³…‹@{±½�®šÀäB�^�Vv¬ƒÈÄ:Œ›J
“#Ñ&S }²ó1^ºbŒƒÇ7;1âé�†¸'º”6Äàmð 6XŒ¹2EÏ*1¡áÙ©�±1Ø*$ûÎhÔŠÎŠÕ›�)«Dœ÷¬X39onË@kTx´¬z¢œÙ²(„u U�P…(gvÂ]Œ‰Ç …1†BcjXÏ;€š¢‘[Y”:O6ÓÀB.Ie²\Ä±‹VŒ$¡èý!ú’–Ø¤­Ì¸he�±§ Š/ÒÒÒ9ÍW~­ÃÚ¬ý*,ÌÍ–‹ÓâËÓïÑ»Ø>ï-N®™Ð°eJ…oC–FG?ýv]åZÜÃš³>>"cÏÐëv�Þ€ö[P~¬ð†¹DÝ/Â‹vnZÎ„8eU["½•DÓ©ep-ç�¡²à#c¦	 ‡
È1´9»›ßb¶åª¢ùÙ”�”Ë .�Á�…#ùžÇDô€7ŸûU¿Mµx~ð{Fû§àËÂP´‰ÿbGêHä4ù�Â‡Ôñ–“¥ÈRÜi¶…UÕE(³Êî‹¾YìOUE³;:Ç©K:´eFÌü¤©QT%ÍF1ÁXó‘­>'þNé;¼ÛÝ7:ß°G7[7Ýúw° ÿÓ.zi
ÊçÅ½ZR(ÒÊ§B
Ë7IâzÕ�¥/1ºQÉ”$4t
Ž%ì¡ÇÏ³¢šAáÜ¼¡wï£„­ÌÀçwÔ¢”!”-×ø½45¸Dü–J…Àö…J/ƒ'¦´	ØI^dÀ,7[Ž†f*¾ÙµsGÇÄÅWÜì”òr!5ÞåH YØ[¦Ç’•JÕ¶›ê§YÕÖR ¿Ä=®ò}1 iE!O[pMŸ±:IŸð~^@tö…ýÊ¥²_skM»‰]Æã:~<oòÂCX_a²PÕ�o ’N¶'‘y¦@\Š]¸Q34UÖà´ôP�„\ÝüŸÄ¹7d è‘½‹7v*èé‹XÝ‹ZJ\WV'xŠ{Áxûc)zóâ\Óyc�WXÂgˆ8¡<Ü°šG›lÕŠèNM8ªdÐUŸlÆÍQòÈÛIà×,ç'ÔnVêŠ£šüÛ=0ŸPns“Ù&™+ˆ›X€ÃX»ƒêlX�§jÐJ-oOø»“´ž”÷¤Ï�Ç³³R1¥ìÚÙ¥öÃJÒ‘:<Ô‘Ï†täÁÂ 'µXˆ|�Ã5tœTBixºfµÙJE7æ]ë´ˆxŒ5Ž½ø¸7ºÔæoðû£"r+mþå¸—³ôÍè=¦©9Æ^þ${¢7½³—“îå$íå¤RË_`/WDÙ’±ß-»
+�Ó ¥n…g×¶„rÔ®= ‰<E°r@8CêI‡{è
Kûò q£mæõ:„Dî|wd%Î¼GŒDÌw½§ú2NþÝÐ”.©.×]Îåú%—½V“ÛÁ½õg=êÞ'¿¦
HƒÕñýx�IS¿‡Ío¿D¬Ô
Fª˜Ö‘~#ï¨ÌÛ†Ä½89…£7›¤Å‡½(?«,P…(žð‰ˆh³u¬Ü|‹ª3íæPoÇá«É«”$HX×Â™_^=®rß€Yá|YV…úpeø¬Qî"@|+�`ÌÄc:·ý[$ 5ÑL´à~yížZ¨> }V}H9-O‰~ß0àó€ø=(#gÄï!ÉS+¿³2ò°j”Ðþÿ¶^Óbã5Î”Î-ˆé´Ø˜Ž3¥óæ”–šSzÄœÒ£æ”:Ì)=fNéMò{Z®Õ^w×s¯²·<¯,g›Ì£®±ú	u‰<¹�‰-}ß¼Ù)úCº3Ï§‰ÂCÍÓë-é„u¿…|¬™]<©ºXc¤o¹bµ=¥íÇÀÛ;÷:¤ÎÌ¡xòñãªŸ1ý©~
v?Ž%¿§BÖ†å†ãí^Ôn*µ?j¿¨Û/Æ·?¦Ú¿¸ÈöÇuûãÕ´?j·PP=8to�ãA½T¿LrK2â¯êEŸ`‹;^
:“bå÷mîyeŒh¢ÂžÚ¹‘žu§yIÙ9q7ë.bÜM—CŒ»)y‡”
kYÔ}:x«,16…‚²À�¸>{X~ÔegH¼*;‘°˜ÖþÎæ·ËŽŸ±;¾îøŠÓñ–Š›†®–ð¼æ´ñ-žÏjx¾m@�×Ô½�š¥r×ñÂ ã.Ñbï«(ƒ9jñÞ5=i„Æ™ÎOþ�±›á¹
í½Ë9lÒ‹¸aÞi|p-1>qó*ìFîåùp/±‹ðÎÅ/×xwØ>•^Ø¸¡½'¶R@¹ÒN%©	Ò�P{Q�
ï¥³žäp6ü©*f<ŽØ"üR‡'\—_R^L¸ÍþŸUâ‹ð‚´‡H¸Á–Òô™ãï3Ù¥i÷~ô_	Ü8‰ÄQ^½Èû€™‡×þ6FÂgåQ›†ÎÊM
¿ ­“<	‚õ&˜ˆýÎ•/Yh_²/x6yB>eVËR42
“oòï›ï-^t™pskúœ÷ï¥y9!cæäJYð£5¿Jù ¾Ö>d¾�¤åª—þ«<�Û…¾B®þá×Rýšªþé0DRNº”Î�Ø}4Tü\�ÉüQÅ×þX4_ûVðKŒKþ(Š,úÛhÜŽ#ÇØáSê5º\…6©¼î€8à¿l˜Š@¦ùÇ¹Œ|ß#y¿;Ž|R÷ìŸÂ€#ŸFÍ0Ž|­Gp¯hÓC¿|ŽC­@@!*÷ó*÷*÷¤
}Qå~I¥}Y…ÚUè+*ôUúš
�R¡¯«®†:‚/qhiðY=|™C�¿Â¡sA+‡ÎízSð=ü*‡ú‚¯r¨7ø<‡Î_ãÐƒÁ¤¹Õ@Zö8œâÐCÁ94|�CKbeÎÉÇ²Ø"çe‘þØ"Ke‘b‹<"‹œ‰-ò¨,’�-¢¨ßQP©Èc²ÈÃ±EÞ¤iè	ëç–€Öiã>±çÅÚu8Þ/ Ý+VåœXÁ¥Hÿ;1p«O´à3Á§ƒOŸ^>|<øe<ïDn3ä6‹9. èÇ=/RŸ‡ÔÍÁg5.õ+,&GÒ¿JHÚç±|ðü:‚“ø]_Ä/"ø’®ËFWÚ©îW¨îW©î×¨î)ªûuò“#?)o>“?h›Tù&¹ÈÙã¶Õ™]àìaÛê‰Ìáì¢mõäÕÊžü¦’=Ù‰S=Ú°ÆƒCtgœì‰’:™]un4§ßQIê$$ob‰¡ ¬	²ã!„\½!)¯¡yÊŽ@‰äPJV™‰È(Œ^Ð’ÃZÜ7ÄÐ%krõCRÀZŠ‡k°êãE2¤!:PÒ"pzbö¸˜“ÁRfv³ãè-”`H2HgKvÉ×)åPŠ(sB‰mhK®CI§{�ÜZ@ˆµˆv�ÅÊî.(^±›âjË¡Ë8–¹\¸Š0ÌÙk^¾9C�Åd´¨º”�19þÊÈ(	h†¶ÌêŒAÁçÐûž%GdÊäòB<N,?NkbQa/?(Ká
/NL�š˜œÔ‹ŠS£˜`¨%Äˆha€° ;32Õû$œFÉê*âz›¬~Ã9£Íæ·Å°Çå×²>‹dù+y Å	h1"WÀÓw?¬CJ@€ )Ðo»I‹ï7Eî6á‚ï6¾aÂ‘ýôŠìŒ#of†('2÷/(�Yª/õ›¤F•TOæÚ…†`ª,P´N­'æ_º“8ë'ZÙS'c)P——o½¢à50;¹ÃSìä·¿ÆAeó¡IÙ|hV¼W0ãÙ¢ÍB´\Ž¶|Ÿä!¥]yÊ/æ±“†Û�ß,›&µ—áº¶ÚæÆÛU]íXÆñvÙ¹¡gî´­)Å!|4‡Rìf9q9õ‹ôw¥qâ.æ‰!Ò
Î–q€hÄ%5`�P³îW�M%!.`Ñ—öØh�\¼î0[	ç�•sXoÂt‚ŠÊf$§1¬R=¯fƒÏRºæß„—ØØ¾kõŒV™¼©]Q¬rÛ§Oà–41¬Å�B°®ŸEÒãÇ�æ2EÑUÌpVÌð—æ�sµšçz›½ƒßÌÂÒCD‚MšH°)DYÙ�×ZÑL]b³=ˆ®ŠƒPrû6µq,¼@ZaÊ}y@}i«mýÑ¥š#>S5b;mê–¯™Y›S>h®ÄÂÄæ›\0öù«ÎÝ"Y7!ã&äÜ„ÀMH»	’ë¿Ìô‚²C3VSä'§‘#» ÒÐ®6þ»;_«×Ñˆ¯µó�ìZ:ð‚=ðD4t+¤Ê^6»Š‘}lÐUDê‚ýøi³`K]pê#	ÓÄÇy:ï‚½~#Ñ¡h�Ÿ­U
÷àw œ£C&Øç7páœç×†Šfý(+�5„I
4kZãçj±„æ"÷Qa4f{¯(’­P¦”uñP‹M	ä0¥Þi"×‡d£dpŸµ˜fý­•¿Ï¯õ3z4X¦ÖtŠ±
jqPU?\ÆÀlâV“ÞC&¸öÁÌÖ.°$Ê5U,3¹r´$;c@5&øyùŽàò�ôÔôÁÞL­=wuß„ƒÂ÷œ^/YÕìfó2ºqk˜
ejä'%› ¿óS¸¼õDÃNaaŽÀ¼’Ì©SI¼@”¤d,ÔÙ99bXÚÇõ¡}L)¥mþ6‹«�èW÷½Y•ð‰“¡&{™å¢.uy?ÊüƒoÃ‚.“¨ÔýLîÇ)í¿�1_â·ËLE[×§HTs�…=ô…9
½ê’8Ã¡™ô©èxÈp–[¢?æ{@•xPµ!Ñ›3ySo0'õ0< 6KÌˆñPï­ºk¬‘(
^Ž92ktÛ*r€ñ�\š6QÈL¢W¤&‰x…ý¨Ä´“HäÊJk0 -˜ÊI:›´&´£Ô›t-Y+SLW¼Ô¸÷iÐY½Í–xbl¨5œ•8×Ã#;éÔgPd7xZM$�IÝˆõ«‚`>•9rÕóˆ¥àšUœ…ÇgáMQœ…Dð¸*ðDð$kÁi‘M.ôæà-z*’štÁ]
V¡U¡¢
�©ÐEW¡‰à‡žV¡K*4©B—UhJ…J*4
¡­zk0CTÖ2ý3ËRú‡¸ì¸¥¤Îß•X�¿·VÔù{««ów“¯áßgy`‡	A¦Ínf·ÐeÔåA¤·–å9õ6&Çåìã˜ýŒ›½>¯8o"{ÆÈ®ŽZûvE­Ý…´\Ã'DÌ¦ÖA+§¼•s×Þó
�¨z£.ÑA´¥Zž[Ë°¬e±BzŸžœ)j2˜yp[
Y©ˆjÏ±vÁ±‡çŠs@°{ë)B•˜2£(¨ã…©ÑÉ"+CMOO^óf3®}3fØºCªA‡èÿÃé5/ø¡ýº°}£ntÞµÙK½AC«ç¥Çyº7<Õz–�þ,¿É_ÂÅùò‰M²^™òéOúé~FÉ›ä‹–ŽÑRp¤tfâ,¶&.�¯Î+ƒHMJižïÏâíÉãzgTÝšhº”Ž¿ÞÚ83Iè
‹ÔÅ©“Eêc‹ÔË"
±E”hkÃÍ.”ÈÞìep­@;‰Ë¡¿älïMHÏ¡NÆ—K%VQÊ_ý¶4¢H&}Ëbâ§”ÅDz,ø¾Ü0°½ê—
šÍ×R*hAHs<¤ÐgP¯¯^ Šü4ÙWr+&.÷ˆ|‰'TôçEþ¹yEUkQL~	ƒÓüÂ[¢;'ËåI l
„†ð]Ú'½B&dOšÔU.)“èÛÎù.>]	pûŽš…c<ÕÀ€‚öc7¥þS,Þ%†±ŒÜÏ‚¿
lAÒ–þ‰¬––S ¼ƒ&¹Lª¼Ðh}9Ú<ÚTŸÂƒÑ³ˆvTìo@ Ä`+U­A§eêjÙÍWË¼ZvG_-�ô‡/—ÿT•oœNî‹¿\Âõôõq]<X¼v?U¼T¼&Oò2HJS²Þeø¢Á¼G¦=ñZqîÝ(ÅU6-F9³4ñÏ#S“¾ÙµÙbù|iVÌLÆ ðKg
³ª£ãB]CCI`‹èøë½(ùîC°J°Yjªh•Rü[(�LL@ì8Êãc³µ‰2•��™„(iµÿK@NÎC°Ìt&KWÎˆ5žäiãM]	_¸¤aRënc¤´?=F
ø‹ çùfò–ý)>}8Íàá$’Ì9È^}¾ÁùÉ'U#k"¾ûZ¾§*\…µê*”ƒ�"‹õXVžµ`Û¯Þ¸Ø™Z—×hR5šíÕnaäDŸg²nKìÈZäà[c‹´æÝ—fÛ`È¢Œ*ZôM²T�µÝ«¤þ¶Hgâ­‡dÉevÉdØ¿ˆÛBØMíØMGì”;•2Cl%ÏÓ[¤KY[d…,²2¶ÈJCE5|å?Í»»;|åw‡¯üUØâê>éŒÓyù™z­.R°R]³5D—ÉJºÌsè{U°&X«N{ul”`½›¼aðVƒlDñskoÂôžls8�éR¦Ø2ù½[á²$CãÚü?x\-ÛDšÑÞå¤]*T1ƒÝ’Î^!I>[´r]«Ó¤¬½-ª6×é$ìŒ�v”‘Ø
ÁTY©Oc1bGn7ôu-¬¹lbÍQU}$XNÐñ»(m).iKßl�-ÜT1áç4³skjòÄ²rb>èi;IÍ Ú—E43�öñc§r�Ñ]a½ª¯Ä¼¸¶* xÞöÀs‚Ma¥‘(›`Ð¤*€Æ-Ž`º2ÏÞÕv³ý¶`³¦=žä¼=¼ïxÉ<´o¾]Ôl²˜/Q¸=hæhZ•E<¹¶j<y¯Â“÷ \�6€Ô„ˆE>-^�Ý.¥HÐðò€+£' þ�'ý‘8¨ ÂQÕòhÔW,].’W.Ã"*ý5åSlÛ¨¶Í”ÕÂ?œpÕ»ª-ÝL³|F¯yª)îš1.ÍÎ–.{ü�ë'ŒmâpTþkLlÃ€J+±›°ó²ØG„�e£<	!Éj‘¾¡lï
ÚZÿ™F\Ö.£°\"I-+Å³�9…¼R„¬ÓhËKÊX�w*†ŒÕR™ŽØ¤È¡.˜´'e�E,_¼b$ÖÃÅÊÃöÃ?ZÈOÉBBº4ý>û¨4sD6‡dYÑ5;™2¬³Û‰0B^Å±âŒXP-…H!3ï´6’ÏAÇÚÏ�çÅÒÐ%ƒê8êHç"#â™TÕ®,—xð`£!�›ŽÄyÖlîmÃˆ±Q�Ô8ç!¡­;YçEd‹6üêÚ ƒ[Úš‹¾·ÒdÒŒI&ÍÑ‘Œ ‹�˜˜›WÏi/éKO�9IÍÆeÔbF]8£>oyßÒär²)œAþ [Â­¦›I3c‰é–ÓÌhÇŒef"–GÎåF>Ã£‹^¬�‰uaC¿[d…ÄêLû•qåE»+€Aâä¯dl„(—*³›D�tf@¾sý lzÑRv0ìÂ5›‚5øwí`¨“uy) cW[�¹h¥“	îRã!ù€tÐ#†ÔCÊáé`³ˆl–‘-"²EF¶ŠÈVÙ&"Ûdd»ˆl—�¿;dd§ˆì”‘]"²KFv‹Ø†ƒÙ£‡”ae‘é
JŠCí
‹Cí%]Á«½äìi?íšîªü 8@Ì÷ˆÈ=DÈûT#Ò·äA‰Þg‚CÊèê¹‡ƒÈ›þ¸*ê¹ÃÚÉ~“¢|ï ¿�†•‹�}˜÷)#ÑGlk’'@sÌ2štËÊJ‡øir\�ý„Öù§«HÎï${¸evÃrI°ÈåÅÚ½zžQ5�J‹™àþì�æ�˜•ªz¯±\!ÕûqÝN™ë†Ýì¤:é ?`7d£åt•žÇû�…Wc‡<jP¹08­ÌìÅ• —ÅãJÆA=ç×º£~pP	»€€œÉƒhOð�ìi·é­ü	-ìufÉL¤œÑ�Õ³\Ò,jº9ÏyÈuî�É¹
àëX÷}²ÚÙ*ª=lU€î7L°
Òò^¶ìýKó9Ûû”úiïÖVIÈþeÊ$Ð¯ÎÏÏçPÁˆ¬¦Phî8Û„€dX¦£~–—é>ŽY1®aÀ0‡Œ¥ÅPï•oõGÈ€ˆŒLP½6ÅÓÄA'<ªa?K"ÐÁ£.ÙŠÝÇˆl•
Þ7–\oa”ö¸�†5žžÄ†ryNx3']RlTºþëÏ�%�„®õÈ‚uTÐºæM÷ß+žøŽ|K5Î8…»¤·¬§œë�“‡œ‹�“/8—'œ«n¡§iÒò%=¬¨{qÐÒñÖÞH_Òà—h{/)�ÀÃôÕ%PïÆÿ“~!Ö›4TñTý …÷¸MPY„O®läþri´~¤¦Êè#C °às
ì ¢Ë(ù/¡Ö¦)íšÊ±Rj<5<k
•EÚ¿VYºðà6,'XseåËŽsI%ˆKžãgƒx~ëˆ­pRÀ#ê5%MÄê÷•íšý3Y�=Ó731zfbJ<FÆuP¥²ç.'j¸ÿ"çQvB6)ÒÄ`Q“æüL±xJ%qîÉÉR™5mt>%J�£3ÅÂ˜*�/�’Î”XóQln¦huÐk%¥œŽz�oº4=7­€Š^½¤£1ò
‡îÉ ÀsŠ|Ï
;.ÈL§i'K—‡K'JW½üÜåâD.NOgl¤Êæ�B9
±4±Lçg®ë´ŠþÆB–¸C^IÎ£ë·é¹Y¡
ácb!KWäxW0ÊÅ
÷qè6l´0[€ÁÙÇ'‹3àûþÔPõÿ Ãkñ”¼VOf¼ã#bx£väCÎÛµK'yåÒäÄ(o¯ÊŽÆ(|¾4Í¡D-}vb¤0ÙW˜öÐ�ÜxI,¶X1º©ÑÂÌ™ÂµÒœ¤7=V,^ê-\c
	l
ÒÈzùaO:w°Ä¨xÇ"'ÃàËÍ›ÿ‹ó§0;3qõ<šU.ÕëšwÅ÷Ä‰ žúâ4Aõ½>ˆˆÅ@­=p¤féõ¡Jb	ÓÅ?#s3•J~ŽóÐŠžT”¯(_¢î&¶ˆn«™?„‚£aÍ·j	„8oNÉ¿Tý¤À'ÀQ×Ej²/¼û�Åì5¯Ž%�ëØ‹A2¨gÂdÐÀ"„X£Ñ¨�¹Mè6Œ#ÍÙµ:§%ûßªáÖ �“— ¯.Ž,ÍþÞü¿–‘öìŸÌÿ¹¬°Lõß‘ýþ÷¿/Ëtš‘å(pÍ‘®ìßéy¬Vrrwö¾=µ²Ìªìž!UaµÈÙ"#kxX{­‚Âº´,°>;66&#ÌÈÆì~ðÙ„ì*®ÝlæÐ–`+‡¶Û9´ƒ
C$ƒ]Án®¾'{KÏh/÷‚+º7Õ~�Û‡;äÀ9‹�.þsmf_yå>F»‡ªm7²ö½‹ª}_pØª}dQs:(6ÀË9Í^¹R’‘cÙ¿ú«¿’‘ãÙï|çdä„Yçdööí—¼ëåˆr>^À“�ÇPóEFä˜9nFN˜‘“Qs/Nè~‰ìŠ/ö¼THNj'0úªñ£Rj�ñya­JÞº	®Ý—·Þ_mÜìVíUûLð�U;ÿºj,räg­Ú/²¶½ÉYûœUûü¢Öµ;ûÍo~I®«„GB-	µÚyl‘zÓ€½é0r0ûþ�¼_FÏ.ÅÓk	>ÅïIxõŠß[ Ê¼Õn(Äm<…E­�-
vùûÆÈF«ÑÚ…Eµ¶$[#Ïó”8¹
r�èî0Ú^ü²pµf‡ã{Yä
M}t‘S¯ÓÓÛ†¨MÞãy5ÞÒÏ¿ê¥®y™+^zÜKÎxÙ/(LN�¼VñÂö–\dDÔkFô¯,pš[ÊbóX?ëæ!è"`.-L$g=RŒLh�Ídð4DjØl$›z®�|¨@-€ú¡ÑÁ6´jÈÖ"Ê� QòO\USé-Ý0
¤®f¢uy·Z=ô‡jëA½f’‘ÍŒ�ýç£âÒ«»Žú¤¢™V³ÃÇP8æ˜OÔ¹†ZX›)¿!(1Á¼äJ¦ý4Òæê ÷­~kæÔŸ½tôÐËƒŸ­rT?yÔNÕ€[1
àYÌô³É¾VÐ
lös~6˜A™±leQXfeÎÚ™«P?›2¼Š	8e¥¨Ê)^·\g�#?é'3Ÿüô>úí{Ÿ«íÃz•|íÝß;ºë¿þä6&×±Ó´t.Z-ÉzgLãþÏ.\æŠ]¦^—Q1™WgÕ÷©þU£¾Q3Y•*Z°k‚jãë™9¶�¬b>õ}v�º¸9ÐØ3$_­æ
,gÜ�¯yÜb¼µR�Ôq}Ÿ=Öº¾P¿61Ñ'C¡yˆ‘Õ¼–‘q{jõ" Zßçì
«Nhmå\e9§Ê{¨Ò>u¿£(ó^ð,½ñ>æYx©‰>¾
ÿ¾ÿ¾Ã1µZ‰é`¡ï4°Ðb%’¬ø[D^’•‘˜üÜÂ=>+‰Éï²¯I~>rNœùng¤‹£¿GÑŽ÷á�6lô€v¼/žv¬Ý÷Î7t7@Å›’÷V&ë:U:˜3Ì‡b=(ÕR}z®<«[”0®Óa2Éd“�f€äXiR#IÅ1Ëp,ð>SD»^,i�Ò7Á'DÐÓ®›¥[hôB3�’”¿L>¤Ë^oqzv\z”¾Ô3Ã$ÚñYÌ6}7‹QZ™Ç‡ax!eƒ4¯DŽâÿkÞUCIöCä)™c‘�Ô¼&(Okkõ1ae+“Ggl…�dJ2é$É*£î|{f–©¢'Q}Œþ¬ãUäjMÓMu¦#ÛÐÑª]�6Ü\áyi”TEÅj�Ÿf
^\x‹íãý0MÉ�â×„œLóMâ:~5<��êÙß¦ˆwÛ
?Åi¼e¥™Q\]¬–Í´Á¯ºÊm¡ÊKH÷¬šÊKB•—úèB¹šÊKÍÊ #—Ù³ç�ŽîÿÕAT!‡`‡i5Ü×ÑæŒg.#ñ˜$ëß×’y

¶R7ôÇ(ïØYlwAŸ¨ôP¬/ú+·…*kÐ/XyI¨²ý‚•—š•=5©�š”@E)c¥ŠÎ@}í ïÞE€0¼{Âðî]k^ÿÆ
ÿÏ	­Ï
'†°:Ûj@•R>–Š2¶DuïÈ—”~}_ÒÃˆ˜áúÐµmíu6/µ&bÆ!{S‹Ý²¯{¶J9Ã0Ùý.Þ(ËI(÷F–…Ê’_£·XEVÈ7¶m(ƒÄë
ßC²B·VLŽ¬ÀO�UÊóØO’úŽ4EIG{-UéñRˆ‰	TæA–›Z‡ÖkÅˆTëÄ#>›–ìœ.¹ÆXõ(è¥¬0RÄœþB¹->lèdlÄN7áß¼ûÓ²&�g³vo•¶(ŒabëýäÀm­F·D}êBI¶ºúp[O+§.ºâ695×í¡¹nÍu;,Gà×«Eú:¡Ú!ÅÀ¤H †Q=z‡ÜumýßX¡T;­I"êaNg—Ï¢:»�„oðè2Rö}?+7• ß¤ìef]<üµñ›,*\”|<R§ªGßo4²ÌytXøÑ¹J>:]—íÔ6g\¼dR�~]R¯Ëý8éç|¿óº”ïžíÖ»g¾ác�PóÆ»“‡"ž—Ñ�%­Öax<×ºÖ*âM%ßOçKÎSJÆN'KW¼±‰©Ñ<Hd<S˜˜„'×ŸãHY=ÊN\C•Œá9Ñ5Žv.Ë¥™ÙSsS(@¤p³Åò,¼4‹3ÏG­ajÕ9ØKì]<K“³bÊðR¼\
Œ£´Žùr´k�À¤OŠ§/Èµ !èK,™17í�BK„Úèa–zŒ|Þ–¯¦yú 
#&C
 ©ðÔÜåáâÌÀØñ¹Ùqƒ‰ËÅ3…k°�Êt4YnAS-%©A>-fƒúêÞ¥|IC„)EëÝ€Íi	Poh¦T²Twô~57ÒÝöp}_XO‰«þl9-%QÅ[20�,fr€b¡äœŸ@‰K'¹ÆO Ê¸“\ë'Ð¨Š“þ�ëÂÉõ~Bžqfr<2ÃÉð lÌÄ	m4‘½/Ðî(x‰aðXlßoÍîýÖ<x‘í¬1&{À.;Â´�8<‰qx»Y9|ÀµæñrªEe	¼I½	n«íæ&4 ¼ÙKisÞ>6{nº0Rô’Ò1ç=m’Ô)aÆÑ÷À’üØËÒ=dTþRÌÏÞþaF�Â…ÚóÈŸŠ³²Œ)Ÿ×Ù†O>¶¡ŽÅ5”†aáÌ|¤Î››%�LËÿhÀÜ)0ÀV¶7˜jz¼œÞKYÞ'�„ÑyF`—kíf�è3Ë
É#×îuí�V½Z%öt]—ÖV³X‘—
ü"²’Šª—ññý5ŠÝ˜F/jôPÍ¶Ðê¸Ïà–¡-˜	ª,ÇðÙd�ä$ak°÷Xe¹‘fê ­*õƒ±iÏ–ü`5é8ù¾\…àf�\s³þ|À®õOqr7[Ù#™¯Aÿõ�¿:l«qÐà‹)îå50¼}|>°Ag)¤$Œñ*ëWÊpú:š„?	ù^M/`©ÿ³ú�¶K±LN†¸	ýSåÙÂ”8ø†ÔöZVò[ËÎG¥uOsº>Üv’Ä%g�”³Î
ãÖ
Â‘OB‡4wØ­Ï_äW}äÉ¼>¿@mÚjdówáæQ°Ö ôzá
½Š-¶Ž£bµÎ6–@ŸÙÎ
ü{ö˜]Í
d�¨¥�oÁÈT³™‹z2j�31¶.HÉ1œ¾1ÏÆ†Mr¶5ŒÇr)²!'Wk­ëž\+'éN¬[ÙCG˜žE—s6,HÂ¾:ÊDº±è+,•=µè1uhÑ3áE¯»¹ÎòìfùÙÑ{$5ªe™Ñ‰Òéð¾³�+C[™â3æ�¾.íC§”Ý¥�ç‘ I*'ÁÊ}DPÛ¬¬2j4®ð°D þtžp‡ð'B%µç*©LÕ×ßÜ' äÕŒº<G¨88u8a–U'‡3Ì]G}`sSf*nÊmÊl»ú2ã6e–7e.´)s¼)ÅeUGàß±ŸA¦â"á|¡Ö)a!¼Šël!‚ÍÇnjÏáXõs ýš•ûunâ_Ÿ�d“éeë Û¿_‰3z2¡Åc)P«=¢dœáv÷îÜnÝlSZâ¦¿5ÛÐÃ‘zŽnÞLMQY"®eýí>lu�¢)ø§å:+õ¼û ’ð�ßÆ)ùhÐýâ™mïRÜ“‰30ªX~Eäµî×8SOÏ‹?=	4}‘ËŽr5ðÝñáû5/
f!øî¨¾µ§Ï8Úmcg€kmW­óŠƒÜ
OõÚÍ^�FØÆiòŸü0SCÔŒ²^×‘G¦]^l‰�„DÜN„9'00úòhÍ²�j}­kòk
Ø¢*ƒðyešRÝ…#é–¦Tw÷Ÿ¡ãã9 '«ïúÛöÂåè€‰ÁŸ Â/yÔÈj¢øl�¨Ÿ“Ì#>ÛöÊsý	rF!¹LnM‹Ââvèè”Í§CG'ráþí«„
¶y
ÙÄî„M§OËã,+MŸ*–Ö�q+Ç/˜ï{áUù
ï
X•'»*1pJ†à„=2¯á¤fÿ·^ÜìùÅðü£žýÞÐìGõ.‰ÅúOKÙ
¯ËÈD|à¥È10sÚ�’_	¥ðyÆ™Ðzg4ž›Œ]#|õ�(<«‘ìàe¤¼ßñÂxDZQ~Ä®«hßOº›ª·CÒÚÛ<…çC‡ý|4‚X¶‚€ÄŒ�×x	ÑÇôö%Üš�Ÿo”Ž…×g_Õ‘
ÙÄï‚NF6fŸK(ÿÃK²EOE–fÇt¤#û‡:²"ûŠŽ´gÿ•ŽìÌ~Çc!ûhÖX+Ü¢Á>Z±ý˜}`�Yc÷Ä°ÆÎUdm"“Së6#™Zâ˜Z(¨™ZÿWÔ¼ñ/2«ÄÔ²*¬,WÂ�í¬±:ðÙ¹ò8{Z�N+ÇÆŒâepš:ñ,©xù¢�‡
WÅ½Ý?5Z¼ª¸=³2A”·Ö‹`gìê¬*<Vš¹,‡9efÌ'K#àÙôÜµòlñ²œ,-�ÌEk �ˆ¢–è9ÖytFÉ¿è)PŒ™ÀŸ��„œ)>S�é¤a"…éÙ¹efí$zUV×®€.ïœTý·¬M+iÖ‚È{¦†ö¨9þ'YpÕÎ‹Ô³7Q~¨4GÞ2�O5+V˜2¤…éÑ¢jÎ1_
2œr Tì:�ÌÎ&eÛs3„¾EaŠŒ©còøäd/õ¶¯ÏgU/£’¸Çÿhzà†êVïŸ¥…È	®¥hÙ�6ªMS°€ŽË¥¥N/{%åÉK`
@Ô;é†s`˜›-ÃÚ–¦zg
EL†žAƒàÊªY‰ž­ë•‹…™‘qXž!öyê…éM“gV9"ªCc3åY°o =‰âNî/ÃF§0fcSðyˆÝE	Sb™Åž�àÐ>ÁÐº¢…B@6ÆêÀ~0í@8™°#§FÉ´ßLé²úÎ°PžM{›¥Ô2|¡/bBÒ8øp¯’MfÓß‡aJ3Žmw}BÔ<5ƒn‘Cgˆ!Š|’@55Ú*¤…ªG&'F.9&Íá˜�oaT�oÖŒÇ'fÏ‘å+Ê—ßûq¬†Á7Q8ô8cöC¥)ý©iÑl0ì®wíÅ¢ÞÐCW±+q²Ð¿\ÿÛù�ÄÙs³4P	{,‚ùŒBÙ‘W°¸äan{Œ¯à°‡`Í"ªh Æ$AøF0­‰Z§öÝÆÿÈš.x§,¶“BGÖ”ŸBV½r†Ã.Ã.ÛÉdaeDXû‚’¶—kCæÛë T«|©&±ŒýÖ´¬zê4Ûã¥KÞw]ÁAE"œ8ma”ŸS%eÓ~Æ¤ý6 NHÞ_æOl4pÇÕ:
ÈÊYl‹Ó4—…¼w°�Á­6A¾~P#áÜ„&£wÒ‡ßLI7;žÖºµ%yM«×lY¯5Þ´Z³rÞÛæØª~4J±(ÅÜfø»tÐ€W»–¥„eF‚Vo2%)©;éEöÉ„CHë”›c9Ë&‚.ñ[�mÊ�ìË¬•â×íèsÖ*ƒýHÄ”*[í'¬xSÚŽc·Èlai
lm�âR"Ö’`"XN¯¾N)…×¢=„K­—¥6 |d£;—�˜¼IvÞ3hÚ�ÞŒÍmQ0ßxs°`‰Ä½Òä(Y±MN¯P¨‰™w[á34_pÛœ­÷6Ïèg»ìØ§‰`4€¤µØÆNãû¹—;ÚaV“f¾;¯5à‚=ÚÀý^5�}4&_Žé¥ð˜öÛcª ¨q Â0ã=LU4 Ñwnÿ�:¸v†ýÝ«FzPŽ»ãcbµñìTH
‹…ýºœ[†…oÔ!ÅÖn„3%]â‹óT‰s‰ØJ^j
lÂƒu¾¤NÆB;òš!M«tGdÏðpÐ@+UMOH‚ê��e�Cx…»?„[àHØŒã«ÀÑüuÓY,$cÊ†cvóŽ“rãæ.ƒ^p"OÿžÔnòè³é´:Þ©;Fsƒé3~DY‰¤ø1ß—S¼ßùr6xU|ö§ÔÖ9nê,�àR%’R,<ð’æ—~G¸ƒãšÙÖá…N*ºŽ«Žïá=îY¼ÿÕ36U“`Àü*w×glÓ'#ÒúˆÊ§îŒ„Û˜Áf¶*¿¬�wŠŽyËå½jæÛ=¨áŠjgæ±ežÛÒ�EbWpÚ D!hÞkØœîêºú»dÅÃÎ%¹Á…_ô1"«?ps?Hl×÷xÁ´—™@”Ò×Ï®ÜèÄŒW7Y*]š›öjðAD‚¨ÿ´ö¯ÓsLX8Í7k$NC¬¯À¯
ã4A¿â€`*ŠßƒYS;y«•ü‡2Y‚ýÒh­DYöe™ü dö›¸3Q‰E%æ£¢ÏF%>l$ÖÈÄÁ®ó0Ä›¥è9>@Ïå5#ç«¯’¦Ð9L�ˆìyFd7&©ê#FóÀkc¿u6µñ„¸¯?ûª‡]òQ	BYrÃ«ˆ€Bó½Fs¶ô„LÅI<†'Ç#y‡âù&íÆï¤Æ¼Á£›¯Fé°üq£Ê¼jú~¢rß0‹¯]•…–ÎÐ³ÀžÚ<â£¦Û‚©yA=Áç¯ÕP½×N •Ê�òÁô$�·Òœž´æ´DŸ’M¨âzÉ‘<I”âÕl‡ùÍXƒ/¾·¨ËðqF6íGÅ÷ÍGEFšËÅnŸ"¿!ÁP^‹[9ï-ysE/¨‹V÷W`|.g¯wDÌOà+hŽÉ9H’'/k‹¹/bñÚì*FN‡_Y‚¾¡#+ZKcäqC´4Kílµ4gˆÈ±—ÅNÌÜTZÊýÈÍµD‚™ëmº »àôpzaÐ]Xt¢Aw¡è.TÝ…Eƒ.41t>4‚I’+a6QL†„Ép4L†+Àd¸2L†	“ˆ‰™0V0©“®ZÅ'6² LF¢a2R&#•a2òša¢&fÂdD�ÛMx†m"‘±3„Ô‘™¥Í���Q±Šæè ’l@þüo&"0õ©JL‚©³	óž	ÿ»²_Æ>ð×6†€Þ¬�å’ºdè�¡e0Å;¤@§š5¥ZØqC^R‚~ÑÞ,cõ±·‹yÃš€~œ^pïvÞ”æÕÆ/Rb’†ùp8¼çG6^ËÊýÍ¤È3;ÐÄ7°ß£®Ç—q.?x!åž|³óƒ•Aƒ³ßâ…1�¬,nCKÒ~Îã– °ÜªkÄ3Â¡å”Òð˜z7�ÝÜÆ#r=ž_’8~ZãøàøY·Q*y$•„JŠñõ²ïPdÁ¤_J}ùò±oè�¶EVC{Y±ë wŠUÉÐèP£¥Ñg{¼TÉóiôI=z�õÒÆè;=h2�¿$�1ÃM^4_°'<óí¸C
‡«¬ÆóüÔ�¸ß·qãŽÁ/û´xéD$q'my%&âŽ¤¾¦û
?\øâ Ój Tà±Ô¿’þ9©=eæåÖ~SÒ†7­±9õzè�gëSÆ�
ÕøÁAšƒ§,¶€ª�jcPZ'aõ!"`Ãž5ü$UìéA>¾
!¾s{ô·b|i<ÉRxLŠ2ð„¼Y†e`D
2p!ÅMŸ‡‘±p0:üßUJŒú‘¼³—%QRHë,?	:ëÐüŽüÀîÏÂi[Ì…*(úX½'om™²Ç³:«Þ…P½ó‘í.ß‰*–/é._’—ñÏ³Îž©rOThÔ8&ÞO7
ß+÷Ø¤5ï'Bó~L¥ô:çðË°Txˆ¥ñ“°¾�b¨¡7‡N/IÂÍr‰xBš r\º™4Æ)ÇPg¤mQiôIk-˜LKëÆ“tAŒ;mà
Ñ*¿Ï:¾
ž–Õz@­'¤ÿî@s³¾¯Ìe‡8øî�@yÈšréþ%D—ÎÙ<úº§‘Tï±Ì.‰*´mEFP×ßê�ºV£ïÒ™ Œs1}—Öá@gUÍ903‘õ’Œ¸ú®Á=¸ßP¾E­jQb§Y>…³æ‡´5oÊ1�ÊÆê˜`®‘�§0ùÂÂQá¤wŸôƒòR«%ZT‘b›iôü« ‹jÝ$˜º¤cÕ@öBÕÄÖvÛÛï?¾jÞoWœûí¿2wå-•uzóõCÿ^å¯!’bŽÌ–Jd.oþ¼Ù¤ù­=k˜àðRÔX–Ô_l{ŸF
0I¤|(�ô£yÅ„Mù>ÝúÜ%Ù^Ê,ÙÞ�%ÛËNV²u�£~†?õ#~ŠCÇÄ%Ä`{³’&Ö_ó$.Å¼Zj3³‰¹ðö°3Þð·kpÐÐI—öüŽAötÂÍyç £¤×ÄÐŸËsäªˆ¼Kyž~Þ9NVñ	µ5¯?ö+Qû»M»6E^˜œÄº~ó$­ÈµØ†<…ªû”ñš÷0súiï{1Ò°/Ð†ÿgQÙ¢�"Xˆ>Ê@²vV3^”œÔÕú5ù^ü{=$bû^ìêzdÙ‡a&Áêðäww&‹òšï|½ß)ÎÉ>È(Ò/pQ“‡6¡B%…¥íàBŠ…Þ´¾î_Ä¿’Ø@

äò%9ÈJ§”M>?¢³«ôüQ%!z¶v´AìF±·î‰“µ çþ"€ª7Ú“÷TµkiQ””2å�Ø‹nº$4eÊ2’kÓ¡«Ç]ÉÉ�(åÐP8éê`„yË(“—CCQ©®X&Ê�ZR�ŽH¤UÚó²d¾@tmx’ì(‹Žjw®†#Wr{^ ¯g¼AïÌyï¼ø{Â<á)ÑTð£dXòl!Ôj³åY
:Sð&Xf»'\Ò”ÀºÛ„®NeBÇM„¿•´iº#óñøðP~:}Ìe
Ð©¨2h53ò¬³ÏÙ“	Õ¬‰t/Ë×br]Å2õÊˆ5DÌ¤1Òª“(Ü©ÓS¸9¢pK\á–HAøe™D‘ ÆÀÂIdKüÝ`)f·«»jÙÇ³ÐÎ˜§V¹ƒoÜÍ|ãî‹5ÐA»!ªýNÕþrj­öiÞ*¯ 97Z�.Ö T	+L¼ie^iw$ƒnv:«Š®Òi9?[+�|Õ+é‰ÀÏX©¬°¬îg|Ç–¬C%çµ	*³ÆxÝA;2?Åùk£Û@ÉŸ1¡s�ÑŒPæÿ/œ¿^>{ÝqD5ÊoÚ`ƒôËªäôò8WØ(+˜3‰êaWØÔ¯Y]Ál=z7ôhd]Ô†R�ý´�kFlšÍDK‰Íßæ(*äw�ëÌ
ù+uŽÚ·[QØüñ“0
Ý£–v¨-¾“ŽÊwÅK²ÎIä�cÃnÍB�,�oD:¾”–
½`—�§cÖnås�îdï±OåKÀ“öžgUâIžt�ñ¤mˆ'ŒÃ“@œ²0=
¾áÁíø¯|¥ªßÈ&·VÂ•Â5
�šñâÈ¥~q/;•qU^EÜ»=„úLHß”å¢öS�FE#>Ñˆš2W�™�‰C¸Òêˆ4¡ÏMöHHSSº*Rª^©ü+ÔÊB¸D
Ã�bŽŠ7U\m¹E jåéÉ‰©k^$‰µç.¶0~°nñ¸‘s…¾:3´FÜPà\Yˆ;‘•j*>YIn#VI¸YÑ}ÙÕY‰:Ô1Ë¨C$áR“lAK<¤ðº3Üz}NŽ*"_�ª¢u3šªÑpx€Ì#�‘—�A-*Þ¨N×¦ðh_²F;ä-Øj|–{#/)5G	ö–ÃäuÕ4/ÛJ_ó4/|o2¢q¶6%¼„ml/É�“Œ�%Œùtq)$*<²vü»L¯Û;CX8ì ´M›‘FNé…¯æ©BX…äC‘<ÉÄ€»ƒHž&•t9RvÞƒ`Ï²["‘Ü…dÍIÏð»½ÞµT±bP²§Ù(Öm$iõÉ.†cZµ`uÛY‰ýmŸ'>H˜•%›œd±E[¾»e}BumÍlö5­6×jãÅµ:
žöÆâZkŒZ÷ÆméÈ}ÙÞJ-D;ÈnÜ¾S¤Å÷Å—!¦ü“ˆ�MäÎ¿I@†Þ$Èµ‘Ð]dàžØ;¡[®Oz-M:³ÙóÇ¼‹Qµ3é“ñe4‰qsþo1_c;Ó—Í¤+ÎÙþ„•NQÂ`7Úßr‚5ÔSøÝì®t,ø	ž!”üšŽ VQ_¨�‘ŠgÝÄJ&š^1Ë+Fiâ¬d¯ÿbÈêŽ^rdŽÝFŽÓ=Œß}uñK§7ß:ó©Ê”{�[×õ–ÎLäAÄmo ¶}üšÿ¶ÒÌÂ›¥ÒùÚÂ@e9¡Ù…Žu®&ã¦»¼Aò.Çˆ›ÄFÉÂ±Ö§wžÁ±‰0»¿�¡gõFø§1¤¬žRí·L¤	‚˜Âu…ëâ
7UG¢Â­Ñ$¥èÂ!êÌ†Ç^QxM\á•…WÆ^Qxm\áu…×ÅÞi‰d€ŸÊ=Šõ°Ù©»�ÍtùÞ¢žÃ‡ð#9Ú°Ëƒ�í�óÛ‹Wg·v ]Þù†ihâÆ«"žÄhA‚Ô€£jëg±‘8ŒáQñÓôÊ€©ã¯lØ¾©¬'Ÿ¡x®u°KSNL²qÓ¼E…|Ü›±LÎîÁ�ºtqEEç¦ÎO\.ŠÛºF´þ¶˜}´‹+³1#94²»øÍzç¼býß!DfqþØ“=Þ_Çœ¦ä^ 0®V¥îW·|Èæv`�ê«Í¼‰PÃ¾Ì
u7[$W¹4Év;Nð«²ä)ƒ:6.Ù€ö•ó$xkIÂ4EtÔÑÑú¨Žšl|¨­ÐQß’×½ð�onˆ-RŸac+æµáß%‘š¾KõµŒeâÚ`lA1ˆEs\^‰°)�5r­.güœ¼ÂéŠ“W:³XœÓÄnuPßËõz<¨ïu�&âI´Ý<‰æþ¾ªÝ8ŸÜå21|vélôPþ•ÇÉœ0-Nwðí7QÎòd‰CDQluh²øLqr§7‚ælT�þ)e]c¢Œ¥©ÃQàˆlƒ|9ž%iô!—B3Ð&GÕS£�aC,œi8$ŠîÔ‹65C•¦J³c×°Ùã1Ê*×Ê¢v1Róó&¦ž)L¢aŽt|H`áAÍLL]Ô>Ë:Ã»„4ÄîŸ/ÎLÌŠZ1WŒãRû™€Å…*½¢Ýºvž2®Õ�§ÅˆâwñE²¢>tW&~&‚¸Lzµ=^
fcèãw§PÈ(jQx™¼,[ÞÏ2s*×Ï"‚ú5Ps’ŽU~ Ôj‰/î8,—™“ñAÖ¯—/�n¸‰Rÿ*ñFgÜˆI}1/î&ºc*Q›øü¼enÚ,ÒÊDEãUwRÒõ@�1ûwÿ?‘Á6ßÏdoþ_ËH�-ýñ<F¬ŠivQ–ÍþÃ?ü*…2ÿç2d¿ùWìœÝ÷“šÛ›¦H
J½å”ÒSåÈy�›\ƒF+rA›”[Bf,j‚¥f
HN‚ée¸ÇäñOë½IêÏóNë 
Mƒ×þF,mü(:µ!˜V¶#`|Fàí½²nÛüŒc¨8a[_NpÎ[Y*®ÓXÿôÍœ¸ÂøþVê41Æ•‡Ú�¨Ÿ:d›’ívLËÖ²·³.ß¢ËÃÒ¢ì2rÅ�ëñÒåñbqðÔˆ¾´uhüQb¯IlÎFÌû×ÙÛ„-{kÎû]	sÞšã%×ZË*T�H£èwàIÅ©�”`b%´&Âkô\ù¤Ž„^SI¾àyËj†ß3a·VktÈÓo?c�¼ø7gKrÚù>øòÈ#¹e_ù	{F#díš\¼®ï—†=mø°?¿°KÚ� ?�òÓR,y™ÞØ'^Ufs6±luJo_ïù¬¾:p¤mHö.ø‰c)aÛ@2wÁw¬ÝÏê2¿Å‰í¼&–öv»)Cß¤SLÆFaÅƒ}K¾o}KúÓÚ@•ï@4‹úHÑN
Ñ4@ô¯%D—Ð
ÜÐ“0À˜R`Ìùj‡8£JØ£J£ÂãÌAãœVì}8™4.MóÐŒ½Gk™ó¢{Ñ@4îC¿úû°fáû0·ð}Xº3x!dü}füœ¾3~mô}˜ÅŠYQQÝ‡YQQÝ‡YQQÝ‡ñ5^Gãô>j·A¤¾Ý0vO_ŠÊˆäz7¹o¿ºÐ}Xoß‡,>lœJ—µ›¢ãŸg�¼×s¥\¯+·¥+ÕYÈˆ¾/‹w#‰ü-¤¤ø.]Øeš}aßé½ç¥Ò7°qÐ¸#ü ú˜T‰$kåÚ¡�,P •ã…PK™¾
s¢3!ÅÇ´bþd—-m¹ì/ðø,¿6ÔFSæ¡j!½M§çx;öÜì}_$®ŸV¬�ÈGõuvœ`en‘/îJ#"ÑµW¤9Œ,ƒå”‘NZ^yFv7>¶êA¤‘K±ßäŠhÇtÚoæ¶J‡IkØî¹ZïE7¸�éÝH7¸Ï¥\š˜*o?QšEið5I¨pãC^sÅÊz\6d'˜¡DxŒ)Im8r¶p‘Û™¥÷þ0F‡.�°dòÝöÚÂ”Â7Ôö#Iét²°FÈrT hX9¥äà}g•…Z(€VóêÑL¨è¨h<VíÆjRë0o¬µ¸±Gn¬A±%ÔæúL*Ýøqb{ìæ2Êë
Æ	,ÜÎ¶˜Õ¿˜(-3ËîB ù{(%fW±‘‡Š³3#e¯46V.Bùa+y²86ëÍ
Œd[&7¥Ü‡]ç�)
Îk° J�j"‘ç°¦«q¯<^-]ÑyFí¼NÂt¶�ä
£áU£ewéa”ïÐÈlP˜ÚZœ»í^•zÃ¾aÊÌ˜ßp6d¿5Èksn^�Ê«]èÛ¯5¼LÙh¡¢õªhƒ£ßøAî·Q¿A€^Ji¬µÞ­L
šÅMÖ"~­â×æ'Ñ
ÖI@ê�yª((ƒ+oqâ­N¼ÍˆQ¯ƒXÓ©
Ê¬ÛRCjHièÖ/‰¥
íUeƒÿòlíˆ:[½ 3XÎ§l—R [¬äPw°ŠC«ƒ5Z¬ãÐú`‡6›lu0Òeì‘èÐfG[,‡Ù[â²I>j«Î®òlß¦Îö#|¶“»�#‘g;�ã·“	çs"Aðïï€š7~�Ø{ÀC%Ï¨¤Oyãè'n÷x7n8€O‹Ö žul*ÊºÁX�„{ÃÔ8
:{c…ÉrqnšþEçÔ>B	ºSúD™øË³3sPþÁ²PE1U–ä¡^“�«8ÞA8BqÀ3…Ñ	‡ro0ÌCv³� €rí|Ï\[×Š<Ð�?Ä¨hÕûn;Óï;ù;Kcž¯åŽ KŒ#}SDZúîŒÁóœ+c§[¨ÆõD];hX�®³¯‹$š›¹â%Ç½?nƒs¢^¾ÈÓZ>¶Ò|}=HFÚdl$ÏtHñÅIkã£­
"ÏúY‘MYŠ,…Èwsi‡È?«¡È2ˆLÖS¤"�Mé„ÈŽVqµµáCVïw’·Vy(á�½}û%¶”4…kÁrN]§,EVˆ¬ð²BÌ�õ»½`¥*�}þÌÏÏ{Ù={öÐzœ1èH’ÜÕ‚bŠƒvãËµiñp·*GôŸÓý¯µúGh|ï{ßÓ•õˆP‡Cá1ø±cHÆŽ!1†VÃ;Ü‡ç¥<9.Ia£)$î&ÛM*¶›T…nþæoþFu“­¦1Ý€N\âÖöŠ»W¯`ìnÃÚ?þñ�½ì¿ûw¯T±ÛZiÑŸ\ÅV¿÷½Ï[pÿ´Rúc´ZÕŠµR»ôg±ëÐJSu+èþ—Æ;q6DÀå'?ùÉOïÛóÛíáwu‡û0æx7œâÞä½Ž3ø§t6ˆåh£a¾‘Ãîú;t­í~= �Øú?‹×Ãðç×Zµ»w¶F]kßùÎ·«½Öäð~øÃVy{ETþîwÿC•—T\Ï‹¼¤Ät_ÌëíŸß3?¿gîàÇŠ˜Ýù±þËÌÏwïÏwï?J,©Îÿ9–„°æ-ñÿï­¯çùsL¬Ú/äÞÏ&Æ’"ÝL0Ýœ8e¹f3Éûü»V
­CUš´yPb™=ëƒ4‡¢ÔóÒyÅÍIshSÐÃÂ›ÝÞÃJÝRäcKä§6²UqrŽb¯’“s4ž“c±êÿy+Ô¼±.õ`eNN$¿Ù7Ä‘A[wÊçg,Þå‚+Na²8S-›ÞäÈ“n‹Ëf�eh;iý—ÁáTiªâ³GðÖCÌtê«0âÎ›IŽ4ƒÉæ"Î«‹PgI1=úÂ,÷Œò<Ks³�k0º"¹L³âÿoXü?)
”¦ÉïÄts¹85Ç­�”.—ò¥©ûGaýÀMí©‰ÉIjZ+N�bÂkcZÍ¨­B®i«ab…%'là:€
‰9&ÇË–(—&'"Ta~Fy`¯4þy`i[ZÂöPº^ÉLˆC-Èá±æšÂÈ*ÎV
ÕdíosíZ-Ð°M[7Ý·*‘=Q˜ºCAÆ�ÈÂ0ê
SwfÊÝ
ØßïÖzHkšèLn&Q«ŠµÒ­EÂRãˆ3Á×_ì’|ø“	^.aó²Kó¬F“òüM¸ÕSE’,œ˜‰´VÈ9r'‡©d©MòXšÁ‚y­Ïf|œjVÜjËò,#Z+ËªÐÄŠ�$+ÚÊö·—‡ZnÀ–Ü–—cË
< ®PµzSYWëÊ³³”vªÕ™¢ÍºÚŠ¼‚N€ ±S­«ÕºÕVæYt«u‡ªÕ˜DºZwžåÆ�}š–û´6ÂJO"XÅ»ÛN]Í,];u�@~ÐkÄÚÔ€Zˆ—Ù÷Ìßd(i�t„†ãX+~ëÅ–ˆû
~½xwÔùµÒ%ÉÄ;‡knŒ¯Y/êÖ¡Œ¹Uó®Ù õbÐó®	¬FDÁDYö©§žbœ–oµ ¼”Â`±í¡§šFÉŒ&ð�ýT“
Ú/ršLÎY=ŽŒV|ù&.Mèp»SØl]R6«¯mÌ8ü ñMl\!Ô8§”]8|Z
³%qk�¶`Â(ØJÿ’ÍÛõ€ð¤ƒÎîØ
õ@Ç>uì/¢ã*V²;¼’¿ýÛ¿o§?°z'd›¥§ê}Q«½ÇX/ÑQ’:JVÕÑ"ÖueŠÖu®ëŸ{·–{ÁÎì_‹^©û«W¯zÙW^y%æzæ€ž4ÔÁL1a¹ž¬tü„S•úÐWg²	/îMJÞ–¤	ïÂ	 úX©bó5§'""7–ïÌ²ÓhÎl jºû»Ø™ý;¯ÒùÒb¶\5ü;äñRuecT�Æâ™Ó2vbÊ‹{ïÓÂ|”]íÖ×Îó¨h“•«³§£ŠŒOeÀFVjÀÄo	£´}
îl×WT{~@"10¦aN`Ç½YáRÎ¹›U:ÙÏù¹Š�ó}¾|Çg¼š/7²ËFv{Ù‘=^fd¯—Ùçù#û½óÉê/{ò�œsàMý1—Ã2>ó¬Z„.œêÍyÍ­Y›ÀXV*<×JC[6–q†–4‡Vý>1]–í¡}—ï»¬&šU;>?ÔjÔñ�Œ¥[:é…¾º·ŸìW¤³Béì¾(îÁ¿ñï!I:Ã÷Hpo}‹ÜM];¬¨kGâ©k^p48ÆÔµ•Áq%g}bàÖƒZoúxéÕÁûuð”×Aí¯Lñ$»_ŸA§.ÓG¸utod‹±¬oE±]ôÏn‚t@-!ð´Ä0ýn¿¤öGÂyqÀ€ØpA;¼[«<Ï6æ"ÔtÝZíEpp"’ð×%¦âÍ ÍFRq¡—Ó¢H§'îÕ‹RëŸºV«ªµ³¢ÈJÐ>ðl%Z(¤šË<OG«jõ¼(Òí‰‹Ê3­|[Æ¹ºÄ5g›ëªªå1Qd•'�oaƒi]·Öy1ÖÐªê+/Š¬'�¤µ³.˜ž™P5dÖHÈŒ”¦fgJ“åíç&.OOIRŸ c¥TÕòý¢ÈZïV³±’Ljì‚)p¸ª¦E‘õr�Ñú]°eŒxÕ[wƒw«Íž¼šöÙbõË³ÌƒÝi�²—èßeúT¬ª6ÿ_Qd�w£×Ë	>¤&'iòš€
“¿’,ËÉödÜ%&µIéÔáˆÌ¤tN‚Çš™Éâ~^,'×ÄˆW1ãc¢Àÿâªÿþÿÿþÿÿþÿ	ÿþÿiconÿþÿÿþÿiconöƒFôÈÿ¾L“ì¡sÎ¶ÿþÿÿþÿlabelÿþÿButtonÿþÿlabelE»b[cF•EÀ\G½ŒÿþÿÿþÿlabelPlacementÿþÿleftÿþÿrightÿþÿtopÿþÿbottomÿþÿlabelPlacementå•¢T åIŸÄß^æãD©ÿþÿÿþÿselectedÿþÿfalseÿþÿselectedî/Ï?ëZJ�ñ…ƒ|úìgÿþÿÿþÿtoggleÿþÿfalseÿþÿtoggleg¿¥íY˜D¾ê±Ìœ²ÿþÿÿþÿenabledÿþÿtrueÿþÿenabled!º—À­RG¸5S8ìêbmÿþÿOtherÿþÿvisibleÿþÿtrueÿþÿvisibleD*Lc³XTC¦$úv±¢ÿþÿOtherÿþÿ	minHeightÿþÿ0ÿþÿ	minHeightÃP¬»¸K¨‰u@•&ÓjÿþÿSizeÿþÿminWidthÿþÿ0ÿþÿminWidth!7“C2«I”»¼ú l/›ÿþÿSizeÿþÿÿý)<?xml version="1.0" encoding ="utf-8"?>

<componentPackage xmlns="http://www.macromedia.com/flash/swccatalog/7">

<component id="Button" class="mx.controls.Button" implementation="Button.swf" iconFile="Button.png" tooltip="Button" src="mx.controls.Button.asi" modified="1059073889">

<movieBounds xmin="0" xmax="2000" ymin="0" ymax="440" />

    <include id="BoundingBox"/>

    <include id="SimpleButton"/>

    <include id="Border"/>

    <include id="RectBorder"/>

    <include id="ButtonSkin"/>

    <exportAfter id="__Packages.mx.controls.Button"/>

<class id="mx.controls.Button" >

      <Event param1="click" />

      <TagName param1="Button" />

      <IconFile param1="Button.png" />

   <property id="_inherited_selected" type="Boolean" >

      <Bindable />

      <ChangeEvent param1="click" />

   </property>

   <method id="icon" >

      <param id="linkage"  />

      <Inspectable defaultValue="" />

   </method>

   <method id="label" >

      <param id="lbl" type="String" />

      <Inspectable defaultValue="Button" />

   </method>

   <method id="labelPlacement" >

      <param id="val" type="String" />

      <Inspectable enumeration="left,right,top,bottom" defaultValue="right" />

   </method>

</class>

<class id="mx.controls.SimpleButton" >

      <Event param1="click" />

      <TagName param1="SimpleButton" />

   <method id="selected" returnType="Boolean">

      <Inspectable defaultValue="false" />

   </method>

   <method id="toggle" returnType="Boolean">

      <Inspectable defaultValue="false" />

   </method>

</class>

<class id="mx.core.UIComponent" >

      <Event param1="focusIn" />

      <Event param1="focusOut" />

      <Event param1="keyDown" />

      <Event param1="keyUp" />

   <property id="enabled" type="Boolean" >

      <Inspectable defaultValue="true" verbose="1" category="Other" />

   </property>

</class>

<class id="mx.core.UIObject" >

      <Event param1="resize" />

      <Event param1="move" />

      <Event param1="draw" />

      <Event param1="load" />

      <Event param1="unload" />

   <method id="minHeight" returnType="Number">

      <Inspectable defaultValue="0" verbose="1" category="Size" />

   </method>

   <method id="minWidth" returnType="Number">

      <Inspectable defaultValue="0" verbose="1" category="Size" />

   </method>

   <method id="visible" returnType="Boolean">

      <Inspectable defaultValue="true" verbose="1" category="Other" />

   </method>

</class>

<asset id="BoundingBox" modified="1054593655">

</asset>

<asset id="UIComponentExtensions" modified="1058814666">

      <exportAfter id="__Packages.mx.core.ext.UIComponentExtensions"/>

</asset>

<asset id="FocusRect" modified="1055744819">

      <include id="BoundingBox"/>

      <exportAfter id="__Packages.mx.skins.halo.FocusRect"/>

</asset>

<asset id="FocusManager" modified="1055744781">

      <include id="FocusRect"/>

      <include id="UIObject"/>

      <exportAfter id="__Packages.mx.managers.FocusManager"/>

</asset>

<asset id="UIObjectExtensions" modified="1058814702">

      <exportAfter id="__Packages.mx.core.ext.UIObjectExtensions"/>

</asset>

<asset id="Defaults" modified="1055737279">

      <exportAfter id="__Packages.mx.skins.halo.Defaults"/>

</asset>

<asset id="UIObject" modified="1058814731">

      <include id="Defaults"/>

      <include id="UIObjectExtensions"/>

      <exportAfter id="__Packages.mx.core.UIObject"/>

</asset>

<asset id="UIComponent" modified="1058814700">

      <include id="UIObject"/>

      <include id="FocusManager"/>

      <include id="UIComponentExtensions"/>

      <exportAfter id="__Packages.mx.core.UIComponent"/>

</asset>

<asset id="SimpleButtonUp" modified="1062225026">

      <include id="BrdrBlk"/>

      <include id="BrdrFace"/>

      <include id="BrdrShdw"/>

      <include id="BrdrHilght"/>

      <include id="BrdrFace"/>

</asset>

<asset id="BrdrHilght" modified="1052770908">

</asset>

<asset id="BrdrBlk" modified="1052770913">

</asset>

<asset id="SimpleButtonIn" modified="1062225020">

      <include id="BrdrBlk"/>

      <include id="BrdrHilght"/>

      <include id="BrdrShdw"/>

      <include id="BrdrFace"/>

</asset>

<asset id="BrdrFace" modified="1051767541">

</asset>

<asset id="BrdrShdw" modified="1058931521">

</asset>

<asset id="SimpleButtonDown" modified="1062225019">

      <include id="BrdrShdw"/>

      <include id="BrdrFace"/>

</asset>

<asset id="SimpleButton" modified="1055744781">

      <include id="BoundingBox"/>

      <include id="SimpleButtonDown"/>

      <include id="SimpleButtonIn"/>

      <include id="SimpleButtonUp"/>

      <include id="UIComponent"/>

      <exportAfter id="__Packages.mx.controls.SimpleButton"/>

</asset>

<asset id="Border" modified="1062224872">

      <include id="UIObject"/>

      <exportAfter id="__Packages.mx.skins.Border"/>

</asset>

<asset id="RectBorder" modified="1062224887">

      <include id="Border"/>

      <exportAfter id="__Packages.mx.skins.halo.RectBorder"/>

</asset>

<asset id="ButtonSkin" modified="1062224893">

      <exportAfter id="__Packages.mx.skins.halo.ButtonSkin"/>

</asset>

<asset id="__Packages.mx.skins.ColoredSkinElement" src="mx.skins.ColoredSkinElement.asi" modified="1062582563">

</asset>

<asset id="__Packages.mx.core.UIObject" src="mx.core.UIObject.asi" modified="1062582563">

    <include id="__Packages.mx.skins.SkinElement" />

    <include id="__Packages.mx.styles.CSSStyleDeclaration" />

    <include id="__Packages.mx.styles.StyleManager" />

</asset>

<asset id="__Packages.mx.skins.SkinElement" src="mx.skins.SkinElement.asi" modified="1062582564">

</asset>

<asset id="__Packages.mx.styles.CSSTextStyles" src="mx.styles.CSSTextStyles.asi" modified="1062582564">

</asset>

<asset id="__Packages.mx.styles.CSSStyleDeclaration" src="mx.styles.CSSStyleDeclaration.asi" modified="1062582564">

    <include id="__Packages.mx.styles.StyleManager" />

    <exportAfter id="__Packages.mx.styles.CSSTextStyles" />

</asset>

<asset id="__Packages.mx.styles.StyleManager" src="mx.styles.StyleManager.asi" modified="1062582564">

</asset>

<asset id="__Packages.mx.core.UIComponent" src="mx.core.UIComponent.asi" modified="1062582563">

    <exportAfter id="__Packages.mx.core.UIObject" />

</asset>

<asset id="__Packages.mx.controls.SimpleButton" src="mx.controls.SimpleButton.asi" modified="1061503691">

    <exportAfter id="__Packages.mx.core.UIComponent" />

</asset>

<asset id="__Packages.mx.controls.Button" src="mx.controls.Button.asi" modified="1061503690">

    <exportAfter id="__Packages.mx.controls.SimpleButton" />

    <exportAfter id="__Packages.mx.core.UIObject" />

</asset>

<asset id="__Packages.mx.events.EventDispatcher" src="mx.events.EventDispatcher.asi" modified="1062582563">

</asset>

<asset id="__Packages.mx.events.UIEventDispatcher" src="mx.events.UIEventDispatcher.asi" modified="1062582563">

    <exportAfter id="__Packages.mx.events.EventDispatcher" />

</asset>

<asset id="__Packages.mx.core.ext.UIObjectExtensions" src="mx.core.ext.UIObjectExtensions.asi" modified="1062582563">

    <include id="__Packages.mx.skins.ColoredSkinElement" />

    <include id="__Packages.mx.styles.CSSStyleDeclaration" />

    <exportAfter id="__Packages.mx.core.UIObject" />

    <exportAfter id="__Packages.mx.skins.SkinElement" />

    <exportAfter id="__Packages.mx.styles.CSSTextStyles" />

    <exportAfter id="__Packages.mx.events.UIEventDispatcher" />

</asset>

<asset id="__Packages.mx.skins.halo.Defaults" src="mx.skins.halo.Defaults.asi" modified="1062582564">

    <include id="__Packages.mx.core.UIComponent" />

    <exportAfter id="__Packages.mx.core.UIObject" />

    <exportAfter id="__Packages.mx.styles.CSSStyleDeclaration" />

    <exportAfter id="__Packages.mx.core.ext.UIObjectExtensions" />

</asset>

<asset id="__Packages.mx.skins.halo.FocusRect" src="mx.skins.halo.FocusRect.asi" modified="1062582564">

    <include id="__Packages.mx.managers.DepthManager" />

    <exportAfter id="__Packages.mx.core.UIComponent" />

    <exportAfter id="__Packages.mx.skins.SkinElement" />

    <exportAfter id="__Packages.mx.skins.halo.Defaults" />

</asset>

<asset id="__Packages.mx.managers.DepthManager" src="mx.managers.DepthManager.asi" modified="1062582563">

    <include id="__Packages.mx.core.UIObject" />

</asset>

<asset id="__Packages.mx.managers.FocusManager" src="mx.managers.FocusManager.asi" modified="1062726409">

    <include id="__Packages.mx.controls.SimpleButton" />

    <include id="__Packages.mx.managers.DepthManager" />

    <include id="__Packages.mx.managers.SystemManager" />

    <exportAfter id="__Packages.mx.core.UIComponent" />

    <exportAfter id="__Packages.mx.core.ext.UIObjectExtensions" />

</asset>

<asset id="__Packages.mx.managers.SystemManager" src="mx.managers.SystemManager.asi" modified="1062582563">

    <include id="__Packages.mx.core.UIComponent" />

    <include id="__Packages.mx.events.EventDispatcher" />

</asset>

<asset id="__Packages.mx.managers.OverlappedWindows" src="mx.managers.OverlappedWindows.asi" modified="1062582563">

    <include id="__Packages.mx.core.UIComponent" />

    <exportAfter id="__Packages.mx.managers.SystemManager" />

</asset>

<asset id="__Packages.mx.core.ext.UIComponentExtensions" src="mx.core.ext.UIComponentExtensions.asi" modified="1062582563">

    <include id="__Packages.mx.styles.CSSSetStyle" />

    <exportAfter id="__Packages.mx.core.UIComponent" />

    <exportAfter id="__Packages.mx.managers.FocusManager" />

    <exportAfter id="__Packages.mx.managers.OverlappedWindows" />

</asset>

<asset id="__Packages.mx.styles.CSSSetStyle" src="mx.styles.CSSSetStyle.asi" modified="1062582564">

    <include id="__Packages.mx.styles.StyleManager" />

    <exportAfter id="__Packages.mx.styles.CSSStyleDeclaration" />

</asset>

<asset id="__Packages.mx.skins.Border" src="mx.skins.Border.asi" modified="1062582563">

    <exportAfter id="__Packages.mx.core.UIObject" />

</asset>

<asset id="__Packages.mx.skins.RectBorder" src="mx.skins.RectBorder.asi" modified="1062582564">

    <exportAfter id="__Packages.mx.skins.Border" />

</asset>

<asset id="__Packages.mx.skins.halo.ButtonSkin" src="mx.skins.halo.ButtonSkin.asi" modified="1062582563">

    <exportAfter id="__Packages.mx.core.ext.UIObjectExtensions" />

    <exportAfter id="__Packages.mx.skins.RectBorder" />

</asset>

<asset id="__Packages.mx.skins.halo.RectBorder" src="mx.skins.halo.RectBorder.asi" modified="1062582564">

    <include id="__Packages.mx.styles.CSSStyleDeclaration" />

    <exportAfter id="__Packages.mx.core.ext.UIObjectExtensions" />

    <exportAfter id="__Packages.mx.skins.RectBorder" />

</asset>

</component>

</componentPackage>

Media 1ÿþÿBitmap 1ÿþÿ
Button.png·Ô±C·Ô±Cÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿ2Hxií’Ñ	@!EÛéíäNw'w*¯ øQa}Æ$K=™ÙÚÛÒEäFsW<_µ,)�œCQj>˜QYÅ§œïZqªuDÜŠSyK0þzöÏÏúÀÏÃ_Y?AžŽ÷7šÆðIsQŸ$ÅÿþÿButtonÐ¸ÿþÿButtonÿþÿ
Button.swf	ëW?+ÿþÿBorderÿþÿBorderÿþÿ
Button.swfèCP?ÿþÿUIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.skins.Borderÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿBoundingBoxÿþÿBoundingBoxÿþÿ
Button.swfwÒÛ>ÿþÿÿþÿÿþÿBrdrBlkÿþÿBrdrBlkÿþÿ
Button.swfaÀ>ÿþÿÿþÿÿþÿBrdrFaceÿþÿBrdrFaceÿþÿ
Button.swfõ²°>ÿþÿÿþÿÿþÿ
BrdrHilghtÿþÿ
BrdrHilghtÿþÿ
Button.swf\À>ÿþÿÿþÿÿþÿBrdrShdwÿþÿBrdrShdwÿþÿ
Button.swfA?ÿþÿÿþÿÿþÿ
ButtonSkinÿþÿ
ButtonSkinÿþÿ
Button.swfýCP?ÿþÿ#__Packages.mx.skins.halo.ButtonSkinÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿDefaultsÿþÿDefaultsÿþÿ
Button.swf¿Eí>‚ýÿÿÿƒ„…†‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿÿþÿ!__Packages.mx.skins.halo.Defaultsÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿFocusManagerÿþÿFocusManagerÿþÿ
Button.swf
cí>ÿþÿ	FocusRectÿþÿ
Button.swfÿþÿÿþÿÿþÿUIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿ#__Packages.mx.managers.FocusManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿ	FocusRectÿþÿ	FocusRectÿþÿ
Button.swf3cí>ÿþÿBoundingBoxÿþÿ
Button.swfÿþÿÿþÿÿþÿ"__Packages.mx.skins.halo.FocusRectÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿ
RectBorderÿþÿ
RectBorderÿþÿ
Button.swf÷CP?ÿþÿBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿ#__Packages.mx.skins.halo.RectBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿSimpleButtonÿþÿSimpleButtonÿþÿ
Button.swf
cí>ÿþÿBoundingBoxÿþÿ
Button.swfÿþÿÿþÿÿþÿSimpleButtonDownÿþÿ
Button.swfÿþÿÿþÿÿþÿSimpleButtonInÿþÿ
Button.swfÿþÿÿþÿÿþÿSimpleButtonUpÿþÿ
Button.swfÿþÿÿþÿÿþÿUIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ#__Packages.mx.controls.SimpleButtonÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿSimpleButtonDownÿþÿSimpleButtonDownÿþÿ
Button.swf{DP?ÿþÿBrdrShdwÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrFaceÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿSimpleButtonInÿþÿSimpleButtonInÿþÿ
Button.swf|DP?ÿþÿBrdrBlkÿþÿ
Button.swfÿþÿÿþÿÿþÿ
BrdrHilghtÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrShdwÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrFaceÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿSimpleButtonUpÿþÿSimpleButtonUpÿþÿ
Button.swf‚DP?ÿþÿBrdrBlkÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrFaceÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrShdwÿþÿ
Button.swfÿþÿÿþÿÿþÿ
BrdrHilghtÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrFaceÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿUIComponentÿþÿUIComponentÿþÿ
Button.swfì:?ÿþÿUIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿFocusManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿUIComponentExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿUIComponentExtensionsÿþÿUIComponentExtensionsÿþÿ
Button.swfÊ:?ÿþÿ,__Packages.mx.core.ext.UIComponentExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿUIObjectÿþÿUIObjectÿþÿ
Button.swf;?ÿþÿDefaultsÿþÿ
Button.swfÿþÿÿþÿÿþÿUIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿUIObjectExtensionsÿþÿUIObjectExtensionsÿþÿ
Button.swfî:?ÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿ__Packages.mx.controls.Buttonÿþÿ__Packages.mx.controls.Buttonÿþÿ
Button.swfÊBE?ÿþÿ#__Packages.mx.controls.SimpleButtonÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.controls.Buttonÿþÿÿqimport mx.core.UIObject;

import mx.controls.SimpleButton;

import mx.core.UIComponent;



[Event("click")] 

[TagName("Button")] 

[IconFile("Button.png")] 

intrinsic class mx.controls.Button extends mx.controls.SimpleButton

{

   public function Button();

   public var __get__icon:Function;

   public var __get__label:Function;

   public var __get__labelPlacement:Function;

   public var __label:String;

   public var __labelPlacement:String;

   public var _color;

   public function _getIcon(Void):String;

   public var _iconLinkageName:String;

   [Bindable] [ChangeEvent("click")] public var _inherited_selected:Boolean;

   public function _setIcon(linkage):Void;

   public var borderW:Number;

   public var btnOffset:Number;

   public function calcSize(tag:Number, ref:Object):Void;

   public var centerContent:Boolean;

   public var className:String;

   public var clipParameters:Object;

   public function createChildren(Void):Void;

   public function draw();

   public var falseDisabledIcon:String;

   public var falseDisabledSkin:String;

   public var falseDownIcon:String;

   public var falseDownSkin:String;

   public var falseOverIcon:String;

   public var falseOverSkin:String;

   public var falseUpIcon:String;

   public var falseUpSkin:String;

   public function getBtnOffset(Void):Number;

   public function getLabel(Void):String;

   public function getLabelPlacement(Void):String;

   public var hitArea_mc:MovieClip;

   function get icon():String;

   [Inspectable(defaultValue="")] function set icon(linkage);

   public function init(Void):Void;

   public var initIcon;

   public function invalidateStyle(c:String):Void;

   [Inspectable(defaultValue="Button")] function set label(lbl:String);

   function get label():String;

   public var labelPath:Object;

   [Inspectable(enumeration="left,right,top,bottom"defaultValue="right")] function set labelPlacement(val:String);

   function get labelPlacement():String;

   static var mergedClipParameters:Boolean;

   public function onRelease(Void):Void;

   public function setColor(c:Number):Void;

   public function setEnabled(enable:Boolean):Void;

   public function setHitArea(w:Number, h:Number);

   public function setLabel(label:String):Void;

   public function setLabelPlacement(val:String):Void;

   public function setSkin(tag:Number, linkageName:String, initobj:Object):MovieClip;

   public function setView(offset:Number):Void;

   public function size(Void):Void;

   static var symbolName:String;

   static var symbolOwner;

   public var trueDisabledIcon:String;

   public var trueDisabledSkin:String;

   public var trueDownIcon:String;

   public var trueDownSkin:String;

   public var trueOverIcon:String;

   public var trueOverSkin:String;

   public var trueUpIcon:String;

   public var trueUpSkin:String;

   static var version:String;

   public function viewSkin(varName:String):Void;

};

ÿþÿ#__Packages.mx.controls.SimpleButtonÿþÿ#__Packages.mx.controls.SimpleButtonÿþÿ
Button.swfËBE?ÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.controls.SimpleButtonÿþÿÿimport mx.core.UIComponent;



[Event("click")] 

[TagName("SimpleButton")] 

intrinsic class mx.controls.SimpleButton extends mx.core.UIComponent

{

   public function SimpleButton();

   public var __emphasized:Boolean;

   public var __emphatic:Boolean;

   public var __emphaticStyleName:String;

   public var __get__emphasized:Function;

   public var __get__selected:Function;

   public var __get__toggle:Function;

   public var __get__value:Function;

   public var __state:Boolean;

   public var __toggle:Boolean;

   public var autoRepeat:Boolean;

   public var boundingBox_mc:MovieClip;

   public var btnOffset:Number;

   public var buttonDownHandler:Function;

   public function calcSize(Void):Void;

   public function changeIcon(tag:Number, linkageName:String):Void;

   public function changeSkin(tag:Number, linkageName:String):Void;

   public var className:String;

   public var clickHandler:Function;

   public function createChildren(Void):Void;

   public var detail:Number;

   public var dfi;

   public var dfs;

   public var disabledIcon:Object;

   public var disabledSkin:Object;

   public var downIcon:Object;

   public var downSkin:Object;

   public function draw(Void):Void;

   public var dti;

   public var dts;

   function get emphasized():Boolean;

   function set emphasized(val:Boolean);

   static var emphasizedStyleDeclaration;

   static var falseDisabled:Number;

   public var falseDisabledIcon:String;

   public var falseDisabledIconEmphasized:String;

   public var falseDisabledSkin:String;

   public var falseDisabledSkinEmphasized:String;

   static var falseDown:Number;

   public var falseDownIcon:String;

   public var falseDownIconEmphasized:String;

   public var falseDownSkin:String;

   public var falseDownSkinEmphasized:String;

   static var falseOver:Number;

   public var falseOverIcon:String;

   public var falseOverIconEmphasized:String;

   public var falseOverSkin:String;

   public var falseOverSkinEmphasized:String;

   static var falseUp:Number;

   public var falseUpIcon:String;

   public var falseUpIconEmphasized:String;

   public var falseUpSkin:String;

   public var falseUpSkinEmphasized:String;

   public var fdi;

   public var fds;

   public var fri;

   public var frs;

   public var fui;

   public var fus;

   public function getLabel(Void):String;

   public function getSelected():Boolean;

   public function getState(Void):Boolean;

   public function getToggle(Void):Boolean;

   public var iconName:Object;

   public var idNames;

   public function init(Void):Void;

   public var initializing:Boolean;

   public var interval;

   public function keyDown(e:Object):Void;

   public function keyUp(e:Object):Void;

   public var linkLength:Number;

   public function onDragOut(Void):Void;

   public function onDragOver(Void):Void;

   public function onKillFocus(newFocus:Object):Void;

   public function onPress(Void):Void;

   public function onPressDelay(Void):Void;

   public function onPressRepeat(Void):Void;

   public function onRelease(Void):Void;

   public function onReleaseOutside(Void):Void;

   public function onRollOut(Void):Void;

   public function onRollOver(Void):Void;

   public var phase:String;

   public var preset:Boolean;

   public var refNames;

   public function refresh(Void):Void;

   public function removeIcons();

   public var rolloverIcon:Object;

   public var rolloverSkin:Object;

   function set selected(val:Boolean);

   [Inspectable(defaultValue=false)] function get selected():Boolean;

   public function setEnabled(val:Boolean):Void;

   public function setIcon(tag:Number, linkageName:String):Object;

   public function setLabel(val:String):Void;

   public function setSelected(val:Boolean);

   public function setSkin(tag:Number, linkageName:String, initobj:Object):MovieClip;

   public function setState(state:Boolean):Void;

   public function setStateVar(state:Boolean):Void;

   public function setToggle(val:Boolean);

   public function setView(offset:Boolean):Void;

   public function showEmphasized(e:Boolean):Void;

   public function size(Void):Void;

   public var skinName:Object;

   public var stateNames;

   public var style3dInset:Number;

   static var symbolName:String;

   static var symbolOwner:Object;

   public var tagMap;

   public var tdi;

   public var tds;

   function set toggle(val:Boolean);

   [Inspectable(defaultValue=false)] function get toggle():Boolean;

   public var tri;

   public var trs;

   static var trueDisabled:Number;

   public var trueDisabledIcon:String;

   public var trueDisabledIconEmphasized:String;

   public var trueDisabledSkin:String;

   public var trueDisabledSkinEmphasized:String;

   static var trueDown:Number;

   public var trueDownIcon:String;

   public var trueDownIconEmphasized:String;

   public var trueDownSkin:String;

   public var trueDownSkinEmphasized:String;

   static var trueOver:Number;

   public var trueOverIcon:String;

   public var trueOverIconEmphasized:String;

   public var trueOverSkin:String;

   public var trueOverSkinEmphasized:String;

   static var trueUp:Number;

   public var trueUpIcon:String;

   public var trueUpIconEmphasized:String;

   public var trueUpSkin:String;

   public var trueUpSkinEmphasized:String;

   public var tui;

   public var tus;

   public var upIcon:Object;

   public var upSkin:Object;

   function set value(val:Boolean);

   function get value():Boolean;

   static var version:String;

   public function viewIcon(varName:String):Void;

   public function viewSkin(varName:String, initObj:Object):Void;

};

ÿþÿ__Packages.mx.core.UIComponentÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.core.UIComponentÿþÿÿþimport mx.core.UIObject;

import mx.skins.SkinElement;



[Event("focusIn")] 

[Event("focusOut")] 

[Event("keyDown")] 

[Event("keyUp")] 

intrinsic class mx.core.UIComponent extends mx.core.UIObject

{

   public function UIComponent();

   public var clipParameters:Object;

   public function dispatchValueChangedEvent(value):Void;

   public var drawFocus:Function;

   [Inspectable(defaultValue=true, verbose=1, category="Other")] public var enabled:Boolean;

   public function enabledChanged(id:String, oldValue:Boolean, newValue:Boolean):Boolean;

   public function findFocusFromObject(o:Object):Object;

   public function findFocusInChildren(o:Object):Object;

   public var focusEnabled:Boolean;

   public var focusManager:MovieClip;

   public var focusTextField:Object;

   public function getFocus():Object;

   public function getFocusManager():Object;

   public var groupName:String;

   function get height():Number;

   public function init():Void;

   public function isParent(o:Object):Boolean;

   static var kStretch:Number;

   static var mergedClipParameters:Boolean;

   public function onKillFocus(newFocus:Object):Void;

   public function onSetFocus(oldFocus:Object):Void;

   public var origBorderStyles:Object;

   public var origBorderValues:Object;

   public var popUp:Boolean;

   public function pressFocus():Void;

   public function releaseFocus():Void;

   public function setEnabled(enabled:Boolean):Void;

   public function setFocus():Void;

   public function setVisible(x:Boolean, noEvent:Boolean):Void;

   public function size():Void;

   static var symbolName:String;

   static var symbolOwner:Object;

   public var tabEnabled:Boolean;

   public var tabIndex:Number;

   static var version:String;

   function get width():Number;

};

ÿþÿ__Packages.mx.core.UIObjectÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.skins.SkinElementÿþÿ
Button.swfÿþÿÿþÿÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swfÿþÿÿþÿÿþÿ!__Packages.mx.styles.StyleManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.core.UIObjectÿþÿÿÃimport mx.styles.StyleManager;

import mx.styles.CSSStyleDeclaration;

import mx.skins.SkinElement;



[Event("resize")] 

[Event("move")] 

[Event("draw")] 

[Event("load")] 

[Event("unload")] 

intrinsic class mx.core.UIObject extends MovieClip

{

   public function UIObject();

   public function __getTextFormat(tf:TextFormat, bAll:Boolean):Boolean;

   public var __get__minHeight:Function;

   public var __get__minWidth:Function;

   public var __get__scaleX:Function;

   public var __get__scaleY:Function;

   public var __get__visible:Function;

   public var __height:Number;

   private var __onUnload:Function;

   public var __width:Number;

   public var _color;

   public function _createChildren(Void):Void;

   private var _endInit:Function;

   public function _getTextFormat(Void):TextFormat;

   private var _id:String;

   private var _maxHeight:Number;

   private var _maxWidth:Number;

   private var _minHeight:Number;

   private var _minWidth:Number;

   private var _preferredHeight:Number;

   private var _preferredWidth:Number;

   private var _tf:TextFormat;

   public var _topmost:Boolean;

   public var addEventListener:Function;

   function get bottom():Number;

   public var buildDepthTable:Function;

   public function cancelAllDoLaters(Void):Void;

   public var changeColorStyleInChildren:Function;

   public var changeTextStyleInChildren:Function;

   public var childrenCreated:Boolean;

   public var className:String;

   public var clipParameters:Object;

   public var color:Number;

   public function constructObject(Void):Void;

   public var createAccessibilityImplementation:Function;

   public var createChildAtDepth:Function;

   public function createChildren(Void):Void;

   public var createClassChildAtDepth:Function;

   public function createClassObject(className:Function, id:String, depth:Number, initobj:Object):mx.core.UIObject;

   public function createEmptyObject(id:String, depth:Number):mx.core.UIObject;

   public var createEvent:Function;

   public function createLabel(name:String, depth:Number, text):TextField;

   public function createObject(linkageName:String, id:String, depth:Number, initobj:Object):MovieClip;

   public function createSkin(tag:Number):mx.core.UIObject;

   public function destroyObject(id:String):Void;

   public var dispatchEvent:Function;

   public function doLater(obj:Object, fn:String):Void;

   public function doLaterDispatcher(Void):Void;

   public function draw(Void):Void;

   public function drawRect(x1:Number, y1:Number, x2:Number, y2:Number):Void;

   public var embedFonts:Boolean;

   public var findNextAvailableDepth:Function;

   public var fontFamily:String;

   public var fontSize:Number;

   public var fontStyle:String;

   public var fontWeight:String;

   public function getClassStyleDeclaration(Void):mx.styles.CSSStyleDeclaration;

   public function getMinHeight(Void):Number;

   public function getMinWidth(Void):Number;

   public function getSkinIDName(tag:Number):String;

   public function getStyle(styleProp:String);

   public function getStyleName(Void):String;

   public var handleEvent:Function;

   function get height():Number;

   public var idNames:Array;

   public var ignoreClassStyleDeclaration:Object;

   public function init(Void):Void;

   public function initFromClipParameters(Void):Void;

   public var initProperties:Function;

   public function invalidate(Void):Void;

   private var invalidateFlag:Boolean;

   public function invalidateStyle(Void):Void;

   function get left():Number;

   private var lineColor:Number;

   private var lineWidth:Number;

   public var marginLeft:Number;

   public var marginRight:Number;

   static function mergeClipParameters(o, p):Boolean;

   public var methodTable:Array;

   [Inspectable(defaultValue=0, verbose=1, category="Size")] function get minHeight():Number;

   function set minHeight(h:Number):Void;

   [Inspectable(defaultValue=0, verbose=1, category="Size")] function get minWidth():Number;

   function set minWidth(w:Number):Void;

   public function move(x:Number, y:Number, noEvent:Boolean):Void;

   public var notifyStyleChangeInChildren:Function;

   public function redraw(bAlways:Boolean):Void;

   public var removeEventListener:Function;

   function get right():Number;

   function get scaleX():Number;

   function set scaleX(x:Number):Void;

   function get scaleY():Number;

   function set scaleY(y:Number):Void;

   public function setColor(color:Number):Void;

   public function setMinHeight(h:Number):Void;

   public function setMinWidth(w:Number):Void;

   public function setSize(w:Number, h:Number, noEvent:Boolean):Void;

   public function setSkin(tag:Number, linkageName:String, initObj:Object):MovieClip;

   public var setStyle:Function;

   public function setVisible(x:Boolean, noEvent:Boolean):Void;

   public function size(Void):Void;

   public var styleName:String;

   public var stylecache:Object;

   static var symbolName:String;

   static var symbolOwner:Object;

   public var tabEnabled:Boolean;

   public var textAlign:String;

   static var textColorList;

   public var textDecoration:String;

   public var textIndent:Number;

   private var tfList:Object;

   function get top():Number;

   public var validateNow:Boolean;

   static var version:String;

   [Inspectable(defaultValue=true, verbose=1, category="Other")] function get visible():Boolean;

   function set visible(x:Boolean):Void;

   function get width():Number;

   function get x():Number;

   function get y():Number;

};

ÿþÿ,__Packages.mx.core.ext.UIComponentExtensionsÿþÿ,__Packages.mx.core.ext.UIComponentExtensionsÿþÿ
Button.swf#¹U?ÿþÿ __Packages.mx.styles.CSSSetStyleÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ#__Packages.mx.managers.FocusManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ(__Packages.mx.managers.OverlappedWindowsÿþÿ
Button.swfÿþÿÿþÿÿþÿ!mx.core.ext.UIComponentExtensionsÿþÿÿ:import mx.core.UIComponent;



intrinsic class mx.core.ext.UIComponentExtensions

{

   static function Extensions():Boolean;

   static var FocusManagerDependency;

   static var OverlappedWindowsDependency;

   static var UIComponentDependency;

   static var UIComponentExtended;

   static var bExtended;

};

ÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swf#¹U?ÿþÿ&__Packages.mx.skins.ColoredSkinElementÿþÿ
Button.swfÿþÿÿþÿÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.skins.SkinElementÿþÿ
Button.swfÿþÿÿþÿÿþÿ"__Packages.mx.styles.CSSTextStylesÿþÿ
Button.swfÿþÿÿþÿÿþÿ&__Packages.mx.events.UIEventDispatcherÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.core.ext.UIObjectExtensionsÿþÿÿûimport mx.core.UIObject;

import mx.styles.CSSStyleDeclaration;

import mx.skins.SkinElement;

import mx.events.UIEventDispatcher;



intrinsic class mx.core.ext.UIObjectExtensions

{

   static var CSSTextStylesDependency;

   static function Extensions():Boolean;

   static var SkinElementDependency;

   static var UIEventDispatcherDependency;

   static var UIObjectDependency;

   static var UIObjectExtended;

   static function addGeometry(tf:Object, ui:Object):Void;

   static var bExtended;

};

ÿþÿ$__Packages.mx.events.EventDispatcherÿþÿ$__Packages.mx.events.EventDispatcherÿþÿ
Button.swf#¹U?ÿþÿmx.events.EventDispatcherÿþÿÿ

intrinsic class mx.events.EventDispatcher

{

   static var _fEventDispatcher:mx.events.EventDispatcher;

   static function _removeEventListener(queue:Object, event:String, handler):Void;

   public function addEventListener(event:String, handler):Void;

   public function dispatchEvent(eventObj:Object):Void;

   public function dispatchQueue(queueObj:Object, eventObj:Object):Void;

   static function initialize(object:Object):Void;

   public function removeEventListener(event:String, handler):Void;

};

ÿþÿ&__Packages.mx.events.UIEventDispatcherÿþÿ&__Packages.mx.events.UIEventDispatcherÿþÿ
Button.swf#¹U?ÿþÿ$__Packages.mx.events.EventDispatcherÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.events.UIEventDispatcherÿþÿÿimport mx.core.UIObject;

import mx.events.EventDispatcher;



intrinsic class mx.events.UIEventDispatcher extends mx.events.EventDispatcher

{

   public function __addEventListener(event:String, handler):Void;

   public var __origAddEventListener:Function;

   public var __sentLoadEvent;

   static var _fEventDispatcher:mx.events.UIEventDispatcher;

   static function addKeyEvents(obj:Object):Void;

   static function addLoadEvents(obj:Object):Void;

   public function dispatchEvent(eventObj:Object):Void;

   static function initialize(obj:Object):Void;

   static var keyEvents:Object;

   static var loadEvents:Object;

   static var lowLevelEvents:Object;

   public function onKeyDown(Void):Void;

   public function onKeyUp(Void):Void;

   public function onLoad(Void):Void;

   public function onUnload(Void):Void;

   public var owner:Object;

   public function removeEventListener(event:String, handler):Void;

   static function removeKeyEvents(obj:Object):Void;

   static function removeLoadEvents(obj:Object):Void;

};

ÿþÿ#__Packages.mx.managers.DepthManagerÿþÿ#__Packages.mx.managers.DepthManagerÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.managers.DepthManagerÿþÿÿoimport mx.core.UIObject;



intrinsic class mx.managers.DepthManager

{

   public function DepthManager();

   static var __depthManager:mx.managers.DepthManager;

   public var _childCounter:Number;

   public var _parent:MovieClip;

   public var _topmost:Boolean;

   public function buildDepthTable(Void):Array;

   public function createChildAtDepth(linkageName:String, depthFlag:Number, initObj:Object):MovieClip;

   public function createClassChildAtDepth(className:Function, depthFlag:Number, initObj:Object):mx.core.UIObject;

   public var createClassObject:Function;

   static function createClassObjectAtDepth(className:Object, depthSpace:Number, initObj:Object):mx.core.UIObject;

   public var createObject:Function;

   static function createObjectAtDepth(linkageName:String, depthSpace:Number, initObj:Object):MovieClip;

   public function findNextAvailableDepth(targetDepth:Number, depthTable:Array, direction:String):Number;

   public var getDepth:Function;

   public function getDepthByFlag(depthFlag:Number, depthTable:Array):Number;

   static var highestDepth:Number;

   static private var holder:MovieClip;

   static var kBottom:Number;

   static var kCursor:Number;

   static var kNotopmost:Number;

   static var kTooltip:Number;

   static var kTop:Number;

   static var kTopmost:Number;

   static var lowestDepth:Number;

   static var numberOfAuthortimeLayers:Number;

   static var reservedDepth:Number;

   public function setDepthAbove(targetInstance:MovieClip):Void;

   public function setDepthBelow(targetInstance:MovieClip):Void;

   public function setDepthTo(depthFlag:Number):Void;

   public function shuffleDepths(subject:MovieClip, targetDepth:Number, depthTable:Array, direction:String):Void;

   static function sortFunction(a:MovieClip, b:MovieClip):Number;

   public var swapDepths:Function;

   static function test(depth:Number):Boolean;

};

ÿþÿ#__Packages.mx.managers.FocusManagerÿþÿ#__Packages.mx.managers.FocusManagerÿþÿ
Button.swf	ëW?ÿþÿ#__Packages.mx.controls.SimpleButtonÿþÿ
Button.swfÿþÿÿþÿÿþÿ#__Packages.mx.managers.DepthManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ$__Packages.mx.managers.SystemManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.managers.FocusManagerÿþÿÿêimport mx.core.UIObject;

import mx.managers.SystemManager;

import mx.controls.SimpleButton;

import mx.core.UIComponent;



intrinsic class mx.managers.FocusManager extends mx.core.UIComponent

{

   public function FocusManager();

   static var UIObjectExtensionsDependency;

   public var __defaultPushButton:mx.controls.SimpleButton;

   public var __get__defaultPushButton:Function;

   private var _firstNode:Object;

   private var _firstObj:Object;

   private var _foundList:Object;

   private var _lastNode:Object;

   private var _lastObj:Object;

   private var _lastTarget:Object;

   private var _lastx:Object;

   private var _needPrev:Boolean;

   private var _nextIsNext:Boolean;

   private var _nextNode:Object;

   private var _nextObj:Object;

   public function _onMouseDown(Void):Void;

   private var _prevNode:Object;

   private var _prevObj:Object;

   private var _searchKey:Number;

   public function activate(Void):Void;

   private var activated:Boolean;

   public var bDrawFocus:Boolean;

   public var bNeedFocus:Boolean;

   public var className:String;

   public function deactivate(Void):Void;

   public var defPushButton:mx.controls.SimpleButton;

   function get defaultPushButton():mx.controls.SimpleButton;

   function set defaultPushButton(x:mx.controls.SimpleButton);

   public var defaultPushButtonEnabled:Boolean;

   static function enableFocusManagement():Void;

   public function enabledChanged(id:String, oldValue:Boolean, newValue:Boolean):Boolean;

   public var form;

   public function getActualFocus(o:Object):Object;

   public function getFocus(Void):Object;

   public function getFocusManagerFromObject(o:Object):Object;

   public function getMaxTabIndex(o:mx.core.UIComponent):Number;

   public function getMousedComponentFromChildren(x:Number, y:Number, o:Object):Object;

   public function getNextTabIndex(Void):Number;

   public function getSelectionFocus():Object;

   public function getTabCandidate(o:MovieClip, index:Number, groupName:String, dir:Boolean, firstChild:Boolean):Void;

   public function getTabCandidateFromChildren(o:MovieClip, index:Number, groupName:String, dir:Boolean, firstChild:Boolean):Void;

   public function handleEvent(e:Object);

   public function init(Void):Void;

   static var initialized:Boolean;

   public function isOurFocus(o:Object):Boolean;

   public var lastFocus:Object;

   public var lastSelFocus:Object;

   public var lastTabFocus:Object;

   public var lastXMouse:Number;

   public var lastYMouse:Number;

   public function mouseActivate(Void):Void;

   function get nextTabIndex():Number;

   public function onKeyDown(Void):Void;

   public function onMouseUp(Void):Void;

   public function onSetFocus(o:Object, n:Object):Void;

   public function onUnload(Void):Void;

   public function relocate(Void):Void;

   public function restoreFocus(Void):Void;

   public function sendDefaultPushButtonEvent(Void):Void;

   public function setFocus(o:Object):Void;

   static var symbolName:String;

   static var symbolOwner:Object;

   private var tabCapture:MovieClip;

   public function tabHandler(Void):Void;

   static var version:String;

   public function walkTree(p:MovieClip, index:Number, groupName:String, dir:Boolean, lookup:Boolean, firstChild:Boolean):Void;

};

ÿþÿ(__Packages.mx.managers.OverlappedWindowsÿþÿ(__Packages.mx.managers.OverlappedWindowsÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ$__Packages.mx.managers.SystemManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.managers.OverlappedWindowsÿþÿÿ(import mx.managers.SystemManager;

import mx.core.UIComponent;



intrinsic class mx.managers.OverlappedWindows

{

   static var SystemManagerDependency;

   static function __addEventListener(e:String, o:Object, l:Function):Void;

   static function __removeEventListener(e:String, o:Object, l:Function):Void;

   static function activate(f:MovieClip):Void;

   static function addFocusManager(f:mx.core.UIComponent):Void;

   static function checkIdle(Void):Void;

   static function deactivate(f:MovieClip):Void;

   static function enableOverlappedWindows():Void;

   static var initialized:Boolean;

   static function onMouseDown(Void):Void;

   static function onMouseMove(Void):Void;

   static function onMouseUp(Void):Void;

   static function removeFocusManager(f:mx.core.UIComponent):Void;

};

ÿþÿ$__Packages.mx.managers.SystemManagerÿþÿ$__Packages.mx.managers.SystemManagerÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ$__Packages.mx.events.EventDispatcherÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.managers.SystemManagerÿþÿÿ�import mx.events.EventDispatcher;

import mx.core.UIComponent;



[Event("idle")] 

[Event("resize")] 

intrinsic class mx.managers.SystemManager

{

   static var __addEventListener:Function;

   static var __removeEventListener:Function;

   static var __screen:Object;

   static private var _initialized:Boolean;

   static var _xAddEventListener:Function;

   static var _xRemoveEventListener:Function;

   static var activate:Function;

   static var addEventListener:Function;

   static function addFocusManager(f:mx.core.UIComponent):Void;

   static var checkIdle:Function;

   static var deactivate:Function;

   static var dispatchEvent:Function;

   static var form:MovieClip;

   static var forms:Array;

   static var idleFrames:Number;

   static function init(Void):Void;

   static var interval:Number;

   static var isMouseDown;

   static function onMouseDown(Void):Void;

   static var onMouseMove:Function;

   static var onMouseUp:Function;

   static function onResize(Void):Void;

   static var removeEventListener:Function;

   static function removeFocusManager(f:mx.core.UIComponent):Void;

   static function get screen():Object;

};

ÿþÿ__Packages.mx.skins.Borderÿþÿ__Packages.mx.skins.Borderÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.Borderÿþÿÿhimport mx.core.UIObject;



intrinsic class mx.skins.Border extends mx.core.UIObject

{

   public function Border();

   public var borderStyle:String;

   public var className:String;

   public var idNames:Array;

   public function init(Void):Void;

   static var symbolName:String;

   static var symbolOwner:Object;

   public var tagBorder:Number;

};

ÿþÿ&__Packages.mx.skins.ColoredSkinElementÿþÿ&__Packages.mx.skins.ColoredSkinElementÿþÿ
Button.swf#¹U?ÿþÿmx.skins.ColoredSkinElementÿþÿÿ�

intrinsic class mx.skins.ColoredSkinElement

{

   public var _color;

   public function draw(Void):Void;

   public var getStyle:Function;

   public function invalidateStyle(Void):Void;

   static var mixins:mx.skins.ColoredSkinElement;

   public var onEnterFrame:Function;

   public function setColor(c:Number):Void;

   static function setColorStyle(p:Object, colorStyle:String):Void;

};

ÿþÿ__Packages.mx.skins.RectBorderÿþÿ__Packages.mx.skins.RectBorderÿþÿ
Button.swf$¹U?ÿþÿ__Packages.mx.skins.Borderÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.RectBorderÿþÿÿÅimport mx.skins.Border;

import mx.styles.CSSStyleDeclaration;



intrinsic class mx.skins.RectBorder extends mx.skins.Border

{

   public function RectBorder();

   public var __borderMetrics:Object;

   public var backgroundColorName:String;

   public var borderColorName:String;

   function get borderMetrics():Object;

   public var borderStyleName:String;

   public var buttonColorName:String;

   public var className:String;

   public function draw(Void):Void;

   public function drawBorder(Void):Void;

   public function getBorderMetrics(Void):Object;

   function get height():Number;

   public var highlightColorName:String;

   public function init(Void):Void;

   public var offset:Number;

   public function setColor(Void):Void;

   public var shadowColorName:String;

   public function size(Void):Void;

   static var symbolName:String;

   static var symbolOwner:Object;

   static var version:String;

   function get width():Number;

};

ÿþÿ__Packages.mx.skins.SkinElementÿþÿ__Packages.mx.skins.SkinElementÿþÿ
Button.swf$¹U?ÿþÿmx.skins.SkinElementÿþÿÿ¥

intrinsic class mx.skins.SkinElement extends MovieClip

{

   public function __set__visible(visible:Boolean):Void;

   public var height:Number;

   public function move(x:Number, y:Number):Void;

   static function registerElement(name:String, className:Function):Void;

   public function setSize(w:Number, h:Number):Void;

   public var top:Number;

   public var visible:Boolean;

   public var width:Number;

};

ÿþÿ#__Packages.mx.skins.halo.ButtonSkinÿþÿ#__Packages.mx.skins.halo.ButtonSkinÿþÿ
Button.swf#¹U?ÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.skins.RectBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.halo.ButtonSkinÿþÿÿimport mx.skins.RectBorder;

import mx.core.ext.UIObjectExtensions;

import mx.skins.SkinElement;



intrinsic class mx.skins.halo.ButtonSkin extends mx.skins.RectBorder

{

   public function ButtonSkin();

   static var UIObjectExtensionsDependency;

   public var backgroundColorName;

   static function classConstruct():Boolean;

   static var classConstructed:Boolean;

   public var className;

   public function drawHaloRect(w:Number, h:Number):Void;

   public var drawRoundRect:Function;

   public function init():Void;

   public function size():Void;

   static var symbolName:String;

   static var symbolOwner:Object;

};

ÿþÿ!__Packages.mx.skins.halo.Defaultsÿþÿ!__Packages.mx.skins.halo.Defaultsÿþÿ
Button.swf$¹U?ÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swfÿþÿÿþÿÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.halo.Defaultsÿþÿÿ·import mx.core.UIObject;

import mx.core.ext.UIObjectExtensions;

import mx.styles.CSSStyleDeclaration;



intrinsic class mx.skins.halo.Defaults

{

   static var CSSStyleDeclarationDependency;

   static var UIObjectDependency;

   static var UIObjectExtensionsDependency;

   public var beginFill:Function;

   public var beginGradientFill:Function;

   static function classConstruct():Boolean;

   static var classConstructed;

   public var curveTo:Function;

   public function drawRoundRect(x, y, w, h, r, c, alpha, rot, gradient, ratios);

   public var endFill:Function;

   public var lineTo:Function;

   public var moveTo:Function;

   static function setThemeDefaults():Void;

};

ÿþÿ"__Packages.mx.skins.halo.FocusRectÿþÿ"__Packages.mx.skins.halo.FocusRectÿþÿ
Button.swf$¹U?ÿþÿ#__Packages.mx.managers.DepthManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.skins.SkinElementÿþÿ
Button.swfÿþÿÿþÿÿþÿ!__Packages.mx.skins.halo.Defaultsÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.halo.FocusRectÿþÿÿÎimport mx.core.UIObject;

import mx.skins.halo.Defaults;

import mx.managers.DepthManager;

import mx.skins.SkinElement;

import mx.core.UIComponent;



intrinsic class mx.skins.halo.FocusRect extends mx.skins.SkinElement

{

   static var DefaultsDependency:mx.skins.halo.Defaults;

   public function FocusRect();

   static var UIComponentDependency:mx.core.UIComponent;

   public var boundingBox_mc:MovieClip;

   static function classConstruct():Boolean;

   static var classConstructed:Boolean;

   public function draw(o:Object):Void;

   public var drawRoundRect:Function;

   public function handleEvent(e:Object):Void;

   public function setSize(w:Number, h:Number, r, a:Number, rectCol:Number):Void;

};

ÿþÿ#__Packages.mx.skins.halo.RectBorderÿþÿ#__Packages.mx.skins.halo.RectBorderÿþÿ
Button.swf$¹U?ÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swfÿþÿÿþÿÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.skins.RectBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.halo.RectBorderÿþÿÿoimport mx.core.ext.UIObjectExtensions;

import mx.skins.Border;

import mx.styles.CSSStyleDeclaration;



intrinsic class mx.skins.halo.RectBorder extends mx.skins.RectBorder

{

   public function RectBorder();

   static var UIObjectExtensionsDependency;

   public var borderCapColorName:String;

   private var borderWidths:Object;

   static function classConstruct():Boolean;

   static var classConstructed:Boolean;

   private var colorList:Object;

   public function draw3dBorder(c1:Number, c2:Number, c3:Number, c4:Number, c5:Number, c6:Number):Void;

   public function drawBorder(Void):Void;

   public var drawRoundRect:Function;

   public function getBorderMetrics(Void):Object;

   public function init(Void):Void;

   public var shadowCapColorName:String;

   static var symbolName:String;

   static var symbolOwner:Object;

   static var version:String;

};

ÿþÿ __Packages.mx.styles.CSSSetStyleÿþÿ __Packages.mx.styles.CSSSetStyleÿþÿ
Button.swf$¹U?ÿþÿ!__Packages.mx.styles.StyleManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.styles.CSSSetStyleÿþÿÿbimport mx.styles.StyleManager;

import mx.styles.CSSStyleDeclaration;



intrinsic class mx.styles.CSSSetStyle

{

   static var CSSStyleDeclarationDependency;

   public var _color:Number;

   public function _setStyle(styleProp:String, newValue):Void;

   public function changeColorStyleInChildren(sheetName:String, colorStyle:String, newValue):Void;

   public function changeTextStyleInChildren(styleProp:String):Void;

   static function classConstruct():Boolean;

   static var classConstructed:Boolean;

   static function enableRunTimeCSS():Void;

   public var invalidateStyle:Function;

   public function notifyStyleChangeInChildren(sheetName:String, styleProp:String, newValue):Void;

   public var setColor:Function;

   public function setStyle(styleProp:String, newValue):Void;

   public var styleName:String;

   public var stylecache:Object;

};

ÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swf$¹U?ÿþÿ!__Packages.mx.styles.StyleManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ"__Packages.mx.styles.CSSTextStylesÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.styles.CSSStyleDeclarationÿþÿÿ%import mx.styles.StyleManager;

import mx.styles.CSSTextStyles;



intrinsic class mx.styles.CSSStyleDeclaration

{

   static var CSSTextStylesDependency;

   public function __getTextFormat(tf:TextFormat, bAll:Boolean):Boolean;

   public var _tf:TextFormat;

   static function classConstruct():Boolean;

   static var classConstructed:Boolean;

   public var color:Number;

   public var embedFonts:Boolean;

   public var fontFamily:String;

   public var fontSize:Number;

   public var fontStyle:String;

   public var fontWeight:String;

   public function getStyle(styleProp:String);

   public var marginLeft:Number;

   public var marginRight:Number;

   public var styleName:String;

   public var textAlign:String;

   public var textDecoration:String;

   public var textIndent:Number;

};

ÿþÿ"__Packages.mx.styles.CSSTextStylesÿþÿ"__Packages.mx.styles.CSSTextStylesÿþÿ
Button.swf$¹U?ÿþÿmx.styles.CSSTextStylesÿþÿt

intrinsic class mx.styles.CSSTextStyles

{

   static function addTextStyles(o:Object, bColor:Boolean):Void;

};

ÿþÿ!__Packages.mx.styles.StyleManagerÿþÿ!__Packages.mx.styles.StyleManagerÿþÿ
Button.swf$¹U?ÿþÿmx.styles.StyleManagerÿþÿÿµ

intrinsic class mx.styles.StyleManager

{

   static var TextFormatStyleProps:Object;

   static var TextStyleMap:Object;

   static var colorNames:Object;

   static var colorStyles:Object;

   static function getColorName(colorName:String):Number;

   static var inheritingStyles:Object;

   static function isColorName(colorName:String):Boolean;

   static function isColorStyle(styleName:String):Boolean;

   static function isInheritingStyle(styleName:String):Boolean;

   static function registerColorName(colorName:String, colorValue:Number):Void;

   static function registerColorStyle(styleName:String):Void;

   static function registerInheritingStyle(styleName:String):Void;

};

ÿþÿBoundingBoxÿþÿ
Button.swfÿþÿÿþÿÿþÿSimpleButtonÿþÿ
Button.swfÿþÿÿþÿÿþÿBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿ
RectBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿ
ButtonSkinÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.controls.Buttonÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.controls.Buttonÿþÿÿqimport mx.core.UIObject;

import mx.controls.SimpleButton;

import mx.core.UIComponent;



[Event("click")] 

[TagName("Button")] 

[IconFile("Button.png")] 

intrinsic class mx.controls.Button extends mx.controls.SimpleButton

{

   public function Button();

   public var __get__icon:Function;

   public var __get__label:Function;

   public var __get__labelPlacement:Function;

   public var __label:String;

   public var __labelPlacement:String;

   public var _color;

   public function _getIcon(Void):String;

   public var _iconLinkageName:String;

   [Bindable] [ChangeEvent("click")] public var _inherited_selected:Boolean;

   public function _setIcon(linkage):Void;

   public var borderW:Number;

   public var btnOffset:Number;

   public function calcSize(tag:Number, ref:Object):Void;

   public var centerContent:Boolean;

   public var className:String;

   public var clipParameters:Object;

   public function createChildren(Void):Void;

   public function draw();

   public var falseDisabledIcon:String;

   public var falseDisabledSkin:String;

   public var falseDownIcon:String;

   public var falseDownSkin:String;

   public var falseOverIcon:String;

   public var falseOverSkin:String;

   public var falseUpIcon:String;

   public var falseUpSkin:String;

   public function getBtnOffset(Void):Number;

   public function getLabel(Void):String;

   public function getLabelPlacement(Void):String;

   public var hitArea_mc:MovieClip;

   function get icon():String;

   [Inspectable(defaultValue="")] function set icon(linkage);

   public function init(Void):Void;

   public var initIcon;

   public function invalidateStyle(c:String):Void;

   [Inspectable(defaultValue="Button")] function set label(lbl:String);

   function get label():String;

   public var labelPath:Object;

   [Inspectable(enumeration="left,right,top,bottom"defaultValue="right")] function set labelPlacement(val:String);

   function get labelPlacement():String;

   static var mergedClipParameters:Boolean;

   public function onRelease(Void):Void;

   public function setColor(c:Number):Void;

   public function setEnabled(enable:Boolean):Void;

   public function setHitArea(w:Number, h:Number);

   public function setLabel(label:String):Void;

   public function setLabelPlacement(val:String):Void;

   public function setSkin(tag:Number, linkageName:String, initobj:Object):MovieClip;

   public function setView(offset:Number):Void;

   public function size(Void):Void;

   static var symbolName:String;

   static var symbolOwner;

   public var trueDisabledIcon:String;

   public var trueDisabledSkin:String;

   public var trueDownIcon:String;

   public var trueDownSkin:String;

   public var trueOverIcon:String;

   public var trueOverSkin:String;

   public var trueUpIcon:String;

   public var trueUpSkin:String;

   static var version:String;

   public function viewSkin(varName:String):Void;

};

ÌÈ
h�hhhhÿÿÿÿÀÀÀÿ´ÿþÿPropSheet::ActiveTabÿþÿ7641”ÿþÿ!PublishGifProperties::PaletteNameÿþÿÿþÿ PublishRNWKProperties::speed256Kÿþÿ0ÿþÿ"PublishHtmlProperties::StartPausedÿþÿ0ÿþÿ%PublishFormatProperties::htmlFileNameÿþÿstorage_dialog.htmlÿþÿ PublishQTProperties::LayerOptionÿþÿÿþÿ PublishQTProperties::AlphaOptionÿþÿÿþÿ"PublishQTProperties::MatchMovieDimÿþÿ1ÿþÿVector::Debugging Permittedÿþÿ0ÿþÿPublishProfileProperties::nameÿþÿDefaultÿþÿPublishHtmlProperties::Loopÿþÿ1ÿþÿPublishFormatProperties::jpegÿþÿ0ÿþÿPublishQTProperties::Widthÿþÿ215ÿþÿ$PublishPNGProperties::OptimizeColorsÿþÿ1ÿþÿ&PublishRNWKProperties::speedSingleISDNÿþÿ0ÿþÿ&PublishRNWKProperties::singleRateAudioÿþÿ0ÿþÿVector::External Playerÿþÿÿþÿ%PublishHtmlProperties::showTagWarnMsgÿþÿ1ÿþÿPublishHtmlProperties::Unitsÿþÿ0ÿþÿ4PublishHtmlProperties::UsingDefaultAlternateFilenameÿþÿ1ÿþÿPublishGifProperties::Smoothÿþÿ1ÿþÿ%PublishRNWKProperties::mediaCopyrightÿþÿ(c) 2000ÿþÿ#PublishRNWKProperties::flashBitRateÿþÿ1200ÿþÿVector::Compress Movieÿþÿ1ÿþÿVector::Package Pathsÿþÿÿþÿ&PublishFormatProperties::flashFileNameÿþÿ..\..\storage_dialog.swfÿþÿ'PublishFormatProperties::gifDefaultNameÿþÿ1ÿþÿ%PublishFormatProperties::projectorMacÿþÿ0ÿþÿ"PublishGifProperties::DitherOptionÿþÿÿþÿ!PublishRNWKProperties::exportSMILÿþÿ1ÿþÿ PublishRNWKProperties::speed384Kÿþÿ0ÿþÿ"PublishRNWKProperties::exportAudioÿþÿ1ÿþÿVector::FireFoxÿþÿ0ÿþÿPublishHtmlProperties::Qualityÿþÿ4ÿþÿ(PublishHtmlProperties::VerticalAlignmentÿþÿ1ÿþÿ$PublishFormatProperties::pngFileNameÿþÿstorage_dialog.pngÿþÿPublishFormatProperties::htmlÿþÿ0ÿþÿ"PublishPNGProperties::FilterOptionÿþÿÿþÿ'PublishRNWKProperties::mediaDescriptionÿþÿÿþÿVector::Override Soundsÿþÿ0ÿþÿ!PublishHtmlProperties::DeviceFontÿþÿ0ÿþÿ-PublishFormatProperties::generatorDefaultNameÿþÿ1ÿþÿPublishQTProperties::Flattenÿþÿ1ÿþÿPublishPNGProperties::BitDepthÿþÿ24-bit with AlphaÿþÿPublishPNGProperties::Smoothÿþÿ1ÿþÿ"PublishGifProperties::DitherSolidsÿþÿ0ÿþÿPublishGifProperties::Interlaceÿþÿ0ÿþÿPublishJpegProperties::DPIÿþÿ4718592ÿþÿVector::Qualityÿþÿ80ÿþÿVector::Protectÿþÿ0ÿþÿ"PublishHtmlProperties::DisplayMenuÿþÿ1ÿþÿ*PublishHtmlProperties::HorizontalAlignmentÿþÿ1ÿþÿ2PublishHtmlProperties::VersionDetectionIfAvailableÿþÿ0ÿþÿVector::Templateÿþÿ0ÿþÿ*PublishFormatProperties::generatorFileNameÿþÿstorage_dialog.swtÿþÿ(PublishFormatProperties::rnwkDefaultNameÿþÿ1ÿþÿ(PublishFormatProperties::jpegDefaultNameÿþÿ1ÿþÿPublishFormatProperties::gifÿþÿ0ÿþÿPublishGifProperties::Loopÿþÿ1ÿþÿPublishGifProperties::Widthÿþÿ215ÿþÿ$PublishRNWKProperties::mediaKeywordsÿþÿÿþÿ!PublishRNWKProperties::mediaTitleÿþÿÿþÿPublishRNWKProperties::speed28Kÿþÿ1ÿþÿ#PublishFormatProperties::qtFileNameÿþÿstorage_dialog.movÿþÿ"PublishPNGProperties::DitherOptionÿþÿÿþÿ#PublishGifProperties::PaletteOptionÿþÿÿþÿ#PublishGifProperties::MatchMovieDimÿþÿ1ÿþÿ$PublishRNWKProperties::speedDualISDNÿþÿ0ÿþÿ$PublishRNWKProperties::realVideoRateÿþÿ100000ÿþÿPublishJpegProperties::Qualityÿþÿ80ÿþÿPublishFormatProperties::flashÿþÿ1ÿþÿ#PublishPNGProperties::PaletteOptionÿþÿÿþÿ#PublishPNGProperties::MatchMovieDimÿþÿ1ÿþÿ$PublishJpegProperties::MatchMovieDimÿþÿ1ÿþÿVector::Package Export Frameÿþÿ1ÿþÿ!PublishProfileProperties::versionÿþÿ1ÿþÿPublishHtmlProperties::Alignÿþÿ0ÿþÿ-PublishFormatProperties::projectorWinFileNameÿþÿstorage_dialog.exeÿþÿ'PublishFormatProperties::pngDefaultNameÿþÿ1ÿþÿ0PublishFormatProperties::projectorMacDefaultNameÿþÿ1ÿþÿ#PublishQTProperties::PlayEveryFrameÿþÿ0ÿþÿ"PublishPNGProperties::DitherSolidsÿþÿ0ÿþÿ"PublishJpegProperties::Progressiveÿþÿ0ÿþÿVector::Debugging PasswordÿþÿÿþÿVector::Omit Trace Actionsÿþÿ0ÿþÿPublishHtmlProperties::Heightÿþÿ138ÿþÿPublishHtmlProperties::Widthÿþÿ215ÿþÿ%PublishFormatProperties::jpegFileNameÿþÿstorage_dialog.jpgÿþÿ)PublishFormatProperties::flashDefaultNameÿþÿ0ÿþÿPublishPNGProperties::Interlaceÿþÿ0ÿþÿPublishGifProperties::Heightÿþÿ138ÿþÿPublishJpegProperties::Sizeÿþÿ0ÿþÿVector::DeviceSoundÿþÿ0ÿþÿVector::TopDownÿþÿ0ÿþÿ'PublishHtmlProperties::TemplateFileNameÿþÿ�C:\Documents and Settings\bradneuberg\Local Settings\Application Data\Macromedia\Flash MX 2004\en\Configuration\Html\Default.htmlÿþÿ!PublishHtmlProperties::WindowModeÿþÿ0ÿþÿ2PublishHtmlProperties::UsingDefaultContentFilenameÿþÿ1ÿþÿ-PublishFormatProperties::projectorMacFileNameÿþÿstorage_dialog.hqxÿþÿ(PublishFormatProperties::htmlDefaultNameÿþÿ1ÿþÿPublishFormatProperties::rnwkÿþÿ0ÿþÿPublishFormatProperties::pngÿþÿ0ÿþÿPublishQTProperties::Heightÿþÿ138ÿþÿ%PublishPNGProperties::RemoveGradientsÿþÿ0ÿþÿPublishGifProperties::MaxColorsÿþÿ255ÿþÿ'PublishGifProperties::TransparentOptionÿþÿÿþÿPublishGifProperties::LoopCountÿþÿÿþÿPublishRNWKProperties::speed56Kÿþÿ1ÿþÿVector::Reportÿþÿ0ÿþÿ+PublishHtmlProperties::OwnAlternateFilenameÿþÿÿþÿ(PublishHtmlProperties::AlternateFilenameÿþÿÿþÿ&PublishHtmlProperties::ContentFilenameÿþÿÿþÿ"PublishFormatProperties::generatorÿþÿ0ÿþÿ$PublishGifProperties::OptimizeColorsÿþÿ1ÿþÿ"PublishRNWKProperties::audioFormatÿþÿ0ÿþÿVector::Versionÿþÿ7ÿþÿVector::Event Formatÿþÿ0ÿþÿVector::Stream Compressÿþÿ7ÿþÿPublishFormatProperties::qtÿþÿ0ÿþÿPublishPNGProperties::Heightÿþÿ138ÿþÿPublishPNGProperties::Widthÿþÿ215ÿþÿ%PublishGifProperties::ªZ|o4’ºÜçaIÀm>€�d´bÎ)#Áäì2®ïOª$M,çðŒ…R0´÷½QH)\µˆÒ™¦4¶ýÉã>~¨¼žˆ´µýMašÎMñXtV×ÙoKÀ~[’<÷ß@“­‘ôß‹ß”¿hˆV`O§¼,NÝFünaý½�ÐsP©|M:H“
5K�ÐbxN®‰]O“{š†ó1Ùd
ÃÈ'kJl“Ï“E’Y--:Ô¥µ·§C2)µ!•þH°ÃóÞR0½Q0^þ;’4ÔZ�Vn{áñÎCÏãqo–&™€Áœ!9ú=9b“t#†™BŒ§ýn-dûzü®tb±Ë?Õ ×œ‡T¤þŒ!S¢àô‡ÄîR§Ã9on¶#ú¾é0ì@ž6£,Ö‡BÚ¬þ_µÉfaè!‰¶za&pQ1ÿ2fà/k!jA³¼K˜%žÈÐ ‡ã‡S~ëHü(–ø1äÈJ3âÇü³˜8Ê�
*c<nœ|^`áïñÅ8Àûy8dÚ'&Z·ôwJÈ»¢eðÝ!_Š¦t‘LOOwßöÌ•Ÿ®]åþÑ“#ïºxIÞ¶«ÛÁeê^„ „+Ís˜Q+Í_zO¨°«
®Dà‰'ž€®ÞW‡Þzùèé¾};�>�a;ùbçaüZZPÍ›¹ÒÜ/èf§CIÐÁ¼vÂ±J®2™ÏÍIF—KFðý £>ôæËãoD÷�•Œv…�â«Ñ_£ËÃŒv1£ãt˜¯µÞ† n^�uâ×Vãº\E–¶‚`:ŽxûUXcõLÓ0AM\huÃ¤](;–¸Ü-Í¥ø=R|úÅ�¼5yì�µûz¥ø+Ââ—*9«ò¿G‰ßÎ¯`ñ�9�Ï
é
/tõ=sÖ}þÍw?Ñù…]ï~�_:n÷1¿âw%@ÞžÉ;tGõþ³ü4±Ü_;þÒC×ç}Ìö	Û¡›±&6×tu§´2¸º+à¯kµ?‘«Û-V·Þ¾)\]ÛE0¹ÞÖ(Ò~ûjíëžQ¦ÐB¦ðkµ_©ý÷À±KSXÁS¯™ÂD±‰Ê›pÙT–È�–&Á.WJó-M) Ûï5ò(9Jl–ïUüa±=m´�6®�kØQr·‰KŽ ™Ü‰�Ü÷–‘/
Å«°+èw«`Ôš61«J„ÕB‚VÃ½âRclÞµŠU»T$ÔØ¹44?2®òéØJ"×óÎ.4Zlè8´·ÿ•+áùÖxäÐÒ7"h-dþsô{ï�ëB/ÝŽwïý§‘/¾T}öG•¿;‚h›±£¿­¶·Ö}[¾xÉÑƒp5~ˆöNŠúZB4Úûù
ÙŒ†ímÊ7Pw®9uÂ,æ«B†Þ<Æ×ZºŽ—´O,i;Å#SÈJ);yø:/eg«i³‰äµÖq­¨O®t„¸GŽFÌ²;[¡¥Ã0kv¬úÊÇº"èŠ¨Ù5Ðõ\E)¶›É¯Sž6‹æÊ"sƒ·˜kiò0R*”KEôõÐzÞŽý×s
ôüVR¬g§èýÙ¥kÜhER+wß“�„öË�AòH”òûM!)×(íýÁñß~æ±F’¸OÓÄÝÐýÐOå¼+!qæ£ïr£íº÷[µ+ÜHà„+ÿcä¥°"6…¿¹ú×!h0$íÓBÚ®ÊsŠÚ26ˆ†@Û@#@PÙÜHeçÛ‘PœÜd
Þ@Zš-FÙ"_")#Ê÷IQÍU÷:&½—šªîjì)àôpò°‰]Eÿ‚·Shw�+QL2ÛÐØJ33ã£œr‚U4§êŒpS=KP³`å#H Q]ÁpñTâƒù—h5j£÷µ�oàõZ‹zè}í«¢1€‹FPÝ[¥Po=ì�LßÆ¯/S¿,ù2}™dB]ÚôxK¼ &sÊBY%•�¥„�q0@òaàƒÖ‰éíÛÀ.«µæMŒt¸ófÖÃM�Éœ1³Ð—«;ó;yÓÞÙd¿®u&tüÔ‹è2êÑ·ziêb³o2®\)¹%w¡ly›½À¢fúø1ÈUÌ9Èd4c¹"(Ç�çÊxÅ,Ð+ÙEÓ±éd&:ÃICÁž§™�NNZî™J©<î˜3UÎö�“÷ˆ8×¯R <iDü,^;’JqÅù€G¬¡qúÏ'N<ú_ø´	8Œç£b0¬øÞÏÉÀÍhlq¿°�ž¥‹Ž§0];7ñ}¥¸‚�·ñž tu@ŒÓ�…©´.vr½ÁÀ}%;;äq¨Í¿òŠÄ—¥�žª¢üx¥§$‘Ž:" nWÚi‚dJrß¹˜ ÷Ð·C¤ZÖ_“ý9ñ<É°6àç«x›¡¥ÄW,¬þ]žg0‰Òq]”…Òz]ä3ðJÓ(s
½…Xî/jˆÒ$](1ºÖdŠ(Ÿùö¥‚Â³†¤gm`Ïªó¬,zÆNkè|y�F<õû-¿ÛÄ�ÙßGÐƒ«ne6ëÊ¶ïSþ+m&ƒÞ“ÉˆrõGÀäã¹÷W@kÚåw`Ñô>ÜR™Þ†eËûÁ,S6+äÕ!úS%Œ�õF� Ó^ÄÊøÁ«‚‹‘… 2"Àe¼PW
B=ª]
µ±uŸzîV!••–·sT¬‹ª<gWË¦›Í�]$±$Iï•\Pô›ÜË¯Û êøC!)hçê±çäJ§0˜U `¹ùRî,Å~›´íLEéA(Ê!£’[ìGEŠx(RYéPÍÛ¸¸Yª&pŽ:Î¨]
jˆªî4=É‹pLÅxZÈ=@?ç¼Ïº”%ñ}E<Ô#¦P;~È%$Zœ™†‹DÃ)Þ?Å÷YkÞ·-'§6—žåé‹yB›Ä6T‰Ï$iCŒRÅ®kfóì²cÄ1«Uµ/-¦J�Ÿ©9ª:¨X3T€PaÔ`e…–³ÐáJª…K:j•Q¶©YÛÉñ§XµÙ2LÛÅ\Ù;zÑ´
ÌêœYæ¯*ÎEòûžJ»n�£Ì•�£?UV2ed´‘¦™»Ê‚ÜUƒÛ©b\µë<R
ŸGÑGQ•ávV~Œ0U]›«­ˆÍf­*ZºíØîÂe¶4ƒébâ«˜› Te4ÉÒ�¯”
$Õ“ì”�,næÍ*êœ¶f«â.ˆ*)!6Êž5Ñ3(ÇdS¬Š•ÎâªZ¤,^#îµ²fŽ²œ)b´lŽU3™™ŒŸ„°£²á•*ÓEû­Î5~ƒ‰[¤ƒXÓ˜NñÏ¸Y°�þd÷¦Kaõ´Y™Á)ðŸSg9z†ÀivÛE}f
vC´Ð7ï>$jjÈþ�ò•"áü˜ŸT*U!×b 
_’²[…)+7^¢ÌO–;±6 NðÀ§ÊC1(òÇH8+S¬uÕÁã3»:QÄ¸d»jLÓ¬ÊŒUg(ñ‡Ý³sþoï�!D¡/1=žRÇ$_*û»„ìæ¼™óT®XÓV£ìðÚ¢[îZf.çÙ¦ã-Èp.#6í‰ó°ðÿ.Ë,­mÈ2Å=¸Nç!<x^øô†gÈh:!rÑzÌGÌçƒ3ÎˆÌ
ãò¦}Zeš×š–}m
}Ë¼¾ö†¾¯¯ó}Ëúº¼¾îôõx}Ûeß
–®7©f¨SG<}|™Üw�Á+“jšºÁm�Á‰ºìYñ¶ÊãmµHõõ!Ðò^j¼
ScÙ¿Æ›¾ê&J¤‘µA"ƒJvW7,öšô°:"ô_‡¿�¿u>é9�¿Ÿ¿õ×ç¯ßãoC�Hëø[ïó·q±—ÎQ8F±$r³G@Uªl’/ÊwKÆ6Ñ™GQùJ·‡«A
M<¨x‚ë]èk½ #�ãÀVïø´­Á¢6yZ¹Éh¶�àQIlli›/ÒPÙíÙ›ƒd¤LÛI¦ºªŸÜŽr·xävúä<r·4’Ûá“»u±›Ž'O�2PSÐs’î.ÿ×tbB�vá§»=T0€‡Q­N­»Øgö¥eUÈmü–¯lh¿°BCYáoÊo»Cž‡$E½KßUÄ.ùˆÝŒ)®k¹=|Z�‘%T¢@KKÔ½ßÁO¬BXÂÜu{ä“ëÞdšj{®Ö¤wÖyÓ@@Ž&¬ÉQwÕ�JÈ…:àU2„µu¨¿A-wy&|�V3BîcLuæÌ…*|	”JOq¥�x0'1ŸðæÅ}ÀS
#'CoÀ·xoÀZ½¡'¹î‰Wû0kçOku(¦:²Áøá8ßáçÛˆsTmÈºeÐ!>-ó[€¨
�y[…WßD�Ù«6À£E^t1&U!ãQ7±s$~ÿº±~]¶F|æ –÷9¨HF“µ�%½âDìñ8#Â:–ÜÀÓñø	´³	t¨ëó4^gkä
M+³#Mh³£Lèäâ*z¢ˆ
�>¿ƒÃnˆÎïca<(Ê¦¤#êÝËU�Sb4�èu-‘“Ÿ^\K:¤ÉùÜÍñ1Éà“Ý÷`iw“’¥Æ#Š´c‚vRÆ¯òŒë–RM.kÎˆË"-¾‰Œœ¿î1Œ”²ò†7ÊÀ<4ƒXRuaáPCØ¿KÕP¥
®P04š'‡ä
˜ßÒÍ§Ò®ŸÔ‡N'#ŠÁ+Ép¾(ªÓàZÖÛ[ï]ÜF”Ð$5ÿ E:-‚NLÑù’,m½Oˆé×wÈkEÞRµøý¬¨ûüjQñŠÒF9ˆ±ZA±4™ö
p˜äMr¾û“Þßë¦¤ä9·¸Bí@(„.„Øªh¨nM[ÅÕéÁÓÈƒ‹íä-C({žžiÄ’�ñJ‹?ª¹ájúT}<}X
¶â�†_F''~4í—÷ø•ôê:6ÓP^÷˜²ÖØÊ%ÌÅµQ»æŒ(8Fð”¦J°ìâ ðœˆAhzÐr¢´Ì)\æ¢T{Žë¾Mï?»·XÓ¤?é¢õø;“æm‹êª
vÌ´�Î[sÅ[^ˆ@WÖÄÛ­Ð
SÊ§ET1áœÒ„/¢Ý,îŸ¯‹pýõ+d§e�½€{¦­ô9©TÇ×H”S€á:b…7>ß)6@J*)s®ÒGòG#Jþƒ¼Þ`§~\pUÜ¾!Jp…á…7ãJx3>ÜŒƒ‰u5Ý£êµ¢AˆuäÚq¥ö”ü¸ƒØ{©æåIh:×�à\1¹Ë)ä9�â?Uƒ}S%H!¥>$Wø—åV5jðc‚hŒÑv%9‹Ïú«•¨×ÞãÍ•:«ê�/&YôP@Ÿt9É¼R¾dëSâÿ)#tÆÿÛÞ›@Çu]‚¿ª~UýÂ¾‘ @�àN‚ûN‘wˆ $ª@�”dI¶ÀP  ‚(ˆ¤¼È²%“^ÂX^˜flyë8Þí8Nœ3Ó9™¤“žvÔîé%�ÌØŸô™Lwr<Óé>>í8‹#Ì»Ë[ÿÿ…‚D¹™±uTàÛ—ûÞï¾»^Ï±À zÖýÎzø|›•¡t
Œºöƒ·çUO¾ìILì%	µw|Ñx"*©�â�7[àœ¬…Ã`ÌË
ünÒÛœ¦¼+øý>—'ÙM1è€Gð1O+©Ã‡¼ÿ>o/ø�Zpº+²gP¾<¶2Í‹‘fQ
b��` ’ac|dþ–4O³€f5£úoÉ×:ªo$C£úd’`ön.F‡¹€YZ¯Ë6¦aÌSIzR¼‡„ð¥ðÿÆB·¨™B:Ôº‡k�rj½SëE¬•äZïuj½7¦Ö{Iø2Aµ®;µnÄÔº�µnq­÷9µÞSëýXë×ú€SëƒF­eF­”û¡î:®ûNÝ›1uouÿÒ£º¿èÔýPÌh?„£ýu®õ’SëÃ1µ>ŒµÞÎµ>âÔúhÌ8?jŒó×ý˜S÷c1=~{¬Q‡vN‚ä?@ƒ(û>>uaŸæpŸæ¸™)üVs(êz‹’VÐ©—Nˆ±•\ðÎAÙêë4ÊZçV3
‰Æ¹	5¦ûÜø*¨ÁÁÕhøØMÖ„š‘ãy&Ïbº’Ø¦ÆÕÅ„_"­‘ãYþ/…
J„ãŸ8´‰&G¨ÖŽÓêqÉ#–ðíc¿½*üæ�'¸‚Ò÷Ï1q*ü2ÞL$â½0…àãòÖþÄ z3&ƒ÷‚B›ùlxY^ <ÚçÍí`�s'�ÓÜí.!ãåÁ#·�…¾Â]Y8Ucì‰Gö	@ÛÅu#®£²ä’xK“úº	 ÃOÂ/–ÑßèŠ©W"íˆ1¥N)ÃeÎá@3æ”:Ïdô4#¡'F·ÑÚÝˆügÛ�²YiãN'H„0BÜÏY,™å’õØ|V7¾c7ÿJmP×WÔ§Ïà•Ù^±Ô§¡û„Ú ¡›ŠèMé¸¦5\Íõí6¡'WWÃ°•aˆ_�9UÙ!áy¬xI“f@¼WK±ÔÈg`7'Qñ¹‚#û	ïŠÑÞà=Ç$£‚èCâ¾äÅÓ2ð9ô˜óLääÏÿtàV;„Îï%(ÓwGäÊƒþ26Á¯`&ê:%‚ÏÊOXîW¡Ü!Ä’ƒÏSk_ ¾Hÿ|‰þù2ýóúç«Ôa;”r@´2Kòp|M¾+¿>hg×`öÒ¸ì:Ìþ5�MÉË™MÑ‰Ù_p³Wqv7f1®ñÌþ†[{‹ÖPÙ¿îfoçì­˜ýÍ¸Æ1û7ÜÚ›¸öFÌþ|\í³Ûâ²0û7ã²›1û[FßD}2ZÔç·”¨ÏflíhH'D,JˆÎ–žûrjÝøšøBâ¤ç¢Åæ´à€Ëû·…,ÁWrEqNA²ƒŒ?(©ê`™Ž»�ÅYÒ1ó£Ók¶Yœ‰TE†fZ÷šÑM/ÈÞì )‘DÒdJSÔÎH)<ÉHòSôøw�“¬ ¦p
È%LÓ(jˆ>t¹,’ÅV«Ylu|Lµ89mž¤i§ø(jÐ…uá+À
”…›Táf,\�D[‹Úæ[x›oÄm¾ÅÝæ(\±ýä¹s CÀ²ó
ŸÎBÅ=‰UQ;�JÙuôf/ŒŽé naˆ'¸²&ëå&¦JSESx‚Ï®ÀFX„"$…±8!”Rb ÕÈcÜmÙI‡vteiUñ	iŠmÉK
“¬ÆÛÒ&/ó·Ù0‰=«H;i«æÄFUÜÍFÝJtþÔHü¾v°ÝìîÐ¢»ËxA�h§®_÷x¿Õc�n*‡ˆïm$š[%�¹^ñ˜ëpœ
Æ8oIúxÉ{ÝjŒ‡P#A¨1B¯©»¦øîš¨»æ;Ù]K|w-Ô]ë�\ÿ6ÑN[ìú·-¸þmQëß†ã\r'Á²4,K	,íw²»eñÝ-£î:îdw�ñÝuRwËïä¢w�i”ØEïZpÑ»¢½Ç¹âN‚ee<XVXVÝU{½w«ë}+_ïÛðzß{½‡Ä*ç¾�‚ê7þR C•.ùPM}Õ»˜CUI`šÂˆxç�@0`l'¥”¼ƒ]Ø8…]´8jî-N'¹ûdýM.òŽ�äd{<àd�[ð_�)ÝnoIèä÷ù§·€ï`ë¡þA“7$—QÞ®Œ4'$Ž<Ä¬‚¤þ ™;\d„ˆ,’(Ï&M0MáblÞI»…›ÖÝ*¥b4©ê!EºÎ–Ž¤Q ðàk-Ê‘õ H3-�× ŽÖI›éDìÇ˜tû©Ç¿
ˆ- �£¢‚
¡ƒLåhrZªö0hV‡Á6>6àa°-ú0°>Ðù†Ïd¡Þ�RÆŸVýùËÇkHjØŽ—#‹Õ»W‹kå£²-wl•¥³B†TI)Ïì”ñF'fÄ<àÔŠ÷Ö¯ãÅ¡'Æób¸ÀÊý³3¢4uþMó [ºXPy,MN<£R,áì±‰ÉI
9Zùå‘Qí¼îQª ö‚R¥ö!@Ýá’LGE‰¢æÅPþŒNíµÆáæž�)–Ëv¦¶+HgK£…kn`ƒ²4c�³0m�NFÇ@™s&EÿÞ•ñ‰YXøQïâL±8%RçŠâ½v”¼kÅÉÉÒoäZaÊ/L–ú°„N@1Ì¦.£¯|Kâ{Ïx"šïB~Jâs´`Jìëg¡ñTÏC…iyW2ìêÑi>4�åÝvC}$õÚ^‘dTS«÷¬Š¢¯ˆ¿Y¢
JJŠ8˜£j¯�¯
tf�gun1¨qP»˜ÔD îf7+Q&ÕÉä%0øh¶dÜ`ê‰®ä'´:¦Œn)n0õr0xùÊÁ4F5Ñ½@¢rÒÑ‚&qÛ5‹_‹øµŠ_›ø-¿¥â×žNd•=9pkJ×ËDj‡øuŠßrñƒÚ]â·BüVŠ_·ø­¿Õâ·FüÖŠß:ñ[/~Äo£øm¿ñÛ,~[Äo«øm¿í¢·eÔÛÐ[}°Coä�`{ÑveÁD°;f’ƒ=ÙyÈÛ+þ‰ûD¢øg¿()dšØlúÑ�¶xÁÁ¬÷Ïç½l-5¿š?Ü+:½�'q8íGÄï¨¿ãâwBüNŠ´Þ´ªyjÞ�ÀYÂ5[P¸Sâ×'~§˜ýâ×+¦UGµ«»ÞP×ûv¾Þ×âõ¾=Z9Õ°©ÐÐ\•ndR§âõSuy}±+­U[#5Z%Uij]MVB:9§ð(äHõC{ÑÐ˜­hmRÀG�sxÙ¡˜Ì“…$*2fF¤^kiêAq¡R…KÅkhÐ‡ô÷PâWY-y�L“6)¶307ë¨’‚ò#µSš:'Ç ž"v;X¹_ÜQ½ª8(ž¢d¥»‡Å´–¤¡¥Jƒ"ìzÈšÓpSÃ3&…r‘"å³4c¼ÌPP)´J¥UìP oŽ«¡6§Ô»“U³ÆÃŠ� ðŒ‘B‘8mÌ°"Ø¥s³3EhÇ '[7-Ù¶`TÏ@­CÔ7=‘è¤ñ4iÉ´Sï¶Ûõùlè~ýŒ33sÎÐòÊ†4L%®™åÕ¨¼ZÒÝñ;‘m!å[\óZ%Ywsˆ·‚pH
¼‰®½äTñ
…ØªCõ!)ÌÉj!Åÿ¦Cí·Lñ‰zâ·€L¨Üº!ñÁ5žfBYB‰ ECª•
·Þÿ´tÁxL¬J�Gñ.°ŒÏbÙm›‚R›i½�ÚiSý±¦™˜ÿ%€hËtì`–úÒƒ?‰´?´ÓVŒâ÷çM	�e@ ÙPúöQÖYäuÈÕè$Á}q
›)`º8XR×X‰Ö®Ó*Þ­¦²J÷%–‘Od·¯Õ¡¾VË¾ÖDöe/Ô´…»VŠÒ(Ã|ZêV�gà›)�¼&®‹Ÿˆ4“Ø`�’DGâˆ	Í�š¤Wò¾Âk *A­—¤)é°À±Lã7ûiñÜ|È3ËnÊ³Ð†LÓàY7(«tFeoTV#õÇÀŠh~�÷Ó~<N¹à–†'}á¦)özÆú'Þ‹\£”±F›Õö?1ž$Ê¢'í)ù9[¬IR[ÌU:ä™ßÒ�‘æ�ds¾ÃªRÛN¾b8¾�aØ‘x›;ˆm¸—A
"K¢ìÙÁ”tÞ)æ¿‹a#Ï@”GØ-?ˆ=ò<ÛmHŒ5yÖWW¯f»÷f#Ë²%é’íÆ£«+Øìg–´óI1Éè€’œ¹'Zræ`p'à÷fo´*˜û@E
C Ô¡ÃÁÄ¦éfá™£ÚŽ.·xÌ¾p$¶*þÍG?2TnÁŒ8>èˆÔäœ'¤xÇIGú#‹Ù½:»J\ú~…KïÀÖŽ6€)¥„ˆ¹¸ôÔìLi²¼Ý26ßpß¨ycsö[‘5U²mŠi¬:„p#ÊØ]qÖµn¦Å>lÑ�Å�º“s3e@˜lóÒÅLqŒ
R\š˜BL
�–ý	­L°… .•dÚ ­²z8’Ù››ÀáNìýY°C04TžE,ˆù"ðhÍAaaicGL�—3lØŠÓø0ë"·ÀÅ±&þ/"Ô™>*^ž/¶;êÝ¯ƒ³…‹@{±½�®šÀäB�^�Vv¬ƒÈÄ:Œ›J
“#Ñ&S }²ó1^ºbŒƒÇ7;1âé�†¸'º”6Äàmð 6XŒ¹2EÏ*1¡áÙ©�±1Ø*$ûÎhÔŠÎŠÕ›�)«Dœ÷¬X39onË@kTx´¬z¢œÙ²(„u U�P…(gvÂ]Œ‰Ç …1†BcjXÏ;€š¢‘[Y”:O6ÓÀB.Ie²\Ä±‹VŒ$¡èý!ú’–Ø¤­Ì¸he�±§ Š/ÒÒÒ9ÍW~­ÃÚ¬ý*,ÌÍ–‹ÓâËÓïÑ»Ø>ï-N®™Ð°eJ…oC–FG?ýv]åZÜÃš³>>"cÏÐëv�Þ€ö[P~¬ð†¹DÝ/Â‹vnZÎ„8eU["½•DÓ©ep-ç�¡²à#c¦	 ‡
È1´9»›ßb¶åª¢ùÙ”�”Ë .�Á�…#ùžÇDô€7ŸûU¿Mµx~ð{Fû§àËÂP´‰ÿbGêHä4ù�Â‡Ôñ–“¥ÈRÜi¶…UÕE(³Êî‹¾YìOUE³;:Ç©K:´eFÌü¤©QT%ÍF1ÁXó‘­>'þNé;¼ÛÝ7:ß°G7[7Ýúw° ÿÓ.zi
ÊçÅ½ZR(ÒÊ§B
Ë7IâzÕ�¥/1ºQÉ”$4t
Ž%ì¡ÇÏ³¢šAáÜ¼¡wï£„­ÌÀçwÔ¢”!”-×ø½45¸Dü–J…Àö…J/ƒ'¦´	ØI^dÀ,7[Ž†f*¾ÙµsGÇÄÅWÜì”òr!5ÞåH YØ[¦Ç’•JÕ¶›ê§YÕÖR ¿Ä=®ò}1 iE!O[pMŸ±:IŸð~^@tö…ýÊ¥²_skM»‰]Æã:~<oòÂCX_a²PÕ�o ’N¶'‘y¦@\Š]¸Q34UÖà´ôP�„\ÝüŸÄ¹7d è‘½‹7v*èé‹XÝ‹ZJ\WV'xŠ{Áxûc)zóâ\Óyc�WXÂgˆ8¡<Ü°šG›lÕŠèNM8ªdÐUŸlÆÍQòÈÛIà×,ç'ÔnVêŠ£šüÛ=0ŸPns“Ù&™+ˆ›X€ÃX»ƒêlX�§jÐJ-oOø»“´ž”÷¤Ï�Ç³³R1¥ìÚÙ¥öÃJÒ‘:<Ô‘Ï†täÁÂ 'µXˆ|�Ã5tœTBixºfµÙJE7æ]ë´ˆxŒ5Ž½ø¸7ºÔæoðû£"r+mþå¸—³ôÍè=¦©9Æ^þ${¢7½³—“îå$íå¤RË_`/WDÙ’±ß-»
+�Ó ¥n…g×¶„rÔ®= ‰<E°r@8CêI‡{è
Kûò q£mæõ:„Dî|wd%Î¼GŒDÌw½§ú2NþÝÐ”.©.×]Îåú%—½V“ÛÁ½õg=êÞ'¿¦
HƒÕñýx�IS¿‡Ío¿D¬Ô
Fª˜Ö‘~#ï¨ÌÛ†Ä½89…£7›¤Å‡½(?«,P…(žð‰ˆh³u¬Ü|‹ª3íæPoÇá«É«”$HX×Â™_^=®rß€Yá|YV…úpeø¬Qî"@|+�`ÌÄc:·ý[$ 5ÑL´à~yížZ¨> }V}H9-O‰~ß0àó€ø=(#gÄï!ÉS+¿³2ò°j”Ðþÿ¶^Óbã5Î”Î-ˆé´Ø˜Ž3¥óæ”–šSzÄœÒ£æ”:Ì)=fNéMò{Z®Õ^w×s¯²·<¯,g›Ì£®±ú	u‰<¹�‰-}ß¼Ù)úCº3Ï§‰ÂCÍÓë-é„u¿…|¬™]<©ºXc¤o¹bµ=¥íÇÀÛ;÷:¤ÎÌ¡xòñãªŸ1ý©~
v?Ž%¿§BÖ†å†ãí^Ôn*µ?j¿¨Û/Æ·?¦Ú¿¸ÈöÇuûãÕ´?j·PP=8to�ãA½T¿LrK2â¯êEŸ`‹;^
:“bå÷mîyeŒh¢ÂžÚ¹‘žu§yIÙ9q7ë.bÜM—CŒ»)y‡”
kYÔ}:x«,16…‚²À�¸>{X~ÔegH¼*;‘°˜ÖþÎæ·ËŽŸ±;¾îøŠÓñ–Š›†®–ð¼æ´ñ-žÏjx¾m@�×Ô½�š¥r×ñÂ ã.Ñbï«(ƒ9jñÞ5=i„Æ™ÎOþ�±›á¹
í½Ë9lÒ‹¸aÞi|p-1>qó*ìFîåùp/±‹ðÎÅ/×xwØ>•^Ø¸¡½'¶R@¹ÒN%©	Ò�P{Q�
ï¥³žäp6ü©*f<ŽØ"üR‡'\—_R^L¸ÍþŸUâ‹ð‚´‡H¸Á–Òô™ãï3Ù¥i÷~ô_	Ü8‰ÄQ^½Èû€™‡×þ6FÂgåQ›†ÎÊM
¿ ­“<	‚õ&˜ˆýÎ•/Yh_²/x6yB>eVËR42
“oòï›ï-^t™pskúœ÷ï¥y9!cæäJYð£5¿Jù ¾Ö>d¾�¤åª—þ«<�Û…¾B®þá×Rýšªþé0DRNº”Î�Ø}4Tü\�ÉüQÅ×þX4_ûVðKŒKþ(Š,úÛhÜŽ#ÇØáSê5º\…6©¼î€8à¿l˜Š@¦ùÇ¹Œ|ß#y¿;Ž|R÷ìŸÂ€#ŸFÍ0Ž|­Gp¯hÓC¿|ŽC­@@!*÷ó*÷*÷¤
}Qå~I¥}Y…ÚUè+*ôUúš
�R¡¯«®†:‚/qhiðY=|™C�¿Â¡sA+‡ÎízSð=ü*‡ú‚¯r¨7ø<‡Î_ãÐƒÁ¤¹Õ@Zö8œâÐCÁ94|�CKbeÎÉÇ²Ø"çe‘þØ"Ke‘b‹<"‹œ‰-ò¨,’�-¢¨ßQP©Èc²ÈÃ±EÞ¤iè	ëç–€Öiã>±çÅÚu8Þ/ Ý+VåœXÁ¥Hÿ;1p«O´à3Á§ƒOŸ^>|<øe<ïDn3ä6‹9. èÇ=/RŸ‡ÔÍÁg5.õ+,&GÒ¿JHÚç±|ðü:‚“ø]_Ä/"ø’®ËFWÚ©îW¨îW©î×¨î)ªûuò“#?)o>“?h›Tù&¹ÈÙã¶Õ™]àìaÛê‰Ìáì¢mõäÕÊžü¦’=Ù‰S=Ú°ÆƒCtgœì‰’:™]un4§ßQIê$$ob‰¡ ¬	²ã!„\½!)¯¡yÊŽ@‰äPJV™‰È(Œ^Ð’ÃZÜ7ÄÐ%krõCRÀZŠ‡k°êãE2¤!:PÒ"pzbö¸˜“ÁRfv³ãè-”`H2HgKvÉ×)åPŠ(sB‰mhK®CI§{�ÜZ@ˆµˆv�ÅÊî.(^±›âjË¡Ë8–¹\¸Š0ÌÙk^¾9C�Åd´¨º”�19þÊÈ(	h†¶ÌêŒAÁçÐûž%GdÊäòB<N,?NkbQa/?(Ká
/NL�š˜œÔ‹ŠS£˜`¨%Äˆha€° ;32Õû$œFÉê*âz›¬~Ã9£Íæ·Å°Çå×²>‹dù+y Å	h1"WÀÓw?¬CJ@€ )Ðo»I‹ï7Eî6á‚ï6¾aÂ‘ýôŠìŒ#of†('2÷/(�Yª/õ›¤F•TOæÚ…†`ª,P´N­'æ_º“8ë'ZÙS'c)P——o½¢à50;¹ÃSìä·¿ÆAeó¡IÙ|hV¼W0ãÙ¢ÍB´\Ž¶|Ÿä!¥]yÊ/æ±“†Û�ß,›&µ—áº¶ÚæÆÛU]íXÆñvÙ¹¡gî´­)Å!|4‡Rìf9q9õ‹ôw¥qâ.æ‰!Ò
Î–q€hÄ%5`�P³îW�M%!.`Ñ—öØh�\¼î0[	ç�•sXoÂt‚ŠÊf$§1¬R=¯fƒÏRºæß„—ØØ¾kõŒV™¼©]Q¬rÛ§Oà–41¬Å�B°®ŸEÒãÇ�æ2EÑUÌpVÌð—æ�sµšçz›½ƒßÌÂÒCD‚MšH°)DYÙ�×ZÑL]b³=ˆ®ŠƒPrû6µq,¼@ZaÊ}y@}i«mýÑ¥š#>S5b;mê–¯™Y›S>h®ÄÂÄæ›\0öù«ÎÝ"Y7!ã&äÜ„ÀMH»	’ë¿Ìô‚²C3VSä'§‘#» ÒÐ®6þ»;_«×Ñˆ¯µó�ìZ:ð‚=ðD4t+¤Ê^6»Š‘}lÐUDê‚ýøi³`K]pê#	ÓÄÇy:ï‚½~#Ñ¡h�Ÿ­U
÷àw œ£C&Øç7páœç×†Šfý(+�5„I
4kZãçj±„æ"÷Qa4f{¯(’­P¦”uñP‹M	ä0¥Þi"×‡d£dpŸµ˜fý­•¿Ï¯õ3z4X¦ÖtŠ±
jqPU?\ÆÀlâV“ÞC&¸öÁÌÖ.°$Ê5U,3¹r´$;c@5&øyùŽàò�ôÔôÁÞL­=wuß„ƒÂ÷œ^/YÕìfó2ºqk˜
ejä'%› ¿óS¸¼õDÃNaaŽÀ¼’Ì©SI¼@”¤d,ÔÙ99bXÚÇõ¡}L)¥mþ6‹«�èW÷½Y•ð‰“¡&{™å¢.uy?ÊüƒoÃ‚.“¨ÔýLîÇ)í¿�1_â·ËLE[×§HTs�…=ô…9
½ê’8Ã¡™ô©èxÈp–[¢?æ{@•xPµ!Ñ›3ySo0'õ0< 6KÌˆñPï­ºk¬‘(
^Ž92ktÛ*r€ñ�\š6QÈL¢W¤&‰x…ý¨Ä´“HäÊJk0 -˜ÊI:›´&´£Ô›t-Y+SLW¼Ô¸÷iÐY½Í–xbl¨5œ•8×Ã#;éÔgPd7xZM$�IÝˆõ«‚`>•9rÕóˆ¥àšUœ…ÇgáMQœ…Dð¸*ðDð$kÁi‘M.ôæà-z*’štÁ]
V¡U¡¢
�©ÐEW¡‰à‡žV¡K*4©B—UhJ…J*4
¡­zk0CTÖ2ý3ËRú‡¸ì¸¥¤Îß•X�¿·VÔù{««ów“¯áßgy`‡	A¦Ínf·ÐeÔåA¤·–å9õ6&Çåìã˜ýŒ›½>¯8o"{ÆÈ®ŽZûvE­Ý…´\Ã'DÌ¦ÖA+§¼•s×Þó
�¨z£.ÑA´¥Zž[Ë°¬e±BzŸžœ)j2˜yp[
Y©ˆjÏ±vÁ±‡çŠs@°{ë)B•˜2£(¨ã…©ÑÉ"+CMOO^óf3®}3fØºCªA‡èÿÃé5/ø¡ýº°}£ntÞµÙK½AC«ç¥Çyº7<Õz–�þ,¿É_ÂÅùò‰M²^™òéOúé~FÉ›ä‹–ŽÑRp¤tfâ,¶&.�¯Î+ƒHMJižïÏâíÉãzgTÝšhº”Ž¿ÞÚ83Iè
‹ÔÅ©“Eêc‹ÔË"
±E”hkÃÍ.”ÈÞìep­@;‰Ë¡¿älïMHÏ¡NÆ—K%VQÊ_ý¶4¢H&}Ëbâ§”ÅDz,ø¾Ü0°½ê—
šÍ×R*hAHs<¤ÐgP¯¯^ Šü4ÙWr+&.÷ˆ|‰'TôçEþ¹yEUkQL~	ƒÓüÂ[¢;'ËåI l
„†ð]Ú'½B&dOšÔU.)“èÛÎù.>]	pûŽš…c<ÕÀ€‚öc7¥þS,Þ%†±ŒÜÏ‚¿
lAÒ–þ‰¬––S ¼ƒ&¹Lª¼Ðh}9Ú<ÚTŸÂƒÑ³ˆvTìo@ Ä`+U­A§eêjÙÍWË¼ZvG_-�ô‡/—ÿT•oœNî‹¿\Âõôõq]<X¼v?U¼T¼&Oò2HJS²Þeø¢Á¼G¦=ñZqîÝ(ÅU6-F9³4ñÏ#S“¾ÙµÙbù|iVÌLÆ ðKg
³ª£ãB]CCI`‹èøë½(ùîC°J°Yjªh•Rü[(�LL@ì8Êãc³µ‰2•��™„(iµÿK@NÎC°Ìt&KWÎˆ5žäiãM]	_¸¤aRënc¤´?=F
ø‹ çùfò–ý)>}8Íàá$’Ì9È^}¾ÁùÉ'U#k"¾ûZ¾§*\…µê*”ƒ�"‹õXVžµ`Û¯Þ¸Ø™Z—×hR5šíÕnaäDŸg²nKìÈZäà[c‹´æÝ—fÛ`È¢Œ*ZôM²T�µÝ«¤þ¶Hgâ­‡dÉevÉdØ¿ˆÛBØMíØMGì”;•2Cl%ÏÓ[¤KY[d…,²2¶ÈJCE5|å?Í»»;|åw‡¯üUØâê>éŒÓyù™z­.R°R]³5D—ÉJºÌsè{U°&X«N{ul”`½›¼aðVƒlDñskoÂôžls8�éR¦Ø2ù½[á²$CãÚü?x\-ÛDšÑÞå¤]*T1ƒÝ’Î^!I>[´r]«Ó¤¬½-ª6×é$ìŒ�v”‘Ø
ÁTY©Oc1bGn7ôu-¬¹lbÍQU}$XNÐñ»(m).iKßl�-ÜT1áç4³skjòÄ²rb>èi;IÍ Ú—E43�öñc§r�Ñ]a½ª¯Ä¼¸¶* xÞöÀs‚Ma¥‘(›`Ð¤*€Æ-Ž`º2ÏÞÕv³ý¶`³¦=žä¼=¼ïxÉ<´o¾]Ôl²˜/Q¸=hæhZ•E<¹¶j<y¯Â“÷ \�6€Ô„ˆE>-^�Ý.¥HÐðò€+£' þ�'ý‘8¨ ÂQÕòhÔW,].’W.Ã"*ý5åSlÛ¨¶Í”ÕÂ?œpÕ»ª-ÝL³|F¯yª)îš1.ÍÎ–.{ü�ë'ŒmâpTþkLlÃ€J+±›°ó²ØG„�e£<	!Éj‘¾¡lï
ÚZÿ™F\Ö.£°\"I-+Å³�9…¼R„¬ÓhËKÊX�w*†ŒÕR™ŽØ¤È¡.˜´'e�E,_¼b$ÖÃÅÊÃöÃ?ZÈOÉBBº4ý>û¨4sD6‡dYÑ5;™2¬³Û‰0B^Å±âŒXP-…H!3ï´6’ÏAÇÚÏ�çÅÒÐ%ƒê8êHç"#â™TÕ®,—xð`£!�›ŽÄyÖlîmÃˆ±Q�Ô8ç!¡­;YçEd‹6üêÚ ƒ[Úš‹¾·ÒdÒŒI&ÍÑ‘Œ ‹�˜˜›WÏi/éKO�9IÍÆeÔbF]8£>oyßÒär²)œAþ [Â­¦›I3c‰é–ÓÌhÇŒef"–GÎåF>Ã£‹^¬�‰uaC¿[d…ÄêLû•qåE»+€Aâä¯dl„(—*³›D�tf@¾sý lzÑRv0ìÂ5›‚5øwí`¨“uy) cW[�¹h¥“	îRã!ù€tÐ#†ÔCÊáé`³ˆl–‘-"²EF¶ŠÈVÙ&"Ûdd»ˆl—�¿;dd§ˆì”‘]"²KFv‹Ø†ƒÙ£‡”ae‘é
JŠCí
‹Cí%]Á«½äìi?íšîªü 8@Ì÷ˆÈ=DÈûT#Ò·äA‰Þg‚CÊèê¹‡ƒÈ›þ¸*ê¹ÃÚÉ~“¢|ï ¿�†•‹�}˜÷)#ÑGlk’'@sÌ2štËÊJ‡øir\�ý„Öù§«HÎï${¸evÃrI°ÈåÅÚ½zžQ5�J‹™àþì�æ�˜•ªz¯±\!ÕûqÝN™ë†Ýì¤:é ?`7d£åt•žÇû�…Wc‡<jP¹08­ÌìÅ• —ÅãJÆA=ç×º£~pP	»€€œÉƒhOð�ìi·é­ü	-ìufÉL¤œÑ�Õ³\Ò,jº9ÏyÈuî�É¹
àëX÷}²ÚÙ*ª=lU€î7L°
Òò^¶ìýKó9Ûû”úiïÖVIÈþeÊ$Ð¯ÎÏÏçPÁˆ¬¦Phî8Û„€dX¦£~–—é>ŽY1®aÀ0‡Œ¥ÅPï•oõGÈ€ˆŒLP½6ÅÓÄA'<ªa?K"ÐÁ£.ÙŠÝÇˆl•
Þ7–\oa”ö¸�†5žžÄ†ryNx3']RlTºþëÏ�%�„®õÈ‚uTÐºæM÷ß+žøŽ|K5Î8…»¤·¬§œë�“‡œ‹�“/8—'œ«n¡§iÒò%=¬¨{qÐÒñÖÞH_Òà—h{/)�ÀÃôÕ%PïÆÿ“~!Ö›4TñTý …÷¸MPY„O®läþri´~¤¦Êè#C °às
ì ¢Ë(ù/¡Ö¦)íšÊ±Rj<5<k
•EÚ¿VYºðà6,'XseåËŽsI%ˆKžãgƒx~ëˆ­pRÀ#ê5%MÄê÷•íšý3Y�=Ó731zfbJ<FÆuP¥²ç.'j¸ÿ"çQvB6)ÒÄ`Q“æüL±xJ%qîÉÉR™5mt>%J�£3ÅÂ˜*�/�’Î”XóQln¦huÐk%¥œŽz�oº4=7­€Š^½¤£1ò
‡îÉ ÀsŠ|Ï
;.ÈL§i'K—‡K'JW½üÜåâD.NOgl¤Êæ�B9
±4±Lçg®ë´ŠþÆB–¸C^IÎ£ë·é¹Y¡
ácb!KWäxW0ÊÅ
÷qè6l´0[€ÁÙÇ'‹3àûþÔPõÿ Ãkñ”¼VOf¼ã#bx£väCÎÛµK'yåÒäÄ(o¯ÊŽÆ(|¾4Í¡D-}vb¤0ÙW˜öÐ�ÜxI,¶X1º©ÑÂÌ™ÂµÒœ¤7=V,^ê-\c
	l
ÒÈzùaO:w°Ä¨xÇ"'ÃàËÍ›ÿ‹ó§0;3qõ<šU.ÕëšwÅ÷Ä‰ žúâ4Aõ½>ˆˆÅ@­=p¤féõ¡Jb	ÓÅ?#s3•J~ŽóÐŠžT”¯(_¢î&¶ˆn«™?„‚£aÍ·j	„8oNÉ¿Tý¤À'ÀQ×Ej²/¼û�Åì5¯Ž%�ëØ‹A2¨gÂdÐÀ"„X£Ñ¨�¹Mè6Œ#ÍÙµ:§%ûßªáÖ �“— ¯.Ž,ÍþÞü¿–‘öìŸÌÿ¹¬°Lõß‘ýþ÷¿/Ëtš‘å(pÍ‘®ìßéy¬Vrrwö¾=µ²Ìªìž!UaµÈÙ"#kxX{­‚Âº´,°>;66&#ÌÈÆì~ðÙ„ì*®ÝlæÐ–`+‡¶Û9´ƒ
C$ƒ]Án®¾'{KÏh/÷‚+º7Õ~�Û‡;äÀ9‹�.þsmf_yå>F»‡ªm7²ö½‹ª}_pØª}dQs:(6ÀË9Í^¹R’‘cÙ¿ú«¿’‘ãÙï|çdä„Yçdööí—¼ëåˆr>^À“�ÇPóEFä˜9nFN˜‘“Qs/Nè~‰ìŠ/ö¼THNj'0úªñ£Rj�ñya­JÞº	®Ý—·Þ_mÜìVíUûLð�U;ÿºj,räg­Ú/²¶½ÉYûœUûü¢Öµ;ûÍo~I®«„GB-	µÚyl‘zÓ€½é0r0ûþ�¼_FÏ.ÅÓk	>ÅïIxõŠß[ Ê¼Õn(Äm<…E­�-
vùûÆÈF«ÑÚ…Eµ¶$[#Ïó”8¹
r�èî0Ú^ü²pµf‡ã{Yä
M}t‘S¯ÓÓÛ†¨MÞãy5ÞÒÏ¿ê¥®y™+^zÜKÎxÙ/(LN�¼VñÂö–\dDÔkFô¯,pš[ÊbóX?ëæ!è"`.-L$g=RŒLh�Ídð4DjØl$›z®�|¨@-€ú¡ÑÁ6´jÈÖ"Ê� QòO\USé-Ý0
¤®f¢uy·Z=ô‡jëA½f’‘ÍŒ�ýç£âÒ«»Žú¤¢™V³ÃÇP8æ˜OÔ¹†ZX›)¿!(1Á¼äJ¦ý4Òæê ÷­~kæÔŸ½tôÐËƒŸ­rT?yÔNÕ€[1
àYÌô³É¾VÐ
lös~6˜A™±leQXfeÎÚ™«P?›2¼Š	8e¥¨Ê)^·\g�#?é'3Ÿüô>úí{Ÿ«íÃz•|íÝß;ºë¿þä6&×±Ó´t.Z-ÉzgLãþÏ.\æŠ]¦^—Q1™WgÕ÷©þU£¾Q3Y•*Z°k‚jãë™9¶�¬b>õ}v�º¸9ÐØ3$_­æ
,gÜ�¯yÜb¼µR�Ôq}Ÿ=Öº¾P¿61Ñ'C¡yˆ‘Õ¼–‘q{jõ" Zßçì
«Nhmå\e9§Ê{¨Ò>u¿£(ó^ð,½ñ>æYx©‰>¾
ÿ¾ÿ¾Ã1µZ‰é`¡ï4°Ðb%’¬ø[D^’•‘˜üÜÂ=>+‰Éï²¯I~>rNœùng¤‹£¿GÑŽ÷á�6lô€v¼/žv¬Ý÷Î7t7@Å›’÷V&ë:U:˜3Ì‡b=(ÕR}z®<«[”0®Óa2Éd“�f€äXiR#IÅ1Ëp,ð>SD»^,i�Ò7Á'DÐÓ®›¥[hôB3�’”¿L>¤Ë^oqzv\z”¾Ô3Ã$ÚñYÌ6}7‹QZ™Ç‡ax!eƒ4¯DŽâÿkÞUCIöCä)™c‘�Ô¼&(Okkõ1ae+“Ggl…�dJ2é$É*£î|{f–©¢'Q}Œþ¬ãUäjMÓMu¦#ÛÐÑª]�6Ü\áyi”TEÅj�Ÿf
^\x‹íãý0MÉ�â×„œLóMâ:~5<��êÙß¦ˆwÛ
?Åi¼e¥™Q\]¬–Í´Á¯ºÊm¡ÊKH÷¬šÊKB•—úèB¹šÊKÍÊ #—Ù³ç�ŽîÿÕAT!‡`‡i5Ü×ÑæŒg.#ñ˜$ëß×’y

¶R7ôÇ(ïØYlwAŸ¨ôP¬/ú+·…*kÐ/XyI¨²ý‚•—š•=5©�š”@E)c¥ŠÎ@}í ïÞE€0¼{Âðî]k^ÿÆ
ÿÏ	­Ï
'†°:Ûj@•R>–Š2¶DuïÈ—”~}_ÒÃˆ˜áúÐµmíu6/µ&bÆ!{S‹Ý²¯{¶J9Ã0Ùý.Þ(ËI(÷F–…Ê’_£·XEVÈ7¶m(ƒÄë
ßC²B·VLŽ¬ÀO�UÊóØO’úŽ4EIG{-UéñRˆ‰	TæA–›Z‡ÖkÅˆTëÄ#>›–ìœ.¹ÆXõ(è¥¬0RÄœþB¹->lèdlÄN7áß¼ûÓ²&�g³vo•¶(ŒabëýäÀm­F·D}êBI¶ºúp[O+§.ºâ695×í¡¹nÍu;,Gà×«Eú:¡Ú!ÅÀ¤H †Q=z‡ÜumýßX¡T;­I"êaNg—Ï¢:»�„oðè2Rö}?+7• ß¤ìef]<üµñ›,*\”|<R§ªGßo4²ÌytXøÑ¹J>:]—íÔ6g\¼dR�~]R¯Ëý8éç|¿óº”ïžíÖ»g¾ác�PóÆ»“‡"ž—Ñ�%­Öax<×ºÖ*âM%ßOçKÎSJÆN'KW¼±‰©Ñ<Hd<S˜˜„'×ŸãHY=ÊN\C•Œá9Ñ5Žv.Ë¥™ÙSsS(@¤p³Åò,¼4‹3ÏG­ajÕ9ØKì]<K“³bÊðR¼\
Œ£´Žùr´k�À¤OŠ§/Èµ !èK,™17í�BK„Úèa–zŒ|Þ–¯¦yú 
#&C
 ©ðÔÜåáâÌÀØñ¹Ùqƒ‰ËÅ3…k°�Êt4YnAS-%©A>-fƒúêÞ¥|IC„)EëÝ€Íi	Poh¦T²Twô~57ÒÝöp}_XO‰«þl9-%QÅ[20�,fr€b¡äœŸ@‰K'¹ÆO Ê¸“\ë'Ð¨Š“þ�ëÂÉõ~Bžqfr<2ÃÉð lÌÄ	m4‘½/Ðî(x‰aðXlßoÍîýÖ<x‘í¬1&{À.;Â´�8<‰qx»Y9|ÀµæñrªEe	¼I½	n«íæ&4 ¼ÙKisÞ>6{nº0Rô’Ò1ç=m’Ô)aÆÑ÷À’üØËÒ=dTþRÌÏÞþaF�Â…ÚóÈŸŠ³²Œ)Ÿ×Ù†O>¶¡ŽÅ5”†aáÌ|¤Î››%�LËÿhÀÜ)0ÀV¶7˜jz¼œÞKYÞ'�„ÑyF`—kíf�è3Ë
É#×îuí�V½Z%öt]—ÖV³X‘—
ü"²’Šª—ññý5ŠÝ˜F/jôPÍ¶Ðê¸Ïà–¡-˜	ª,ÇðÙd�ä$ak°÷Xe¹‘fê ­*õƒ±iÏ–ü`5é8ù¾\…àf�\s³þ|À®õOqr7[Ù#™¯Aÿõ�¿:l«qÐà‹)îå50¼}|>°Ag)¤$Œñ*ëWÊpú:š„?	ù^M/`©ÿ³ú�¶K±LN†¸	ýSåÙÂ”8ø†ÔöZVò[ËÎG¥uOsº>Üv’Ä%g�”³Î
ãÖ
Â‘OB‡4wØ­Ï_äW}äÉ¼>¿@mÚjdówáæQ°Ö ôzá
½Š-¶Ž£bµÎ6–@ŸÙÎ
ü{ö˜]Í
d�¨¥�oÁÈT³™‹z2j�31¶.HÉ1œ¾1ÏÆ†Mr¶5ŒÇr)²!'Wk­ëž\+'éN¬[ÙCG˜žE—s6,HÂ¾:ÊDº±è+,•=µè1uhÑ3áE¯»¹ÎòìfùÙÑ{$5ªe™Ñ‰Òéð¾³�+C[™â3æ�¾.íC§”Ý¥�ç‘ I*'ÁÊ}DPÛ¬¬2j4®ð°D þtžp‡ð'B%µç*©LÕ×ßÜ' äÕŒº<G¨88u8a–U'‡3Ì]G}`sSf*nÊmÊl»ú2ã6e–7e.´)s¼)ÅeUGàß±ŸA¦â"á|¡Ö)a!¼Šël!‚ÍÇnjÏáXõs ýš•ûunâ_Ÿ�d“éeë Û¿_‰3z2¡Åc)P«=¢dœáv÷îÜnÝlSZâ¦¿5ÛÐÃ‘zŽnÞLMQY"®eýí>lu�¢)ø§å:+õ¼û ’ð�ßÆ)ùhÐýâ™mïRÜ“‰30ªX~Eäµî×8SOÏ‹?=	4}‘ËŽr5ðÝñáû5/
f!øî¨¾µ§Ï8Úmcg€kmW­óŠƒÜ
OõÚÍ^�FØÆiòŸü0SCÔŒ²^×‘G¦]^l‰�„DÜN„9'00úòhÍ²�j}­kòk
Ø¢*ƒðyešRÝ…#é–¦Tw÷Ÿ¡ãã9 '«ïúÛöÂåè€‰ÁŸ Â/yÔÈj¢øl�¨Ÿ“Ì#>ÛöÊsý	rF!¹LnM‹Ââvèè”Í§CG'ráþí«„
¶y
ÙÄî„M§OËã,+MŸ*–Ö�q+Ç/˜ï{áUù
ï
X•'»*1pJ†à„=2¯á¤fÿ·^ÜìùÅðü£žýÞÐìGõ.‰ÅúOKÙ
¯ËÈD|à¥È10sÚ�’_	¥ðyÆ™Ðzg4ž›Œ]#|õ�(<«‘ìàe¤¼ßñÂxDZQ~Ä®«hßOº›ª·CÒÚÛ<…çC‡ý|4‚X¶‚€ÄŒ�×x	ÑÇôö%Üš�Ÿo”Ž…×g_Õ‘
ÙÄï‚NF6fŸK(ÿÃK²EOE–fÇt¤#û‡:²"ûŠŽ´gÿ•ŽìÌ~Çc!ûhÖX+Ü¢Á>Z±ý˜}`�Yc÷Ä°ÆÎUdm"“Së6#™Zâ˜Z(¨™ZÿWÔ¼ñ/2«ÄÔ²*¬,WÂ�í¬±:ðÙ¹ò8{Z�N+ÇÆŒâepš:ñ,©xù¢�‡
WÅ½Ý?5Z¼ª¸=³2A”·Ö‹`gìê¬*<Vš¹,‡9efÌ'K#àÙôÜµòlñ²œ,-�ÌEk �ˆ¢–è9ÖytFÉ¿è)PŒ™ÀŸ��„œ)>S�é¤a"…éÙ¹efí$zUV×®€.ïœTý·¬M+iÖ‚È{¦†ö¨9þ'YpÕÎ‹Ô³7Q~¨4GÞ2�O5+V˜2¤…éÑ¢jÎ1_
2œr Tì:�ÌÎ&eÛs3„¾EaŠŒ©còøäd/õ¶¯ÏgU/£’¸Çÿhzà†êVïŸ¥…È	®¥hÙ�6ªMS°€ŽË¥¥N/{%åÉK`
@Ô;é†s`˜›-ÃÚ–¦zg
EL†žAƒàÊªY‰ž­ë•‹…™‘qXž!öyê…éM“gV9"ªCc3åY°o =‰âNî/ÃF§0fcSðyˆÝE	Sb™Åž�àÐ>ÁÐº¢…B@6ÆêÀ~0í@8™°#§FÉ´ßLé²úÎ°PžM{›¥Ô2|¡/bBÒ8øp¯’MfÓß‡aJ3Žmw}BÔ<5ƒn‘Cgˆ!Š|’@55Ú*¤…ªG&'F.9&Íá˜�oaT�oÖŒÇ'fÏ‘å+Ê—ßûq¬†Á7Q8ô8cöC¥)ý©iÑl0ì®wíÅ¢ÞÐCW±+q²Ð¿\ÿÛù�ÄÙs³4P	{,‚ùŒBÙ‘W°¸äan{Œ¯à°‡`Í"ªh Æ$AøF0­‰Z§öÝÆÿÈš.x§,¶“BGÖ”ŸBV½r†Ã.Ã.ÛÉdaeDXû‚’¶—kCæÛë T«|©&±ŒýÖ´¬zê4Ûã¥KÞw]ÁAE"œ8ma”ŸS%eÓ~Æ¤ý6 NHÞ_æOl4pÇÕ:
ÈÊYl‹Ó4—…¼w°�Á­6A¾~P#áÜ„&£wÒ‡ßLI7;žÖºµ%yM«×lY¯5Þ´Z³rÞÛæØª~4J±(ÅÜfø»tÐ€W»–¥„eF‚Vo2%)©;éEöÉ„CHë”›c9Ë&‚.ñ[�mÊ�ìË¬•â×íèsÖ*ƒýHÄ”*[í'¬xSÚŽc·Èlai
lm�âR"Ö’`"XN¯¾N)…×¢=„K­—¥6 |d£;—�˜¼IvÞ3hÚ�ÞŒÍmQ0ßxs°`‰Ä½Òä(Y±MN¯P¨‰™w[á34_pÛœ­÷6Ïèg»ìØ§‰`4€¤µØÆNãû¹—;ÚaV“f¾;¯5à‚=ÚÀý^5�}4&_Žé¥ð˜öÛcª ¨q Â0ã=LU4 Ñwnÿ�:¸v†ýÝ«FzPŽ»ãcbµñìTH
‹…ýºœ[†…oÔ!ÅÖn„3%]â‹óT‰s‰ØJ^j
lÂƒu¾¤NÆB;òš!M«tGdÏðpÐ@+UMOH‚ê��e�Cx…»?„[àHØŒã«ÀÑüuÓY,$cÊ†cvóŽ“rãæ.ƒ^p"OÿžÔnòè³é´:Þ©;Fsƒé3~DY‰¤ø1ß—S¼ßùr6xU|ö§ÔÖ9nê,�àR%’R,<ð’æ—~G¸ƒãšÙÖá…N*ºŽ«Žïá=îY¼ÿÕ36U“`Àü*w×glÓ'#ÒúˆÊ§îŒ„Û˜Áf¶*¿¬�wŠŽyËå½jæÛ=¨áŠjgæ±ežÛÒ�EbWpÚ D!hÞkØœîêºú»dÅÃÎ%¹Á…_ô1"«?ps?Hl×÷xÁ´—™@”Ò×Ï®ÜèÄŒW7Y*]š›öjðAD‚¨ÿ´ö¯ÓsLX8Í7k$NC¬¯À¯
ã4A¿â€`*ŠßƒYS;y«•ü‡2Y‚ýÒh­DYöe™ü dö›¸3Q‰E%æ£¢ÏF%>l$ÖÈÄÁ®ó0Ä›¥è9>@Ïå5#ç«¯’¦Ð9L�ˆìyFd7&©ê#FóÀkc¿u6µñ„¸¯?ûª‡]òQ	BYrÃ«ˆ€Bó½Fs¶ô„LÅI<†'Ç#y‡âù&íÆï¤Æ¼Á£›¯Fé°üq£Ê¼jú~¢rß0‹¯]•…–ÎÐ³ÀžÚ<â£¦Û‚©yA=Áç¯ÕP½×N •Ê�òÁô$�·Òœž´æ´DŸ’M¨âzÉ‘<I”âÕl‡ùÍXƒ/¾·¨ËðqF6íGÅ÷ÍGEFšËÅnŸ"¿!ÁP^‹[9ï-ysE/¨‹V÷W`|.g¯wDÌOà+hŽÉ9H’'/k‹¹/bñÚì*FN‡_Y‚¾¡#+ZKcäqC´4Kílµ4gˆÈ±—ÅNÌÜTZÊýÈÍµD‚™ëmº »àôpzaÐ]Xt¢Aw¡è.TÝ…Eƒ.41t>4‚I’+a6QL†„Ép4L†+Àd¸2L†	“ˆ‰™0V0©“®ZÅ'6² LF¢a2R&#•a2òša¢&fÂdD�ÛMx†m"‘±3„Ô‘™¥Í���Q±Šæè ’l@þüo&"0õ©JL‚©³	óž	ÿ»²_Æ>ð×6†€Þ¬�å’ºdè�¡e0Å;¤@§š5¥ZØqC^R‚~ÑÞ,cõ±·‹yÃš€~œ^pïvÞ”æÕÆ/Rb’†ùp8¼çG6^ËÊýÍ¤È3;ÐÄ7°ß£®Ç—q.?x!åž|³óƒ•Aƒ³ßâ…1�¬,nCKÒ~Îã– °ÜªkÄ3Â¡å”Òð˜z7�ÝÜÆ#r=ž_’8~ZãøàøY·Q*y$•„JŠñõ²ïPdÁ¤_J}ùò±oè�¶EVC{Y±ë wŠUÉÐèP£¥Ñg{¼TÉóiôI=z�õÒÆè;=h2�¿$�1ÃM^4_°'<óí¸C
‡«¬ÆóüÔ�¸ß·qãŽÁ/û´xéD$q'my%&âŽ¤¾¦û
?\øâ Ój Tà±Ô¿’þ9©=eæåÖ~SÒ†7­±9õzè�gëSÆ�
ÕøÁAšƒ§,¶€ª�jcPZ'aõ!"`Ãž5ü$UìéA>¾
!¾s{ô·b|i<ÉRxLŠ2ð„¼Y†e`D
2p!ÅMŸ‡‘±p0:üßUJŒú‘¼³—%QRHë,?	:ëÐüŽüÀîÏÂi[Ì…*(úX½'om™²Ç³:«Þ…P½ó‘í.ß‰*–/é._’—ñÏ³Îž©rOThÔ8&ÞO7
ß+÷Ø¤5ï'Bó~L¥ô:çðË°Txˆ¥ñ“°¾�b¨¡7‡N/IÂÍr‰xBš r\º™4Æ)ÇPg¤mQiôIk-˜LKëÆ“tAŒ;mà
Ñ*¿Ï:¾
ž–Õz@­'¤ÿî@s³¾¯Ìe‡8øî�@yÈšréþ%D—ÎÙ<úº§‘Tï±Ì.‰*´mEFP×ßê�ºV£ïÒ™ Œs1}—Öá@gUÍ903‘õ’Œ¸ú®Á=¸ßP¾E­jQb§Y>…³æ‡´5oÊ1�ÊÆê˜`®‘�§0ùÂÂQá¤wŸôƒòR«%ZT‘b›iôü« ‹jÝ$˜º¤cÕ@öBÕÄÖvÛÛï?¾jÞoWœûí¿2wå-•uzóõCÿ^å¯!’bŽÌ–Jd.oþ¼Ù¤ù­=k˜àðRÔX–Ô_l{ŸF
0I¤|(�ô£yÅ„Mù>ÝúÜ%Ù^Ê,ÙÞ�%ÛËNV²u�£~†?õ#~ŠCÇÄ%Ä`{³’&Ö_ó$.Å¼Zj3³‰¹ðö°3Þð·kpÐÐI—öüŽAötÂÍyç £¤×ÄÐŸËsäªˆ¼Kyž~Þ9NVñ	µ5¯?ö+Qû»M»6E^˜œÄº~ó$­ÈµØ†<…ªû”ñš÷0súiï{1Ò°/Ð†ÿgQÙ¢�"Xˆ>Ê@²vV3^”œÔÕú5ù^ü{=$bû^ìêzdÙ‡a&Áêðäww&‹òšï|½ß)ÎÉ>È(Ò/pQ“‡6¡B%…¥íàBŠ…Þ´¾î_Ä¿’Ø@

äò%9ÈJ§”M>?¢³«ôüQ%!z¶v´AìF±·î‰“µ çþ"€ª7Ú“÷TµkiQ””2å�Ø‹nº$4eÊ2’kÓ¡«Ç]ÉÉ�(åÐP8éê`„yË(“—CCQ©®X&Ê�ZR�ŽH¤UÚó²d¾@tmx’ì(‹Žjw®†#Wr{^ ¯g¼AïÌyï¼ø{Â<á)ÑTð£dXòl!Ôj³åY
:Sð&Xf»'\Ò”ÀºÛ„®NeBÇM„¿•´iº#óñøðP~:}Ìe
Ð©¨2h53ò¬³ÏÙ“	Õ¬‰t/Ë×br]Å2õÊˆ5DÌ¤1Òª“(Ü©ÓS¸9¢pK\á–HAøe™D‘ ÆÀÂIdKüÝ`)f·«»jÙÇ³ÐÎ˜§V¹ƒoÜÍ|ãî‹5ÐA»!ªýNÕþrj­öiÞ*¯ 97Z�.Ö T	+L¼ie^iw$ƒnv:«Š®Òi9?[+�|Õ+é‰ÀÏX©¬°¬îg|Ç–¬C%çµ	*³ÆxÝA;2?Åùk£Û@ÉŸ1¡s�ÑŒPæÿ/œ¿^>{ÝqD5ÊoÚ`ƒôËªäôò8WØ(+˜3‰êaWØÔ¯Y]Ál=z7ôhd]Ô†R�ý´�kFlšÍDK‰Íßæ(*äw�ëÌ
ù+uŽÚ·[QØüñ“0
Ý£–v¨-¾“ŽÊwÅK²ÎIä�cÃnÍB�,�oD:¾”–
½`—�§cÖnås�îdï±OåKÀ“öžgUâIžt�ñ¤mˆ'ŒÃ“@œ²0=
¾áÁíø¯|¥ªßÈ&·VÂ•Â5
�šñâÈ¥~q/;•qU^EÜ»=„úLHß”å¢öS�FE#>Ñˆš2W�™�‰C¸Òêˆ4¡ÏMöHHSSº*Rª^©ü+ÔÊB¸D
Ã�bŽŠ7U\m¹E jåéÉ‰©k^$‰µç.¶0~°nñ¸‘s…¾:3´FÜPà\Yˆ;‘•j*>YIn#VI¸YÑ}ÙÕY‰:Ô1Ë¨C$áR“lAK<¤ðº3Üz}NŽ*"_�ª¢u3šªÑpx€Ì#�‘—�A-*Þ¨N×¦ðh_²F;ä-Øj|–{#/)5G	ö–ÃäuÕ4/ÛJ_ó4/|o2¢q¶6%¼„ml/É�“Œ�%Œùtq)$*<²vü»L¯Û;CX8ì ´M›‘FNé…¯æ©BX…äC‘<ÉÄ€»ƒHž&•t9RvÞƒ`Ï²["‘Ü…dÍIÏð»½ÞµT±bP²§Ù(Öm$iõÉ.†cZµ`uÛY‰ýmŸ'>H˜•%›œd±E[¾»e}BumÍlö5­6×jãÅµ:
žöÆâZkŒZ÷ÆméÈ}ÙÞJ-D;ÈnÜ¾S¤Å÷Å—!¦ü“ˆ�MäÎ¿I@†Þ$Èµ‘Ð]dàžØ;¡[®Oz-M:³ÙóÇ¼‹Qµ3é“ñe4‰qsþo1_c;Ó—Í¤+ÎÙþ„•NQÂ`7Úßr‚5ÔSøÝì®t,ø	ž!”üšŽ VQ_¨�‘ŠgÝÄJ&š^1Ë+Fiâ¬d¯ÿbÈêŽ^rdŽÝFŽÓ=Œß}uñK§7ß:ó©Ê”{�[×õ–ÎLäAÄmo ¶}üšÿ¶ÒÌÂ›¥ÒùÚÂ@e9¡Ù…Žu®&ã¦»¼Aò.Çˆ›ÄFÉÂ±Ö§wžÁ±‰0»¿�¡gõFø§1¤¬žRí·L¤	‚˜Âu…ëâ
7UG¢Â­Ñ$¥èÂ!êÌ†Ç^QxM\á•…WÆ^Qxm\áu…×ÅÞi‰d€ŸÊ=Šõ°Ù©»�ÍtùÞ¢žÃ‡ð#9Ú°Ëƒ�í�óÛ‹Wg·v ]Þù†ihâÆ«"žÄhA‚Ô€£jëg±‘8ŒáQñÓôÊ€©ã¯lØ¾©¬'Ÿ¡x®u°KSNL²qÓ¼E…|Ü›±LÎîÁ�ºtqEEç¦ÎO\.ŠÛºF´þ¶˜}´‹+³1#94²»øÍzç¼býß!DfqþØ“=Þ_Çœ¦ä^ 0®V¥îW·|Èæv`�ê«Í¼‰PÃ¾Ì
u7[$W¹4Év;Nð«²ä)ƒ:6.Ù€ö•ó$xkIÂ4EtÔÑÑú¨Žšl|¨­ÐQß’×½ð�onˆ-RŸac+æµáß%‘š¾KõµŒeâÚ`lA1ˆEs\^‰°)�5r­.güœ¼ÂéŠ“W:³XœÓÄnuPßËõz<¨ïu�&âI´Ý<‰æþ¾ªÝ8ŸÜå21|vélôPþ•ÇÉœ0-Nwðí7QÎòd‰CDQluh²øLqr§7‚ælT�þ)e]c¢Œ¥©ÃQàˆlƒ|9ž%iô!—B3Ð&GÕS£�aC,œi8$ŠîÔ‹65C•¦J³c×°Ùã1Ê*×Ê¢v1Róó&¦ž)L¢aŽt|H`áAÍLL]Ô>Ë:Ã»„4ÄîŸ/ÎLÌŠZ1WŒãRû™€Å…*½¢Ýºvž2®Õ�§ÅˆâwñE²¢>tW&~&‚¸Lzµ=^
fcèãw§PÈ(jQx™¼,[ÞÏ2s*×Ï"‚ú5Ps’ŽU~ Ôj‰/î8,—™“ñAÖ¯—/�n¸‰Rÿ*ñFgÜˆI}1/î&ºc*Q›øü¼enÚ,ÒÊDEãUwRÒõ@�1ûwÿ?‘Á6ßÏdoþ_ËH�-ýñ<F¬ŠivQ–ÍþÃ?ü*…2ÿç2d¿ùWìœÝ÷“šÛ›¦H
J½å”ÒSåÈy�›\ƒF+rA›”[Bf,j‚¥f
HN‚ée¸ÇäñOë½IêÏóNë 
Mƒ×þF,mü(:µ!˜V¶#`|Fàí½²nÛüŒc¨8a[_NpÎ[Y*®ÓXÿôÍœ¸ÂøþVê41Æ•‡Ú�¨Ÿ:d›’ívLËÖ²·³.ß¢ËÃÒ¢ì2rÅ�ëñÒåñbqðÔˆ¾´uhüQb¯IlÎFÌû×ÙÛ„-{kÎû]	sÞšã%×ZË*T�H£èwàIÅ©�”`b%´&Âkô\ù¤Ž„^SI¾àyËj†ß3a·VktÈÓo?c�¼ø7gKrÚù>øòÈ#¹e_ù	{F#díš\¼®ï—†=mø°?¿°KÚ� ?�òÓR,y™ÞØ'^Ufs6±luJo_ïù¬¾:p¤mHö.ø‰c)aÛ@2wÁw¬ÝÏê2¿Å‰í¼&–öv»)Cß¤SLÆFaÅƒ}K¾o}KúÓÚ@•ï@4‹úHÑN
Ñ4@ô¯%D—Ð
ÜÐ“0À˜R`Ìùj‡8£JØ£J£ÂãÌAãœVì}8™4.MóÐŒ½Gk™ó¢{Ñ@4îC¿úû°fáû0·ð}Xº3x!dü}füœ¾3~mô}˜ÅŠYQQÝ‡YQQÝ‡YQQÝ‡ñ5^Gãô>j·A¤¾Ý0vO_ŠÊˆäz7¹o¿ºÐ}Xoß‡,>lœJ—µ›¢ãŸg�¼×s¥\¯+·¥+ÕYÈˆ¾/‹w#‰ü-¤¤ø.]Øeš}aßé½ç¥Ò7°qÐ¸#ü ú˜T‰$kåÚ¡�,P •ã…PK™¾
s¢3!ÅÇ´bþd—-m¹ì/ðø,¿6ÔFSæ¡j!½M§çx;öÜì}_$®ŸV¬�ÈGõuvœ`en‘/îJ#"ÑµW¤9Œ,ƒå”‘NZ^yFv7>¶êA¤‘K±ßäŠhÇtÚoæ¶J‡IkØî¹ZïE7¸�éÝH7¸Ï¥\š˜*o?QšEið5I¨pãC^sÅÊz\6d'˜¡DxŒ)Im8r¶p‘Û™¥÷þ0F‡.�°dòÝöÚÂ”Â7Ôö#Iét²°FÈrT hX9¥äà}g•…Z(€VóêÑL¨è¨h<VíÆjRë0o¬µ¸±Gn¬A±%ÔæúL*Ýøqb{ìæ2Êë
Æ	,ÜÎ¶˜Õ¿˜(-3ËîB ù{(%fW±‘‡Š³3#e¯46V.Bùa+y²86ëÍ
Œd[&7¥Ü‡]ç�)
Îk° J�j"‘ç°¦«q¯<^-]ÑyFí¼NÂt¶�ä
£áU£ewéa”ïÐÈlP˜ÚZœ»í^•zÃ¾aÊÌ˜ßp6d¿5Èksn^�Ê«]èÛ¯5¼LÙh¡¢õªhƒ£ßøAî·Q¿A€^Ji¬µÞ­L
šÅMÖ"~­â×æ'Ñ
ÖI@ê�yª((ƒ+oqâ­N¼ÍˆQ¯ƒXÓ©
Ê¬ÛRCjHièÖ/‰¥
íUeƒÿòlíˆ:[½ 3XÎ§l—R [¬äPw°ŠC«ƒ5Z¬ãÐú`‡6›lu0Òeì‘èÐfG[,‡Ù[â²I>j«Î®òlß¦Îö#|¶“»�#‘g;�ã·“	çs"Aðïï€š7~�Ø{ÀC%Ï¨¤Oyãè'n÷x7n8€O‹Ö žul*ÊºÁX�„{ÃÔ8
:{c…ÉrqnšþEçÔ>B	ºSúD™øË³3sPþÁ²PE1U–ä¡^“�«8ÞA8BqÀ3…Ñ	‡ro0ÌCv³� €rí|Ï\[×Š<Ð�?Ä¨hÕûn;Óï;ù;Kcž¯åŽ KŒ#}SDZúîŒÁóœ+c§[¨ÆõD];hX�®³¯‹$š›¹â%Ç½?nƒs¢^¾ÈÓZ>¶Ò|}=HFÚdl$ÏtHñÅIkã£­
"ÏúY‘MYŠ,…Èwsi‡È?«¡È2ˆLÖS¤"�Mé„ÈŽVqµµáCVïw’·Vy(á�½}û%¶”4…kÁrN]§,EVˆ¬ð²BÌ�õ»½`¥*�}þÌÏÏ{Ù={öÐzœ1èH’ÜÕ‚bŠƒvãËµiñp·*GôŸÓý¯µúGh|ï{ßÓ•õˆP‡Cá1ø±cHÆŽ!1†VÃ;Ü‡ç¥<9.Ia£)$î&ÛM*¶›T…nþæoþFu“­¦1Ý€N\âÖöŠ»W¯`ìnÃÚ?þñ�½ì¿ûw¯T±ÛZiÑŸ\ÅV¿÷½Ï[pÿ´Rúc´ZÕŠµR»ôg±ëÐJSu+èþ—Æ;q6DÀå'?ùÉOïÛóÛíáwu‡û0æx7œâÞä½Ž3ø§t6ˆåh£a¾‘Ãîú;t­í~= �Øú?‹×Ãðç×Zµ»w¶F]kßùÎ·«½Öäð~øÃVy{ETþîwÿC•—T\Ï‹¼¤Ät_ÌëíŸß3?¿gîàÇŠ˜Ýù±þËÌÏwïÏwï?J,©Îÿ9–„°æ-ñÿï­¯çùsL¬Ú/äÞÏ&Æ’"ÝL0Ýœ8e¹f3Éûü»V
­CUš´yPb™=ëƒ4‡¢ÔóÒyÅÍIshSÐÃÂ›ÝÞÃJÝRäcKä§6²UqrŽb¯’“s4ž“c±êÿy+Ô¼±.õ`eNN$¿Ù7Ä‘A[wÊçg,Þå‚+Na²8S-›ÞäÈ“n‹Ëf�eh;iý—ÁáTiªâ³GðÖCÌtê«0âÎ›IŽ4ƒÉæ"Î«‹PgI1=úÂ,÷Œò<Ks³�k0º"¹L³âÿoXü?)
”¦ÉïÄts¹85Ç­�”.—ò¥©ûGaýÀMí©‰ÉIjZ+N�bÂkcZÍ¨­B®i«ab…%'là:€
‰9&ÇË–(—&'"Ta~Fy`¯4þy`i[ZÂöPº^ÉLˆC-Èá±æšÂÈ*ÎV
ÕdíosíZ-Ð°M[7Ý·*‘=Q˜ºCAÆ�ÈÂ0ê
SwfÊÝ
ØßïÖzHkšèLn&Q«ŠµÒ­EÂRãˆ3Á×_ì’|ø“	^.aó²Kó¬F“òüM¸ÕSE’,œ˜‰´VÈ9r'‡©d©MòXšÁ‚y­Ïf|œjVÜjËò,#Z+ËªÐÄŠ�$+ÚÊö·—‡ZnÀ–Ü–—cË
< ®PµzSYWëÊ³³”vªÕ™¢ÍºÚŠ¼‚N€ ±S­«ÕºÕVæYt«u‡ªÕ˜DºZwžåÆ�}š–û´6ÂJO"XÅ»ÛN]Í,];u�@~ÐkÄÚÔ€Zˆ—Ù÷Ìßd(i�t„†ãX+~ëÅ–ˆû
~½xwÔùµÒ%ÉÄ;‡knŒ¯Y/êÖ¡Œ¹Uó®Ù õbÐó®	¬FDÁDYö©§žbœ–oµ ¼”Â`±í¡§šFÉŒ&ð�ýT“
Ú/ršLÎY=ŽŒV|ù&.Mèp»SØl]R6«¯mÌ8ü ñMl\!Ô8§”]8|Z
³%qk�¶`Â(ØJÿ’ÍÛõ€ð¤ƒÎîØ
õ@Ç>uì/¢ã*V²;¼’¿ýÛ¿o§?°z'd›¥§ê}Q«½ÇX/ÑQ’:JVÕÑ"ÖueŠÖu®ëŸ{·–{ÁÎì_‹^©û«W¯zÙW^y%æzæ€ž4ÔÁL1a¹ž¬tü„S•úÐWg²	/îMJÞ–¤	ïÂ	 úX©bó5§'""7–ïÌ²ÓhÎl jºû»Ø™ý;¯ÒùÒb¶\5ü;äñRuecT�Æâ™Ó2vbÊ‹{ïÓÂ|”]íÖ×Îó¨h“•«³§£ŠŒOeÀFVjÀÄo	£´}
îl×WT{~@"10¦aN`Ç½YáRÎ¹›U:ÙÏù¹Š�ó}¾|Çg¼š/7²ËFv{Ù‘=^fd¯—Ùçù#û½óÉê/{ò�œsàMý1—Ã2>ó¬Z„.œêÍyÍ­Y›ÀXV*<×JC[6–q†–4‡Vý>1]–í¡}—ï»¬&šU;>?ÔjÔñ�Œ¥[:é…¾º·ŸìW¤³Béì¾(îÁ¿ñï!I:Ã÷Hpo}‹ÜM];¬¨kGâ©k^p48ÆÔµ•Áq%g}bàÖƒZoúxéÕÁûuð”×Aí¯Lñ$»_ŸA§.ÓG¸utod‹±¬oE±]ôÏn‚t@-!ð´Ä0ýn¿¤öGÂyqÀ€ØpA;¼[«<Ï6æ"ÔtÝZíEpp"’ð×%¦âÍ ÍFRq¡—Ó¢H§'îÕ‹RëŸºV«ªµ³¢ÈJÐ>ðl%Z(¤šË<OG«jõ¼(Òí‰‹Ê3­|[Æ¹ºÄ5g›ëªªå1Qd•'�oaƒi]·Öy1ÖÐªê+/Š¬'�¤µ³.˜ž™P5dÖHÈŒ”¦fgJ“åíç&.OOIRŸ c¥TÕòý¢ÈZïV³±’Ljì‚)p¸ª¦E‘õr�Ñú]°eŒxÕ[wƒw«Íž¼šöÙbõË³ÌƒÝi�²—èßeúT¬ª6ÿ_Qd�w£×Ë	>¤&'iòš€
“¿’,ËÉödÜ%&µIéÔáˆÌ¤tN‚Çš™Éâ~^,'×ÄˆW1ãc¢Àÿâªÿþÿÿþÿÿþÿ	ÿþÿiconÿþÿÿþÿiconöƒFôÈÿ¾L“ì¡sÎ¶ÿþÿÿþÿlabelÿþÿButtonÿþÿlabelE»b[cF•EÀ\G½ŒÿþÿÿþÿlabelPlacementÿþÿleftÿþÿrightÿþÿtopÿþÿbottomÿþÿlabelPlacementå•¢T åIŸÄß^æãD©ÿþÿÿþÿselectedÿþÿfalseÿþÿselectedî/Ï?ëZJ�ñ…ƒ|úìgÿþÿÿþÿtoggleÿþÿfalseÿþÿtoggleg¿¥íY˜D¾ê±Ìœ²ÿþÿÿþÿenabledÿþÿtrueÿþÿenabled!º—À­RG¸5S8ìêbmÿþÿOtherÿþÿvisibleÿþÿtrueÿþÿvisibleD*Lc³XTC¦$úv±¢ÿþÿOtherÿþÿ	minHeightÿþÿ0ÿþÿ	minHeightÃP¬»¸K¨‰u@•&ÓjÿþÿSizeÿþÿminWidthÿþÿ0ÿþÿminWidth!7“C2«I”»¼ú l/›ÿþÿSizeÿþÿÿý)<?xml version="1.0" encoding ="utf-8"?>

<componentPackage xmlns="http://www.macromedia.com/flash/swccatalog/7">

<component id="Button" class="mx.controls.Button" implementation="Button.swf" iconFile="Button.png" tooltip="Button" src="mx.controls.Button.asi" modified="1059073889">

<movieBounds xmin="0" xmax="2000" ymin="0" ymax="440" />

    <include id="BoundingBox"/>

    <include id="SimpleButton"/>

    <include id="Border"/>

    <include id="RectBorder"/>

    <include id="ButtonSkin"/>

    <exportAfter id="__Packages.mx.controls.Button"/>

<class id="mx.controls.Button" >

      <Event param1="click" />

      <TagName param1="Button" />

      <IconFile param1="Button.png" />

   <property id="_inherited_selected" type="Boolean" >

      <Bindable />

      <ChangeEvent param1="click" />

   </property>

   <method id="icon" >

      <param id="linkage"  />

      <Inspectable defaultValue="" />

   </method>

   <method id="label" >

      <param id="lbl" type="String" />

      <Inspectable defaultValue="Button" />

   </method>

   <method id="labelPlacement" >

      <param id="val" type="String" />

      <Inspectable enumeration="left,right,top,bottom" defaultValue="right" />

   </method>

</class>

<class id="mx.controls.SimpleButton" >

      <Event param1="click" />

      <TagName param1="SimpleButton" />

   <method id="selected" returnType="Boolean">

      <Inspectable defaultValue="false" />

   </method>

   <method id="toggle" returnType="Boolean">

      <Inspectable defaultValue="false" />

   </method>

</class>

<class id="mx.core.UIComponent" >

      <Event param1="focusIn" />

      <Event param1="focusOut" />

      <Event param1="keyDown" />

      <Event param1="keyUp" />

   <property id="enabled" type="Boolean" >

      <Inspectable defaultValue="true" verbose="1" category="Other" />

   </property>

</class>

<class id="mx.core.UIObject" >

      <Event param1="resize" />

      <Event param1="move" />

      <Event param1="draw" />

      <Event param1="load" />

      <Event param1="unload" />

   <method id="minHeight" returnType="Number">

      <Inspectable defaultValue="0" verbose="1" category="Size" />

   </method>

   <method id="minWidth" returnType="Number">

      <In‚ýÿÿÿƒ„…†‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿspectable defaultValue="0" verbose="1" category="Size" />

   </method>

   <method id="visible" returnType="Boolean">

      <Inspectable defaultValue="true" verbose="1" category="Other" />

   </method>

</class>

<asset id="BoundingBox" modified="1054593655">

</asset>

<asset id="UIComponentExtensions" modified="1058814666">

      <exportAfter id="__Packages.mx.core.ext.UIComponentExtensions"/>

</asset>

<asset id="FocusRect" modified="1055744819">

      <include id="BoundingBox"/>

      <exportAfter id="__Packages.mx.skins.halo.FocusRect"/>

</asset>

<asset id="FocusManager" modified="1055744781">

      <include id="FocusRect"/>

      <include id="UIObject"/>

      <exportAfter id="__Packages.mx.managers.FocusManager"/>

</asset>

<asset id="UIObjectExtensions" modified="1058814702">

      <exportAfter id="__Packages.mx.core.ext.UIObjectExtensions"/>

</asset>

<asset id="Defaults" modified="1055737279">

      <exportAfter id="__Packages.mx.skins.halo.Defaults"/>

</asset>

<asset id="UIObject" modified="1058814731">

      <include id="Defaults"/>

      <include id="UIObjectExtensions"/>

      <exportAfter id="__Packages.mx.core.UIObject"/>

</asset>

<asset id="UIComponent" modified="1058814700">

      <include id="UIObject"/>

      <include id="FocusManager"/>

      <include id="UIComponentExtensions"/>

      <exportAfter id="__Packages.mx.core.UIComponent"/>

</asset>

<asset id="SimpleButtonUp" modified="1062225026">

      <include id="BrdrBlk"/>

      <include id="BrdrFace"/>

      <include id="BrdrShdw"/>

      <include id="BrdrHilght"/>

      <include id="BrdrFace"/>

</asset>

<asset id="BrdrHilght" modified="1052770908">

</asset>

<asset id="BrdrBlk" modified="1052770913">

</asset>

<asset id="SimpleButtonIn" modified="1062225020">

      <include id="BrdrBlk"/>

      <include id="BrdrHilght"/>

      <include id="BrdrShdw"/>

      <include id="BrdrFace"/>

</asset>

<asset id="BrdrFace" modified="1051767541">

</asset>

<asset id="BrdrShdw" modified="1058931521">

</asset>

<asset id="SimpleButtonDown" modified="1062225019">

      <include id="BrdrShdw"/>

      <include id="BrdrFace"/>

</asset>

<asset id="SimpleButton" modified="1055744781">

      <include id="BoundingBox"/>

      <include id="SimpleButtonDown"/>

      <include id="SimpleButtonIn"/>

      <include id="SimpleButtonUp"/>

      <include id="UIComponent"/>

      <exportAfter id="__Packages.mx.controls.SimpleButton"/>

</asset>

<asset id="Border" modified="1062224872">

      <include id="UIObject"/>

      <exportAfter id="__Packages.mx.skins.Border"/>

</asset>

<asset id="RectBorder" modified="1062224887">

      <include id="Border"/>

      <exportAfter id="__Packages.mx.skins.halo.RectBorder"/>

</asset>

<asset id="ButtonSkin" modified="1062224893">

      <exportAfter id="__Packages.mx.skins.halo.ButtonSkin"/>

</asset>

<asset id="__Packages.mx.skins.ColoredSkinElement" src="mx.skins.ColoredSkinElement.asi" modified="1062582563">

</asset>

<asset id="__Packages.mx.core.UIObject" src="mx.core.UIObject.asi" modified="1062582563">

    <include id="__Packages.mx.skins.SkinElement" />

    <include id="__Packages.mx.styles.CSSStyleDeclaration" />

    <include id="__Packages.mx.styles.StyleManager" />

</asset>

<asset id="__Packages.mx.skins.SkinElement" src="mx.skins.SkinElement.asi" modified="1062582564">

</asset>

<asset id="__Packages.mx.styles.CSSTextStyles" src="mx.styles.CSSTextStyles.asi" modified="1062582564">

</asset>

<asset id="__Packages.mx.styles.CSSStyleDeclaration" src="mx.styles.CSSStyleDeclaration.asi" modified="1062582564">

    <include id="__Packages.mx.styles.StyleManager" />

    <exportAfter id="__Packages.mx.styles.CSSTextStyles" />

</asset>

<asset id="__Packages.mx.styles.StyleManager" src="mx.styles.StyleManager.asi" modified="1062582564">

</asset>

<asset id="__Packages.mx.core.UIComponent" src="mx.core.UIComponent.asi" modified="1062582563">

    <exportAfter id="__Packages.mx.core.UIObject" />

</asset>

<asset id="__Packages.mx.controls.SimpleButton" src="mx.controls.SimpleButton.asi" modified="1061503691">

    <exportAfter id="__Packages.mx.core.UIComponent" />

</asset>

<asset id="__Packages.mx.controls.Button" src="mx.controls.Button.asi" modified="1061503690">

    <exportAfter id="__Packages.mx.controls.SimpleButton" />

    <exportAfter id="__Packages.mx.core.UIObject" />

</asset>

<asset id="__Packages.mx.events.EventDispatcher" src="mx.events.EventDispatcher.asi" modified="1062582563">

</asset>

<asset id="__Packages.mx.events.UIEventDispatcher" src="mx.events.UIEventDispatcher.asi" modified="1062582563">

    <exportAfter id="__Packages.mx.events.EventDispatcher" />

</asset>

<asset id="__Packages.mx.core.ext.UIObjectExtensions" src="mx.core.ext.UIObjectExtensions.asi" modified="1062582563">

    <include id="__Packages.mx.skins.ColoredSkinElement" />

    <include id="__Packages.mx.styles.CSSStyleDeclaration" />

    <exportAfter id="__Packages.mx.core.UIObject" />

    <exportAfter id="__Packages.mx.skins.SkinElement" />

    <exportAfter id="__Packages.mx.styles.CSSTextStyles" />

    <exportAfter id="__Packages.mx.events.UIEventDispatcher" />

</asset>

<asset id="__Packages.mx.skins.halo.Defaults" src="mx.skins.halo.Defaults.asi" modified="1062582564">

    <include id="__Packages.mx.core.UIComponent" />

    <exportAfter id="__Packages.mx.core.UIObject" />

    <exportAfter id="__Packages.mx.styles.CSSStyleDeclaration" />

    <exportAfter id="__Packages.mx.core.ext.UIObjectExtensions" />

</asset>

<asset id="__Packages.mx.skins.halo.FocusRect" src="mx.skins.halo.FocusRect.asi" modified="1062582564">

    <include id="__Packages.mx.managers.DepthManager" />

    <exportAfter id="__Packages.mx.core.UIComponent" />

    <exportAfter id="__Packages.mx.skins.SkinElement" />

    <exportAfter id="__Packages.mx.skins.halo.Defaults" />

</asset>

<asset id="__Packages.mx.managers.DepthManager" src="mx.managers.DepthManager.asi" modified="1062582563">

    <include id="__Packages.mx.core.UIObject" />

</asset>

<asset id="__Packages.mx.managers.FocusManager" src="mx.managers.FocusManager.asi" modified="1062726409">

    <include id="__Packages.mx.controls.SimpleButton" />

    <include id="__Packages.mx.managers.DepthManager" />

    <include id="__Packages.mx.managers.SystemManager" />

    <exportAfter id="__Packages.mx.core.UIComponent" />

    <exportAfter id="__Packages.mx.core.ext.UIObjectExtensions" />

</asset>

<asset id="__Packages.mx.managers.SystemManager" src="mx.managers.SystemManager.asi" modified="1062582563">

    <include id="__Packages.mx.core.UIComponent" />

    <include id="__Packages.mx.events.EventDispatcher" />

</asset>

<asset id="__Packages.mx.managers.OverlappedWindows" src="mx.managers.OverlappedWindows.asi" modified="1062582563">

    <include id="__Packages.mx.core.UIComponent" />

    <exportAfter id="__Packages.mx.managers.SystemManager" />

</asset>

<asset id="__Packages.mx.core.ext.UIComponentExtensions" src="mx.core.ext.UIComponentExtensions.asi" modified="1062582563">

    <include id="__Packages.mx.styles.CSSSetStyle" />

    <exportAfter id="__Packages.mx.core.UIComponent" />

    <exportAfter id="__Packages.mx.managers.FocusManager" />

    <exportAfter id="__Packages.mx.managers.OverlappedWindows" />

</asset>

<asset id="__Packages.mx.styles.CSSSetStyle" src="mx.styles.CSSSetStyle.asi" modified="1062582564">

    <include id="__Packages.mx.styles.StyleManager" />

    <exportAfter id="__Packages.mx.styles.CSSStyleDeclaration" />

</asset>

<asset id="__Packages.mx.skins.Border" src="mx.skins.Border.asi" modified="1062582563">

    <exportAfter id="__Packages.mx.core.UIObject" />

</asset>

<asset id="__Packages.mx.skins.RectBorder" src="mx.skins.RectBorder.asi" modified="1062582564">

    <exportAfter id="__Packages.mx.skins.Border" />

</asset>

<asset id="__Packages.mx.skins.halo.ButtonSkin" src="mx.skins.halo.ButtonSkin.asi" modified="1062582563">

    <exportAfter id="__Packages.mx.core.ext.UIObjectExtensions" />

    <exportAfter id="__Packages.mx.skins.RectBorder" />

</asset>

<asset id="__Packages.mx.skins.halo.RectBorder" src="mx.skins.halo.RectBorder.asi" modified="1062582564">

    <include id="__Packages.mx.styles.CSSStyleDeclaration" />

    <exportAfter id="__Packages.mx.core.ext.UIObjectExtensions" />

    <exportAfter id="__Packages.mx.skins.RectBorder" />

</asset>

</component>

</componentPackage>

Media 1ÿþÿBitmap 1ÿþÿ
Button.png·Ô±C·Ô±Cÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿ2Hxií’Ñ	@!EÛéíäNw'w*¯ øQa}Æ$K=™ÙÚÛÒEäFsW<_µ,)�œCQj>˜QYÅ§œïZqªuDÜŠSyK0þzöÏÏúÀÏÃ_Y?AžŽ÷7šÆðIsQŸ$ÅÿþÿButtonÐ¸ÿþÿButtonÿþÿ
Button.swf	ëW?+ÿþÿBorderÿþÿBorderÿþÿ
Button.swfèCP?ÿþÿUIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.skins.Borderÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿBoundingBoxÿþÿBoundingBoxÿþÿ
Button.swfwÒÛ>ÿþÿÿþÿÿþÿBrdrBlkÿþÿBrdrBlkÿþÿ
Button.swfaÀ>ÿþÿÿþÿÿþÿBrdrFaceÿþÿBrdrFaceÿþÿ
Button.swfõ²°>ÿþÿÿþÿÿþÿ
BrdrHilghtÿþÿ
BrdrHilghtÿþÿ
Button.swf\À>ÿþÿÿþÿÿþÿBrdrShdwÿþÿBrdrShdwÿþÿ
Button.swfA?ÿþÿÿþÿÿþÿ
ButtonSkinÿþÿ
ButtonSkinÿþÿ
Button.swfýCP?ÿþÿ#__Packages.mx.skins.halo.ButtonSkinÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿDefaultsÿþÿDefaultsÿþÿ
Button.swf¿Eí>ÿþÿ!__Packages.mx.skins.halo.Defaultsÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿFocusManagerÿþÿFocusManagerÿþÿ
Button.swf
cí>ÿþÿ	FocusRectÿþÿ
Button.swfÿþÿÿþÿÿþÿUIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿ#__Packages.mx.managers.FocusManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿ	FocusRectÿþÿ	FocusRectÿþÿ
Button.swf3cí>ÿþÿBoundingBoxÿþÿ
Button.swfÿþÿÿþÿÿþÿ"__Packages.mx.skins.halo.FocusRectÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿ
RectBorderÿþÿ
RectBorderÿþÿ
Button.swf÷CP?ÿþÿBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿ#__Packages.mx.skins.halo.RectBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿSimpleButtonÿþÿSimpleButtonÿþÿ
Button.swf
cí>ÿþÿBoundingBoxÿþÿ
Button.swfÿþÿÿþÿÿþÿSimpleButtonDownÿþÿ
Button.swfÿþÿÿþÿÿþÿSimpleButtonInÿþÿ
Button.swfÿþÿÿþÿÿþÿSimpleButtonUpÿþÿ
Button.swfÿþÿÿþÿÿþÿUIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ#__Packages.mx.controls.SimpleButtonÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿSimpleButtonDownÿþÿSimpleButtonDownÿþÿ
Button.swf{DP?ÿþÿBrdrShdwÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrFaceÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿSimpleButtonInÿþÿSimpleButtonInÿþÿ
Button.swf|DP?ÿþÿBrdrBlkÿþÿ
Button.swfÿþÿÿþÿÿþÿ
BrdrHilghtÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrShdwÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrFaceÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿSimpleButtonUpÿþÿSimpleButtonUpÿþÿ
Button.swf‚DP?ÿþÿBrdrBlkÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrFaceÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrShdwÿþÿ
Button.swfÿþÿÿþÿÿþÿ
BrdrHilghtÿþÿ
Button.swfÿþÿÿþÿÿþÿBrdrFaceÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿUIComponentÿþÿUIComponentÿþÿ
Button.swfì:?ÿþÿUIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿFocusManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿUIComponentExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿUIComponentExtensionsÿþÿUIComponentExtensionsÿþÿ
Button.swfÊ:?ÿþÿ,__Packages.mx.core.ext.UIComponentExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿUIObjectÿþÿUIObjectÿþÿ
Button.swf;?ÿþÿDefaultsÿþÿ
Button.swfÿþÿÿþÿÿþÿUIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿUIObjectExtensionsÿþÿUIObjectExtensionsÿþÿ
Button.swfî:?ÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿÿþÿÿþÿ__Packages.mx.controls.Buttonÿþÿ__Packages.mx.controls.Buttonÿþÿ
Button.swfÊBE?ÿþÿ#__Packages.mx.controls.SimpleButtonÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.controls.Buttonÿþÿÿqimport mx.core.UIObject;

import mx.controls.SimpleButton;

import mx.core.UIComponent;



[Event("click")] 

[TagName("Button")] 

[IconFile("Button.png")] 

intrinsic class mx.controls.Button extends mx.controls.SimpleButton

{

   public function Button();

   public var __get__icon:Function;

   public var __get__label:Function;

   public var __get__labelPlacement:Function;

   public var __label:String;

   public var __labelPlacement:String;

   public var _color;

   public function _getIcon(Void):String;

   public var _iconLinkageName:String;

   [Bindable] [ChangeEvent("click")] public var _inherited_selected:Boolean;

   public function _setIcon(linkage):Void;

   public var borderW:Number;

   public var btnOffset:Number;

   public function calcSize(tag:Number, ref:Object):Void;

   public var centerContent:Boolean;

   public var className:String;

   public var clipParameters:Object;

   public function createChildren(Void):Void;

   public function draw();

   public var falseDisabledIcon:String;

   public var falseDisabledSkin:String;

   public var falseDownIcon:String;

   public var falseDownSkin:String;

   public var falseOverIcon:String;

   public var falseOverSkin:String;

   public var falseUpIcon:String;

   public var falseUpSkin:String;

   public function getBtnOffset(Void):Number;

   public function getLabel(Void):String;

   public function getLabelPlacement(Void):String;

   public var hitArea_mc:MovieClip;

   function get icon():String;

   [Inspectable(defaultValue="")] function set icon(linkage);

   public function init(Void):Void;

   public var initIcon;

   public function invalidateStyle(c:String):Void;

   [Inspectable(defaultValue="Button")] function set label(lbl:String);

   function get label():String;

   public var labelPath:Object;

   [Inspectable(enumeration="left,right,top,bottom"defaultValue="right")] function set labelPlacement(val:String);

   function get labelPlacement():String;

   static var mergedClipParameters:Boolean;

   public function onRelease(Void):Void;

   public function setColor(c:Number):Void;

   public function setEnabled(enable:Boolean):Void;

   public function setHitArea(w:Number, h:Number);

   public function setLabel(label:String):Void;

   public function setLabelPlacement(val:String):Void;

   public function setSkin(tag:Number, linkageName:String, initobj:Object):MovieClip;

   public function setView(offset:Number):Void;

   public function size(Void):Void;

   static var symbolName:String;

   static var symbolOwner;

   public var trueDisabledIcon:String;

   public var trueDisabledSkin:String;

   public var trueDownIcon:String;

   public var trueDownSkin:String;

   public var trueOverIcon:String;

   public var trueOverSkin:String;

   public var trueUpIcon:String;

   public var trueUpSkin:String;

   static var version:String;

   public function viewSkin(varName:String):Void;

};

ÿþÿ#__Packages.mx.controls.SimpleButtonÿþÿ#__Packages.mx.controls.SimpleButtonÿþÿ
Button.swfËBE?ÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.controls.SimpleButtonÿþÿÿimport mx.core.UIComponent;



[Event("click")] 

[TagName("SimpleButton")] 

intrinsic class mx.controls.SimpleButton extends mx.core.UIComponent

{

   public function SimpleButton();

   public var __emphasized:Boolean;

   public var __emphatic:Boolean;

   public var __emphaticStyleName:String;

   public var __get__emphasized:Function;

   public var __get__selected:Function;

   public var __get__toggle:Function;

   public var __get__value:Function;

   public var __state:Boolean;

   public var __toggle:Boolean;

   public var autoRepeat:Boolean;

   public var boundingBox_mc:MovieClip;

   public var btnOffset:Number;

   public var buttonDownHandler:Function;

   public function calcSize(Void):Void;

   public function changeIcon(tag:Number, linkageName:String):Void;

   public function changeSkin(tag:Number, linkageName:String):Void;

   public var className:String;

   public var clickHandler:Function;

   public function createChildren(Void):Void;

   public var detail:Number;

   public var dfi;

   public var dfs;

   public var disabledIcon:Object;

   public var disabledSkin:Object;

   public var downIcon:Object;

   public var downSkin:Object;

   public function draw(Void):Void;

   public var dti;

   public var dts;

   function get emphasized():Boolean;

   function set emphasized(val:Boolean);

   static var emphasizedStyleDeclaration;

   static var falseDisabled:Number;

   public var falseDisabledIcon:String;

   public var falseDisabledIconEmphasized:String;

   public var falseDisabledSkin:String;

   public var falseDisabledSkinEmphasized:String;

   static var falseDown:Number;

   public var falseDownIcon:String;

   public var falseDownIconEmphasized:String;

   public var falseDownSkin:String;

   public var falseDownSkinEmphasized:String;

   static var falseOver:Number;

   public var falseOverIcon:String;

   public var falseOverIconEmphasized:String;

   public var falseOverSkin:String;

   public var falseOverSkinEmphasized:String;

   static var falseUp:Number;

   public var falseUpIcon:String;

   public var falseUpIconEmphasized:String;

   public var falseUpSkin:String;

   public var falseUpSkinEmphasized:String;

   public var fdi;

   public var fds;

   public var fri;

   public var frs;

   public var fui;

   public var fus;

   public function getLabel(Void):String;

   public function getSelected():Boolean;

   public function getState(Void):Boolean;

   public function getToggle(Void):Boolean;

   public var iconName:Object;

   public var idNames;

   public function init(Void):Void;

   public var initializing:Boolean;

   public var interval;

   public function keyDown(e:Object):Void;

   public function keyUp(e:Object):Void;

   public var linkLength:Number;

   public function onDragOut(Void):Void;

   public function onDragOver(Void):Void;

   public function onKillFocus(newFocus:Object):Void;

   public function onPress(Void):Void;

   public function onPressDelay(Void):Void;

   public function onPressRepeat(Void):Void;

   public function onRelease(Void):Void;

   public function onReleaseOutside(Void):Void;

   public function onRollOut(Void):Void;

   public function onRollOver(Void):Void;

   public var phase:String;

   public var preset:Boolean;

   public var refNames;

   public function refresh(Void):Void;

   public function removeIcons();

   public var rolloverIcon:Object;

   public var rolloverSkin:Object;

   function set selected(val:Boolean);

   [Inspectable(defaultValue=false)] function get selected():Boolean;

   public function setEnabled(val:Boolean):Void;

   public function setIcon(tag:Number, linkageName:String):Object;

   public function setLabel(val:String):Void;

   public function setSelected(val:Boolean);

   public function setSkin(tag:Number, linkageName:String, initobj:Object):MovieClip;

   public function setState(state:Boolean):Void;

   public function setStateVar(state:Boolean):Void;

   public function setToggle(val:Boolean);

   public function setView(offset:Boolean):Void;

   public function showEmphasized(e:Boolean):Void;

   public function size(Void):Void;

   public var skinName:Object;

   public var stateNames;

   public var style3dInset:Number;

   static var symbolName:String;

   static var symbolOwner:Object;

   public var tagMap;

   public var tdi;

   public var tds;

   function set toggle(val:Boolean);

   [Inspectable(defaultValue=false)] function get toggle():Boolean;

   public var tri;

   public var trs;

   static var trueDisabled:Number;

   public var trueDisabledIcon:String;

   public var trueDisabledIconEmphasized:String;

   public var trueDisabledSkin:String;

   public var trueDisabledSkinEmphasized:String;

   static var trueDown:Number;

   public var trueDownIcon:String;

   public var trueDownIconEmphasized:String;

   public var trueDownSkin:String;

   public var trueDownSkinEmphasized:String;

   static var trueOver:Number;

   public var trueOverIcon:String;

   public var trueOverIconEmphasized:String;

   public var trueOverSkin:String;

   public var trueOverSkinEmphasized:String;

   static var trueUp:Number;

   public var trueUpIcon:String;

   public var trueUpIconEmphasized:String;

   public var trueUpSkin:String;

   public var trueUpSkinEmphasized:String;

   public var tui;

   public var tus;

   public var upIcon:Object;

   public var upSkin:Object;

   function set value(val:Boolean);

   function get value():Boolean;

   static var version:String;

   public function viewIcon(varName:String):Void;

   public function viewSkin(varName:String, initObj:Object):Void;

};

ÿþÿ__Packages.mx.core.UIComponentÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.core.UIComponentÿþÿÿþimport mx.core.UIObject;

import mx.skins.SkinElement;



[Event("focusIn")] 

[Event("focusOut")] 

[Event("keyDown")] 

[Event("keyUp")] 

intrinsic class mx.core.UIComponent extends mx.core.UIObject

{

   public function UIComponent();

   public var clipParameters:Object;

   public function dispatchValueChangedEvent(value):Void;

   public var drawFocus:Function;

   [Inspectable(defaultValue=true, verbose=1, category="Other")] public var enabled:Boolean;

   public function enabledChanged(id:String, oldValue:Boolean, newValue:Boolean):Boolean;

   public function findFocusFromObject(o:Object):Object;

   public function findFocusInChildren(o:Object):Object;

   public var focusEnabled:Boolean;

   public var focusManager:MovieClip;

   public var focusTextField:Object;

   public function getFocus():Object;

   public function getFocusManager():Object;

   public var groupName:String;

   function get height():Number;

   public function init():Void;

   public function isParent(o:Object):Boolean;

   static var kStretch:Number;

   static var mergedClipParameters:Boolean;

   public function onKillFocus(newFocus:Object):Void;

   public function onSetFocus(oldFocus:Object):Void;

   public var origBorderStyles:Object;

   public var origBorderValues:Object;

   public var popUp:Boolean;

   public function pressFocus():Void;

   public function releaseFocus():Void;

   public function setEnabled(enabled:Boolean):Void;

   public function setFocus():Void;

   public function setVisible(x:Boolean, noEvent:Boolean):Void;

   public function size():Void;

   static var symbolName:String;

   static var symbolOwner:Object;

   public var tabEnabled:Boolean;

   public var tabIndex:Number;

   static var version:String;

   function get width():Number;

};

ÿþÿ__Packages.mx.core.UIObjectÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.skins.SkinElementÿþÿ
Button.swfÿþÿÿþÿÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swfÿþÿÿþÿÿþÿ!__Packages.mx.styles.StyleManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.core.UIObjectÿþÿÿÃimport mx.styles.StyleManager;

import mx.styles.CSSStyleDeclaration;

import mx.skins.SkinElement;



[Event("resize")] 

[Event("move")] 

[Event("draw")] 

[Event("load")] 

[Event("unload")] 

intrinsic class mx.core.UIObject extends MovieClip

{

   public function UIObject();

   public function __getTextFormat(tf:TextFormat, bAll:Boolean):Boolean;

   public var __get__minHeight:Function;

   public var __get__minWidth:Function;

   public var __get__scaleX:Function;

   public var __get__scaleY:Function;

   public var __get__visible:Function;

   public var __height:Number;

   private var __onUnload:Function;

   public var __width:Number;

   public var _color;

   public function _createChildren(Void):Void;

   private var _endInit:Function;

   public function _getTextFormat(Void):TextFormat;

   private var _id:String;

   private var _maxHeight:Number;

   private var _maxWidth:Number;

   private var _minHeight:Number;

   private var _minWidth:Number;

   private var _preferredHeight:Number;

   private var _preferredWidth:Number;

   private var _tf:TextFormat;

   public var _topmost:Boolean;

   public var addEventListener:Function;

   function get bottom():Number;

   public var buildDepthTable:Function;

   public function cancelAllDoLaters(Void):Void;

   public var changeColorStyleInChildren:Function;

   public var changeTextStyleInChildren:Function;

   public var childrenCreated:Boolean;

   public var className:String;

   public var clipParameters:Object;

   public var color:Number;

   public function constructObject(Void):Void;

   public var createAccessibilityImplementation:Function;

   public var createChildAtDepth:Function;

   public function createChildren(Void):Void;

   public var createClassChildAtDepth:Function;

   public function createClassObject(className:Function, id:String, depth:Number, initobj:Object):mx.core.UIObject;

   public function createEmptyObject(id:String, depth:Number):mx.core.UIObject;

   public var createEvent:Function;

   public function createLabel(name:String, depth:Number, text):TextField;

   public function createObject(linkageName:String, id:String, depth:Number, initobj:Object):MovieClip;

   public function createSkin(tag:Number):mx.core.UIObject;

   public function destroyObject(id:String):Void;

   public var dispatchEvent:Function;

   public function doLater(obj:Object, fn:String):Void;

   public function doLaterDispatcher(Void):Void;

   public function draw(Void):Void;

   public function drawRect(x1:Number, y1:Number, x2:Number, y2:Number):Void;

   public var embedFonts:Boolean;

   public var findNextAvailableDepth:Function;

   public var fontFamily:String;

   public var fontSize:Number;

   public var fontStyle:String;

   public var fontWeight:String;

   public function getClassStyleDeclaration(Void):mx.styles.CSSStyleDeclaration;

   public function getMinHeight(Void):Number;

   public function getMinWidth(Void):Number;

   public function getSkinIDName(tag:Number):String;

   public function getStyle(styleProp:String);

   public function getStyleName(Void):String;

   public var handleEvent:Function;

   function get height():Number;

   public var idNames:Array;

   public var ignoreClassStyleDeclaration:Object;

   public function init(Void):Void;

   public function initFromClipParameters(Void):Void;

   public var initProperties:Function;

   public function invalidate(Void):Void;

   private var invalidateFlag:Boolean;

   public function invalidateStyle(Void):Void;

   function get left():Number;

   private var lineColor:Number;

   private var lineWidth:Number;

   public var marginLeft:Number;

   public var marginRight:Number;

   static function mergeClipParameters(o, p):Boolean;

   public var methodTable:Array;

   [Inspectable(defaultValue=0, verbose=1, category="Size")] function get minHeight():Number;

   function set minHeight(h:Number):Void;

   [Inspectable(defaultValue=0, verbose=1, category="Size")] function get minWidth():Number;

   function set minWidth(w:Number):Void;

   public function move(x:Number, y:Number, noEvent:Boolean):Void;

   public var notifyStyleChangeInChildren:Function;

   public function redraw(bAlways:Boolean):Void;

   public var removeEventListener:Function;

   function get right():Number;

   function get scaleX():Number;

   function set scaleX(x:Number):Void;

   function get scaleY():Number;

   function set scaleY(y:Number):Void;

   public function setColor(color:Number):Void;

   public function setMinHeight(h:Number):Void;

   public function setMinWidth(w:Number):Void;

   public function setSize(w:Number, h:Number, noEvent:Boolean):Void;

   public function setSkin(tag:Number, linkageName:String, initObj:Object):MovieClip;

   public var setStyle:Function;

   public function setVisible(x:Boolean, noEvent:Boolean):Void;

   public function size(Void):Void;

   public var styleName:String;

   public var stylecache:Object;

   static var symbolName:String;

   static var symbolOwner:Object;

   public var tabEnabled:Boolean;

   public var textAlign:String;

   static var textColorList;

   public var textDecoration:String;

   public var textIndent:Number;

   private var tfList:Object;

   function get top():Number;

   public var validateNow:Boolean;

   static var version:String;

   [Inspectable(defaultValue=true, verbose=1, category="Other")] function get visible():Boolean;

   function set visible(x:Boolean):Void;

   function get width():Number;

   function get x():Number;

   function get y():Number;

};

ÿþÿ,__Packages.mx.core.ext.UIComponentExtensionsÿþÿ,__Packages.mx.core.ext.UIComponentExtensionsÿþÿ
Button.swf#¹U?ÿþÿ __Packages.mx.styles.CSSSetStyleÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ#__Packages.mx.managers.FocusManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ(__Packages.mx.managers.OverlappedWindowsÿþÿ
Button.swfÿþÿÿþÿÿþÿ!mx.core.ext.UIComponentExtensionsÿþÿÿ:import mx.core.UIComponent;



intrinsic class mx.core.ext.UIComponentExtensions

{

   static function Extensions():Boolean;

   static var FocusManagerDependency;

   static var OverlappedWindowsDependency;

   static var UIComponentDependency;

   static var UIComponentExtended;

   static var bExtended;

};

ÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swf#¹U?ÿþÿ&__Packages.mx.skins.ColoredSkinElementÿþÿ
Button.swfÿþÿÿþÿÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.skins.SkinElementÿþÿ
Button.swfÿþÿÿþÿÿþÿ"__Packages.mx.styles.CSSTextStylesÿþÿ
Button.swfÿþÿÿþÿÿþÿ&__Packages.mx.events.UIEventDispatcherÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.core.ext.UIObjectExtensionsÿþÿÿûimport mx.core.UIObject;

import mx.styles.CSSStyleDeclaration;

import mx.skins.SkinElement;

import mx.events.UIEventDispatcher;



intrinsic class mx.core.ext.UIObjectExtensions

{

   static var CSSTextStylesDependency;

   static function Extensions():Boolean;

   static var SkinElementDependency;

   static var UIEventDispatcherDependency;

   static var UIObjectDependency;

   static var UIObjectExtended;

   static function addGeometry(tf:Object, ui:Object):Void;

   static var bExtended;

};

ÿþÿ$__Packages.mx.events.EventDispatcherÿþÿ$__Packages.mx.events.EventDispatcherÿþÿ
Button.swf#¹U?ÿþÿmx.events.EventDispatcherÿþÿÿ

intrinsic class mx.events.EventDispatcher

{

   static var _fEventDispatcher:mx.events.EventDispatcher;

   static function _removeEventListener(queue:Object, event:String, handler):Void;

   public function addEventListener(event:String, handler):Void;

   public function dispatchEvent(eventObj:Object):Void;

   public function dispatchQueue(queueObj:Object, eventObj:Object):Void;

   static function initialize(object:Object):Void;

   public function removeEventListener(event:String, handler):Void;

};

ÿþÿ&__Packages.mx.events.UIEventDispatcherÿþÿ&__Packages.mx.events.UIEventDispatcherÿþÿ
Button.swf#¹U?ÿþÿ$__Packages.mx.events.EventDispatcherÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.events.UIEventDispatcherÿþÿÿimport mx.core.UIObject;

import mx.events.EventDispatcher;



intrinsic class mx.events.UIEventDispatcher extends mx.events.EventDispatcher

{

   public function __addEventListener(event:String, handler):Void;

   public var __origAddEventListener:Function;

   public var __sentLoadEvent;

   static var _fEventDispatcher:mx.events.UIEventDispatcher;

   static function addKeyEvents(obj:Object):Void;

   static function addLoadEvents(obj:Object):Void;

   public function dispatchEvent(eventObj:Object):Void;

   static function initialize(obj:Object):Void;

   static var keyEvents:Object;

   static var loadEvents:Object;

   static var lowLevelEvents:Object;

   public function onKeyDown(Void):Void;

   public function onKeyUp(Void):Void;

   public function onLoad(Void):Void;

   public function onUnload(Void):Void;

   public var owner:Object;

   public function removeEventListener(event:String, handler):Void;

   static function removeKeyEvents(obj:Object):Void;

   static function removeLoadEvents(obj:Object):Void;

};

ÿþÿ#__Packages.mx.managers.DepthManagerÿþÿ#__Packages.mx.managers.DepthManagerÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.managers.DepthManagerÿþÿÿoimport mx.core.UIObject;



intrinsic class mx.managers.DepthManager

{

   public function DepthManager();

   static var __depthManager:mx.managers.DepthManager;

   public var _childCounter:Number;

   public var _parent:MovieClip;

   public var _topmost:Boolean;

   public function buildDepthTable(Void):Array;

   public function createChildAtDepth(linkageName:String, depthFlag:Number, initObj:Object):MovieClip;

   public function createClassChildAtDepth(className:Function, depthFlag:Number, initObj:Object):mx.ýÿÿÿ	

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿcore.UIObject;

   public var createClassObject:Function;

   static function createClassObjectAtDepth(className:Object, depthSpace:Number, initObj:Object):mx.core.UIObject;

   public var createObject:Function;

   static function createObjectAtDepth(linkageName:String, depthSpace:Number, initObj:Object):MovieClip;

   public function findNextAvailableDepth(targetDepth:Number, depthTable:Array, direction:String):Number;

   public var getDepth:Function;

   public function getDepthByFlag(depthFlag:Number, depthTable:Array):Number;

   static var highestDepth:Number;

   static private var holder:MovieClip;

   static var kBottom:Number;

   static var kCursor:Number;

   static var kNotopmost:Number;

   static var kTooltip:Number;

   static var kTop:Number;

   static var kTopmost:Number;

   static var lowestDepth:Number;

   static var numberOfAuthortimeLayers:Number;

   static var reservedDepth:Number;

   public function setDepthAbove(targetInstance:MovieClip):Void;

   public function setDepthBelow(targetInstance:MovieClip):Void;

   public function setDepthTo(depthFlag:Number):Void;

   public function shuffleDepths(subject:MovieClip, targetDepth:Number, depthTable:Array, direction:String):Void;

   static function sortFunction(a:MovieClip, b:MovieClip):Number;

   public var swapDepths:Function;

   static function test(depth:Number):Boolean;

};

ÿþÿ#__Packages.mx.managers.FocusManagerÿþÿ#__Packages.mx.managers.FocusManagerÿþÿ
Button.swf	ëW?ÿþÿ#__Packages.mx.controls.SimpleButtonÿþÿ
Button.swfÿþÿÿþÿÿþÿ#__Packages.mx.managers.DepthManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ$__Packages.mx.managers.SystemManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.managers.FocusManagerÿþÿÿêimport mx.core.UIObject;

import mx.managers.SystemManager;

import mx.controls.SimpleButton;

import mx.core.UIComponent;



intrinsic class mx.managers.FocusManager extends mx.core.UIComponent

{

   public function FocusManager();

   static var UIObjectExtensionsDependency;

   public var __defaultPushButton:mx.controls.SimpleButton;

   public var __get__defaultPushButton:Function;

   private var _firstNode:Object;

   private var _firstObj:Object;

   private var _foundList:Object;

   private var _lastNode:Object;

   private var _lastObj:Object;

   private var _lastTarget:Object;

   private var _lastx:Object;

   private var _needPrev:Boolean;

   private var _nextIsNext:Boolean;

   private var _nextNode:Object;

   private var _nextObj:Object;

   public function _onMouseDown(Void):Void;

   private var _prevNode:Object;

   private var _prevObj:Object;

   private var _searchKey:Number;

   public function activate(Void):Void;

   private var activated:Boolean;

   public var bDrawFocus:Boolean;

   public var bNeedFocus:Boolean;

   public var className:String;

   public function deactivate(Void):Void;

   public var defPushButton:mx.controls.SimpleButton;

   function get defaultPushButton():mx.controls.SimpleButton;

   function set defaultPushButton(x:mx.controls.SimpleButton);

   public var defaultPushButtonEnabled:Boolean;

   static function enableFocusManagement():Void;

   public function enabledChanged(id:String, oldValue:Boolean, newValue:Boolean):Boolean;

   public var form;

   public function getActualFocus(o:Object):Object;

   public function getFocus(Void):Object;

   public function getFocusManagerFromObject(o:Object):Object;

   public function getMaxTabIndex(o:mx.core.UIComponent):Number;

   public function getMousedComponentFromChildren(x:Number, y:Number, o:Object):Object;

   public function getNextTabIndex(Void):Number;

   public function getSelectionFocus():Object;

   public function getTabCandidate(o:MovieClip, index:Number, groupName:String, dir:Boolean, firstChild:Boolean):Void;

   public function getTabCandidateFromChildren(o:MovieClip, index:Number, groupName:String, dir:Boolean, firstChild:Boolean):Void;

   public function handleEvent(e:Object);

   public function init(Void):Void;

   static var initialized:Boolean;

   public function isOurFocus(o:Object):Boolean;

   public var lastFocus:Object;

   public var lastSelFocus:Object;

   public var lastTabFocus:Object;

   public var lastXMouse:Number;

   public var lastYMouse:Number;

   public function mouseActivate(Void):Void;

   function get nextTabIndex():Number;

   public function onKeyDown(Void):Void;

   public function onMouseUp(Void):Void;

   public function onSetFocus(o:Object, n:Object):Void;

   public function onUnload(Void):Void;

   public function relocate(Void):Void;

   public function restoreFocus(Void):Void;

   public function sendDefaultPushButtonEvent(Void):Void;

   public function setFocus(o:Object):Void;

   static var symbolName:String;

   static var symbolOwner:Object;

   private var tabCapture:MovieClip;

   public function tabHandler(Void):Void;

   static var version:String;

   public function walkTree(p:MovieClip, index:Number, groupName:String, dir:Boolean, lookup:Boolean, firstChild:Boolean):Void;

};

ÿþÿ(__Packages.mx.managers.OverlappedWindowsÿþÿ(__Packages.mx.managers.OverlappedWindowsÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ$__Packages.mx.managers.SystemManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.managers.OverlappedWindowsÿþÿÿ(import mx.managers.SystemManager;

import mx.core.UIComponent;



intrinsic class mx.managers.OverlappedWindows

{

   static var SystemManagerDependency;

   static function __addEventListener(e:String, o:Object, l:Function):Void;

   static function __removeEventListener(e:String, o:Object, l:Function):Void;

   static function activate(f:MovieClip):Void;

   static function addFocusManager(f:mx.core.UIComponent):Void;

   static function checkIdle(Void):Void;

   static function deactivate(f:MovieClip):Void;

   static function enableOverlappedWindows():Void;

   static var initialized:Boolean;

   static function onMouseDown(Void):Void;

   static function onMouseMove(Void):Void;

   static function onMouseUp(Void):Void;

   static function removeFocusManager(f:mx.core.UIComponent):Void;

};

ÿþÿ$__Packages.mx.managers.SystemManagerÿþÿ$__Packages.mx.managers.SystemManagerÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ$__Packages.mx.events.EventDispatcherÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.managers.SystemManagerÿþÿÿ�import mx.events.EventDispatcher;

import mx.core.UIComponent;



[Event("idle")] 

[Event("resize")] 

intrinsic class mx.managers.SystemManager

{

   static var __addEventListener:Function;

   static var __removeEventListener:Function;

   static var __screen:Object;

   static private var _initialized:Boolean;

   static var _xAddEventListener:Function;

   static var _xRemoveEventListener:Function;

   static var activate:Function;

   static var addEventListener:Function;

   static function addFocusManager(f:mx.core.UIComponent):Void;

   static var checkIdle:Function;

   static var deactivate:Function;

   static var dispatchEvent:Function;

   static var form:MovieClip;

   static var forms:Array;

   static var idleFrames:Number;

   static function init(Void):Void;

   static var interval:Number;

   static var isMouseDown;

   static function onMouseDown(Void):Void;

   static var onMouseMove:Function;

   static var onMouseUp:Function;

   static function onResize(Void):Void;

   static var removeEventListener:Function;

   static function removeFocusManager(f:mx.core.UIComponent):Void;

   static function get screen():Object;

};

ÿþÿ__Packages.mx.skins.Borderÿþÿ__Packages.mx.skins.Borderÿþÿ
Button.swf#¹U?ÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.Borderÿþÿÿhimport mx.core.UIObject;



intrinsic class mx.skins.Border extends mx.core.UIObject

{

   public function Border();

   public var borderStyle:String;

   public var className:String;

   public var idNames:Array;

   public function init(Void):Void;

   static var symbolName:String;

   static var symbolOwner:Object;

   public var tagBorder:Number;

};

ÿþÿ&__Packages.mx.skins.ColoredSkinElementÿþÿ&__Packages.mx.skins.ColoredSkinElementÿþÿ
Button.swf#¹U?ÿþÿmx.skins.ColoredSkinElementÿþÿÿ�

intrinsic class mx.skins.ColoredSkinElement

{

   public var _color;

   public function draw(Void):Void;

   public var getStyle:Function;

   public function invalidateStyle(Void):Void;

   static var mixins:mx.skins.ColoredSkinElement;

   public var onEnterFrame:Function;

   public function setColor(c:Number):Void;

   static function setColorStyle(p:Object, colorStyle:String):Void;

};

ÿþÿ__Packages.mx.skins.RectBorderÿþÿ__Packages.mx.skins.RectBorderÿþÿ
Button.swf$¹U?ÿþÿ__Packages.mx.skins.Borderÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.RectBorderÿþÿÿÅimport mx.skins.Border;

import mx.styles.CSSStyleDeclaration;



intrinsic class mx.skins.RectBorder extends mx.skins.Border

{

   public function RectBorder();

   public var __borderMetrics:Object;

   public var backgroundColorName:String;

   public var borderColorName:String;

   function get borderMetrics():Object;

   public var borderStyleName:String;

   public var buttonColorName:String;

   public var className:String;

   public function draw(Void):Void;

   public function drawBorder(Void):Void;

   public function getBorderMetrics(Void):Object;

   function get height():Number;

   public var highlightColorName:String;

   public function init(Void):Void;

   public var offset:Number;

   public function setColor(Void):Void;

   public var shadowColorName:String;

   public function size(Void):Void;

   static var symbolName:String;

   static var symbolOwner:Object;

   static var version:String;

   function get width():Number;

};

ÿþÿ__Packages.mx.skins.SkinElementÿþÿ__Packages.mx.skins.SkinElementÿþÿ
Button.swf$¹U?ÿþÿmx.skins.SkinElementÿþÿÿ¥

intrinsic class mx.skins.SkinElement extends MovieClip

{

   public function __set__visible(visible:Boolean):Void;

   public var height:Number;

   public function move(x:Number, y:Number):Void;

   static function registerElement(name:String, className:Function):Void;

   public function setSize(w:Number, h:Number):Void;

   public var top:Number;

   public var visible:Boolean;

   public var width:Number;

};

ÿþÿ#__Packages.mx.skins.halo.ButtonSkinÿþÿ#__Packages.mx.skins.halo.ButtonSkinÿþÿ
Button.swf#¹U?ÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.skins.RectBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.halo.ButtonSkinÿþÿÿimport mx.skins.RectBorder;

import mx.core.ext.UIObjectExtensions;

import mx.skins.SkinElement;



intrinsic class mx.skins.halo.ButtonSkin extends mx.skins.RectBorder

{

   public function ButtonSkin();

   static var UIObjectExtensionsDependency;

   public var backgroundColorName;

   static function classConstruct():Boolean;

   static var classConstructed:Boolean;

   public var className;

   public function drawHaloRect(w:Number, h:Number):Void;

   public var drawRoundRect:Function;

   public function init():Void;

   public function size():Void;

   static var symbolName:String;

   static var symbolOwner:Object;

};

ÿþÿ!__Packages.mx.skins.halo.Defaultsÿþÿ!__Packages.mx.skins.halo.Defaultsÿþÿ
Button.swf$¹U?ÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIObjectÿþÿ
Button.swfÿþÿÿþÿÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swfÿþÿÿþÿÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.halo.Defaultsÿþÿÿ·import mx.core.UIObject;

import mx.core.ext.UIObjectExtensions;

import mx.styles.CSSStyleDeclaration;



intrinsic class mx.skins.halo.Defaults

{

   static var CSSStyleDeclarationDependency;

   static var UIObjectDependency;

   static var UIObjectExtensionsDependency;

   public var beginFill:Function;

   public var beginGradientFill:Function;

   static function classConstruct():Boolean;

   static var classConstructed;

   public var curveTo:Function;

   public function drawRoundRect(x, y, w, h, r, c, alpha, rot, gradient, ratios);

   public var endFill:Function;

   public var lineTo:Function;

   public var moveTo:Function;

   static function setThemeDefaults():Void;

};

ÿþÿ"__Packages.mx.skins.halo.FocusRectÿþÿ"__Packages.mx.skins.halo.FocusRectÿþÿ
Button.swf$¹U?ÿþÿ#__Packages.mx.managers.DepthManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.core.UIComponentÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.skins.SkinElementÿþÿ
Button.swfÿþÿÿþÿÿþÿ!__Packages.mx.skins.halo.Defaultsÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.halo.FocusRectÿþÿÿÎimport mx.core.UIObject;

import mx.skins.halo.Defaults;

import mx.managers.DepthManager;

import mx.skins.SkinElement;

import mx.core.UIComponent;



intrinsic class mx.skins.halo.FocusRect extends mx.skins.SkinElement

{

   static var DefaultsDependency:mx.skins.halo.Defaults;

   public function FocusRect();

   static var UIComponentDependency:mx.core.UIComponent;

   public var boundingBox_mc:MovieClip;

   static function classConstruct():Boolean;

   static var classConstructed:Boolean;

   public function draw(o:Object):Void;

   public var drawRoundRect:Function;

   public function handleEvent(e:Object):Void;

   public function setSize(w:Number, h:Number, r, a:Number, rectCol:Number):Void;

};

ÿþÿ#__Packages.mx.skins.halo.RectBorderÿþÿ#__Packages.mx.skins.halo.RectBorderÿþÿ
Button.swf$¹U?ÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swfÿþÿÿþÿÿþÿ)__Packages.mx.core.ext.UIObjectExtensionsÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.skins.RectBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.skins.halo.RectBorderÿþÿÿoimport mx.core.ext.UIObjectExtensions;

import mx.skins.Border;

import mx.styles.CSSStyleDeclaration;



intrinsic class mx.skins.halo.RectBorder extends mx.skins.RectBorder

{

   public function RectBorder();

   static var UIObjectExtensionsDependency;

   public var borderCapColorName:String;

   private var borderWidths:Object;

   static function classConstruct():Boolean;

   static var classConstructed:Boolean;

   private var colorList:Object;

   public function draw3dBorder(c1:Number, c2:Number, c3:Number, c4:Number, c5:Number, c6:Number):Void;

   public function drawBorder(Void):Void;

   public var drawRoundRect:Function;

   public function getBorderMetrics(Void):Object;

   public function init(Void):Void;

   public var shadowCapColorName:String;

   static var symbolName:String;

   static var symbolOwner:Object;

   static var version:String;

};

ÿþÿ __Packages.mx.styles.CSSSetStyleÿþÿ __Packages.mx.styles.CSSSetStyleÿþÿ
Button.swf$¹U?ÿþÿ!__Packages.mx.styles.StyleManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.styles.CSSSetStyleÿþÿÿbimport mx.styles.StyleManager;

import mx.styles.CSSStyleDeclaration;



intrinsic class mx.styles.CSSSetStyle

{

   static var CSSStyleDeclarationDependency;

   public var _color:Number;

   public function _setStyle(styleProp:String, newValue):Void;

   public function changeColorStyleInChildren(sheetName:String, colorStyle:String, newValue):Void;

   public function changeTextStyleInChildren(styleProp:String):Void;

   static function classConstruct():Boolean;

   static var classConstructed:Boolean;

   static function enableRunTimeCSS():Void;

   public var invalidateStyle:Function;

   public function notifyStyleChangeInChildren(sheetName:String, styleProp:String, newValue):Void;

   public var setColor:Function;

   public function setStyle(styleProp:String, newValue):Void;

   public var styleName:String;

   public var stylecache:Object;

};

ÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ(__Packages.mx.styles.CSSStyleDeclarationÿþÿ
Button.swf$¹U?ÿþÿ!__Packages.mx.styles.StyleManagerÿþÿ
Button.swfÿþÿÿþÿÿþÿ"__Packages.mx.styles.CSSTextStylesÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.styles.CSSStyleDeclarationÿþÿÿ%import mx.styles.StyleManager;

import mx.styles.CSSTextStyles;



intrinsic class mx.styles.CSSStyleDeclaration

{

   static var CSSTextStylesDependency;

   public function __getTextFormat(tf:TextFormat, bAll:Boolean):Boolean;

   public var _tf:TextFormat;

   static function classConstruct():Boolean;

   static var classConstructed:Boolean;

   public var color:Number;

   public var embedFonts:Boolean;

   public var fontFamily:String;

   public var fontSize:Number;

   public var fontStyle:String;

   public var fontWeight:String;

   public function getStyle(styleProp:String);

   public var marginLeft:Number;

   public var marginRight:Number;

   public var styleName:String;

   public var textAlign:String;

   public var textDecoration:String;

   public var textIndent:Number;

};

ÿþÿ"__Packages.mx.styles.CSSTextStylesÿþÿ"__Packages.mx.styles.CSSTextStylesÿþÿ
Button.swf$¹U?ÿþÿmx.styles.CSSTextStylesÿþÿt

intrinsic class mx.styles.CSSTextStyles

{

   static function addTextStyles(o:Object, bColor:Boolean):Void;

};

ÿþÿ!__Packages.mx.styles.StyleManagerÿþÿ!__Packages.mx.styles.StyleManagerÿþÿ
Button.swf$¹U?ÿþÿmx.styles.StyleManagerÿþÿÿµ

intrinsic class mx.styles.StyleManager

{

   static var TextFormatStyleProps:Object;

   static var TextStyleMap:Object;

   static var colorNames:Object;

   static var colorStyles:Object;

   static function getColorName(colorName:String):Number;

   static var inheritingStyles:Object;

   static function isColorName(colorName:String):Boolean;

   static function isColorStyle(styleName:String):Boolean;

   static function isInheritingStyle(styleName:String):Boolean;

   static function registerColorName(colorName:String, colorValue:Number):Void;

   static function registerColorStyle(styleName:String):Void;

   static function registerInheritingStyle(styleName:String):Void;

};

ÿþÿBoundingBoxÿþÿ
Button.swfÿþÿÿþÿÿþÿSimpleButtonÿþÿ
Button.swfÿþÿÿþÿÿþÿBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿ
RectBorderÿþÿ
Button.swfÿþÿÿþÿÿþÿ
ButtonSkinÿþÿ
Button.swfÿþÿÿþÿÿþÿ__Packages.mx.controls.Buttonÿþÿ
Button.swfÿþÿÿþÿÿþÿmx.controls.Buttonÿþÿÿqimport mx.core.UIObject;

import mx.controls.SimpleButton;

import mx.core.UIComponent;



[Event("click")] 

[TagName("Button")] 

[IconFile("Button.png")] 

intrinsic class mx.controls.Button extends mx.controls.SimpleButton

{

   public function Button();

   public var __get__icon:Function;

   public var __get__label:Function;

   public var __get__labelPlacement:Function;

   public var __label:String;

   public var __labelPlacement:String;

   public var _color;

   public function _getIcon(Void):String;

   public var _iconLinkageName:String;

   [Bindable] [ChangeEvent("click")] public var _inherited_selected:Boolean;

   public function _setIcon(linkage):Void;

   public var borderW:Number;

   public var btnOffset:Number;

   public function calcSize(tag:Number, ref:Object):Void;

   public var centerContent:Boolean;

   public var className:String;

   public var clipParameters:Object;

   public function createChildren(Void):Void;

   public function draw();

   public var falseDisabledIcon:String;

   public var falseDisabledSkin:String;

   public var falseDownIcon:String;

   public var falseDownSkin:String;

   public var falseOverIcon:String;

   public var falseOverSkin:String;

   public var falseUpIcon:String;

   public var falseUpSkin:String;

   public function getBtnOffset(Void):Number;

   public function getLabel(Void):String;

   public function getLabelPlacement(Void):String;

   public var hitArea_mc:MovieClip;

   function get icon():String;

   [Inspectable(defaultValue="")] function set icon(linkage);

   public function init(Void):Void;

   public var initIcon;

   public function invalidateStyle(c:String):Void;

   [Inspectable(defaultValue="Button")] function set label(lbl:String);

   function get label():String;

   public var labelPath:Object;

   [Inspectable(enumeration="left,right,top,bottom"defaultValue="right")] function set labelPlacement(val:String);

   function get labelPlacement():String;

   static var mergedClipParameters:Boolean;

   public function onRelease(Void):Void;

   public function setColor(c:Number):Void;

   public function setEnabled(enable:Boolean):Void;

   public function setHitArea(w:Number, h:Number);

   public function setLabel(label:String):Void;

   public function setLabelPlacement(val:String):Void;

   public function setSkin(tag:Number, linkageName:String, initobj:Object):MovieClip;

   public function setView(offset:Number):Void;

   public function size(Void):Void;

   static var symbolName:String;

   static var symbolOwner;

   public var trueDisabledIcon:String;

   public var trueDisabledSkin:String;

   public var trueDownIcon:String;

   public var trueDownSkin:String;

   public var trueOverIcon:String;

   public var trueOverSkin:String;

   public var trueUpIcon:String;

   public var trueUpSkin:String;

   static var version:String;

   public function viewSkin(varName:String):Void;

};

ÌÈ
h�hhhhÿÿÿÿÀÀÀÿ´ÿþÿPropSheet::ActiveTabÿþÿ7641”ÿþÿ!PublishGifProperties::PaletteNameÿþÿÿþÿ PublishRNWKProperties::speed256Kÿþÿ0ÿþÿ"PublishHtmlProperties::StartPausedÿþÿ0ÿþÿ%PublishFormatProperties::htmlFileNameÿþÿstorage_dialog.htmlÿþÿ PublishQTProperties::LayerOptionÿþÿÿþÿ PublishQTProperties::AlphaOptionÿþÿÿþÿ"PublishQTProperties::MatchMovieDimÿþÿ1ÿþÿVector::Debugging Permittedÿþÿ0ÿþÿPublishProfileProperties::nameÿþÿDefaultÿþÿPublishHtmlProperties::Loopÿþÿ1ÿþÿPublishFormatProperties::jpegÿþÿ0ÿþÿPublishQTProperties::Widthÿþÿ215ÿþÿ$PublishPNGProperties::OptimizeColorsÿþÿ1ÿþÿ&PublishRNWKProperties::speedSingleISDNÿþÿ0ÿþÿ&PublishRNWKProperties::singleRateAudioÿþÿ0ÿþÿVector::External Playerÿþÿÿþÿ%PublishHtmlProperties::showTagWarnMsgÿþÿ1ÿþÿPublishHtmlProperties::Unitsÿþÿ0ÿþÿ4PublishHtmlProperties::UsingDefaultAlternateFilenameÿþÿ1ÿþÿPublishGifProperties::Smoothÿþÿ1ÿþÿ%PublishRNWKProperties::mediaCopyrightÿþÿ(c) 2000ÿþÿ#PublishRNWKProperties::flashBitRateÿþÿ1200ÿþÿVector::Compress Movieÿþÿ1ÿþÿVector::Package Pathsÿþÿÿþÿ&PublishFormatProperties::flashFileNameÿþÿ..\..\storage_dialog.swfÿþÿ'PublishFormatProperties::gifDefaultNameÿþÿ1ÿþÿ%PublishFormatProperties::projectorMacÿþÿ0ÿþÿ"PublishGifProperties::DitherOptionÿþÿÿþÿ!PublishRNWKProperties::exportSMILÿþÿ1ÿþÿ PublishRNWKProperties::speed384Kÿþÿ0ÿþÿ"PublishRNWKProperties::exportAudioÿþÿ1ÿþÿVector::FireFoxÿþÿ0ÿþÿPublishHtmlProperties::Qualityÿþÿ4ÿþÿ(PublishHtmlProperties::VerticalAlignmentÿþÿ1ÿþÿ$PublishFormatProperties::pngFileNameÿþÿstorage_dialog.pngÿþÿPublishFormatProperties::htmlÿþÿ0ÿþÿ"PublishPNGProperties::FilterOptionÿþÿÿþÿ'PublishRNWKProperties::mediaDescriptionÿþÿÿþÿVector::Override Soundsÿþÿ0ÿþÿ!PublishHtmlProperties::DeviceFontÿþÿ0ÿþÿ-PublishFormatProperties::generatorDefaultNameÿþÿ1ÿþÿPublishQTProperties::Flattenÿþÿ1ÿþÿPublishPNGProperties::BitDepthÿþÿ24-bit with AlphaÿþÿPublishPNGProperties::Smoothÿþÿ1ÿþÿ"PublishGifProperties::DitherSolidsÿþÿ0ÿþÿPublishGifProperties::Interlaceÿþÿ0ÿþÿPublishJpegProperties::DPIÿþÿ4718592ÿþÿVector::Qualityÿþÿ80ÿþÿVector::Protectÿþÿ0ÿþÿ"PublishHtmlProperties::DisplayMenuÿþÿ1ÿþÿ*PublishHtmlProperties::HorizontalAlignmentÿþÿ1ÿþÿ2PublishHtmlProperties::VersionDetectionIfAvailableÿþÿ0ÿþÿVector::Templateÿþÿ0ÿþÿ*PublishFormatProperties::generatorFileNameÿþÿstorage_dialog.swtÿþÿ(PublishFormatProperties::rnwkDefaultNameÿþÿ1ÿþÿ(PublishFormatProperties::jpegDefaultNameÿþÿ1ÿþÿPublishFormatProperties::gifÿþÿ0ÿþÿPublishGifProperties::Loopÿþÿ1ÿþÿPublishGifProperties::Widthÿþÿ215ÿþÿ$PublishRNWKProperties::mediaKeywordsÿþÿÿþÿ!PublishRNWKProperties::mediaTitleÿþÿÿþÿPublishRNWKProperties::speed28Kÿþÿ1ÿþÿ#PublishFormatProperties::qtFileNameÿþÿstorage_dialog.movÿþÿ"PublishPNGProperties::DitherOptionÿþÿÿþÿ#PublishGifProperties::PaletteOptionÿþÿÿþÿ#PublishGifProperties::MatchMovieDimÿþÿ1ÿþÿ$PublishRNWKProperties::speedDualISDNÿþÿ0ÿþÿ$PublishRNWKProperties::realVideoRateÿþÿ100000ÿþÿPublishJpegProperties::Qualityÿþÿ80ÿþÿPublishFormatProperties::flashÿþÿ1ÿþÿ#PublishPNGProperties::PaletteOptionÿþÿÿþÿ#PublishPNGProperties::MatchMovieDimÿþÿ1ÿþÿ$PublishJpegProperties::MatchMovieDimÿþÿ1ÿþÿVector::Package Export Frameÿþÿ1ÿþÿ!PublishProfileProperties::versionÿþÿ1ÿþÿPublishHtmlProperties::Alignÿþÿ0ÿþÿ-PublishFormatProperties::projectorWinFileNameÿþÿstorage_dialog.exeÿþÿ'PublishFormatProperties::pngDefaultNameÿþÿ1ÿþÿ0PublishFormatProperties::projectorMacDefaultNameÿþÿ1ÿþÿ#PublishQTProperties::PlayEveryFrameÿþÿ0ÿþÿ"PublishPNGProperties::DitherSolidsÿþÿ0ÿþÿ"PublishJpegProperties::Progressiveÿþÿ0ÿþÿVector::Debugging PasswordÿþÿÿþÿVector::Omit Trace Actionsÿþÿ0ÿþÿPublishHtmlProperties::Heightÿþÿ138ÿþÿPublishHtmlProperties::Widthÿþÿ215ÿþÿ%PublishFormatProperties::jpegFileNameÿþÿstorage_dialog.jpgÿþÿ)PublishFormatProperties::flashDefaultNameÿþÿ0ÿþÿPublishPNGProperties::Interlaceÿþÿ0ÿþÿPublishGifProperties::Heightÿþÿ138ÿþÿPublishJpegProperties::Sizeÿþÿ0ÿþÿVector::DeviceSoundÿþÿ0ÿþÿVector::TopDownÿþÿ0ÿþÿ'PublishHtmlProperties::TemplateFileNameÿþÿ�C:\Documents and Settings\bradneuberg\Local Settings\Application Data\Macromedia\Flash MX 2004\en\Configuration\Html\Default.htmlÿþÿ!PublishHtmlProperties::WindowModeÿþÿ0ÿþÿ2PublishHtmlProperties::UsingDefaultContentFilenameÿþÿ1ÿþÿ-PublishFormatProperties::projectorMacFileNameÿþÿstorage_dialog.hqxÿþÿ(PublishFormatProperties::htmlDefaultNameÿþÿ1ÿþÿPublishFormatProperties::rnwkÿþÿ0ÿþÿPublishFormatProperties::pngÿþÿ0ÿþÿPublishQTProperties::Heightÿþÿ138ÿþÿ%PublishPNGProperties::RemoveGradientsÿþÿ0ÿþÿPublishGifProperties::MaxColorsÿþÿ255ÿþÿ'PublishGifProperties::TransparentOptionÿþÿÿþÿPublishGifProperties::LoopCountÿþÿÿþÿPublishRNWKProperties::speed56Kÿþÿ1ÿþÿVector::Reportÿþÿ0ÿþÿ+PublishHtmlProperties::OwnAlternateFilenameÿþÿÿþÿ(PublishHtmlProperties::AlternateFilenameÿþÿÿþÿ&PublishHtmlProperties::ContentFilenameÿþÿÿþÿ"PublishFormatProperties::generatorÿþÿ0ÿþÿ$PublishGifProperties::OptimizeColorsÿþÿ1ÿþÿ"PublishRNWKProperties::audioFormatÿþÿ0ÿþÿVector::Versionÿþÿ7ÿþÿVector::Event Formatÿþÿ0ÿþÿVector::Stream Compressÿþÿ7ÿþÿPublishFormatProperties::qtÿþÿ0ÿþÿPublishPNGProperties::Heightÿþÿ138ÿþÿPublishPNGProperties::Widthÿþÿ215ÿþÿ%PublishGifProperties::RemoveGradientsÿþÿ0ÿþÿ PublishRNWKProperties::speed512Kÿþÿ0ÿþÿPublishJpegProperties::Heightÿþÿ138ÿþÿVector::ActionScriptVersionÿþÿ2ÿþÿVector::Event Compressÿþÿ7ÿþÿPublishHtmlProperties::Scaleÿþÿ0ÿþÿ0PublishFormatProperties::projectorWinDefaultNameÿþÿ1ÿþÿPublishQTProperties::Loopingÿþÿ0ÿþÿ*PublishQTProperties::UseQTSoundCompressionÿþÿ0ÿþÿ!PublishPNGProperties::PaletteNameÿþÿÿþÿ!PublishPNGProperties::Transparentÿþÿ0ÿþÿ&PublishGifProperties::TransparentAlphaÿþÿ128ÿþÿPublishGifProperties::Animatedÿþÿ0ÿþÿ"PublishRNWKProperties::mediaAuthorÿþÿÿþÿ(PublishRNWKProperties::speedCorporateLANÿþÿ0ÿþÿ&PublishRNWKProperties::showBitrateDlogÿþÿ1ÿþÿ"PublishRNWKProperties::exportFlashÿþÿ1ÿþÿPublishJpegProperties::Widthÿþÿ215ÿþÿVector::Stream Formatÿþÿ0ÿþÿ"PublishHtmlProperties::VersionInfoÿþÿÿþÿ$PublishFormatProperties::gifFileNameÿþÿstorage_dialog.gifÿþÿ&PublishFormatProperties::qtDefaultNameÿþÿ1ÿþÿ"PublishQTProperties::PausedAtStartÿþÿ0ÿþÿ%PublishQTProperties::ControllerOptionÿþÿ0ÿþÿPublishPNGProperties::MaxColorsÿþÿ255ÿþÿ,PublishHtmlProperties::UsingOwnAlternateFileÿþÿ0ÿþÿ%PublishFormatProperties::rnwkFileNameÿþÿstorage_dialog.smilÿþÿ%PublishFormatProperties::projectorWinÿþÿ0ÿþÿ%PublishFormatProperties::defaultNamesÿþÿ0ÿÿÿÿÿþÿÿþÿüÿÿ	CColorDefÿ€ÿ€ÿ€3ÿPï€fÿPï0€™ÿPïH€ÌÿPï`€ÿÿPïx€3ÿï€33ÿ(ï€3fÿ<ï0€3™ÿCïH€3ÌÿFï`€3ÿÿHïx€fÿï0€f3ÿï0€ffÿ(ï0€f™ÿ5ïH€fÌÿ<ï`€fÿÿ@ïx€ÿ€333ÿ0€ÿ€3ÿ ï€33ÿxï€f3ÿdï0€™3ÿ]ïH€Ì3ÿZï`€ÿ3ÿXïx€33ÿÈï€333ÿ0€3f3ÿPPH€3™3ÿPx`€3Ì3ÿP�x€3ÿ3ÿPï�€f3ÿÜï0€f33ÿPH€ff3ÿ(PH€f™3ÿ<x`€fÌ3ÿC�x€fÿ3ÿFï�€ÿ€fffÿ`€ÿ€fÿ ï0€3fÿŒï0€ffÿxï0€™fÿkïH€Ìfÿdï`€ÿfÿ`ïx€3fÿ´ï0€33fÿ PH€3ffÿxPH€3™fÿdx`€3Ìfÿ]�x€3ÿfÿZï�€ffÿÈï0€f3fÿÈPH€fffÿ`€f™fÿP0x€fÌfÿPx�€fÿfÿPï¨€ÿ€™™™ÿ�€ÿ€™ÿ ïH€3™ÿ“ïH€f™ÿ…ïH€™™ÿxïH€Ì™ÿnï`€ÿ™ÿhïx€3™ÿ­ïH€33™ÿ x`€3f™ÿŒx`€3™™ÿxx`€3Ì™ÿk�x€3ÿ™ÿdï�€f™ÿ»ïH€f3™ÿ´x`€ff™ÿ 0x€f™™ÿx0x€fÌ™ÿdx�€fÿ™ÿ]ï¨€ÿ€ÌÌÌÿÀ€ÿ€Ìÿ ï`€3Ìÿ–ï`€fÌÿŒï`€™Ìÿ‚ï`€ÌÌÿxï`€ÿÌÿpïx€3Ìÿªï`€33Ìÿ �x€3fÌÿ“�x€3™Ìÿ…�x€3ÌÌÿx�x€3ÿÌÿnï�€fÌÿ´ï`€f3Ìÿ­�x€ffÌÿ x�€f™ÌÿŒx�€fÌÌÿxx�€fÿÌÿkï¨€ÿ€ÿÿÿÿð€ÿ€ÿÿ ïx€3ÿÿ˜ïx€fÿÿ�ïx€™ÿÿˆïx€Ìÿÿ€ïx€ÿÿÿxïx€3ÿÿ¨ïx€33ÿÿ ï�€3fÿÿ–ï�€3™ÿÿŒï�€3Ìÿÿ‚ï�€3ÿÿÿxï�€fÿÿ°ïx€f3ÿÿªï�€ffÿÿ ï¨€f™ÿÿ“ï¨€fÌÿÿ…ï¨€fÿÿÿxï¨€ÿ€ÿÿïx€ÿ€™ÿïH€™3ÿ
ïH€™fÿïH€™™ÿ(ïH€™Ìÿ2ï`€™ÿÿ8ïx€Ìÿï`€Ì3ÿ
ï`€Ìfÿï`€Ì™ÿï`€ÌÌÿ(ï`€Ìÿÿ0ïx€ÿÿïx€ÿ3ÿïx€ÿfÿïx€ÿ™ÿïx€ÿÌÿ ïx€ÿÿÿ(ïx€ÿ€ÿÿPïx€ÿ€™3ÿãïH€™33ÿx`€™f3ÿx`€™™3ÿ(x`€™Ì3ÿ5�x€™ÿ3ÿ<ï�€Ì3ÿæï`€Ì33ÿ�x€Ìf3ÿ
�x€Ì™3ÿ�x€ÌÌ3ÿ(�x€Ìÿ3ÿ2ï�€ÿ3ÿèïx€ÿ33ÿï�€ÿf3ÿ
ï�€ÿ™3ÿï�€ÿÌ3ÿï�€ÿÿ3ÿ(ï�€ÿ€ÿÿ ïx€ÿ€™fÿÕïH€™3fÿÜx`€™ffÿ0x€™™fÿ(0x€™Ìfÿ<x�€™ÿfÿCï¨€ÌfÿÜï`€Ì3fÿã�x€Ìffÿx�€Ì™fÿx�€ÌÌfÿ(x�€Ìÿfÿ5ï¨€ÿfÿàïx€ÿ3fÿæï�€ÿffÿï¨€ÿ™fÿ
ï¨€ÿÌfÿï¨€ÿÿfÿ(ï¨€ÿ€ÿÿÿ(ïx€ÿ€™™ÿÈïH€™3™ÿÈx`€™f™ÿÈ0x€™™™ÿ�€™Ì™ÿPP¨€™ÿ™ÿPïÀ€Ì™ÿÒï`€Ì3™ÿÕ�x€Ìf™ÿÜx�€Ì™™ÿP¨€ÌÌ™ÿ(P¨€Ìÿ™ÿ<ïÀ€ÿ™ÿØïx€ÿ3™ÿÜï�€ÿf™ÿãï¨€ÿ™™ÿïÀ€ÿÌ™ÿïÀ€ÿÿ™ÿ(ïÀ€ÿ€ÿÿÿxïx€ÿ€™Ìÿ¾ï`€™3Ìÿ»�x€™fÌÿ´x�€™™Ìÿ P¨€™ÌÌÿxP¨€™ÿÌÿdïÀ€ÌÌÿÈï`€Ì3ÌÿÈ�x€ÌfÌÿÈx�€Ì™ÌÿÈP¨€ÌÌÌÿÀ€ÌÿÌÿPïØ€ÿÌÿÐïx€ÿ3ÌÿÒï�€ÿfÌÿÕï¨€ÿ™ÌÿÜïÀ€ÿÌÌÿïØ€ÿÿÌÿ(ïØ€ÿ€ÿÿÿÈïx€ÿ€™ÿÿ¸ïx€™3ÿÿ´ï�€™fÿÿ­ï¨€™™ÿÿ ïÀ€™ÌÿÿŒïÀ€™ÿÿÿxïÀ€ÌÿÿÀïx€Ì3ÿÿ¾ï�€Ìfÿÿ»ï¨€Ì™ÿÿ´ïÀ€ÌÌÿÿ ïØ€ÌÿÿÿxïØ€ÿÿÿÈïx€ÿ3ÿÿÈï�€ÿfÿÿÈï¨€ÿ™ÿÿÈïÀ€ÿÌÿÿÈïØ€ÿÿÿÿð€ÿ€ÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿfýÿ`ÿÿÿÿzÿÿÿÿ€™fÿªÿÌÿÿÿÿÿÿ€ÿÿÿ*ÿÿÿ]ÿÿÿÿÿªÿÿÔÿÿÿÿÿÿÿþÿ"PublishQTProperties::QTSndSettingsÿÿCQTAudioSettingsÿÿÿþÿhÿþÿÿþÿ

ÿÿÿÿÿþÿÿþÿ8ÿþÿPublishJpegProperties::Sizeÿþÿ0ÿþÿVector::DeviceSoundÿþÿ0ÿþÿVector::TopDownÿþÿ0ÿþÿ'PublishHtmlProperties::TemplateFileNameÿþÿ�C:\Documents and Settings\bradneuberg\Local Settings\Application Data\Macromedia\Flash MX 2004\en\Configuration\Html\Default.htmlÿþÿ!PublishHtmlProperties::WindowModeÿþÿ0ÿþÿ2PublishHtmlProperties::UsingDefaultContentFilenameÿþÿ1ÿþÿ-PublishFormatProperties::projectorMacFileNameÿþÿstorage_dialog.hqxÿþÿ(PublishFormatProperties::htmlDefaultNameÿþÿ1ÿþÿPublishFormatProperties::rnwkÿþÿ0ÿþÿPublishFormatProperties::pngÿþÿ0ÿþÿPublishQTProperties::Heightÿþÿ138ÿþÿ%PublishPNGProperties::RemoveGradientsÿþÿ0ÿþÿPublishGifProperties::MaxColorsÿþÿ255ÿþÿ'PublishGifProperties::TransparentOptionÿþÿÿþÿPublishGifProperties::LoopCountÿþÿÿþÿPublishRNWKProperties::speed56Kÿþÿ1ÿþÿVector::Reportÿþÿ0ÿþÿ+PublishHtmlProperties::OwnAlternateFilenameÿþÿÿþÿ(PublishHtmlProperties::AlternateFilenameÿþÿÿþÿ&PublishHtmlProperties::ContentFilenameÿþÿÿþÿ"PublishFormatProperties::generatorÿþÿ0ÿþÿ$PublishGifProperties::OptimizeColorsÿþÿ1ÿþÿ"PublishRNWKProperties::audioFormatÿþÿ0ÿþÿVector::Versionÿþÿ7ÿþÿVector::Event Formatÿþÿ0ÿþÿVector::Stream Compressÿþÿ7ÿþÿPublishFormatProperties::qtÿþÿ0ÿþÿPublishPNGProperties::Heightÿþÿ138ÿþÿPublishPNGProperties::Widthÿþÿ215ÿþÿ%PublishGifProperties::RemoveGradientsÿþÿ0ÿþÿ PublishRNWKProperties::speed512Kÿþÿ0ÿþÿPublishJpegProperties::Heightÿþÿ138ÿþÿVector::ActionScriptVersionÿþÿ2ÿþÿVector::Event Compressÿþÿ7ÿþÿPublishHtmlProperties::Scaleÿþÿ0ÿþÿ0PublishFormatProperties::projectorWinDefaultNameÿþÿ1ÿþÿPublishQTProperties::Loopingÿþÿ0ÿþÿ*PublishQTProperties::UseQTSoundCompressionÿþÿ0ÿþÿ!PublishPNGProperties::PaletteNameÿþÿÿþÿ!PublishPNGProperties::Transparentÿþÿ0ÿþÿ&PublishGifProperties::TransparentAlphaÿþÿ128ÿþÿPublishGifProperties::Animatedÿþÿ0ÿþÿ"PublishRNWKProperties::mediaAuthorÿþÿÿþÿ(PublishRNWKProperties::speedCorporateLANÿþÿ0ÿþÿ&PublishRNWKProperties::showBitrateDlogÿþÿ1ÿþÿ"PublishRNWKProperties::exportFlashÿþÿ1ÿþÿPublishJpegProperties::Widthÿþÿ215ÿþÿVector::Stream Formatÿþÿ0ÿþÿ"PublishHtmlProperties::VersionInfoÿþÿÿþÿ$PublishFormatProperties::gifFileNameÿþÿstorage_dialog.gifÿþÿ&PublishFormatProperties::qtDefaultNameÿþÿ1ÿþÿ"PublishQTProperties::PausedAtStartÿþÿ0ÿþÿ%PublishQTProperties::ControllerOptionÿþÿ0ÿþÿPublishPNGProperties::MaxColorsÿþÿ255ÿþÿ,PublishHtmlProperties::UsingOwnAlternateFileÿþÿ0ÿþÿ%PublishFormatProperties::rnwkFileNameÿþÿstorage_dialog.smilÿþÿ%PublishFormatProperties::projectorWinÿþÿ0ÿþÿ%PublishFormatProperties::defaultNamesÿþÿ0ÿÿÿÿÿþÿÿþÿüÿÿ	CColorDefÿ€ÿ€ÿ€3ÿPï€fÿPï0€™ÿPïH€ÌÿPï`€ÿÿPïx€3ÿï€33ÿ(ï€3fÿ<ï0€3™ÿCïH€3ÌÿFï`€3ÿÿHïx€fÿï0€f3ÿï0€ffÿ(ï0€f™ÿ5ïH€fÌÿ<ï`€fÿÿ@ïx€ÿ€333ÿ0€ÿ€3ÿ ï€33ÿxï€f3ÿdï0€™3ÿ]ïH€Ì3ÿZï`€ÿ3ÿXïx€33ÿÈï€333ÿ0€3f3ÿPPH€3™3ÿPx`€3Ì3ÿP�x€3ÿ3ÿPï�€f3ÿÜï0€f33ÿPH€ff3ÿ(PH€f™3ÿ<x`€fÌ3ÿC�x€fÿ3ÿFï�€ÿ€fffÿ`€ÿ€fÿ ï0€3fÿŒï0€ffÿxï0€™fÿkïH€Ìfÿdï`€ÿfÿ`ïx€3fÿ´ï0€33fÿ PH€3ffÿxPH€3™fÿdx`€3Ìfÿ]�x€3ÿfÿZï�€ffÿÈï0€f3fÿÈPH€fffÿ`€f™fÿP0x€fÌfÿPx�€fÿfÿPï¨€ÿ€™™™ÿ�€ÿ€™ÿ ïH€3™ÿ“ïH€f™ÿ…ïH€™™ÿxïH€Ì™ÿnï`€ÿ™ÿhïx€3™ÿ­ïH€33™ÿ x`€3f™ÿŒx`€3™™ÿxx`€3Ì™ÿk�x€3ÿ™ÿdï�€f™ÿ»ïH€f3™ÿ´x`€ff™ÿ 0x€f™™ÿx0x€fÌ™ÿdx�€fÿ™ÿ]ï¨€ÿ€ÌÌÌÿÀ€ÿ€Ìÿ ï`€3Ìÿ–ï`€fÌÿŒï`€™Ìÿ‚ï`€ÌÌÿxï`€ÿÌÿpïx€3Ìÿªï`€33Ìÿ �x€3fÌÿ“�x€3™Ìÿ…�x€3ÌÌÿx�x€3ÿÌÿnï�€fÌÿ´ï`€f3Ìÿ­�x€ffÌÿ x�€f™ÌÿŒx�€fÌÌÿxx�€fÿÌÿkï¨€ÿ€ÿÿÿÿð€ÿ€ÿÿ ïx€3ÿÿ˜ïx€fÿÿ�ïx€™ÿÿˆïx€Ìÿÿ€ïx€ÿÿÿxïx€3ÿÿ¨ïx€33ÿÿ ï�€3fÿÿ–ï�€3™ÿÿŒï�€3Ìÿÿ‚ï�€3ÿÿÿxï�€fÿÿ°ïx€f3ÿÿªï�€ffÿÿ ï¨€f™ÿÿ“ï¨€fÌÿÿ…ï¨€fÿÿÿxï¨€ÿ€ÿÿïx€ÿ€™ÿïH€™3ÿ
ïH€™fÿïH€™™ÿ(ïH€™Ìÿ2ï`€™ÿÿ8ïx€Ìÿï`€Ì3ÿ
ï`€Ìfÿï`€Ì™ÿï`€ÌÌÿ(ï`€Ìÿÿ0ïx€ÿÿïx€ÿ3ÿïx€ÿfÿïx€ÿ™ÿïx€ÿÌÿ ïx€ÿÿÿ(ïx€ÿ€ÿÿPïx€ÿ€™3ÿãïH€™33ÿx`€™f3ÿx`€™™3ÿ(x`€™Ì3ÿ5�x€™ÿ3ÿ<ï�€Ì3ÿæï`€Ì33ÿ�x€Ìf3ÿ
�x€Ì™3ÿ�x€ÌÌ3ÿ(�x€Ìÿ3ÿ2ï�€ÿ3ÿèïx€ÿ33ÿï�€ÿf3ÿ
ï�€ÿ™3ÿï�€ÿÌ3ÿï�€ÿÿ3ÿ(ï�€ÿ€ÿÿ ïx€ÿ€™fÿÕïH€™3fÿÜx`€™ffÿ0x€™™fÿ(0x€™Ìfÿ<x�€™ÿfÿCï¨€ÌfÿÜï`€Ì3fÿã�x€Ìffÿx�€Ì™fÿx�€ÌÌfÿ(x�€Ìÿfÿ5ï¨€ÿfÿàïx€ÿ3fÿæï�€ÿffÿï¨€ÿ™fÿ
ï¨€ÿÌfÿï¨€ÿÿfÿ(ï¨€ÿ€ÿÿÿ(ïx€ÿ€™™ÿÈïH€™3™ÿÈx`€™f™ÿÈ0x€™™™ÿ�€™Ì™ÿPP¨€™ÿ™ÿPïÀ€Ì™ÿÒï`€Ì3™ÿÕ�x€Ìf™ÿÜx�€Ì™™ÿP¨€ÌÌ™ÿ(P¨€Ìÿ™ÿ<ïÀ€ÿ™ÿØïx€ÿ3™ÿÜï�€ÿf™ÿãï¨€ÿ™™ÿïÀ€ÿÌ™ÿïÀ€ÿÿ™ÿ(ïÀ€ÿ€ÿÿÿxïx€ÿ€™Ìÿ¾ï`€™3Ìÿ»�x€™fÌÿ´x�€™™Ìÿ P¨€™ÌÌÿxP¨€™ÿÌÿdïÀ€ÌÌÿÈï`€Ì3ÌÿÈ�x€ÌfÌÿÈx�€Ì™ÌÿÈP¨€ÌÌÌÿÀ€ÌÿÌÿPïØ€ÿÌÿÐïx€ÿ3ÌÿÒï�€ÿfÌÿÕï¨€ÿ™ÌÿÜïÀ€ÿÌÌÿïØ€ÿÿÌÿ(ïØ€ÿ€ÿÿÿÈïx€ÿ€™ÿÿ¸ïx€™3ÿÿ´ï�€™fÿÿ­ï¨€™™ÿÿ ïÀ€™ÌÿÿŒïÀ€™ÿÿÿxïÀ€ÌÿÿÀïx€Ì3ÿÿ¾ï�€Ìfÿÿ»ï¨€Ì™ÿÿ´ïÀ€ÌÌÿÿ ïØ€ÌÿÿÿxïØ€ÿÿÿÈïx€ÿ3ÿÿÈï�€ÿfÿÿÈï¨€ÿ™ÿÿÈïÀ€ÿÌÿÿÈïØ€ÿÿÿÿð€ÿ€ÿRemoveGradientsÿþÿ0ÿþÿ PublishRNWKProperties::speed512Kÿþÿ0ÿþÿPublishJpegProperties::Heightÿþÿ138ÿþÿVector::ActionScriptVersionÿþÿ2ÿþÿVector::Event Compressÿþÿ7ÿþÿPublishHtmlProperties::Scaleÿþÿ0ÿþÿ0PublishFormatProperties::projectorWinDefaultNameÿþÿ1ÿþÿPublishQTProperties::Loopingÿþÿ0ÿþÿ*PublishQTProperties::UseQTSoundCompressionÿþÿ0ÿþÿ!PublishPNGProperties::PaletteNameÿþÿÿþÿ!PublishPNGProperties::Transparentÿþÿ0ÿþÿ&PublishGifProperties::TransparentAlphaÿþÿ128ÿþÿPublishGifProperties::Animatedÿþÿ0ÿþÿ"PublishRNWKProperties::mediaAuthorÿþÿÿþÿ(PublishRNWKProperties::speedCorporateLANÿþÿ0ÿþÿ&PublishRNWKProperties::showBitrateDlogÿþÿ1ÿþÿ"PublishRNWKProperties::exportFlashÿþÿ1ÿþÿPublishJpegProperties::Widthÿþÿ215ÿþÿVector::Stream Formatÿþÿ0ÿþÿ"PublishHtmlProperties::VersionInfoÿþÿÿþÿ$PublishFormatProperties::gifFileNameÿþÿstorage_dialog.gifÿþÿ&PublishFormatProperties::qtDefaultNameÿþÿ1ÿþÿ"PublishQTProperties::PausedAtStartÿþÿ0ÿþÿ%PublishQTProperties::ControllerOptionÿþÿ0ÿþÿPublishPNGProperties::MaxColorsÿþÿ255ÿþÿ,PublishHtmlProperties::UsingOwnAlternateFileÿþÿ0ÿþÿ%PublishFormatProperties::rnwkFileNameÿþÿstorage_dialog.smilÿþÿ%PublishFormatProperties::projectorWinÿþÿ0ÿþÿ%PublishFormatProperties::defaultNamesÿþÿ0ÿÿÿÿÿþÿÿþÿüÿÿ	CColorDefÿ€ÿ€ÿ€3ÿPï€fÿPï0€™ÿPïH€ÌÿPï`€ÿÿPïx€3ÿï€33ÿ(ï€3fÿ<ï0€3™ÿCïH€3ÌÿFï`€3ÿÿHïx€fÿï0€f3ÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿfýÿ`ÿÿÿÿzÿÿÿÿ€™fÿªÿÌÿÿÿÿÿÿ€ÿÿÿ*ÿÿÿ]ÿÿÿÿÿªÿÿÔÿÿÿÿÿÿÿþÿ"PublishQTProperties::QTSndSettingsÿÿCQTAudioSettinÿï0€ffÿ(ï0€f™ÿ5ïH€fÌÿ<ï`€fÿÿ@ïx€ÿ€333ÿ0€ÿ€3ÿ ï€33ÿxï€f3ÿdï0€™3ÿ]ïH€Ì3ÿZï`€ÿ3ÿXïx€33ÿÈï€333ÿ0€3f3ÿPPH€3™3ÿPx`€3Ì3ÿP�x€3ÿ3ÿPï�€f3ÿÜï0€f33ÿPH€ff3ÿ(PH€f™3ÿ<x`€fÌ3ÿC�x€fÿ3ÿFï�€ÿ€fffÿ`€ÿ€fÿ ï0€3fÿŒï0€ffÿxï0€™fÿkïH€Ìfÿdï`€ÿfÿgsÿÿÿþÿhÿþÿÿþÿ

ÿÿÿÿÿþÿÿþÿ`ïx€3fÿ´ï0€33fÿ PH€3ffÿxPH€3™fÿdx`€3Ìfÿ]�x€3ÿfÿZï�€ffÿÈï0€f3fÿÈPH€fffÿ`€f™fÿP0x€fÌfÿPx�€fÿfÿPï¨€ÿ€™™™ÿ�€ÿ€™ÿ ïH€3™ÿ“ïH€f™ÿ…ïH€™™ÿxïH€Ì™ÿnï`€ÿ™ÿhïx€3™ÿ­ïH€33™ÿ x`€3f™ÿŒx`€3™™ÿxx`€3Ì™ÿk�x€3ÿ™ÿdï�€f™ÿ»ïH€f3™ÿ´x`€ff™ÿ 0x€f™™ÿx0x€fÌ™ÿdx�€fÿ™ÿ]ï¨€ÿ€ÌÌÌÿÀ€ÿ€Ìÿ ï`€3Ìÿ–ï`€fÌÿŒï`€™Ìÿ‚ï`€ÌÌÿxï`€ÿÌÿpïx€3Ìÿªï`€33Ìÿ �x€3fÌÿ“�x€3™Ìÿ…�x€3ÌÌÿx�x€3ÿÌÿnï�€fÌÿ´ï`€f3Ìÿ­�x€ffÌÿ x�€f™ÌÿŒx�€fÌÌÿxx�€fÿÌÿkï¨€ÿ€ÿÿÿÿð€ÿ€ÿÿ ïx€3ÿÿ˜ïx€fÿÿ�ïx€™ÿÿˆïx€Ìÿÿ€ïx€ÿÿÿxïx€3ÿÿ¨ïx€33ÿÿ ï�€3fÿÿ–ï�€3™ÿÿŒï�€3Ìÿÿ‚ï�€3ÿÿÿxï�€fÿÿ°ïx€f3ÿÿªï�€ffÿÿ ï¨€f™ÿÿ“ï¨€fÌÿÿ…ï¨€fÿÿÿxï¨€ÿ€ÿÿïx€ÿ€™ÿïH€™3ÿ
ïH€™fÿïH€™™ÿ(ïH€™Ìÿ2ï`€™ÿÿ8ïx€Ìÿï`€Ì3ÿ
ï`€Ìfÿï`€Ì™ÿï`€ÌÌÿ(ï`€Ìÿÿ0ïx€ÿÿïx€ÿ3ÿïx€ÿfÿïx€ÿ™ÿïx€ÿÌÿ ïx€ÿÿÿ(ïx€ÿ€ÿÿPïx€ÿ€™3ÿãïH€™33ÿx`€™f3ÿx`€™™3ÿ(x`€™Ì3ÿ5�x€™ÿ3ÿ<ï�€Ì3ÿæï`€Ì33ÿ�x€Ìf3ÿ
�x€Ì™3ÿ�x€ÌÌ3ÿ(�x€Ìÿ3ÿ2ï�€ÿ3ÿèïx€ÿ33ÿï�€ÿf3ÿ
ï�€ÿ™3ÿï�€ÿÌ3ÿï�€ÿÿ3ÿ(ï�€ÿ€ÿÿ ïx€ÿ€™fÿÕïH€™3fÿÜx`€™ffÿ0x€™™fÿ(0x€™Ìfÿ<x�€™ÿfÿCï¨€ÌfÿÜï`€Ì3fÿã�x€Ìffÿx�€Ì™fÿx�€ÌÌfÿ(x�€Ìÿfÿ5ï¨€ÿfÿàïx€ÿ3fÿæï�€ÿffÿï¨€ÿ™fÿ
ï¨€ÿÌfÿï¨€ÿÿfÿ(ï¨€ÿ€ÿÿÿ(ïx€ÿ€™™ÿÈïH€™3™ÿÈx`€™f™ÿÈ0x€™™™ÿ�€™Ì™ÿPP¨€™ÿ™ÿPïÀ€Ì™ÿÒï`€Ì3™ÿÕ�x€Ìf™ÿÜx�€Ì™™ÿP¨€ÌÌ™ÿ(P¨€Ìÿ™ÿ<ïÀ€ÿ™ÿØïx€ÿ3™ÿÜï�€ÿf™ÿãï¨€ÿ™™ÿïÀ€ÿÌ™ÿïÀ€ÿÿ™ÿ(ïÀ€ÿ€ÿÿÿxïx€ÿ€™Ìÿ¾ï`€™3Ìÿ»�x€™fÌÿ´x�€™™Ìÿ P¨€™ÌÌÿxP¨€™ÿÌÿdïÀ€ÌÌÿÈï`€Ì3ÌÿÈ�x€ÌfÌÿÈx�€Ì™ÌÿÈP¨€ÌÌÌÿÀ€ÌÿÌÿPïØ€ÿÌÿÐïx€ÿ3ÌÿÒï�€ÿfÌÿÕï¨€ÿ™ÌÿÜïÀ€ÿÌÌÿïØ€ÿÿÌÿ(ïØ€ÿ€ÿÿÿÈïx€ÿ€™ÿÿ¸ïx€™3ÿÿ´ï�€™fÿÿ­ï¨€™™ÿÿ ïÀ€™ÌÿÿŒïÀ€™ÿÿÿxïÀ€ÌÿÿÀïx€Ì3ÿÿ¾ï�€Ìfÿÿ»ï¨€Ì™ÿÿ´ïÀ€ÌÌÿÿ ïØ€ÌÿÿÿxïØ€ÿÿÿÈïx€ÿ3ÿÿÈï�€ÿfÿÿÈï¨€ÿ™ÿÿÈïÀ€ÿÌÿÿÈïØ€ÿÿÿÿð€ÿ€ÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿfýÿ`ÿÿÿÿzÿÿÿÿ€™fÿªÿÌÿÿÿÿÿÿ€ÿÿÿ*ÿÿÿ]ÿÿÿÿÿªÿÿÔÿÿÿÿÿÿÿþÿ"PublishQTProperties::QTSndSettingsÿÿCQTAudioSettingsÿÿÿþÿhÿþÿÿþÿ

ÿÿÿÿÿþÿÿþÿ
__CPAN_FILE__ src/storage/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: ["dojo.storage"],
	browser: ["dojo.storage.browser"],
	dashboard: ["dojo.storage.dashboard"]
});
dojo.provide("dojo.storage.*");


__CPAN_FILE__ src/storage/Storage.as
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

import DojoExternalInterface;

class Storage {
	public static var SUCCESS = "success";
	public static var FAILED = "failed";
	public static var PENDING = "pending";
	
	public var so;
	
	public function Storage(){
		//getURL("javascript:dojo.debug('FLASH:Storage constructor')");
		DojoExternalInterface.initialize();
		DojoExternalInterface.addCallback("put", this, put);
		DojoExternalInterface.addCallback("get", this, get);
		DojoExternalInterface.addCallback("showSettings", this, showSettings);
		DojoExternalInterface.addCallback("clear", this, clear);
		DojoExternalInterface.addCallback("getKeys", this, getKeys);
		DojoExternalInterface.addCallback("remove", this, remove);
		DojoExternalInterface.loaded();
		
		// preload the System Settings finished button movie for offline
		// access so it is in the cache
		_root.createEmptyMovieClip("_settingsBackground", 1);
		_root._settingsBackground.loadMovie(DojoExternalInterface.dojoPath + "storage_dialog.swf");
	}

	public function put(keyName, keyValue, namespace){
		// Get the SharedObject for these values and save it
		so = SharedObject.getLocal(namespace);
		
		// prepare a storage status handler
		var self = this;
		so.onStatus = function(infoObject:Object){
			//getURL("javascript:dojo.debug('FLASH: onStatus, infoObject="+infoObject.code+"')");
			
			// delete the data value if the request was denied
			if (infoObject.code == "SharedObject.Flush.Failed"){
				delete self.so.data[keyName];
			}
			
			var statusResults;
			if(infoObject.code == "SharedObject.Flush.Failed"){
				statusResults = Storage.FAILED;
			}else if(infoObject.code == "SharedObject.Flush.Pending"){
				statusResults = Storage.PENDING;
			}else if(infoObject.code == "SharedObject.Flush.Success"){
				statusResults = Storage.SUCCESS;
			}
			//getURL("javascript:dojo.debug('FLASH: onStatus, statusResults="+statusResults+"')");
			
			// give the status results to JavaScript
			DojoExternalInterface.call("dojo.storage._onStatus", null, statusResults, 
																 keyName);
		}
		
		// save the key and value
		so.data[keyName] = keyValue;
		var flushResults = so.flush();
		
		// return results of this command to JavaScript
		var statusResults;
		if(flushResults == true){
			statusResults = Storage.SUCCESS;
		}else if(flushResults == "pending"){
			statusResults = Storage.PENDING;
		}else{
			statusResults = Storage.FAILED;
		}
		
		DojoExternalInterface.call("dojo.storage._onStatus", null, statusResults, 
															 keyName);
	}

	public function get(keyName, namespace){
		// Get the SharedObject for these values and save it
		so = SharedObject.getLocal(namespace);
		var results = so.data[keyName];
		
		return results;
	}
	
	public function showSettings(){
		// Show the configuration options for the Flash player, opened to the
		// section for local storage controls (pane 1)
		System.showSettings(1);
		
		// there is no way we can intercept when the Close button is pressed, allowing us
		// to hide the Flash dialog. Instead, we need to load a movie in the
		// background that we can show a close button on.
		_root.createEmptyMovieClip("_settingsBackground", 1);
		_root._settingsBackground.loadMovie(DojoExternalInterface.dojoPath + "storage_dialog.swf");
	}
	
	public function clear(namespace){
		so = SharedObject.getLocal(namespace);
		so.clear();
		so.flush();
	}
	
	public function getKeys(namespace){
		// Returns a list of the available keys in this namespace
		
		// get the storage object
		so = SharedObject.getLocal(namespace);
		
		// get all of the keys
		var results = new Array();
		for(var i in so.data)
			results.push(i);	
		
		// join the keys together in a comma seperated string
		results = results.join(",");
		
		return results;
	}
	
	public function remove(keyName, namespace){
		// Removes a key

		// get the storage object
		so = SharedObject.getLocal(namespace);
		
		// delete this value
		delete so.data[keyName];
		
		// save the changes
		so.flush();
	}

	static function main(mc){
		//getURL("javascript:dojo.debug('FLASH: storage loaded')");
		_root.app = new Storage(); 
	}
}


__CPAN_DIR__ src/io
__CPAN_FILE__ src/io/BrowserIO.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.io.BrowserIO");

dojo.require("dojo.io");
dojo.require("dojo.lang.array");
dojo.require("dojo.lang.func");
dojo.require("dojo.string.extras");
dojo.require("dojo.dom");
dojo.require("dojo.undo.browser");

dojo.io.checkChildrenForFile = function(node){
	var hasFile = false;
	var inputs = node.getElementsByTagName("input");
	dojo.lang.forEach(inputs, function(input){
		if(hasFile){ return; }
		if(input.getAttribute("type")=="file"){
			hasFile = true;
		}
	});
	return hasFile;
}

dojo.io.formHasFile = function(formNode){
	return dojo.io.checkChildrenForFile(formNode);
}

dojo.io.updateNode = function(node, urlOrArgs){
	node = dojo.byId(node);
	var args = urlOrArgs;
	if(dojo.lang.isString(urlOrArgs)){
		args = { url: urlOrArgs };
	}
	args.mimetype = "text/html";
	args.load = function(t, d, e){
		while(node.firstChild){
			if(dojo["event"]){
				try{
					dojo.event.browser.clean(node.firstChild);
				}catch(e){}
			}
			node.removeChild(node.firstChild);
		}
		node.innerHTML = d;
	};
	dojo.io.bind(args);
}

dojo.io.formFilter = function(node) {
	var type = (node.type||"").toLowerCase();
	return !node.disabled && node.name
		&& !dojo.lang.inArray(type, ["file", "submit", "image", "reset", "button"]);
}

// TODO: Move to htmlUtils
dojo.io.encodeForm = function(formNode, encoding, formFilter){
	if((!formNode)||(!formNode.tagName)||(!formNode.tagName.toLowerCase() == "form")){
		dojo.raise("Attempted to encode a non-form element.");
	}
	if(!formFilter) { formFilter = dojo.io.formFilter; }
	var enc = /utf/i.test(encoding||"") ? encodeURIComponent : dojo.string.encodeAscii;
	var values = [];

	for(var i = 0; i < formNode.elements.length; i++){
		var elm = formNode.elements[i];
		if(!elm || elm.tagName.toLowerCase() == "fieldset" || !formFilter(elm)) { continue; }
		var name = enc(elm.name);
		var type = elm.type.toLowerCase();

		if(type == "select-multiple"){
			for(var j = 0; j < elm.options.length; j++){
				if(elm.options[j].selected) {
					values.push(name + "=" + enc(elm.options[j].value));
				}
			}
		}else if(dojo.lang.inArray(type, ["radio", "checkbox"])){
			if(elm.checked){
				values.push(name + "=" + enc(elm.value));
			}
		}else{
			values.push(name + "=" + enc(elm.value));
		}
	}

	// now collect input type="image", which doesn't show up in the elements array
	var inputs = formNode.getElementsByTagName("input");
	for(var i = 0; i < inputs.length; i++) {
		var input = inputs[i];
		if(input.type.toLowerCase() == "image" && input.form == formNode
			&& formFilter(input)) {
			var name = enc(input.name);
			values.push(name + "=" + enc(input.value));
			values.push(name + ".x=0");
			values.push(name + ".y=0");
		}
	}
	return values.join("&") + "&";
}

dojo.io.FormBind = function(args) {
	this.bindArgs = {};

	if(args && args.formNode) {
		this.init(args);
	} else if(args) {
		this.init({formNode: args});
	}
}
dojo.lang.extend(dojo.io.FormBind, {
	form: null,

	bindArgs: null,

	clickedButton: null,

	init: function(args) {
		var form = dojo.byId(args.formNode);

		if(!form || !form.tagName || form.tagName.toLowerCase() != "form") {
			throw new Error("FormBind: Couldn't apply, invalid form");
		} else if(this.form == form) {
			return;
		} else if(this.form) {
			throw new Error("FormBind: Already applied to a form");
		}

		dojo.lang.mixin(this.bindArgs, args);
		this.form = form;

		this.connect(form, "onsubmit", "submit");

		for(var i = 0; i < form.elements.length; i++) {
			var node = form.elements[i];
			if(node && node.type && dojo.lang.inArray(node.type.toLowerCase(), ["submit", "button"])) {
				this.connect(node, "onclick", "click");
			}
		}

		var inputs = form.getElementsByTagName("input");
		for(var i = 0; i < inputs.length; i++) {
			var input = inputs[i];
			if(input.type.toLowerCase() == "image" && input.form == form) {
				this.connect(input, "onclick", "click");
			}
		}
	},

	onSubmit: function(form) {
		return true;
	},

	submit: function(e) {
		e.preventDefault();
		if(this.onSubmit(this.form)) {
			dojo.io.bind(dojo.lang.mixin(this.bindArgs, {
				formFilter: dojo.lang.hitch(this, "formFilter")
			}));
		}
	},

	click: function(e) {
		var node = e.currentTarget;
		if(node.disabled) { return; }
		this.clickedButton = node;
	},

	formFilter: function(node) {
		var type = (node.type||"").toLowerCase();
		var accept = false;
		if(node.disabled || !node.name) {
			accept = false;
		} else if(dojo.lang.inArray(type, ["submit", "button", "image"])) {
			if(!this.clickedButton) { this.clickedButton = node; }
			accept = node == this.clickedButton;
		} else {
			accept = !dojo.lang.inArray(type, ["file", "submit", "reset", "button"]);
		}
		return accept;
	},

	// in case you don't have dojo.event.* pulled in
	connect: function(srcObj, srcFcn, targetFcn) {
		if(dojo.evalObjPath("dojo.event.connect")) {
			dojo.event.connect(srcObj, srcFcn, this, targetFcn);
		} else {
			var fcn = dojo.lang.hitch(this, targetFcn);
			srcObj[srcFcn] = function(e) {
				if(!e) { e = window.event; }
				if(!e.currentTarget) { e.currentTarget = e.srcElement; }
				if(!e.preventDefault) { e.preventDefault = function() { window.event.returnValue = false; } }
				fcn(e);
			}
		}
	}
});

dojo.io.XMLHTTPTransport = new function(){
	var _this = this;

	var _cache = {}; // FIXME: make this public? do we even need to?
	this.useCache = false; // if this is true, we'll cache unless kwArgs.useCache = false
	this.preventCache = false; // if this is true, we'll always force GET requests to cache

	// FIXME: Should this even be a function? or do we just hard code it in the next 2 functions?
	function getCacheKey(url, query, method) {
		return url + "|" + query + "|" + method.toLowerCase();
	}

	function addToCache(url, query, method, http) {
		_cache[getCacheKey(url, query, method)] = http;
	}

	function getFromCache(url, query, method) {
		return _cache[getCacheKey(url, query, method)];
	}

	this.clearCache = function() {
		_cache = {};
	}

	// moved successful load stuff here
	function doLoad(kwArgs, http, url, query, useCache) {
		if(	((http.status>=200)&&(http.status<300))|| 	// allow any 2XX response code
			(http.status==304)|| 						// get it out of the cache
			(location.protocol=="file:" && (http.status==0 || http.status==undefined))||
			(location.protocol=="chrome:" && (http.status==0 || http.status==undefined))
		){
			var ret;
			if(kwArgs.method.toLowerCase() == "head"){
				var headers = http.getAllResponseHeaders();
				ret = {};
				ret.toString = function(){ return headers; }
				var values = headers.split(/[\r\n]+/g);
				for(var i = 0; i < values.length; i++) {
					var pair = values[i].match(/^([^:]+)\s*:\s*(.+)$/i);
					if(pair) {
						ret[pair[1]] = pair[2];
					}
				}
			}else if(kwArgs.mimetype == "text/javascript"){
				try{
					ret = dj_eval(http.responseText);
				}catch(e){
					dojo.debug(e);
					dojo.debug(http.responseText);
					ret = null;
				}
			}else if(kwArgs.mimetype == "text/json"){
				try{
					ret = dj_eval("("+http.responseText+")");
				}catch(e){
					dojo.debug(e);
					dojo.debug(http.responseText);
					ret = false;
				}
			}else if((kwArgs.mimetype == "application/xml")||
						(kwArgs.mimetype == "text/xml")){
				ret = http.responseXML;
				if(!ret || typeof ret == "string" || !http.getResponseHeader("Content-Type")) {
					ret = dojo.dom.createDocumentFromText(http.responseText);
				}
			}else{
				ret = http.responseText;
			}

			if(useCache){ // only cache successful responses
				addToCache(url, query, kwArgs.method, http);
			}
			kwArgs[(typeof kwArgs.load == "function") ? "load" : "handle"]("load", ret, http, kwArgs);
		}else{
			var errObj = new dojo.io.Error("XMLHttpTransport Error: "+http.status+" "+http.statusText);
			kwArgs[(typeof kwArgs.error == "function") ? "error" : "handle"]("error", errObj, http, kwArgs);
		}
	}

	// set headers (note: Content-Type will get overriden if kwArgs.contentType is set)
	function setHeaders(http, kwArgs){
		if(kwArgs["headers"]) {
			for(var header in kwArgs["headers"]) {
				if(header.toLowerCase() == "content-type" && !kwArgs["contentType"]) {
					kwArgs["contentType"] = kwArgs["headers"][header];
				} else {
					http.setRequestHeader(header, kwArgs["headers"][header]);
				}
			}
		}
	}

	this.inFlight = [];
	this.inFlightTimer = null;

	this.startWatchingInFlight = function(){
		if(!this.inFlightTimer){
			this.inFlightTimer = setInterval("dojo.io.XMLHTTPTransport.watchInFlight();", 10);
		}
	}

	this.watchInFlight = function(){
		var now = null;
		for(var x=this.inFlight.length-1; x>=0; x--){
			var tif = this.inFlight[x];
			if(!tif){ this.inFlight.splice(x, 1); continue; }
			if(4==tif.http.readyState){
				// remove it so we can clean refs
				this.inFlight.splice(x, 1);
				doLoad(tif.req, tif.http, tif.url, tif.query, tif.useCache);
			}else if (tif.startTime){
				//See if this is a timeout case.
				if(!now){
					now = (new Date()).getTime();
				}
				if(tif.startTime + (tif.req.timeoutSeconds * 1000) < now){
					//Stop the request.
					if(typeof tif.http.abort == "function"){
						tif.http.abort();
					}

					// remove it so we can clean refs
					this.inFlight.splice(x, 1);
					tif.req[(typeof tif.req.timeout == "function") ? "timeout" : "handle"]("timeout", null, tif.http, tif.req);
				}
			}
		}

		if(this.inFlight.length == 0){
			clearInterval(this.inFlightTimer);
			this.inFlightTimer = null;
		}
	}

	var hasXmlHttp = dojo.hostenv.getXmlhttpObject() ? true : false;
	this.canHandle = function(kwArgs){
		// canHandle just tells dojo.io.bind() if this is a good transport to
		// use for the particular type of request.

		// FIXME: we need to determine when form values need to be
		// multi-part mime encoded and avoid using this transport for those
		// requests.
		return hasXmlHttp
			&& dojo.lang.inArray((kwArgs["mimetype"].toLowerCase()||""), ["text/plain", "text/html", "application/xml", "text/xml", "text/javascript", "text/json"])
			&& !( kwArgs["formNode"] && dojo.io.formHasFile(kwArgs["formNode"]) );
	}

	this.multipartBoundary = "45309FFF-BD65-4d50-99C9-36986896A96F";	// unique guid as a boundary value for multipart posts

	this.bind = function(kwArgs){
		if(!kwArgs["url"]){
			// are we performing a history action?
			if( !kwArgs["formNode"]
				&& (kwArgs["backButton"] || kwArgs["back"] || kwArgs["changeUrl"] || kwArgs["watchForURL"])
				&& (!djConfig.preventBackButtonFix)) {
        dojo.deprecated("Using dojo.io.XMLHTTPTransport.bind() to add to browser history without doing an IO request",
        				"Use dojo.undo.browser.addToHistory() instead.", "0.4");
				dojo.undo.browser.addToHistory(kwArgs);
				return true;
			}
		}

		// build this first for cache purposes
		var url = kwArgs.url;
		var query = "";
		if(kwArgs["formNode"]){
			var ta = kwArgs.formNode.getAttribute("action");
			if((ta)&&(!kwArgs["url"])){ url = ta; }
			var tp = kwArgs.formNode.getAttribute("method");
			if((tp)&&(!kwArgs["method"])){ kwArgs.method = tp; }
			query += dojo.io.encodeForm(kwArgs.formNode, kwArgs.encoding, kwArgs["formFilter"]);
		}

		if(url.indexOf("#") > -1) {
			dojo.debug("Warning: dojo.io.bind: stripping hash values from url:", url);
			url = url.split("#")[0];
		}

		if(kwArgs["file"]){
			// force post for file transfer
			kwArgs.method = "post";
		}

		if(!kwArgs["method"]){
			kwArgs.method = "get";
		}

		// guess the multipart value		
		if(kwArgs.method.toLowerCase() == "get"){
			// GET cannot use multipart
			kwArgs.multipart = false;
		}else{
			if(kwArgs["file"]){
				// enforce multipart when sending files
				kwArgs.multipart = true;
			}else if(!kwArgs["multipart"]){
				// default 
				kwArgs.multipart = false;
			}
		}

		if(kwArgs["backButton"] || kwArgs["back"] || kwArgs["changeUrl"]){
			dojo.undo.browser.addToHistory(kwArgs);
		}

		var content = kwArgs["content"] || {};

		if(kwArgs.sendTransport) {
			content["dojo.transport"] = "xmlhttp";
		}

		do { // break-block
			if(kwArgs.postContent){
				query = kwArgs.postContent;
				break;
			}

			if(content) {
				query += dojo.io.argsFromMap(content, kwArgs.encoding);
			}
			
			if(kwArgs.method.toLowerCase() == "get" || !kwArgs.multipart){
				break;
			}

			var	t = [];
			if(query.length){
				var q = query.split("&");
				for(var i = 0; i < q.length; ++i){
					if(q[i].length){
						var p = q[i].split("=");
						t.push(	"--" + this.multipartBoundary,
								"Content-Disposition: form-data; name=\"" + p[0] + "\"", 
								"",
								p[1]);
					}
				}
			}

			if(kwArgs.file){
				if(dojo.lang.isArray(kwArgs.file)){
					for(var i = 0; i < kwArgs.file.length; ++i){
						var o = kwArgs.file[i];
						t.push(	"--" + this.multipartBoundary,
								"Content-Disposition: form-data; name=\"" + o.name + "\"; filename=\"" + ("fileName" in o ? o.fileName : o.name) + "\"",
								"Content-Type: " + ("contentType" in o ? o.contentType : "application/octet-stream"),
								"",
								o.content);
					}
				}else{
					var o = kwArgs.file;
					t.push(	"--" + this.multipartBoundary,
							"Content-Disposition: form-data; name=\"" + o.name + "\"; filename=\"" + ("fileName" in o ? o.fileName : o.name) + "\"",
							"Content-Type: " + ("contentType" in o ? o.contentType : "application/octet-stream"),
							"",
							o.content);
				}
			}

			if(t.length){
				t.push("--"+this.multipartBoundary+"--", "");
				query = t.join("\r\n");
			}
		}while(false);

		// kwArgs.Connection = "close";

		var async = kwArgs["sync"] ? false : true;

		var preventCache = kwArgs["preventCache"] ||
			(this.preventCache == true && kwArgs["preventCache"] != false);
		var useCache = kwArgs["useCache"] == true ||
			(this.useCache == true && kwArgs["useCache"] != false );

		// preventCache is browser-level (add query string junk), useCache
		// is for the local cache. If we say preventCache, then don't attempt
		// to look in the cache, but if useCache is true, we still want to cache
		// the response
		if(!preventCache && useCache){
			var cachedHttp = getFromCache(url, query, kwArgs.method);
			if(cachedHttp){
				doLoad(kwArgs, cachedHttp, url, query, false);
				return;
			}
		}

		// much of this is from getText, but reproduced here because we need
		// more flexibility
		var http = dojo.hostenv.getXmlhttpObject(kwArgs);	
		var received = false;

		// build a handler function that calls back to the handler obj
		if(async){
			var startTime = 
			// FIXME: setting up this callback handler leaks on IE!!!
			this.inFlight.push({
				"req":		kwArgs,
				"http":		http,
				"url":	 	url,
				"query":	query,
				"useCache":	useCache,
				"startTime": kwArgs.timeoutSeconds ? (new Date()).getTime() : 0
			});
			this.startWatchingInFlight();
		}

		if(kwArgs.method.toLowerCase() == "post"){
			// FIXME: need to hack in more flexible Content-Type setting here!
			http.open("POST", url, async);
			setHeaders(http, kwArgs);
			http.setRequestHeader("Content-Type", kwArgs.multipart ? ("multipart/form-data; boundary=" + this.multipartBoundary) : 
				(kwArgs.contentType || "application/x-www-form-urlencoded"));
			try{
				http.send(query);
			}catch(e){
				if(typeof http.abort == "function"){
					http.abort();
				}
				doLoad(kwArgs, {status: 404}, url, query, useCache);
			}
		}else{
			var tmpUrl = url;
			if(query != "") {
				tmpUrl += (tmpUrl.indexOf("?") > -1 ? "&" : "?") + query;
			}
			if(preventCache) {
				tmpUrl += (dojo.string.endsWithAny(tmpUrl, "?", "&")
					? "" : (tmpUrl.indexOf("?") > -1 ? "&" : "?")) + "dojo.preventCache=" + new Date().valueOf();
			}
			http.open(kwArgs.method.toUpperCase(), tmpUrl, async);
			setHeaders(http, kwArgs);
			try {
				http.send(null);
			}catch(e)	{
				if(typeof http.abort == "function"){
					http.abort();
				}
				doLoad(kwArgs, {status: 404}, url, query, useCache);
			}
		}

		if( !async ) {
			doLoad(kwArgs, http, url, query, useCache);
		}

		kwArgs.abort = function(){
			return http.abort();
		}

		return;
	}
	dojo.io.transports.addTransport("XMLHTTPTransport");
}

__CPAN_FILE__ src/io/RhinoIO.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.io.RhinoIO");

// TODO: this doesn't execute
/*dojo.io.SyncHTTPRequest = function(){
	dojo.io.SyncRequest.call(this);

	this.send = function(URI){
	}
}

dojo.inherits(dojo.io.SyncHTTPRequest, dojo.io.SyncRequest);
*/

__CPAN_FILE__ src/io/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: ["dojo.io"],
	rhino: ["dojo.io.RhinoIO"],
	browser: ["dojo.io.BrowserIO", "dojo.io.cookie"],
	dashboard: ["dojo.io.BrowserIO", "dojo.io.cookie"]
});
dojo.provide("dojo.io.*");

__CPAN_FILE__ src/io/ScriptSrcIO.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.io.ScriptSrcIO");
dojo.require("dojo.io.BrowserIO");
dojo.require("dojo.undo.browser");

//FIXME: should constantParams be JS object?
//FIXME: check dojo.io calls. Can we move the BrowserIO defined calls somewhere
//       else so that we don't depend on BrowserIO at all? The dependent calls
//       have to do with dealing with forms and making query params from JS object.
/**
 * See test_ScriptSrcIO.html for usage information.
 * Notes:
 * - The watchInFlight timer is set to 100 ms instead of 10ms (which is what BrowserIO.js uses).
 */
dojo.io.ScriptSrcTransport = new function(){
	this.preventCache = false; // if this is true, we'll always force GET requests to not cache
	this.maxUrlLength = 1000; //Used to calculate if script request should be multipart.
	this.inFlightTimer = null;

	this.DsrStatusCodes = {
		Continue: 100,
		Ok: 200,
		Error: 500
	};

	this.startWatchingInFlight = function(){
		if(!this.inFlightTimer){
			this.inFlightTimer = setInterval("dojo.io.ScriptSrcTransport.watchInFlight();", 100);
		}
	}

	this.watchInFlight = function(){
		var totalCount = 0;
		var doneCount = 0;
		for(var param in this._state){
			totalCount++;
			var currentState = this._state[param];
			if(currentState.isDone){
				doneCount++;
				delete this._state[param];
			}else{
				var listener = currentState.kwArgs;
				try{
					if(currentState.checkString && eval("typeof(" + currentState.checkString + ") != 'undefined'")){
						this._finish(currentState, "load");
						doneCount++;
						delete this._state[param];
					}else if(listener.timeoutSeconds && listener.timeout){
						if(currentState.startTime + (listener.timeoutSeconds * 1000) < (new Date()).getTime()){
							this._finish(currentState, "timeout");
							doneCount++;
							delete this._state[param];
						}
					}else if(!listener.timeoutSeconds){
						//Increment the done count if no timeout is specified, so
						//that we turn off the timer if all that is left in the state
						//list are things we can't clean up because they fail without
						//getting a callback.
						doneCount++;
					}
				}catch(e){
					this._finish(currentState, "error", {status: this.DsrStatusCodes.Error, response: e});
				}
			}
		}
	
		if(doneCount == totalCount){
			clearInterval(this.inFlightTimer);
			this.inFlightTimer = null;
		}
	}

	this.canHandle = function(kwArgs){
		return dojo.lang.inArray((kwArgs["mimetype"].toLowerCase()), ["text/javascript", "text/json"])
			&& (kwArgs["method"].toLowerCase() == "get")
			&& !(kwArgs["formNode"] && dojo.io.formHasFile(kwArgs["formNode"]))
			&& (!kwArgs["sync"] || kwArgs["sync"] == false)
			&& !kwArgs["file"]
			&& !kwArgs["multipart"];
	}

	/**
	 * Removes any script tags from the DOM that may have been added by ScriptSrcTransport.
	 * Be careful though, by removing them from the script, you may invalidate some
	 * script objects that were defined by the js file that was pulled in as the
	 * src of the script tag. Test carefully if you decide to call this method.
	 * 
	 * In MSIE 6 (and probably 5.x), if you removed the script element while 
	 * part of the script is still executing, the browser will crash.
	 */
	this.removeScripts = function(){
		var scripts = document.getElementsByTagName("script");
		for(var i = 0; scripts && i < scripts.length; i++){
			var scriptTag = scripts[i];
			if(scriptTag.className == "ScriptSrcTransport"){
				var parent = scriptTag.parentNode;
				parent.removeChild(scriptTag);
				i--; //Set the index back one since we removed an item.
			}
		}
	}

	this.bind = function(kwArgs){
		//START duplication from BrowserIO.js (some changes made)
		var url = kwArgs.url;
		var query = "";
		
		if(kwArgs["formNode"]){
			var ta = kwArgs.formNode.getAttribute("action");
			if((ta)&&(!kwArgs["url"])){ url = ta; }
			var tp = kwArgs.formNode.getAttribute("method");
			if((tp)&&(!kwArgs["method"])){ kwArgs.method = tp; }
			query += dojo.io.encodeForm(kwArgs.formNode, kwArgs.encoding, kwArgs["formFilter"]);
		}

		if(url.indexOf("#") > -1) {
			dojo.debug("Warning: dojo.io.bind: stripping hash values from url:", url);
			url = url.split("#")[0];
		}

		//Break off the domain/path of the URL.
		var urlParts = url.split("?");
		if(urlParts && urlParts.length == 2){
			url = urlParts[0];
			query += (query ? "&" : "") + urlParts[1];
		}

		if(kwArgs["backButton"] || kwArgs["back"] || kwArgs["changeUrl"]){
			dojo.undo.browser.addToHistory(kwArgs);
		}

		//Create an ID for the request.
		var id = kwArgs["apiId"] ? kwArgs["apiId"] : "id" + this._counter++;

		//Fill out any other content pieces.
		var content = kwArgs["content"];
		var jsonpName = kwArgs.jsonParamName;
		if(kwArgs.sendTransport || jsonpName) {
			if (!content){
				content = {};
			}
			if(kwArgs.sendTransport){
				content["dojo.transport"] = "scriptsrc";
			}

			if(jsonpName){
				content[jsonpName] = "dojo.io.ScriptSrcTransport._state." + id + ".jsonpCall";
			}
		}

		if(kwArgs.postContent){
			query = kwArgs.postContent;
		}else if(content){
			query += ((query) ? "&" : "") + dojo.io.argsFromMap(content, kwArgs.encoding, jsonpName);
		}
		//END duplication from BrowserIO.js

		//START DSR

		//If an apiId is specified, then we want to make sure useRequestId is true.
		if(kwArgs["apiId"]){
			kwArgs["useRequestId"] = true;
		}

		//Set up the state for this request.
		var state = {
			"id": id,
			"idParam": "_dsrid=" + id,
			"url": url,
			"query": query,
			"kwArgs": kwArgs,
			"startTime": (new Date()).getTime()
		};

		if(!url){
			//Error. An URL is needed.
			this._finish(state, "error", {status: this.DsrStatusCodes.Error, statusText: "url.none"});
			return;
		}

		//If this is a jsonp request, intercept the jsonp callback
		if(content && content[jsonpName]){
			state.jsonp = content[jsonpName];
			state.jsonpCall = function(data){
				if(data["Error"]||data["error"]){
					dojo.debug(dojo.json.serialize(data));
					dojo.io.ScriptSrcTransport._finish(this, "error", data);
				}else{
					dojo.io.ScriptSrcTransport._finish(this, "load", data);
				}
			};
		}

		//Only store the request state on the state tracking object if a callback
		//is expected or if polling on a checkString will be done.
		if(kwArgs["useRequestId"] || kwArgs["checkString"] || state["jsonp"]){
			this._state[id] = state;
		}

		//A checkstring is a string that if evaled will not be undefined once the
		//script src loads. Used as an alternative to depending on a callback from
		//the script file. If this is set, then multipart is not assumed to be used,
		//since multipart requires a specific callback. With checkString we will be doing
		//polling.
		if(kwArgs["checkString"]){
			state.checkString = kwArgs["checkString"];
		}

		//Constant params are parameters that should always be sent with each
		//part of a multipart URL.
		state.constantParams = (kwArgs["constantParams"] == null ? "" : kwArgs["constantParams"]);
	
		if(kwArgs["preventCache"] ||
			(this.preventCache == true && kwArgs["preventCache"] != false)){
			state.nocacheParam = "dojo.preventCache=" + new Date().valueOf();
		}else{
			state.nocacheParam = "";
		}

		//Get total length URL, if we were to do it as one URL.
		//Add some padding, extra & separators.
		var urlLength = state.url.length + state.query.length + state.constantParams.length 
				+ state.nocacheParam.length + this._extraPaddingLength;

		if(kwArgs["useRequestId"]){
			urlLength += state.idParam.length;
		}
		
		if(!kwArgs["checkString"] && kwArgs["useRequestId"] 
			&& !state["jsonp"] && !kwArgs["forceSingleRequest"]
			&& urlLength > this.maxUrlLength){
			if(url > this.maxUrlLength){
				//Error. The URL domain and path are too long. We can't
				//segment that, so return an error.
				this._finish(state, "error", {status: this.DsrStatusCodes.Error, statusText: "url.tooBig"});
				return;
			}else{
				//Start the multiple requests.
				this._multiAttach(state, 1);
			}
		}else{
			//Send one URL.
			var queryParams = [state.constantParams, state.nocacheParam, state.query];
			if(kwArgs["useRequestId"] && !state["jsonp"]){
				queryParams.unshift(state.idParam);
			}
			var finalUrl = this._buildUrl(state.url, queryParams);

			//Track the final URL in case we need to use that instead of api ID when receiving
			//the load callback.
			state.finalUrl = finalUrl;
			
			this._attach(state.id, finalUrl);
		}
		//END DSR

		this.startWatchingInFlight();
	}
	
	//Private properties/methods
	this._counter = 1;
	this._state = {};
	this._extraPaddingLength = 16;

	//Is there a dojo function for this already?
	this._buildUrl = function(url, nameValueArray){
		var finalUrl = url;
		var joiner = "?";
		for(var i = 0; i < nameValueArray.length; i++){
			if(nameValueArray[i]){
				finalUrl += joiner + nameValueArray[i];
				joiner = "&";
			}
		}

		return finalUrl;
	}

	this._attach = function(id, url){
		//Attach the script to the DOM.
		var element = document.createElement("script");
		element.type = "text/javascript";
		element.src = url;
		element.id = id;
		element.className = "ScriptSrcTransport";
		document.getElementsByTagName("head")[0].appendChild(element);
	}

	this._multiAttach = function(state, part){
		//Check to make sure we still have a query to send up. This is mostly
		//a protection from a goof on the server side when it sends a part OK
		//response instead of a final response.
		if(state.query == null){
			this._finish(state, "error", {status: this.DsrStatusCodes.Error, statusText: "query.null"});
			return;
		}

		if(!state.constantParams){
			state.constantParams = "";
		}

		//How much of the query can we take?
		//Add a padding constant to account for _part and a couple extra amperstands.
		//Also add space for id since we'll need it now.
		var queryMax = this.maxUrlLength - state.idParam.length
					 - state.constantParams.length - state.url.length
					 - state.nocacheParam.length - this._extraPaddingLength;
		
		//Figure out if this is the last part.
		var isDone = state.query.length < queryMax;
	
		//Break up the query string if necessary.
		var currentQuery;
		if(isDone){
			currentQuery = state.query;
			state.query = null;
		}else{
			//Find the & or = nearest the max url length.
			var ampEnd = state.query.lastIndexOf("&", queryMax - 1);
			var eqEnd = state.query.lastIndexOf("=", queryMax - 1);

			//See if & is closer, or if = is right at the edge,
			//which means we should put it on the next URL.
			if(ampEnd > eqEnd || eqEnd == queryMax - 1){
				//& is nearer the end. So just chop off from there.
				currentQuery = state.query.substring(0, ampEnd);
				state.query = state.query.substring(ampEnd + 1, state.query.length) //strip off amperstand with the + 1.
			}else{
				//= is nearer the end. Take the max amount possible. 
				currentQuery = state.query.substring(0, queryMax);
			 
				//Find the last query name in the currentQuery so we can prepend it to
				//ampEnd. Could be -1 (not there), so account for that.
				var queryName = currentQuery.substring((ampEnd == -1 ? 0 : ampEnd + 1), eqEnd);
				state.query = queryName + "=" + state.query.substring(queryMax, state.query.length);
			}
		}
		
		//Now send a part of the script
		var queryParams = [currentQuery, state.idParam, state.constantParams, state.nocacheParam];
		if(!isDone){
			queryParams.push("_part=" + part);
		}

		var url = this._buildUrl(state.url, queryParams);

		this._attach(state.id + "_" + part, url);
	}

	this._finish = function(state, callback, event){
		if(callback != "partOk" && !state.kwArgs[callback] && !state.kwArgs["handle"]){
			//Ignore "partOk" because that is an internal callback.
			if(callback == "error"){
				state.isDone = true;
				throw event;
			}
		}else{
			switch(callback){
				case "load":
					var response = event ? event.response : null;
					if(!response){
						response = event;
					}
					state.kwArgs[(typeof state.kwArgs.load == "function") ? "load" : "handle"]("load", response, event, state.kwArgs);
					state.isDone = true;
					break;
				case "partOk":
					var part = parseInt(event.response.part, 10) + 1;
					//Update the constant params, if any.
					if(event.response.constantParams){
						state.constantParams = event.response.constantParams;
					}
					this._multiAttach(state, part);
					state.isDone = false;
					break;
				case "error":
					state.kwArgs[(typeof state.kwArgs.error == "function") ? "error" : "handle"]("error", event.response, event, state.kwArgs);
					state.isDone = true;
					break;
				default:
					state.kwArgs[(typeof state.kwArgs[callback] == "function") ? callback : "handle"](callback, event, event, state.kwArgs);
					state.isDone = true;
			}
		}
	}

	dojo.io.transports.addTransport("ScriptSrcTransport");
}

//Define callback handler.
window.onscriptload = function(event){
	var state = null;
	var transport = dojo.io.ScriptSrcTransport;
	
	//Find the matching state object for event ID.
	if(transport._state[event.id]){
		state = transport._state[event.id];
	}else{
		//The ID did not match directly to an entry in the state list.
		//Try searching the state objects for a matching original URL.
		var tempState;
		for(var param in transport._state){
			tempState = transport._state[param];
			if(tempState.finalUrl && tempState.finalUrl == event.id){
				state = tempState;
				break;
			}
		}

		//If no matching original URL is found, then use the URL that was actually used
		//in the SCRIPT SRC attribute.
		if(state == null){
			var scripts = document.getElementsByTagName("script");
			for(var i = 0; scripts && i < scripts.length; i++){
				var scriptTag = scripts[i];
				if(scriptTag.getAttribute("class") == "ScriptSrcTransport"
					&& scriptTag.src == event.id){
					state = transport._state[scriptTag.id];
					break;
				}
			}
		}
		
		//If state is still null, then throw an error.
		if(state == null){
			throw "No matching state for onscriptload event.id: " + event.id;
		}
	}

	var callbackName = "error";
	switch(event.status){
		case dojo.io.ScriptSrcTransport.DsrStatusCodes.Continue:
			//A part of a multipart request.
			callbackName = "partOk";
			break;
		case dojo.io.ScriptSrcTransport.DsrStatusCodes.Ok:
			//Successful reponse.
			callbackName = "load";
			break;
	}

	transport._finish(state, callbackName, event);
};

__CPAN_FILE__ src/io/ShortBusIO.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.io.ShortBusIO");
dojo.require("dojo.io"); // io.js provides setIFrameSrc
// FIXME: determine if we can use XMLHTTP to make x-domain posts despite not
//        being able to hear back about the result
dojo.require("dojo.io.IframeIO"); // for posting across domains
dojo.require("dojo.io.cookie"); // for peering
dojo.require("dojo.event.*");

/*
 * this file defines a "forever-frame" style Comet client. It passes opaque
 * JSON data structures to/from the client. Both styles of request provide a
 * topic for the event to be sent to and a payload object to be acted upon.
 *
 * All outbound events are sent via dojo.io.bind() and all inbound requests are
 * processed by Dojo topic dispatch.
 *
 * ShortBusIO packets have the basic format:
 *
 *	{
 *	 	topic: "/destination/topic/name",
 *		body: {
 * 			// ...
 *		}
 * 	}
 * 
 * Packets bound for the event router (not one of it's clients) or generated
 * from it are prefixed with the special "/meta" topic. Meta-topic events
 * either inform the client to take an action or inform the server of a system
 * event.
 *
 * Upon tunnel creation, the server might therefore send the following meta
 * topic packet to the client to inform the client of it's assigned identity:
 *
 *	// client <-- server
 *	{
 *	 	topic: "/meta",
 *		body: {
 * 			action: "setClientId",
 *			clientId: "fooBar23",
 *			tunnelId: "fooBarTunnel4",
 *			tunnelExpiration: "...", // some date in the future
 *		}
 * 	}
 *
 * The client may then respond with a confirmation:
 * 
 *	// client --> server
 *	{
 *	 	topic: "/meta",
 *		body: {
 * 			action: "confirmClientId",
 *			from: "fooBar23"
 *		}
 * 	}
 *
 * The client must implement a basic vocabulary of /meta topic verbs in order
 * to participate as a ShortBus endpoint. These are TBD.
 *
 * NOTE: this example elides any authentication or authorization steps the
 * client and server may have undertaken prior to tunnel setup.
 */

// TODO: unlike repubsubio we don't handle any sort of connection
// subscription/publishing backlog. Should we?

dojo.io.ShortBusTransport = new function(){

	var initialized = false;
	var connected = false;

	// this class is similar to RepubsubIO save that we don't have the
	// externalized protocol handler code. Our messages are simpler so our code
	// can be as well.

	this.rcvNode = null;
	this.rcvNodeName = "";
	this.topicRoot = null;

	this.getRandStr = function(){
		return Math.random().toString().substring(2, 10);
	}

	this.widenDomain = function(domainStr){
		// allow us to make reqests to the TLD
		var cd = domainStr||document.domain;
		if(cd.indexOf(".")==-1){ return; } // probably file:/// or localhost
		var dps = cd.split(".");
		if(dps.length<=2){ return; } // probably file:/// or an RFC 1918 address
		dps = dps.slice(dps.length-2);
		document.domain = dps.join(".");
	}

	this.canHandle = function(kwArgs){
		return (
			(connected)			&&
			(kwArgs["topic"])	&&
			(! // async only!
				((kwArgs["sync"])&&(kwArgs["sync"] == true))
			)
		);
	}

	this.buildConnection = function(){
		// NOTE: we require the server to cooperate by hosting
		// ShortBusInit.html at the designated endpoint
		this.rcvNodeName = "ShortBusRcv_"+this.getRandStr();
		// the "forever frame" approach
		if(dojo.render.html.ie){
			// use the "htmlfile hack" to prevent the background click junk
			this.rcvNode = new ActiveXObject("htmlfile");
			this.rcvNode.open();
			this.rcvNode.write("<html>");
			this.rcvNode.write("<script>document.domain = '"+document.domain+"'");
			this.rcvNode.write("</html>");
			this.rcvNode.close();

			var ifrDiv = this.rcvNode.createElement("div");
			this.rcvNode.appendChild(ifrDiv);
			this.rcvNode.parentWindow.dojo = dojo;
			ifrDiv.innerHTML = "<iframe src='"+this.topicRoot+"/?tunntelType=htmlfile'></iframe>"
			// and we're ready to go!
			connected = true;
		}else{
			this.rcvNode = dojo.io.createIFrame(this.rcvNodeName);
			dojo.io.setIFrameSrc(this.rcvNode, this.topicRoot+"/?tunnelType=iframe");
			// we're still waiting on this one to call back up and advertise
			// that it's been initialized
		}
	}

	this.iframeConnectionInit = function(){
		connected = true;
	}

	this.dispatchServerEvent = function(eObj){
		// FIXME: implement basic /meta topic semantics here!
	}

	this.init = function(){
		if(initialized){
			return;
		}
		initialized = true;

		this.widenDomain();

		// we want to set up a connection to the designated server. Grab the
		// server location out of djConfig.
		this.topicRoot = djConfig["ShortBusRoot"];
		if(!this.topicRoot){
			dojo.debug("no topic root specified in djConfig.ShortBusRoot");
			return;
		}
	}

	this.dispatch = function(evt){
		// dipatch events along the specified path
	}

    dojo.io.transports.addTransport("ShortBusTransport");
}

__CPAN_FILE__ src/io/ShortBusInit.html
<html>
<!--
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

	http://dojotoolkit.org/community/licensing.shtml
-->
<script type="text/javascript">
	if(window!=window.parent){
		function callByDeRef(fname){
			if(!fname){ return null; }
			// if someone inadvertently passed in "foo(...)", we make it "foo"
			fname = String(fname).split("(")[0];
			// get a real array of arguments
			var aa = [];
			for(var x=1; x<arguments.length; x++){
				aa.push(arguments[x]);
			}

			var parts = String(fname).split(".");
			var obj = window;
			for(var x=0; x<parts.length-1; x++){
				obj = obj[parts[x]];
			}
			var fn = parts.pop(); // the last element is the function name
			// exec the function in the specified namespace
			return obj[fn].apply(obj, aa);
		}

		function widenDomain(domainStr){
			// the purpose of this is to set the most liberal domain policy
			var cd = domainStr||document.domain;
			if(cd.indexOf(".")==-1){ 
				document.domain = cd;
				return;
			}
			var dps = cd.split(".");
			if(dps.length>2){ 
				dps = dps.slice(dps.length-2);
			}
			document.domain = dps.join(".");
		}

		function doInit(){

			widenDomain();

			var baseUrl = document.location.toString();
			var params = baseUrl.split("?", 2);
			if(params.length > 1){
				var paramStr = params[1];
				var pairs = paramStr.split("&");
				var opts = [];
				for(var x in pairs){
					// alert(pairs[x]);
					var sp = pairs[x].split("=");
					opts[sp[0]]=sp[1];
					if(sp[0]=="true"){
						sp[0] = true;
					}else if(sp[0]=="false"){
						sp[0] = false;
					}
				}
				if(opts["callback"]){
					callByDeRef("parent."+opts["callback"]);
				}
			}
		}
		doInit();
	}
</script>
</html>

__CPAN_FILE__ src/io/cookie.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.io.cookie");

dojo.io.cookie.setCookie = function(name, value, days, path, domain, secure) {
	var expires = -1;
	if(typeof days == "number" && days >= 0) {
		var d = new Date();
		d.setTime(d.getTime()+(days*24*60*60*1000));
		expires = d.toGMTString();
	}
	value = escape(value);
	document.cookie = name + "=" + value + ";"
		+ (expires != -1 ? " expires=" + expires + ";" : "")
		+ (path ? "path=" + path : "")
		+ (domain ? "; domain=" + domain : "")
		+ (secure ? "; secure" : "");
}

dojo.io.cookie.set = dojo.io.cookie.setCookie;

dojo.io.cookie.getCookie = function(name) {
	// FIXME: Which cookie should we return?
	//        If there are cookies set for different sub domains in the current
	//        scope there could be more than one cookie with the same name.
	//        I think taking the last one in the list takes the one from the
	//        deepest subdomain, which is what we're doing here.
	var idx = document.cookie.lastIndexOf(name+'=');
	if(idx == -1) { return null; }
	var value = document.cookie.substring(idx+name.length+1);
	var end = value.indexOf(';');
	if(end == -1) { end = value.length; }
	value = value.substring(0, end);
	value = unescape(value);
	return value;
}

dojo.io.cookie.get = dojo.io.cookie.getCookie;

dojo.io.cookie.deleteCookie = function(name) {
	dojo.io.cookie.setCookie(name, "-", 0);
}

dojo.io.cookie.setObjectCookie = function(name, obj, days, path, domain, secure, clearCurrent) {
	if(arguments.length == 5) { // for backwards compat
		clearCurrent = domain;
		domain = null;
		secure = null;
	}
	var pairs = [], cookie, value = "";
	if(!clearCurrent) { cookie = dojo.io.cookie.getObjectCookie(name); }
	if(days >= 0) {
		if(!cookie) { cookie = {}; }
		for(var prop in obj) {
			if(prop == null) {
				delete cookie[prop];
			} else if(typeof obj[prop] == "string" || typeof obj[prop] == "number") {
				cookie[prop] = obj[prop];
			}
		}
		prop = null;
		for(var prop in cookie) {
			pairs.push(escape(prop) + "=" + escape(cookie[prop]));
		}
		value = pairs.join("&");
	}
	dojo.io.cookie.setCookie(name, value, days, path, domain, secure);
}

dojo.io.cookie.getObjectCookie = function(name) {
	var values = null, cookie = dojo.io.cookie.getCookie(name);
	if(cookie) {
		values = {};
		var pairs = cookie.split("&");
		for(var i = 0; i < pairs.length; i++) {
			var pair = pairs[i].split("=");
			var value = pair[1];
			if( isNaN(value) ) { value = unescape(pair[1]); }
			values[ unescape(pair[0]) ] = value;
		}
	}
	return values;
}

dojo.io.cookie.isSupported = function() {
	if(typeof navigator.cookieEnabled != "boolean") {
		dojo.io.cookie.setCookie("__TestingYourBrowserForCookieSupport__",
			"CookiesAllowed", 90, null);
		var cookieVal = dojo.io.cookie.getCookie("__TestingYourBrowserForCookieSupport__");
		navigator.cookieEnabled = (cookieVal == "CookiesAllowed");
		if(navigator.cookieEnabled) {
			// FIXME: should we leave this around?
			this.deleteCookie("__TestingYourBrowserForCookieSupport__");
		}
	}
	return navigator.cookieEnabled;
}

// need to leave this in for backwards-compat from 0.1 for when it gets pulled in by dojo.io.*
if(!dojo.io.cookies) { dojo.io.cookies = dojo.io.cookie; }

__CPAN_FILE__ src/io/cookies.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.deprecated("dojo.io.cookies", "replaced by dojo.io.cookie", "0.4");
dojo.require("dojo.io.cookie");
if(!dojo.io.cookies) { dojo.io.cookies = dojo.io.cookie; }
dojo.provide("dojo.io.cookies");

__CPAN_FILE__ src/io/RepubsubIO.js
//	Copyright (c) 2004 Friendster Inc., Licensed under the Academic Free
//	License version 2.0 or later 

dojo.require("dojo.event.Event");
dojo.require("dojo.event.BrowserEvent");
dojo.require("dojo.io.BrowserIO");

dojo.provide("dojo.io.RepubsubIO");
dojo.provide("dojo.io.repubsub");
dojo.provide("dojo.io.repubsubTransport");

dojo.io.repubsubTranport = new function(){
	var rps = dojo.io.repubsub;
	this.canHandle = function(kwArgs){
		if((kwArgs["mimetype"] == "text/javascript")&&(kwArgs["method"] == "repubsub")){
			return true;
		}
		return false;
	}

	this.bind = function(kwArgs){
		if(!rps.isInitialized){
			// open up our tunnel, queue up requests anyway
			rps.init();
		}
		// FIXME: we need to turn this into a topic subscription
		// var tgtURL = kwArgs.url+"?"+dojo.io.argsFromMap(kwArgs.content);
		// sampleTransport.sendRequest(tgtURL, hdlrFunc);

		// a normal "bind()" call in a request-response transport layer is
		// something that (usually) encodes most of it's payload with the
		// request. Multi-event systems like repubsub are a bit more complex,
		// and repubsub in particular distinguishes the publish and subscribe
		// portions of thep rocess with different method calls to handle each.
		// Therefore, a "bind" in the sense of repubsub must first determine if
		// we have an open subscription to a channel provided by the server,
		// and then "publish" the request payload if there is any. We therefore
		// must take care not to incorrectly or too agressively register or
		// file event handlers which are provided with the kwArgs method.

		// NOTE: we ONLY pay attention to those event handlers that are
		// registered with the bind request that subscribes to the channel. If
		// event handlers are provided with subsequent requests, we might in
		// the future support some additive or replacement syntax, but for now
		// they get dropped on the floor.

		// NOTE: in this case, url MUST be the "topic" to which we
		// subscribe/publish for this channel
		if(!rps.topics[kwArgs.url]){
			kwArgs.rpsLoad = function(evt){
				kwArgs.load("load", evt);
			}
			rps.subscribe(kwArgs.url, kwArgs, "rpsLoad");
		}

		if(kwArgs["content"]){
			// what we wanted to send
			var cEvt = dojo.io.repubsubEvent.initFromProperties(kwArgs.content);
			rps.publish(kwArgs.url, cEvt);
		}
	}

	dojo.io.transports.addTransport("repubsubTranport");
}

dojo.io.repubsub = new function(){
	this.initDoc = "init.html";
	this.isInitialized = false;
	this.subscriptionBacklog = [];
	this.debug = true;
	this.rcvNodeName = null;
	this.sndNodeName = null;
	this.rcvNode = null;
	this.sndNode = null;
	this.canRcv = false;
	this.canSnd = false;
	this.canLog = false;
	this.sndTimer = null;
	this.windowRef = window;
	this.backlog = [];
	this.tunnelInitCount = 0;
	this.tunnelFrameKey = "tunnel_frame";
	this.serverBaseURL = location.protocol+"//"+location.host+location.pathname;
	this.logBacklog = [];
	this.getRandStr = function(){
		return Math.random().toString().substring(2, 10);
	}
	this.userid = "guest";
	this.tunnelID = this.getRandStr();
	this.attachPathList = [];
	this.topics = []; // list of topics we have listeners to

	// actually, now that I think about it a little bit more, it would sure be
	// useful to parse out the <script> src attributes. We're looking for
	// something with a "do_method=lib", since that's what would have included
	// us in the first place (in the common case).
	this.parseGetStr = function(){
		var baseUrl = document.location.toString();
		var params = baseUrl.split("?", 2);
		if(params.length > 1){
			var paramStr = params[1];
			var pairs = paramStr.split("&");
			var opts = [];
			for(var x in pairs){
				var sp = pairs[x].split("=");
				// FIXME: is this eval dangerous?
				try{
					opts[sp[0]]=eval(sp[1]);
				}catch(e){
					opts[sp[0]]=sp[1];
				}
			}
			return opts;
		}else{
			return [];
		}
	}

	// parse URL params and use them as default vals
	var getOpts = this.parseGetStr();
	for(var x in getOpts){
		// FIXME: should I be checking for undefined here before setting? Does
		//        that buy me anything?
		this[x] = getOpts[x];
	}

	if(!this["tunnelURI"]){
		this.tunnelURI = [	"/who/", escape(this.userid), "/s/", 
							this.getRandStr(), "/kn_journal"].join("");
		// this.tunnelURI = this.absoluteTopicURI(this.tunnelURI);
	}

	/*
	if (self.kn_tunnelID) kn.tunnelID = self.kn_tunnelID; // the server says
	if (kn._argv.kn_tunnelID) kn.tunnelID = kn._argv.kn_tunnelID; // the url says
	*/

	// check the options object if it exists and use its properties as an
	// over-ride
	if(window["repubsubOpts"]||window["rpsOpts"]){
		var optObj = window["repubsubOpts"]||window["rpsOpts"];
		for(var x in optObj){
			this[x] = optObj[x]; // copy the option object properties
		}
	}

	// things that get called directly from our iframe to inform us of events
	this.tunnelCloseCallback = function(){
		// when we get this callback, we should immediately attempt to re-start
		// our tunnel connection
		dojo.io.setIFrameSrc(this.rcvNode, this.initDoc+"?callback=repubsub.rcvNodeReady&domain="+document.domain);
	}

	this.receiveEventFromTunnel = function(evt, srcWindow){
		// we should never be getting events from windows we didn't create
		// NOTE: events sourced from the local window are also supported for
		// 		 debugging purposes

		// any event object MUST have a an "elements" property
		if(!evt["elements"]){
			this.log("bailing! event received without elements!", "error");
			return;
		}

		// if the event passes some minimal sanity tests, we need to attempt to
		// dispatch it!

		// first, it seems we have to munge the event object a bit
		var e = {};
		for(var i=0; i<evt.elements.length; i++){
			var ee = evt.elements[i];
			e[ee.name||ee.nameU] = (ee.value||ee.valueU);
			// FIXME: need to enable this only in some extreme debugging mode!
			this.log("[event]: "+(ee.name||ee.nameU)+": "+e[ee.name||ee.nameU]);
		}

		// NOTE: the previous version of this library put a bunch of code here
		// to manage state that tried to make sure that we never, ever, lost
		// any info about an event. If we unload RIGHT HERE, I don't think it's
		// going to make a huge difference one way or another. Time will tell.

		// and with THAT out of the way, dispatch it!
		this.dispatch(e);

		// TODO: remove the script block that created the event obj to save
		// memory, etc.
	}

	this.widenDomain = function(domainStr){
		// the purpose of this is to set the most liberal domain policy
		// available
		var cd = domainStr||document.domain;
		if(cd.indexOf(".")==-1){ return; } // probably file:/// or localhost
		var dps = cd.split(".");
		if(dps.length<=2){ return; } // probably file:/// or an RFC 1918 address
		dps = dps.slice(dps.length-2);
		document.domain = dps.join(".");
	}

	// FIXME: parseCookie and setCookie should be methods that are more broadly
	// available. Perhaps in htmlUtils?

	this.parseCookie = function(){
		var cs = document.cookie;
		var keypairs = cs.split(";");
		for(var x=0; x<keypairs.length; x++){
			keypairs[x] = keypairs[x].split("=");
			if(x!=keypairs.length-1){ cs+=";"; }
		}
		return keypairs;
	}

	this.setCookie = function(keypairs, clobber){
		// NOTE: we want to only ever set session cookies, so never provide an
		// 		 expires date
		if((clobber)&&(clobber==true)){ document.cookie = ""; }
		var cs = "";
		for(var x=0; x<keypairs.length; x++){
			cs += keypairs[x][0]+"="+keypairs[x][1];
			if(x!=keypairs.length-1){ cs+=";"; }
		}
		document.cookie = cs;
	}

	// FIXME: need to replace w/ dojo.log.*
	this.log = function(str, lvl){
		if(!this.debug){ return; } // we of course only care if we're in debug mode
		while(this.logBacklog.length>0){
			if(!this.canLog){ break; }
			var blo = this.logBacklog.shift();
			this.writeLog("["+blo[0]+"]: "+blo[1], blo[2]);
		}
		this.writeLog(str, lvl);
	}

	this.writeLog = function(str, lvl){
		dojo.debug(((new Date()).toLocaleTimeString())+": "+str);
	}

	this.init = function(){
		this.widenDomain();
		// this.findPeers();
		this.openTunnel();
		this.isInitialized = true;
		// FIXME: this seems like entirely the wrong place to replay the backlog
		while(this.subscriptionBacklog.length){
			this.subscribe.apply(this, this.subscriptionBacklog.shift());
		}
	}

	this.clobber = function(){
		if(this.rcvNode){
			this.setCookie( [
					[this.tunnelFrameKey,"closed"],
					["path","/"]
				], false 
			);
		}
	}

	this.openTunnel = function(){
		// We create two iframes here:

		// one for getting data
		this.rcvNodeName = "rcvIFrame_"+this.getRandStr();
		// set cookie that can be used to find the receiving iframe
		this.setCookie( [
				[this.tunnelFrameKey,this.rcvNodeName],
				["path","/"]
			], false
		);

		this.rcvNode = dojo.io.createIFrame(this.rcvNodeName);
		// FIXME: set the src attribute here to the initialization URL
		dojo.io.setIFrameSrc(this.rcvNode, this.initDoc+"?callback=repubsub.rcvNodeReady&domain="+document.domain);

		// the other for posting data in reply

		this.sndNodeName = "sndIFrame_"+this.getRandStr();
		this.sndNode = dojo.io.createIFrame(this.sndNodeName);
		// FIXME: set the src attribute here to the initialization URL
		dojo.io.setIFrameSrc(this.sndNode, this.initDoc+"?callback=repubsub.sndNodeReady&domain="+document.domain);

	}

	this.rcvNodeReady = function(){
		// FIXME: why is this sequence number needed? Why isn't the UID gen
		// 		  function enough?
        var statusURI = [this.tunnelURI, '/kn_status/', this.getRandStr(), '_', 
						 String(this.tunnelInitCount++)].join(""); 
            // (kn._seqNum++); // FIXME: !!!!
		// this.canRcv = true;
		this.log("rcvNodeReady");
		// FIXME: initialize receiver and request the base topic
		// dojo.io.setIFrameSrc(this.rcvNode, this.serverBaseURL+"/kn?do_method=blank");
		var initURIArr = [	this.serverBaseURL, "/kn?kn_from=", escape(this.tunnelURI),
							"&kn_id=", escape(this.tunnelID), "&kn_status_from=", 
							escape(statusURI)];
		// FIXME: does the above really need a kn_response_flush? won't the
		// 		  server already know? If not, what good is it anyway?
		dojo.io.setIFrameSrc(this.rcvNode, initURIArr.join(""));

		// setup a status path listener, but don't tell the server about it,
		// since it already knows we're itnerested in our own tunnel status
		this.subscribe(statusURI, this, "statusListener", true);

		this.log(initURIArr.join(""));
	}

	this.sndNodeReady = function(){
		this.canSnd = true;
		this.log("sndNodeReady");
		this.log(this.backlog.length);
		// FIXME: handle any pent-up send commands
		if(this.backlog.length > 0){
			this.dequeueEvent();
		}
	}

	this.statusListener = function(evt){
		this.log("status listener called");
		this.log(evt.status, "info");
	}

	// this handles local event propigation
	this.dispatch = function(evt){
		// figure out what topic it came from
		if(evt["to"]||evt["kn_routed_from"]){
			var rf = evt["to"]||evt["kn_routed_from"];
			// split off the base server URL
			var topic = rf.split(this.serverBaseURL, 2)[1];
			if(!topic){
				// FIXME: how do we recover when we don't get a sane "from"? Do
				// we try to route to it anyway?
				topic = rf;
			}
			this.log("[topic] "+topic);
			if(topic.length>3){
				if(topic.slice(0, 3)=="/kn"){
					topic = topic.slice(3);
				}
			}
			if(this.attachPathList[topic]){
				this.attachPathList[topic](evt);
			}
		}
	}

	this.subscribe = function(	topic /* kn_from in the old terminilogy */, 
								toObj, toFunc, dontTellServer){
		if(!this.isInitialized){
			this.subscriptionBacklog.push([topic, toObj, toFunc, dontTellServer]);
			return;
		}
		if(!this.attachPathList[topic]){
			this.attachPathList[topic] = function(){ return true; }
			this.log("subscribing to: "+topic);
			this.topics.push(topic);
		}
		var revt = new dojo.io.repubsubEvent(this.tunnelURI, topic, "route");
		var rstr = [this.serverBaseURL+"/kn", revt.toGetString()].join("");
		dojo.event.kwConnect({
			once: true,
			srcObj: this.attachPathList, 
			srcFunc: topic, 
			adviceObj: toObj, 
			adviceFunc: toFunc
		});
		// NOTE: the above is a local mapping, if we're not the leader, we
		// 		 should connect our mapping to the topic handler of the peer
		// 		 leader, this ensures that not matter what happens to the
		// 		 leader, we don't really loose our heads if/when the leader
		// 		 goes away.
		if(!this.rcvNode){ /* this should be an error! */ }
		if(dontTellServer){
			return;
		}
		this.log("sending subscription to: "+topic);
		// create a subscription event object and give it all the props we need
		// to updates on the specified topic

		// FIXME: we should only enqueue if this is our first subscription!
		this.sendTopicSubToServer(topic, rstr);
	}

	this.sendTopicSubToServer = function(topic, str){
		if(!this.attachPathList[topic]["subscriptions"]){
			this.enqueueEventStr(str);
			this.attachPathList[topic].subscriptions = 0;
		}
		this.attachPathList[topic].subscriptions++;
	}

	this.unSubscribe = function(topic, toObj, toFunc){
		// first, locally disconnect
		dojo.event.kwDisconnect({
			srcObj: this.attachPathList, 
			srcFunc: topic, 
			adviceObj: toObj, 
			adviceFunc: toFunc
		});
		
		// FIXME: figure out if there are any remaining listeners to the topic,
		// 		  and if not, inform the server of our desire not to be
		// 		  notified of updates to the topic
	}

	// the "publish" method is really a misnomer, since it really means "take
	// this event and send it to the server". Note that the "dispatch" method
	// handles local event promigulation, and therefore we emulate both sides
	// of a real event router without having to swallow all of the complexity.
	this.publish = function(topic, event){
		var evt = dojo.io.repubsubEvent.initFromProperties(event);
		// FIXME: need to make sure we have from and to set correctly
		// 		  before we serialize and send off to the great blue
		// 		  younder.
		evt.to = topic;
		// evt.from = this.tunnelURI;

		var evtURLParts = [];
		evtURLParts.push(this.serverBaseURL+"/kn");

		// serialize the event to a string and then post it to the correct
		// topic
		evtURLParts.push(evt.toGetString());
		this.enqueueEventStr(evtURLParts.join(""));
	}

	this.enqueueEventStr = function(evtStr){
		this.log("enqueueEventStr");
		this.backlog.push(evtStr);
		this.dequeueEvent();
	}

	this.dequeueEvent = function(force){
		this.log("dequeueEvent");
		if(this.backlog.length <= 0){ return; }
		if((this.canSnd)||(force)){
			dojo.io.setIFrameSrc(this.sndNode, this.backlog.shift()+"&callback=repubsub.sndNodeReady");
			this.canSnd = false;
		}else{
			this.log("sndNode not available yet!", "debug");
		}
	}
}

dojo.io.repubsubEvent = function(to, from, method, id, routeURI, payload, dispname, uid){
	this.to = to;
	this.from = from;
	this.method = method||"route";
	this.id = id||repubsub.getRandStr();
	this.uri = routeURI;
	this.displayname = dispname||repubsub.displayname;
	this.userid = uid||repubsub.userid;
	this.payload = payload||"";
	this.flushChars = 4096;

	this.initFromProperties = function(evt){
		if(evt.constructor = dojo.io.repubsubEvent){ 
			for(var x in evt){
				this[x] = evt[x];
			}
		}else{
			// we want to copy all the properties of the evt object, and transform
			// those that are "stock" properties of dojo.io.repubsubEvent. All others should
			// be copied as-is
			for(var x in evt){
				if(typeof this.forwardPropertiesMap[x] == "string"){
					this[this.forwardPropertiesMap[x]] = evt[x];
				}else{
					this[x] = evt[x];
				}
			}
		}
	}

	this.toGetString = function(noQmark){
		var qs = [ ((noQmark) ? "" : "?") ];
		for(var x=0; x<this.properties.length; x++){
			var tp = this.properties[x];
			if(this[tp[0]]){
				qs.push(tp[1]+"="+encodeURIComponent(String(this[tp[0]])));
			}
			// FIXME: we need to be able to serialize non-stock properties!!!
		}
		return qs.join("&");
	}

}

dojo.io.repubsubEvent.prototype.properties = [["from", "kn_from"], ["to", "kn_to"], 
									["method", "do_method"], ["id", "kn_id"], 
									["uri", "kn_uri"], 
									["displayname", "kn_displayname"], 
									["userid", "kn_userid"], 
									["payload", "kn_payload"],
									["flushChars", "kn_response_flush"],
									["responseFormat", "kn_response_format"] ];

// maps properties from their old names to their new names...
dojo.io.repubsubEvent.prototype.forwardPropertiesMap = {};
// ...and vice versa...
dojo.io.repubsubEvent.prototype.reversePropertiesMap = {};

// and we then populate them both from the properties list
for(var x=0; x<dojo.io.repubsubEvent.prototype.properties.length; x++){
	var tp = dojo.io.repubsubEvent.prototype.properties[x];
	dojo.io.repubsubEvent.prototype.reversePropertiesMap[tp[0]] = tp[1];
	dojo.io.repubsubEvent.prototype.forwardPropertiesMap[tp[1]] = tp[0];
}
// static version of initFromProperties, creates new event and object and
// returns it after init
dojo.io.repubsubEvent.initFromProperties = function(evt){
	var eventObj = new dojo.io.repubsubEvent();
	eventObj.initFromProperties(evt);
	return eventObj;
}

__CPAN_FILE__ src/io/IframeIO.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.io.IframeIO");
dojo.require("dojo.io.BrowserIO");
dojo.require("dojo.uri.*");

// FIXME: is it possible to use the Google htmlfile hack to prevent the
// background click with this transport?

dojo.io.createIFrame = function(fname, onloadstr){
	if(window[fname]){ return window[fname]; }
	if(window.frames[fname]){ return window.frames[fname]; }
	var r = dojo.render.html;
	var cframe = null;
	var turi = dojo.uri.dojoUri("iframe_history.html?noInit=true");
	var ifrstr = ((r.ie)&&(dojo.render.os.win)) ? "<iframe name='"+fname+"' src='"+turi+"' onload='"+onloadstr+"'>" : "iframe";
	cframe = document.createElement(ifrstr);
	with(cframe){
		name = fname;
		setAttribute("name", fname);
		id = fname;
	}
	(document.body||document.getElementsByTagName("body")[0]).appendChild(cframe);
	window[fname] = cframe;
	with(cframe.style){
		position = "absolute";
		left = top = "0px";
		height = width = "1px";
		visibility = "hidden";
		/*
		if(djConfig.isDebug){
			position = "relative";
			height = "300px";
			width = "600px";
			visibility = "visible";
		}
		*/
	}

	if(!r.ie){
		dojo.io.setIFrameSrc(cframe, turi, true);
		cframe.onload = new Function(onloadstr);
	}
	return cframe;
}

// thanks burstlib!
dojo.io.iframeContentWindow = function(iframe_el) {
	var win = iframe_el.contentWindow || // IE
		dojo.io.iframeContentDocument(iframe_el).defaultView || // Moz, opera
		// Moz. TODO: is this available when defaultView isn't?
		dojo.io.iframeContentDocument(iframe_el).__parent__ || 
		(iframe_el.name && document.frames[iframe_el.name]) || null;
	return win;
}

dojo.io.iframeContentDocument = function(iframe_el){
	var doc = iframe_el.contentDocument || // W3
		(
			(iframe_el.contentWindow)&&(iframe_el.contentWindow.document)
		) ||  // IE
		(
			(iframe_el.name)&&(document.frames[iframe_el.name])&&
			(document.frames[iframe_el.name].document)
		) || null;
	return doc;
}

dojo.io.IframeTransport = new function(){
	var _this = this;
	this.currentRequest = null;
	this.requestQueue = [];
	this.iframeName = "dojoIoIframe";

	this.fireNextRequest = function(){
		if((this.currentRequest)||(this.requestQueue.length == 0)){ return; }
		// dojo.debug("fireNextRequest");
		var cr = this.currentRequest = this.requestQueue.shift();
		cr._contentToClean = [];
		var fn = cr["formNode"];
		var content = cr["content"] || {};
		if(cr.sendTransport) {
			content["dojo.transport"] = "iframe";
		}
		if(fn){
			if(content){
				// if we have things in content, we need to add them to the form
				// before submission
				for(var x in content){
					if(!fn[x]){
						var tn;
						if(dojo.render.html.ie){
							tn = document.createElement("<input type='hidden' name='"+x+"' value='"+content[x]+"'>");
							fn.appendChild(tn);
						}else{
							tn = document.createElement("input");
							fn.appendChild(tn);
							tn.type = "hidden";
							tn.name = x;
							tn.value = content[x];
						}
						cr._contentToClean.push(x);
					}else{
						fn[x].value = content[x];
					}
				}
			}
			if(cr["url"]){
				cr._originalAction = fn.getAttribute("action");
				fn.setAttribute("action", cr.url);
			}
			if(!fn.getAttribute("method")){
				fn.setAttribute("method", (cr["method"]) ? cr["method"] : "post");
			}
			cr._originalTarget = fn.getAttribute("target");
			fn.setAttribute("target", this.iframeName);
			fn.target = this.iframeName;
			fn.submit();
		}else{
			// otherwise we post a GET string by changing URL location for the
			// iframe
			var query = dojo.io.argsFromMap(this.currentRequest.content);
			var tmpUrl = (cr.url.indexOf("?") > -1 ? "&" : "?") + query;
			dojo.io.setIFrameSrc(this.iframe, tmpUrl, true);
		}
	}

	this.canHandle = function(kwArgs){
		return (
			(
				// FIXME: can we really handle text/plain and
				// text/javascript requests?
				dojo.lang.inArray(kwArgs["mimetype"], 
				[	"text/plain", "text/html", 
					"text/javascript", "text/json"])
			)&&(
				// make sur we really only get used in file upload cases	
				(kwArgs["formNode"])&&(dojo.io.checkChildrenForFile(kwArgs["formNode"]))
			)&&(
				dojo.lang.inArray(kwArgs["method"].toLowerCase(), ["post", "get"])
			)&&(
				// never handle a sync request
				!  ((kwArgs["sync"])&&(kwArgs["sync"] == true))
			)
		);
	}

	this.bind = function(kwArgs){
		if(!this["iframe"]){ this.setUpIframe(); }
		this.requestQueue.push(kwArgs);
		this.fireNextRequest();
		return;
	}

	this.setUpIframe = function(){

		// NOTE: IE 5.0 and earlier Mozilla's don't support an onload event for
		//       iframes. OTOH, we don't care.
		this.iframe = dojo.io.createIFrame(this.iframeName, "dojo.io.IframeTransport.iframeOnload();");
	}

	this.iframeOnload = function(){
		if(!_this.currentRequest){
			_this.fireNextRequest();
			return;
		}

		var req = _this.currentRequest;

		// remove all the hidden content inputs
		var toClean = req._contentToClean;
		for(var i = 0; i < toClean.length; i++) {
			var key = toClean[i];
			if(dojo.render.html.safari){
				//In Safari (at least 2.0.3), can't use formNode[key] syntax to find the node,
				//for nodes that were dynamically added.
				var fNode = req.formNode;
				for(var j = 0; j < fNode.childNodes.length; j++){
					var chNode = fNode.childNodes[j];
					if(chNode.name == key){
						var pNode = chNode.parentNode;
						pNode.removeChild(chNode);
						break;
					}
				}
			}else{
				var input = req.formNode[key];
				req.formNode.removeChild(input);
				req.formNode[key] = null;
			}
		}

		// restore original action + target
		if(req["_originalAction"]){
			req.formNode.setAttribute("action", req._originalAction);
		}
		req.formNode.setAttribute("target", req._originalTarget);
		req.formNode.target = req._originalTarget;

		var ifd = dojo.io.iframeContentDocument(_this.iframe);
		// handle successful returns
		// FIXME: how do we determine success for iframes? Is there an equiv of
		// the "status" property?
		var value;
		var success = false;

		try{
			var cmt = req.mimetype;
			if((cmt == "text/javascript")||(cmt == "text/json")){
				// FIXME: not sure what to do here? try to pull some evalulable
				// text from a textarea or cdata section? 
				// how should we set up the contract for that?
				var js = ifd.getElementsByTagName("textarea")[0].value;
				if(cmt == "text/json") { js = "(" + js + ")"; }
				value = dj_eval(js);
			}else if(cmt == "text/html"){
				value = ifd;
			}else{ // text/plain
				value = ifd.getElementsByTagName("textarea")[0].value;
			}
			success = true;
		}catch(e){ 
			// looks like we didn't get what we wanted!
			var errObj = new dojo.io.Error("IframeTransport Error");
			if(dojo.lang.isFunction(req["error"])){
				req.error("error", errObj, req);
			}
		}

		// don't want to mix load function errors with processing errors, thus
		// a separate try..catch
		try {
			if(success && dojo.lang.isFunction(req["load"])){
				req.load("load", value, req);
			}
		} catch(e) {
			throw e;
		} finally {
			_this.currentRequest = null;
			_this.fireNextRequest();
		}
	}

	dojo.io.transports.addTransport("IframeTransport");
}

__CPAN_DIR__ src/uri
__CPAN_FILE__ src/uri/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: ["dojo.uri.Uri", false, false]
});
dojo.provide("dojo.uri.*");

__CPAN_FILE__ src/uri/Uri.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.uri.Uri");

dojo.uri = new function() {
	this.joinPath = function() {
		// DEPRECATED: use the dojo.uri.Uri object instead
		var arr = [];
		for(var i = 0; i < arguments.length; i++) { arr.push(arguments[i]); }
		return arr.join("/").replace(/\/{2,}/g, "/").replace(/((https*|ftps*):)/i, "$1/");
	}
	
	this.dojoUri = function (uri) {
		// returns a Uri object resolved relative to the dojo root
		return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri(), uri);
	}
		
	this.Uri = function (/*uri1, uri2, [...]*/) {
		// An object representing a Uri.
		// Each argument is evaluated in order relative to the next until
		// a conanical uri is producued. To get an absolute Uri relative
		// to the current document use
		//      new dojo.uri.Uri(document.baseURI, uri)

		// TODO: support for IPv6, see RFC 2732

		// resolve uri components relative to each other
		var uri = arguments[0];
		for (var i = 1; i < arguments.length; i++) {
			if(!arguments[i]) { continue; }

			// Safari doesn't support this.constructor so we have to be explicit
			var relobj = new dojo.uri.Uri(arguments[i].toString());
			var uriobj = new dojo.uri.Uri(uri.toString());

			if (relobj.path == "" && relobj.scheme == null &&
				relobj.authority == null && relobj.query == null) {
				if (relobj.fragment != null) { uriobj.fragment = relobj.fragment; }
				relobj = uriobj;
			} else if (relobj.scheme == null) {
				relobj.scheme = uriobj.scheme;
			
				if (relobj.authority == null) {
					relobj.authority = uriobj.authority;
					
					if (relobj.path.charAt(0) != "/") {
						var path = uriobj.path.substring(0,
							uriobj.path.lastIndexOf("/") + 1) + relobj.path;

						var segs = path.split("/");
						for (var j = 0; j < segs.length; j++) {
							if (segs[j] == ".") {
								if (j == segs.length - 1) { segs[j] = ""; }
								else { segs.splice(j, 1); j--; }
							} else if (j > 0 && !(j == 1 && segs[0] == "") &&
								segs[j] == ".." && segs[j-1] != "..") {

								if (j == segs.length - 1) { segs.splice(j, 1); segs[j - 1] = ""; }
								else { segs.splice(j - 1, 2); j -= 2; }
							}
						}
						relobj.path = segs.join("/");
					}
				}
			}

			uri = "";
			if (relobj.scheme != null) { uri += relobj.scheme + ":"; }
			if (relobj.authority != null) { uri += "//" + relobj.authority; }
			uri += relobj.path;
			if (relobj.query != null) { uri += "?" + relobj.query; }
			if (relobj.fragment != null) { uri += "#" + relobj.fragment; }
		}

		this.uri = uri.toString();

		// break the uri into its main components
		var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
	    var r = this.uri.match(new RegExp(regexp));

		this.scheme = r[2] || (r[1] ? "" : null);
		this.authority = r[4] || (r[3] ? "" : null);
		this.path = r[5]; // can never be undefined
		this.query = r[7] || (r[6] ? "" : null);
		this.fragment  = r[9] || (r[8] ? "" : null);
		
		if (this.authority != null) {
			// server based naming authority
			regexp = "^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$";
			r = this.authority.match(new RegExp(regexp));
			
			this.user = r[3] || null;
			this.password = r[4] || null;
			this.host = r[5];
			this.port = r[7] || null;
		}
	
		this.toString = function(){ return this.uri; }
	}
};

__CPAN_DIR__ src/math
__CPAN_FILE__ src/math/points.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.math.points");
dojo.require("dojo.math");

// TODO: add a Point class?
dojo.math.points = {
	translate: function(a, b) {
		if( a.length != b.length ) {
			dojo.raise("dojo.math.translate: points not same size (a:[" + a + "], b:[" + b + "])");
		}
		var c = new Array(a.length);
		for(var i = 0; i < a.length; i++) {
			c[i] = a[i] + b[i];
		}
		return c;
	},

	midpoint: function(a, b) {
		if( a.length != b.length ) {
			dojo.raise("dojo.math.midpoint: points not same size (a:[" + a + "], b:[" + b + "])");
		}
		var c = new Array(a.length);
		for(var i = 0; i < a.length; i++) {
			c[i] = (a[i] + b[i]) / 2;
		}
		return c;
	},

	invert: function(a) {
		var b = new Array(a.length);
		for(var i = 0; i < a.length; i++) { b[i] = -a[i]; }
		return b;
	},

	distance: function(a, b) {
		return Math.sqrt(Math.pow(b[0]-a[0], 2) + Math.pow(b[1]-a[1], 2));
	}
};

__CPAN_FILE__ src/math/matrix.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.math.matrix");

//
// some of this code is based on
// http://www.mkaz.com/math/MatrixCalculator.java
// (published under a BSD Open Source License)
//
// the rest is from my vague memory of matricies in school [cal]
//
// the copying of arguments is a little excessive, and could be trimmed back in
// the case where a function doesn't modify them at all (but some do!)
//

dojo.math.matrix.iDF = 0;

dojo.math.matrix.multiply = function(a, b){

	a = dojo.math.matrix.copy(a);
	b = dojo.math.matrix.copy(b);

	var ax = a[0].length;
	var ay = a.length;
	var bx = b[0].length;
	var by = b.length;

	if (ax != by){
		dojo.debug("Can't multiply matricies of sizes "+ax+','+ay+' and '+bx+','+by);
		return [[0]];
	}

	var c = [];

	for(var k=0; k<ay; k++){
		c[k] = [];
		for(var i=0; i<bx; i++){

			c[k][i] = 0;

			for(var m=0; m<ax; m++){

				c[k][i] += a[k][m]*b[m][i];
			}
		}
	}

	return c;
}

dojo.math.matrix.inverse = function(a){

	a = dojo.math.matrix.copy(a);

	// Formula used to Calculate Inverse:
	// inv(A) = 1/det(A) * adj(A)

	var tms = a.length;

	var m = dojo.math.matrix.create(tms, tms);
	var mm = dojo.math.matrix.adjoint(a);

	var det = dojo.math.matrix.determinant(a);
	var dd = 0;

	if (det == 0){
		dojo.debug("Determinant Equals 0, Not Invertible.");
		return [[0]];
	}else{
		dd = 1 / det;
	}

	for (var i = 0; i < tms; i++)
		for (var j = 0; j < tms; j++) {
			m[i][j] = dd * mm[i][j];
		}

	return m;
}

dojo.math.matrix.determinant = function(a){

	a = dojo.math.matrix.copy(a);

	if (a.length != a[0].length){
		dojo.debug("Can't calculate the determiant of a non-squre matrix!");
		return 0;
	}

	var tms = a.length;
	var det = 1;

	var b = dojo.math.matrix.upperTriangle(a);

	for (var i=0; i < tms; i++){
		det *= b[i][i];
	}

	det = det * dojo.math.matrix.iDF;

	return det;
}

dojo.math.matrix.upperTriangle = function(m){

	m = dojo.math.matrix.copy(m);

	var f1 = 0;
	var temp = 0;
	var tms = m.length;
	var v = 1;

	dojo.math.matrix.iDF = 1;

	for (var col = 0; col < tms - 1; col++) {
		for (var row = col + 1; row < tms; row++) {
			v = 1;

			var stop_loop = 0;

			// check if 0 in diagonal
 			while ((m[col][col] == 0) && !stop_loop){

				// if so switch until not
				if (col + v >= tms){

					// check if switched all rows
					dojo.math.matrix.iDF = 0;
					stop_loop = 1;
				}else{
					for (var c = 0; c < tms; c++) {
						temp = m[col][c];
						m[col][c] = m[col + v][c]; // switch rows
						m[col + v][c] = temp;
					}
					v++; // count row switchs
					dojo.math.matrix.iDF *= -1; // each switch changes determinant factor
				}
			}

			if (m[col][col] != 0) {
				f1 = (-1) * m[row][col] / m[col][col];
				for (var i = col; i < tms; i++) {
					m[row][i] = f1 * m[col][i] + m[row][i];
				}
			}
		}
	}

	return m;
}

dojo.math.matrix.create = function(a, b){
	var m = [];
	for(var i=0; i<b; i++){
		m[i] = [];
		for(var j=0; j<a; j++){
			m[i][j] = 0;
		}
	}
	return m;
}

dojo.math.matrix.adjoint = function(a){

	a = dojo.math.matrix.copy(a);

	var tms = a.length;

	if (a.length != a[0].length){
		dojo.debug("Can't find the adjoint of a non-square matrix");
		return [[0]];
	}

	if (tms == 1){
		dojo.debug("Can't find the adjoint of a 1x1 matrix");
		return [[0]];
	}

	var m = dojo.math.matrix.create(tms, tms);

	var ii = 0;
	var jj = 0;
	var ia = 0;
	var ja = 0;
	var det = 0;

	for (var i = 0; i < tms; i++){
		for (var j = 0; j < tms; j++){

			ia = 0;
			ja = 0;

			var ap = dojo.math.matrix.create(tms-1, tms-1);

			for (ii = 0; ii < tms; ii++) {
				for (jj = 0; jj < tms; jj++) {

					if ((ii != i) && (jj != j)) {
						ap[ia][ja] = a[ii][jj];
						ja++;
					}

				}

				if ((ii != i) && (jj != j)) {
					ia++;
				}
				ja = 0;
			}

			det = dojo.math.matrix.determinant(ap);
			m[i][j] = Math.pow(-1 , (i + j)) * det;
		}
	}

	m = dojo.math.matrix.transpose(m);

	return m;
}

dojo.math.matrix.transpose = function(a){

	a = dojo.math.matrix.copy(a);

	var m = dojo.math.matrix.create(a.length, a[0].length);

	for (var i = 0; i < a.length; i++)
		for (var j = 0; j < a[i].length; j++)
			m[j][i] = a[i][j];
	return m;
}

dojo.math.matrix.format = function(a){

	function format_int(x){
		var dp = 5;
		var fac = Math.pow(10 , dp);
		var a = Math.round(x*fac)/fac;
		var b = a.toString();
		if (b.charAt(0) != '-'){ b = ' ' + b;}
		var has_dp = 0;
		for(var i=1; i<b.length; i++){
			if (b.charAt(i) == '.'){ has_dp = 1; }
		}
		if (!has_dp){ b += '.'; }
		while(b.length < dp+3){ b += '0'; }
		return b;
	}

	var ya = a.length;
	var xa = a[0].length;

	var buffer = '';

	for (var y=0; y<ya; y++){
		buffer += '| ';
		for (var x=0; x<xa; x++){
			buffer += format_int(a[y][x]) + ' ';
		}
		buffer += '|\n';
	}

	return buffer;
}

dojo.math.matrix.copy = function(a){

	var ya = a.length;
	var xa = a[0].length;

	var m = dojo.math.matrix.create(xa, ya);

	for (var y=0; y<ya; y++){
		for (var x=0; x<xa; x++){
			m[y][x] = a[y][x];
		}
	}

	return m;
}

dojo.math.matrix.scale = function(k, a){

	a = dojo.math.matrix.copy(a);

	var ya = a.length;
	var xa = a[0].length;

	for (var y=0; y<ya; y++){
		for (var x=0; x<xa; x++){
			a[y][x] *= k;
		}
	}

	return a;
}

__CPAN_FILE__ src/math/curves.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.math.curves");

dojo.require("dojo.math");

/* Curves from Dan's 13th lib stuff.
 * See: http://pupius.co.uk/js/Toolkit.Drawing.js
 *      http://pupius.co.uk/dump/dojo/Dojo.Math.js
 */

dojo.math.curves = {
	//Creates a straight line object
	Line: function(start, end) {
		this.start = start;
		this.end = end;
		this.dimensions = start.length;

		for(var i = 0; i < start.length; i++) {
			start[i] = Number(start[i]);
		}

		for(var i = 0; i < end.length; i++) {
			end[i] = Number(end[i]);
		}

		//simple function to find point on an n-dimensional, straight line
		this.getValue = function(n) {
			var retVal = new Array(this.dimensions);
			for(var i=0;i<this.dimensions;i++)
				retVal[i] = ((this.end[i] - this.start[i]) * n) + this.start[i];
			return retVal;
		}

		return this;
	},


	//Takes an array of points, the first is the start point, the last is end point and the ones in
	//between are the Bezier control points.
	Bezier: function(pnts) {
		this.getValue = function(step) {
			if(step >= 1) return this.p[this.p.length-1];	// if step>=1 we must be at the end of the curve
			if(step <= 0) return this.p[0];					// if step<=0 we must be at the start of the curve
			var retVal = new Array(this.p[0].length);
			for(var k=0;j<this.p[0].length;k++) { retVal[k]=0; }
			for(var j=0;j<this.p[0].length;j++) {
				var C=0; var D=0;
				for(var i=0;i<this.p.length;i++) {
					C += this.p[i][j] * this.p[this.p.length-1][0]
						* dojo.math.bernstein(step,this.p.length,i);
				}
				for(var l=0;l<this.p.length;l++) {
					D += this.p[this.p.length-1][0] * dojo.math.bernstein(step,this.p.length,l);
				}
				retVal[j] = C/D;
			}
			return retVal;
		}
		this.p = pnts;
		return this;
	},


	//Catmull-Rom Spline - allows you to interpolate a smooth curve through a set of points in n-dimensional space
	CatmullRom : function(pnts,c) {
		this.getValue = function(step) {
			var percent = step * (this.p.length-1);
			var node = Math.floor(percent);
			var progress = percent - node;

			var i0 = node-1; if(i0 < 0) i0 = 0;
			var i = node;
			var i1 = node+1; if(i1 >= this.p.length) i1 = this.p.length-1;
			var i2 = node+2; if(i2 >= this.p.length) i2 = this.p.length-1;

			var u = progress;
			var u2 = progress*progress;
			var u3 = progress*progress*progress;

			var retVal = new Array(this.p[0].length);
			for(var k=0;k<this.p[0].length;k++) {
				var x1 = ( -this.c * this.p[i0][k] ) + ( (2 - this.c) * this.p[i][k] ) + ( (this.c-2) * this.p[i1][k] ) + ( this.c * this.p[i2][k] );
				var x2 = ( 2 * this.c * this.p[i0][k] ) + ( (this.c-3) * this.p[i][k] ) + ( (3 - 2 * this.c) * this.p[i1][k] ) + ( -this.c * this.p[i2][k] );
				var x3 = ( -this.c * this.p[i0][k] ) + ( this.c * this.p[i1][k] );
				var x4 = this.p[i][k];

				retVal[k] = x1*u3 + x2*u2 + x3*u + x4;
			}
			return retVal;

		}


		if(!c) this.c = 0.7;
		else this.c = c;
		this.p = pnts;

		return this;
	},

	// FIXME: This is the bad way to do a partial-arc with 2 points. We need to have the user
	// supply the radius, otherwise we always get a half-circle between the two points.
	Arc : function(start, end, ccw) {
		var center = dojo.math.points.midpoint(start, end);
		var sides = dojo.math.points.translate(dojo.math.points.invert(center), start);
		var rad = Math.sqrt(Math.pow(sides[0], 2) + Math.pow(sides[1], 2));
		var theta = dojo.math.radToDeg(Math.atan(sides[1]/sides[0]));
		if( sides[0] < 0 ) {
			theta -= 90;
		} else {
			theta += 90;
		}
		dojo.math.curves.CenteredArc.call(this, center, rad, theta, theta+(ccw?-180:180));
	},

	// Creates an arc object, with center and radius (Top of arc = 0 degrees, increments clockwise)
	//  center => 2D point for center of arc
	//  radius => scalar quantity for radius of arc
	//  start  => to define an arc specify start angle (default: 0)
	//  end    => to define an arc specify start angle
	CenteredArc : function(center, radius, start, end) {
		this.center = center;
		this.radius = radius;
		this.start = start || 0;
		this.end = end;

		this.getValue = function(n) {
			var retVal = new Array(2);
			var theta = dojo.math.degToRad(this.start+((this.end-this.start)*n));

			retVal[0] = this.center[0] + this.radius*Math.sin(theta);
			retVal[1] = this.center[1] - this.radius*Math.cos(theta);

			return retVal;
		}

		return this;
	},

	// Special case of Arc (start = 0, end = 360)
	Circle : function(center, radius) {
		dojo.math.curves.CenteredArc.call(this, center, radius, 0, 360);
		return this;
	},

	Path : function() {
		var curves = [];
		var weights = [];
		var ranges = [];
		var totalWeight = 0;

		this.add = function(curve, weight) {
			if( weight < 0 ) { dojo.raise("dojo.math.curves.Path.add: weight cannot be less than 0"); }
			curves.push(curve);
			weights.push(weight);
			totalWeight += weight;
			computeRanges();
		}

		this.remove = function(curve) {
			for(var i = 0; i < curves.length; i++) {
				if( curves[i] == curve ) {
					curves.splice(i, 1);
					totalWeight -= weights.splice(i, 1)[0];
					break;
				}
			}
			computeRanges();
		}

		this.removeAll = function() {
			curves = [];
			weights = [];
			totalWeight = 0;
		}

		this.getValue = function(n) {
			var found = false, value = 0;
			for(var i = 0; i < ranges.length; i++) {
				var r = ranges[i];
				//w(r.join(" ... "));
				if( n >= r[0] && n < r[1] ) {
					var subN = (n - r[0]) / r[2];
					value = curves[i].getValue(subN);
					found = true;
					break;
				}
			}

			// FIXME: Do we want to assume we're at the end?
			if( !found ) {
				value = curves[curves.length-1].getValue(1);
			}

			for(var j = 0; j < i; j++) {
				value = dojo.math.points.translate(value, curves[j].getValue(1));
			}
			return value;
		}

		function computeRanges() {
			var start = 0;
			for(var i = 0; i < weights.length; i++) {
				var end = start + weights[i] / totalWeight;
				var len = end - start;
				ranges[i] = [start, end, len];
				start = end;
			}
		}

		return this;
	}
};

__CPAN_FILE__ src/math/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: [
		["dojo.math", false, false],
		["dojo.math.curves", false, false],
		["dojo.math.points", false, false]
	]
});
dojo.provide("dojo.math.*");

__CPAN_FILE__ src/math/Math.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.deprecated("dojo.math.Math", "include dojo.math instead", "0.4");
dojo.require("dojo.math");

__CPAN_DIR__ src/collections
__CPAN_FILE__ src/collections/Set.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.collections.Set");
dojo.require("dojo.collections.Collections");
dojo.require("dojo.collections.ArrayList");

//	straight up sets are based on arrays or array-based collections.
dojo.collections.Set = new function(){
	this.union = function(setA, setB){
		if (setA.constructor == Array) var setA = new dojo.collections.ArrayList(setA);
		if (setB.constructor == Array) var setB = new dojo.collections.ArrayList(setB);
		if (!setA.toArray || !setB.toArray) dojo.raise("Set operations can only be performed on array-based collections.");
		var result = new dojo.collections.ArrayList(setA.toArray());
		var e = setB.getIterator();
		while(!e.atEnd()){
			var item=e.get();
			if(!result.contains(item)){
				result.add(item);
			}
		}
		return result;
	};
	this.intersection = function(setA, setB){
		if (setA.constructor == Array) var setA = new dojo.collections.ArrayList(setA);
		if (setB.constructor == Array) var setB = new dojo.collections.ArrayList(setB);
		if (!setA.toArray || !setB.toArray) dojo.raise("Set operations can only be performed on array-based collections.");
		var result = new dojo.collections.ArrayList();
		var e = setB.getIterator();
		while(!e.atEnd()){
			var item=e.get();
			if(setA.contains(item)){
				result.add(item);
			}
		}
		return result;
	};
	//	returns everything in setA that is not in setB.
	this.difference = function(setA, setB){
		if (setA.constructor == Array) var setA = new dojo.collections.ArrayList(setA);
		if (setB.constructor == Array) var setB = new dojo.collections.ArrayList(setB);
		if (!setA.toArray || !setB.toArray) dojo.raise("Set operations can only be performed on array-based collections.");
		var result = new dojo.collections.ArrayList();
		var e=setA.getIterator();
		while(!e.atEnd()){
			var item=e.get();
			if(!setB.contains(item)){
				result.add(item);
			}
		}
		return result;
	};
	this.isSubSet = function(setA, setB) {
		if (setA.constructor == Array) var setA = new dojo.collections.ArrayList(setA);
		if (setB.constructor == Array) var setB = new dojo.collections.ArrayList(setB);
		if (!setA.toArray || !setB.toArray) dojo.raise("Set operations can only be performed on array-based collections.");
		var e = setA.getIterator();
		while(!e.atEnd()){
			if(!setB.contains(e.get())){
				return false;
			}
		}
		return true;
	};
	this.isSuperSet = function(setA, setB){
		if (setA.constructor == Array) var setA = new dojo.collections.ArrayList(setA);
		if (setB.constructor == Array) var setB = new dojo.collections.ArrayList(setB);
		if (!setA.toArray || !setB.toArray) dojo.raise("Set operations can only be performed on array-based collections.");
		var e = setB.getIterator();
		while(!e.atEnd()){
			if(!setA.contains(e.get())){
				return false;
			}
		}
		return true;
	};
}();

__CPAN_FILE__ src/collections/Collections.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.collections.Collections");

dojo.collections={Collections:true};
dojo.collections.DictionaryEntry=function(/* string */k, /* object */v){
	//	summary
	//	return an object of type dojo.collections.DictionaryEntry
	this.key=k;
	this.value=v;
	this.valueOf=function(){ 
		return this.value; 	//	object
	};
	this.toString=function(){ 
		return String(this.value);	//	string 
	};
}

/*	Iterators
 *	The collections.Iterators (Iterator and DictionaryIterator) are built to
 *	work with the Collections included in this namespace.  However, they *can*
 *	be used with arrays and objects, respectively, should one choose to do so.
 */
dojo.collections.Iterator=function(/* array */arr){
	//	summary
	//	return an object of type dojo.collections.Iterator
	var a=arr;
	var position=0;
	this.element=a[position]||null;
	this.atEnd=function(){
		//	summary
		//	Test to see if the internal cursor has reached the end of the internal collection.
		return (position>=a.length);	//	bool
	};
	this.get=function(){
		//	summary
		//	Test to see if the internal cursor has reached the end of the internal collection.
		if(this.atEnd()){
			return null;		//	object
		}
		this.element=a[position++];
		return this.element;	//	object
	};
	this.map=function(/* function */fn, /* object? */scope){
		//	summary
		//	Functional iteration with optional scope.
		var s=scope||dj_global;
		if(Array.map){
			return Array.map(a,fn,s);	//	array
		}else{
			var arr=[];
			for(var i=0; i<a.length; i++){
				arr.push(fn.call(s,a[i]));
			}
			return arr;		//	array
		}
	};
	this.reset=function(){
		//	summary
		//	reset the internal cursor.
		position=0;
		this.element=a[position];
	};
}

/*	Notes:
 *	The DictionaryIterator no longer supports a key and value property;
 *	the reality is that you can use this to iterate over a JS object
 *	being used as a hashtable.
 */
dojo.collections.DictionaryIterator=function(/* object */obj){
	//	summary
	//	return an object of type dojo.collections.DictionaryIterator
	var a=[];	//	Create an indexing array
	var testObject={};
	for(var p in obj){
		if(!testObject[p]){
			a.push(obj[p]);	//	fill it up
		}
	}
	var position=0;
	this.element=a[position]||null;
	this.atEnd=function(){
		//	summary
		//	Test to see if the internal cursor has reached the end of the internal collection.
		return (position>=a.length);	//	bool
	};
	this.get=function(){
		//	summary
		//	Test to see if the internal cursor has reached the end of the internal collection.
		if(this.atEnd()){
			return null;		//	object
		}
		this.element=a[position++];
		return this.element;	//	object
	};
	this.map=function(/* function */fn, /* object? */scope){
		//	summary
		//	Functional iteration with optional scope.
		var s=scope||dj_global;
		if(Array.map){
			return Array.map(a,fn,s);	//	array
		}else{
			var arr=[];
			for(var i=0; i<a.length; i++){
				arr.push(fn.call(s,a[i]));
			}
			return arr;		//	array
		}
	};
	this.reset=function() { 
		//	summary
		//	reset the internal cursor.
		position=0; 
		this.element=a[position];
	};
};

__CPAN_FILE__ src/collections/Queue.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.collections.Queue");
dojo.require("dojo.collections.Collections");

dojo.collections.Queue=function(/* array? */arr){
	//	summary
	//	return an object of type dojo.collections.Queue
	var q=[];
	if (arr){
		q=q.concat(arr);
	}
	this.count=q.length;
	this.clear=function(){
		//	summary
		//	clears the internal collection
		q=[];
		this.count=q.length;
	};
	this.clone=function(){
		//	summary
		//	creates a new Queue based on this one
		return new dojo.collections.Queue(q);	//	dojo.collections.Queue
	};
	this.contains=function(/* object */ o){
		//	summary
		//	Check to see if the passed object is an element in this queue
		for(var i=0; i<q.length; i++){
			if (q[i]==o){
				return true;	//	bool
			}
		}
		return false;	//	bool
	};
	this.copyTo=function(/* array */ arr, /* int */ i){
		//	summary
		//	Copy the contents of this queue into the passed array at index i.
		arr.splice(i,0,q);
	};
	this.dequeue=function(){
		//	summary
		//	shift the first element off the queue and return it
		var r=q.shift();
		this.count=q.length;
		return r;	//	object
	};
	this.enqueue=function(/* object */ o){
		//	summary
		//	put the passed object at the end of the queue
		this.count=q.push(o);
	};
	this.forEach=function(/* function */ fn, /* object? */ scope){
		//	summary
		//	functional iterator, following the mozilla spec.
		var s=scope||dj_global;
		if(Array.forEach){
			Array.forEach(q, fn, s);
		}else{
			for(var i=0; i<q.length; i++){
				fn.call(s, q[i], i, q);
			}
		}
	};
	this.getIterator=function(){
		//	summary
		//	get an Iterator based on this queue.
		return new dojo.collections.Iterator(q);	//	dojo.collections.Iterator
	};
	this.peek=function(){
		//	summary
		//	get the next element in the queue without altering the queue.
		return q[0];
	};
	this.toArray=function(){
		//	summary
		//	return an array based on the internal array of the queue.
		return [].concat(q);
	};
};

__CPAN_FILE__ src/collections/Stack.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.collections.Stack");
dojo.require("dojo.collections.Collections");

dojo.collections.Stack=function(/* array? */arr){
	//	summary
	//	returns an object of type dojo.collections.Stack
	var q=[];
	if (arr) q=q.concat(arr);
	this.count=q.length;
	this.clear=function(){
		//	summary
		//	Clear the internal array and reset the count
		q=[];
		this.count=q.length;
	};
	this.clone=function(){
		//	summary
		//	Create and return a clone of this Stack
		return new dojo.collections.Stack(q);
	};
	this.contains=function(/* object */o){
		//	summary
		//	check to see if the stack contains object o
		for (var i=0; i<q.length; i++){
			if (q[i] == o){
				return true;	//	bool
			}
		}
		return false;	//	bool
	};
	this.copyTo=function(/* array */ arr, /* int */ i){
		//	summary
		//	copy the stack into array arr at index i
		arr.splice(i,0,q);
	};
	this.forEach=function(/* function */ fn, /* object? */ scope){
		//	summary
		//	functional iterator, following the mozilla spec.
		var s=scope||dj_global;
		if(Array.forEach){
			Array.forEach(q, fn, s);
		}else{
			for(var i=0; i<q.length; i++){
				fn.call(s, q[i], i, q);
			}
		}
	};
	this.getIterator=function(){
		//	summary
		//	get an iterator for this collection
		return new dojo.collections.Iterator(q);	//	dojo.collections.Iterator
	};
	this.peek=function(){
		//	summary
		//	Return the next item without altering the stack itself.
		return q[(q.length-1)];	//	object
	};
	this.pop=function(){
		//	summary
		//	pop and return the next item on the stack
		var r=q.pop();
		this.count=q.length;
		return r;	//	object
	};
	this.push=function(/* object */ o){
		//	summary
		//	Push object o onto the stack
		this.count=q.push(o);
	};
	this.toArray=function(){
		//	summary
		//	create and return an array based on the internal collection
		return [].concat(q);	//	array
	};
}

__CPAN_FILE__ src/collections/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: [
		"dojo.collections.Collections",
		"dojo.collections.SortedList", 
		"dojo.collections.Dictionary", 
		"dojo.collections.Queue", 
		"dojo.collections.ArrayList", 
		"dojo.collections.Stack",
		"dojo.collections.Set"
	]
});
dojo.provide("dojo.collections.*");

__CPAN_FILE__ src/collections/Dictionary.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.collections.Dictionary");
dojo.require("dojo.collections.Collections");

dojo.collections.Dictionary=function(/* dojo.collections.Dictionary? */dictionary){
	//	summary
	//	Returns an object of type dojo.collections.Dictionary
	var items={};
	this.count=0;

	//	comparator for property addition and access.
	var testObject={};

	this.add=function(/* string */k, /* object */v){
		//	summary
		//	Add a new item to the Dictionary.
		var b=(k in items);
		items[k]=new dojo.collections.DictionaryEntry(k,v);
		if(!b){
			this.count++;
		}
	};
	this.clear=function(){
		//	summary
		//	Clears the internal dictionary.
		items={};
		this.count=0;
	};
	this.clone=function(){
		//	summary
		//	Returns a new instance of dojo.collections.Dictionary; note the the dictionary is a clone but items might not be.
		return new dojo.collections.Dictionary(this);	//	dojo.collections.Dictionary
	};
	this.contains=this.containsKey=function(/* string */k){
		//	summary
		//	Check to see if the dictionary has an entry at key "k".
		if(testObject[k]){
			return false;			// bool
		}
		return (items[k]!=null);	//	bool
	};
	this.containsValue=function(/* object */v){
		//	summary
		//	Check to see if the dictionary has an entry with value "v".
		var e=this.getIterator();
		while(e.get()){
			if(e.element.value==v){
				return true;	//	bool
			}
		}
		return false;	//	bool
	};
	this.entry=function(/* string */k){
		//	summary
		//	Accessor method; similar to dojo.collections.Dictionary.item but returns the actual Entry object.
		return items[k];	//	dojo.collections.DictionaryEntry
	};
	this.forEach=function(/* function */ fn, /* object? */ scope){
		//	summary
		//	functional iterator, following the mozilla spec.
		var a=[];	//	Create an indexing array
		for(var p in items) {
			if(!testObject[p]){
				a.push(items[p]);	//	fill it up
			}
		}
		var s=scope||dj_global;
		if(Array.forEach){
			Array.forEach(a, fn, s);
		}else{
			for(var i=0; i<a.length; i++){
				fn.call(s, a[i], i, a);
			}
		}
	};
	this.getKeyList=function(){
		//	summary
		//	Returns an array of the keys in the dictionary.
		return (this.getIterator()).map(function(entry){ 
			return entry.key; 
		});	//	array
	};
	this.getValueList=function(){
		//	summary
		//	Returns an array of the values in the dictionary.
		return (this.getIterator()).map(function(entry){ 
			return entry.value; 
		});	//	array
	};
	this.item=function(/* string */k){
		//	summary
		//	Accessor method.
		if(k in items){
			return items[k].valueOf();	//	object
		}
		return undefined;	//	object
	};
	this.getIterator=function(){
		//	summary
		//	Gets a dojo.collections.DictionaryIterator for iteration purposes.
		return new dojo.collections.DictionaryIterator(items);	//	dojo.collections.DictionaryIterator
	};
	this.remove=function(/* string */k){
		//	summary
		//	Removes the item at k from the internal collection.
		if(k in items && !testObject[k]){
			delete items[k];
			this.count--;
			return true;	//	bool
		}
		return false;	//	bool
	};

	if (dictionary){
		var e=dictionary.getIterator();
		while(e.get()) {
			 this.add(e.element.key, e.element.value);
		}
	}
};

__CPAN_FILE__ src/collections/SortedList.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.collections.SortedList");
dojo.require("dojo.collections.Collections");

dojo.collections.SortedList=function(/* object? */ dictionary){
	//	summary
	//	creates a collection that acts like a dictionary but is also internally sorted.
	//	Note that the act of adding any elements forces an internal resort, making this object potentially slow.
	var _this=this;
	var items={};
	var q=[];
	var sorter=function(a,b){
		if (a.key > b.key) return 1;
		if (a.key < b.key) return -1;
		return 0;
	};
	var build=function(){
		q=[];
		var e=_this.getIterator();
		while (!e.atEnd()){
			q.push(e.get());
		}
		q.sort(sorter);
	};
	var testObject={};

	this.count=q.length;
	this.add=function(/* string */ k,/* object */v){
		//	summary
		//	add the passed value to the dictionary at location k
		if (!items[k]) {
			items[k]=new dojo.collections.DictionaryEntry(k,v);
			this.count=q.push(items[k]);
			q.sort(sorter);
		}
	};
	this.clear=function(){
		//	summary
		//	clear the internal collections
		items={};
		q=[];
		this.count=q.length;
	};
	this.clone=function(){
		//	summary
		//	create a clone of this sorted list
		return new dojo.collections.SortedList(this);	//	dojo.collections.SortedList
	};
	this.contains=this.containsKey=function(/* string */ k){
		//	summary
		//	Check to see if the list has a location k
		if(testObject[k]){
			return false;			//	bool
		}
		return (items[k]!=null);	//	bool
	};
	this.containsValue=function(/* object */ o){
		//	summary
		//	Check to see if this list contains the passed object
		var e=this.getIterator();
		while (!e.atEnd()){
			var item=e.get();
			if(item.value==o){ 
				return true;	//	bool
			}
		}
		return false;	//	bool
	};
	this.copyTo=function(/* array */ arr, /* int */ i){
		//	summary
		//	copy the contents of the list into array arr at index i
		var e=this.getIterator();
		var idx=i;
		while(!e.atEnd()){
			arr.splice(idx,0,e.get());
			idx++;
		}
	};
	this.entry=function(/* string */ k){
		//	summary
		//	return the object at location k
		return items[k];	//	dojo.collections.DictionaryEntry
	};
	this.forEach=function(/* function */ fn, /* object? */ scope){
		//	summary
		//	functional iterator, following the mozilla spec.
		var s=scope||dj_global;
		if(Array.forEach){
			Array.forEach(q, fn, s);
		}else{
			for(var i=0; i<q.length; i++){
				fn.call(s, q[i], i, q);
			}
		}
	};
	this.getByIndex=function(/* int */ i){
		//	summary
		//	return the item at index i
		return q[i].valueOf();	//	object
	};
	this.getIterator=function(){
		//	summary
		//	get an iterator for this object
		return new dojo.collections.DictionaryIterator(items);	//	dojo.collections.DictionaryIterator
	};
	this.getKey=function(/* int */ i){
		//	summary
		//	return the key of the item at index i
		return q[i].key;
	};
	this.getKeyList=function(){
		//	summary
		//	return an array of the keys set in this list
		var arr=[];
		var e=this.getIterator();
		while (!e.atEnd()){
			arr.push(e.get().key);
		}
		return arr;	//	array
	};
	this.getValueList=function(){
		//	summary
		//	return an array of values in this list
		var arr=[];
		var e=this.getIterator();
		while (!e.atEnd()){
			arr.push(e.get().value);
		}
		return arr;	//	array
	};
	this.indexOfKey=function(/* string */ k){
		//	summary
		//	return the index of the passed key.
		for (var i=0; i<q.length; i++){
			if (q[i].key==k){
				return i;	//	int
			}
		}
		return -1;	//	int
	};
	this.indexOfValue=function(/* object */ o){
		//	summary
		//	return the first index of object o
		for (var i=0; i<q.length; i++){
			if (q[i].value==o){
				return i;	//	int
			}
		}
		return -1;	//	int
	};
	this.item=function(/* string */ k){
		// 	summary
		//	return the value of the object at location k.
		if(k in items && !testObject[k]){
			return items[k].valueOf();	//	object
		}
		return undefined;	//	object
	};
	this.remove=function(/* string */k){
		// 	summary
		//	remove the item at location k and rebuild the internal collections.
		delete items[k];
		build();
		this.count=q.length;
	};
	this.removeAt=function(/* int */ i){
		//	summary
		//	remove the item at index i, and rebuild the internal collections.
		delete items[q[i].key];
		build();
		this.count=q.length;
	};
	this.replace=function(/* string */ k, /* object */ v){
		//	summary
		//	Replace an existing item if it's there, and add a new one if not.
		if (!items[k]){
			//	we're adding a new object, return false
			this.add(k,v);
			return false; // bool
		}else{
			//	we're replacing an object, return true
			items[k]=new dojo.collections.DictionaryEntry(k,v);
			q.sort(sorter);
			return true; // bool
		}
	};
	this.setByIndex=function(/* int */ i, /* object */ o){
		//	summary
		//	set an item by index
		items[q[i].key].value=o;
		build();
		this.count=q.length;
	};
	if (dictionary){
		var e=dictionary.getIterator();
		while (!e.atEnd()){
			var item=e.get();
			q[q.length]=items[item.key]=new dojo.collections.DictionaryEntry(item.key,item.value);
		}
		q.sort(sorter);
	}
}

__CPAN_FILE__ src/collections/Graph.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.collections.Graph");
dojo.require("dojo.collections.Collections");

dojo.experimental("dojo.collections.Graph");

dojo.collections.Graph=function(nodes){
	function node(key, data, neighbors) {
		this.key=key;
		this.data=data;
		this.neighbors=neighbors||new adjacencyList();
		this.addDirected=function(){
			if (arguments[0].constructor==edgeToNeighbor){
				this.neighbors.add(arguments[0]);
			}else{
				var n=arguments[0];
				var cost=arguments[1]||0;
				this.neighbors.add(new edgeToNeighbor(n, cost));
			}
		}
	}
	function nodeList(){
		var d=new dojo.collections.Dictionary();
		function nodelistiterator(){
			var o=[] ;	//	Create an indexing array
			var e=d.getIterator();
			while(e.get()){
				o[o.length]=e.element;
			}

			var position=0;
			this.element=o[position]||null;
			this.atEnd=function(){
				return (position>=o.length);
			}
			this.get=function(){
				if(this.atEnd()){
					return null;		//	object
				}
				this.element=o[position++];
				return this.element;	//	object
			};
			this.map=function(/* function */fn, /* object? */scope){
				var s=scope||dj_global;
				if(Array.map){
					return Array.map(o,fn,s);	//	array
				}else{
					var arr=[];
					for(var i=0; i<o.length; i++){
						arr.push(fn.call(s,o[i]));
					}
					return arr;		//	array
				}
			};
			this.reset=function(){
				position=0;
				this.element=o[position];
			};
		}
		
		this.add=function(node){
			d.add(node.key, node);
		};
		this.clear=function(){
			d.clear();
		};
		this.containsKey=function(key){
			return d.containsKey(key);
		};
		this.getIterator=function(){
			return new nodelistiterator(this);
		};
		this.item=function(key){
			return d.item(key);
		};
		this.remove=function(node){
			d.remove(node.key);
		};
	}
	function edgeToNeighbor(node, cost){
		this.neighbor=node;
		this.cost=cost;
	}
	function adjacencyList(){
		var d=[];
		this.add=function(o){
			d.push(o);
		};
		this.item=function(i){
			return d[i];
		};
		this.getIterator=function(){
			return new dojo.collections.Iterator([].concat(d));
		};
	}

	this.nodes=nodes||new nodeList();
	this.count=this.nodes.count;
	this.clear=function(){
		this.nodes.clear();
		this.count=0;
	};
	this.addNode=function(){
		var n=arguments[0];
		if(arguments.length > 1){
			n=new node(arguments[0],arguments[1]);
		}
		if(!this.nodes.containsKey(n.key)){
			this.nodes.add(n);
			this.count++;
		}
	};
	this.addDirectedEdge=function(uKey, vKey, cost){
		var uNode,vNode;
		if(uKey.constructor!= node){
			uNode=this.nodes.item(uKey);
			vNode=this.nodes.item(vKey);
		}else{
			uNode=uKey;
			vNode=vKey;
		}
		var c=cost||0;
		uNode.addDirected(vNode,c);
	};
	this.addUndirectedEdge=function(uKey, vKey, cost){
		var uNode, vNode;
		if(uKey.constructor!=node){
			uNode=this.nodes.item(uKey);
			vNode=this.nodes.item(vKey);
		}else{
			uNode=uKey;
			vNode=vKey;
		}
		var c=cost||0;
		uNode.addDirected(vNode,c);
		vNode.addDirected(uNode,c);
	};
	this.contains=function(n){
		return this.nodes.containsKey(n.key);
	};
	this.containsKey=function(k){
		return this.nodes.containsKey(k);
	};
}

__CPAN_FILE__ src/collections/SkipList.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.collections.SkipList");
dojo.require("dojo.collections.Collections");
dojo.require("dojo.experimental");

dojo.experimental("dojo.collections.SkipList");

dojo.collections.SkipList = function(){
	function node(height, val){
		this.value = val;
		this.height = height;
		this.nodes = new nodeList(height);
		this.compare = function(val){
			if (this.value > val) return 1;
			if (this.value < val) return -1;
			return 0;
		}
		this.incrementHeight = function(){
			this.nodes.incrementHeight();
			this.height++;
		};
		this.decrementHeight = function(){
			this.nodes.decrementHeight();
			this.height--;
		};
	}
	function nodeList(height){
		var arr = [];
		this.height = height;
		for (var i = 0; i < height; i++) arr[i] = null;
		this.item = function(i){
			return arr[i];
		};
		this.incrementHeight = function(){
			this.height++;
			arr[this.height] = null;
		};
		this.decrementHeight = function(){
			arr.splice(arr.length - 1, 1);
			this.height--;
		};
	}
	function iterator(list){
		this.current = list.head;
		this.atEnd = false;
		this.moveNext = function(){
			if (this.atEnd) return !this.atEnd;
			this.current = this.current.nodes[0];
			this.atEnd = (this.current == null);
			return !this.atEnd;
		};
		this.reset = function(){
			this.current = null;
		};
	}

	function chooseRandomHeight(max){
		var level = 1;
		while (Math.random() < PROB && level < max) level++;
		return level;
	}

	var PROB = 0.5;
	var comparisons = 0;

	this.head = new node(1);
	this.count = 0;
	this.add = function(val){
		var updates = [];
		var current = this.head;
		for (var i = this.head.height; i >= 0; i--){
			if (!(current.nodes[i] != null && current.nodes[i].compare(val) < 0)) comparisons++;
			while (current.nodes[i] != null && current.nodes[i].compare(val) < 0){
				current = current.nodes[i];
				comparisons++;
			}
			updates[i] = current;
		}
		if (current.nodes[0] != null && current.nodes[0].compare(val) == 0) return;
		var n = new node(val, chooseRandomHeight(this.head.height + 1));
		this.count++;
		if (n.height > this.head.height){
			this.head.incrementHeight();
			this.head.nodes[this.head.height - 1] = n;
		}
		for (i = 0; i < n.height; i++){
			if (i < updates.length) {
				n.nodes[i] = updates[i].nodes[i];
				updates[i].nodes[i] = n;
			}
		}
	};
	
	this.contains = function(val){
		var current = this.head;
		var i;
		for (i = this.head.height - 1; i >= 0; i--) {
			while (current.item(i) != null) {
				comparisons++;
				var result = current.nodes[i].compare(val);
				if (result == 0) return true;
				else if (result < 0) current = current.nodes[i];
				else break;
			}
		}
		return false;
	};
	this.getIterator = function(){
		return new iterator(this);
	};

	this.remove = function(val){
		var updates = [];
		var current = this.head;
		for (var i = this.head.height - 1; i >= 0; i--){
			if (!(current.nodes[i] != null && current.nodes[i].compare(val) < 0)) comparisons++;
			while (current.nodes[i] != null && current.nodes[i].compare(val) < 0) {
				current = current.nodes[i];
				comparisons++;
			}
			updates[i] = current;
		}
		
		current = current.nodes[0];
		if (current != null && current.compare(val) == 0){
			this.count--;
			for (var i = 0; i < this.head.height; i++){
				if (updates[i].nodes[i] != current) break;
				else updates[i].nodes[i] = current.nodes[i];
			}
			if (this.head.nodes[this.head.height - 1] == null) this.head.decrementHeight();
		}
	};
	this.resetComparisons = function(){ 
		comparisons = 0; 
	};
}

__CPAN_FILE__ src/collections/BinaryTree.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.collections.BinaryTree");
dojo.require("dojo.collections.Collections");
dojo.require("dojo.experimental");

dojo.experimental("dojo.collections.BinaryTree");

dojo.collections.BinaryTree=function(data){
	function node(data, rnode, lnode){
		this.value=data||null;
		this.right=rnode||null;
		this.left=lnode||null;
		this.clone=function(){
			var c=new node();
			if (this.value.value) c.value=this.value.clone();
			else c.value=this.value;
			if (this.left) c.left=this.left.clone();
			if (this.right) c.right=this.right.clone();
		}
		this.compare=function(n){
			if (this.value > n.value) return 1;
			if (this.value < n.value) return -1;
			return 0;
		}
		this.compareData=function(d){
			if (this.value > d) return 1;
			if (this.value < d) return -1;
			return 0;
		}
	}

	function inorderTraversalBuildup(current, a){
		if (current){
			inorderTraversalBuildup(current.left, a);
			a.add(current);
			inorderTraversalBuildup(current.right, a);
		}
	}

	function preorderTraversal(current, sep){
		var s="";
		if (current){
			s=current.value.toString() + sep;
			s += preorderTraversal(current.left, sep);
			s += preorderTraversal(current.right, sep);
		}
		return s;
	}
	function inorderTraversal(current, sep){
		var s="";
		if (current){
			s=inorderTraversal(current.left, sep);
			s += current.value.toString() + sep;
			s += inorderTraversal(current.right, sep);
		}
		return s;
	}
	function postorderTraversal(current, sep){
		var s="";
		if (current){
			s=postorderTraversal(current.left, sep);
			s += postorderTraversal(current.right, sep);
			s += current.value.toString() + sep;
		}
		return s;
	}
	
	function searchHelper(current, data){
		if (!current) return null;
		var i=current.compareData(data);
		if (i==0) return current;
		if (i>0) return searchHelper(current.left, data);
		else return searchHelper(current.right, data);
	}

	this.add=function(data){
		var n=new node(data);
		var i;
		var current=root;
		var parent=null;
		while (current){
			i=current.compare(n);
			if (i == 0) return;
			parent=current;
			if (i > 0) current=current.left;
			else current=current.right;
		}
		this.count++;
		if (!parent) root=n;
		else {
			i=parent.compare(n);
			if (i > 0) parent.left=n;
			else parent.right=n;
		}
	};
	this.clear=function(){
		root=null;
		this.count=0;
	};
	this.clone=function(){
		var c=new dojo.collections.BinaryTree();
		c.root=root.clone();
		c.count=this.count;
		return c;
	};
	this.contains=function(data){
		return this.search(data) != null;
	};
	this.deleteData=function(data){
		var current=root;
		var parent=null;
		var i=current.compareData(data);
		while (i != 0 && current != null){
			if (i > 0){
				parent=current;
				current=current.left;
			} else if (i < 0) {
				parent=current;
				current=current.right;
			}
			i=current.compareData(data);
		}
		if (!current) return;
		this.count--;
		if (!current.right) {
			if (!parent) root=current.left;
			else {
				i=parent.compare(current);
				if (i > 0) parent.left=current.left;
				else if (i < 0) parent.right=current.left;
			}
		} else if (!current.right.left){
			if (!parent) root=current.right;
			else {
				i=parent.compare(current);
				if (i > 0) parent.left=current.right;
				else if (i < 0) parent.right=current.right;
			}
		} else {
			var leftmost=current.right.left;
			var lmParent=current.right;
			while (leftmost.left != null){
				lmParent=leftmost;
				leftmost=leftmost.left;
			}
			lmParent.left=leftmost.right;
			leftmost.left=current.left;
			leftmost.right=current.right;
			if (!parent) root=leftmost;
			else {
				i=parent.compare(current);
				if (i > 0) parent.left=leftmost;
				else if (i < 0) parent.right=leftmost;
			}
		}
	};
	this.getIterator=function(){
		var a=[];
		inorderTraversalBuildup(root, a);
		return new dojo.collections.Iterator(a);
	};
	this.search=function(data){
		return searchHelper(root, data);
	};
	this.toString=function(order, sep){
		if (!order) var order=dojo.collections.BinaryTree.TraversalMethods.Inorder;
		if (!sep) var sep=" ";
		var s="";
		switch (order){
			case dojo.collections.BinaryTree.TraversalMethods.Preorder:
				s=preorderTraversal(root, sep);
				break;
			case dojo.collections.BinaryTree.TraversalMethods.Inorder:
				s=inorderTraversal(root, sep);
				break;
			case dojo.collections.BinaryTree.TraversalMethods.Postorder:
				s=postorderTraversal(root, sep);
				break;
		};
		if (s.length == 0) return "";
		else return s.substring(0, s.length - sep.length);
	};

	this.count=0;
	var root=this.root=null;
	if (data) {
		this.add(data);
	}
}
dojo.collections.BinaryTree.TraversalMethods={
	Preorder : 0,
	Inorder : 1,
	Postorder : 2
};

__CPAN_FILE__ src/collections/ArrayList.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.collections.ArrayList");
dojo.require("dojo.collections.Collections");

dojo.collections.ArrayList=function(/* array? */arr){
	//	summary
	//	Returns a new object of type dojo.collections.ArrayList
	var items=[];
	if(arr) items=items.concat(arr);
	this.count=items.length;
	this.add=function(/* object */obj){
		//	summary
		//	Add an element to the collection.
		items.push(obj);
		this.count=items.length;
	};
	this.addRange=function(/* array */a){
		//	summary
		//	Add a range of objects to the ArrayList
		if(a.getIterator){
			var e=a.getIterator();
			while(!e.atEnd()){
				this.add(e.get());
			}
			this.count=items.length;
		}else{
			for(var i=0; i<a.length; i++){
				items.push(a[i]);
			}
			this.count=items.length;
		}
	};
	this.clear=function(){
		//	summary
		//	Clear all elements out of the collection, and reset the count.
		items.splice(0, items.length);
		this.count=0;
	};
	this.clone=function(){
		//	summary
		//	Clone the array list
		return new dojo.collections.ArrayList(items);	//	dojo.collections.ArrayList
	};
	this.contains=function(/* object */obj){
		//	summary
		//	Check to see if the passed object is a member in the ArrayList
		for(var i=0; i < items.length; i++){
			if(items[i] == obj) {
				return true;	//	bool
			}
		}
		return false;	//	bool
	};
	this.forEach=function(/* function */ fn, /* object? */ scope){
		//	summary
		//	functional iterator, following the mozilla spec.
		var s=scope||dj_global;
		if(Array.forEach){
			Array.forEach(items, fn, s);
		}else{
			for(var i=0; i<items.length; i++){
				fn.call(s, items[i], i, items);
			}
		}
	};
	this.getIterator=function(){
		//	summary
		//	Get an Iterator for this object
		return new dojo.collections.Iterator(items);	//	dojo.collections.Iterator
	};
	this.indexOf=function(/* object */obj){
		//	summary
		//	Return the numeric index of the passed object; will return -1 if not found.
		for(var i=0; i < items.length; i++){
			if(items[i] == obj) {
				return i;	//	int
			}
		}
		return -1;	// int
	};
	this.insert=function(/* int */ i, /* object */ obj){
		//	summary
		//	Insert the passed object at index i
		items.splice(i,0,obj);
		this.count=items.length;
	};
	this.item=function(/* int */ i){
		//	summary
		//	return the element at index i
		return items[i];	//	object
	};
	this.remove=function(/* object */obj){
		//	summary
		//	Look for the passed object, and if found, remove it from the internal array.
		var i=this.indexOf(obj);
		if(i >=0) {
			items.splice(i,1);
		}
		this.count=items.length;
	};
	this.removeAt=function(/* int */ i){
		//	summary
		//	return an array with function applied to all elements
		items.splice(i,1);
		this.count=items.length;
	};
	this.reverse=function(){
		//	summary
		//	Reverse the internal array
		items.reverse();
	};
	this.sort=function(/* function? */ fn){
		//	summary
		//	sort the internal array
		if(fn){
			items.sort(fn);
		}else{
			items.sort();
		}
	};
	this.setByIndex=function(/* int */ i, /* object */ obj){
		//	summary
		//	Set an element in the array by the passed index.
		items[i]=obj;
		this.count=items.length;
	};
	this.toArray=function(){
		//	summary
		//	Return a new array with all of the items of the internal array concatenated.
		return [].concat(items);
	}
	this.toString=function(/* string */ delim){
		//	summary
		//	implementation of toString, follows [].toString();
		return items.join((delim||","));
	};
};

__CPAN_DIR__ src/compat
__CPAN_FILE__ src/compat/0.2.2.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/*
Compatibility package to get 0.2.2 functionality in later Dojo releases.
*/

//**********************************
//From bootstrap1.js
dj_throw = dj_rethrow = function(m, e){
	dojo.deprecated("dj_throw and dj_rethrow", "use dojo.raise instead", "0.4");
	dojo.raise(m, e);
}

dj_debug = dojo.debug;
dj_unimplemented = dojo.unimplemented;
dj_deprecated = dojo.deprecated;

dj_inherits = function(subclass, superclass){
	dojo.deprecated("dj_inherits", "use dojo.inherits instead", "0.4");
	dojo.inherits(subclass, superclass);
}

/**
* Set the base script uri.
*/
// In JScript .NET, see interface System._AppDomain implemented by
// System.AppDomain.CurrentDomain. Members include AppendPrivatePath,
// RelativeSearchPath, BaseDirectory.
dojo.hostenv.setBaseScriptUri = function(uri){ djConfig.baseScriptUri = uri }

//**********************************
//From the old bootstrap2.js
dojo.hostenv.moduleLoaded = function(){
	return dojo.hostenv.startPackage.apply(dojo.hostenv, arguments);
}

dojo.hostenv.require = dojo.hostenv.loadModule;
dojo.requireAfter = dojo.require;
dojo.conditionalRequire = dojo.requireIf;

dojo.requireAll = function() {
	for(var i = 0; i < arguments.length; i++) { dojo.require(arguments[i]); }
}

dojo.hostenv.conditionalLoadModule = function(){
	dojo.kwCompoundRequire.apply(dojo, arguments);
}

dojo.hostenv.provide = dojo.hostenv.startPackage;

//**********************************
//From hostenv_browser.js
dojo.hostenv.byId = dojo.byId;

dojo.hostenv.byIdArray = dojo.byIdArray = function(){
	var ids = [];
	for(var i = 0; i < arguments.length; i++){
		if((arguments[i] instanceof Array)||(typeof arguments[i] == "array")){
			for(var j = 0; j < arguments[i].length; j++){
				ids = ids.concat(dojo.hostenv.byIdArray(arguments[i][j]));
			}
		}else{
			ids.push(dojo.hostenv.byId(arguments[i]));
		}
	}
	return ids;
}

__CPAN_DIR__ src/xml
__CPAN_FILE__ src/xml/svgUtil.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.xml.svgUtil");
// FIXME: add imports for deps!

dojo.xml.svgUtil = new function(){

	this.getInnerWidth = function(node){
		// FIXME: need to find out from dylan how to 
	}

	this.getOuterWidth = function(node){
		
	}

	this.getInnerHeight = function(node){
		
	}

	this.getOuterHeight = function(node){
		
	}

}

__CPAN_FILE__ src/xml/domUtil.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.xml.domUtil");
dojo.require("dojo.graphics.color");
dojo.require("dojo.dom");
dojo.require("dojo.style");

dojo.deprecated("dojo.xml.domUtil", "use dojo.dom instead", "0.4");

// for loading script:
dojo.xml.domUtil = new function(){
	this.nodeTypes = {
		ELEMENT_NODE                  : 1,
		ATTRIBUTE_NODE                : 2,
		TEXT_NODE                     : 3,
		CDATA_SECTION_NODE            : 4,
		ENTITY_REFERENCE_NODE         : 5,
		ENTITY_NODE                   : 6,
		PROCESSING_INSTRUCTION_NODE   : 7,
		COMMENT_NODE                  : 8,
		DOCUMENT_NODE                 : 9,
		DOCUMENT_TYPE_NODE            : 10,
		DOCUMENT_FRAGMENT_NODE        : 11,
		NOTATION_NODE                 : 12
	}
	
	this.dojoml = "http://www.dojotoolkit.org/2004/dojoml";
	this.idIncrement = 0;
	
	this.getTagName = function(){return dojo.dom.getTagName.apply(dojo.dom, arguments);}
	this.getUniqueId = function(){return dojo.dom.getUniqueId.apply(dojo.dom, arguments);}
	this.getFirstChildTag = function() {return dojo.dom.getFirstChildElement.apply(dojo.dom, arguments);}
	this.getLastChildTag = function() {return dojo.dom.getLastChildElement.apply(dojo.dom, arguments);}
	this.getNextSiblingTag = function() {return dojo.dom.getNextSiblingElement.apply(dojo.dom, arguments);}
	this.getPreviousSiblingTag = function() {return dojo.dom.getPreviousSiblingElement.apply(dojo.dom, arguments);}

	this.forEachChildTag = function(node, unaryFunc) {
		var child = this.getFirstChildTag(node);
		while(child) {
			if(unaryFunc(child) == "break") { break; }
			child = this.getNextSiblingTag(child);
		}
	}

	this.moveChildren = function() {return dojo.dom.moveChildren.apply(dojo.dom, arguments);}
	this.copyChildren = function() {return dojo.dom.copyChildren.apply(dojo.dom, arguments);}
	this.clearChildren = function() {return dojo.dom.removeChildren.apply(dojo.dom, arguments);}
	this.replaceChildren = function() {return dojo.dom.replaceChildren.apply(dojo.dom, arguments);}

	this.getStyle = function() {return dojo.style.getStyle.apply(dojo.style, arguments);}
	this.toCamelCase = function() {return dojo.style.toCamelCase.apply(dojo.style, arguments);}
	this.toSelectorCase = function() {return dojo.style.toSelectorCase.apply(dojo.style, arguments);}

	this.getAncestors = function(){return dojo.dom.getAncestors.apply(dojo.dom, arguments);}
	this.isChildOf = function() {return dojo.dom.isDescendantOf.apply(dojo.dom, arguments);}
	this.createDocumentFromText = function() {return dojo.dom.createDocumentFromText.apply(dojo.dom, arguments);}

	if(dojo.render.html.capable || dojo.render.svg.capable) {
		this.createNodesFromText = function(txt, wrap){return dojo.dom.createNodesFromText.apply(dojo.dom, arguments);}
	}

	this.extractRGB = function(color) { return dojo.graphics.color.extractRGB(color); }
	this.hex2rgb = function(hex) { return dojo.graphics.color.hex2rgb(hex); }
	this.rgb2hex = function(r, g, b) { return dojo.graphics.color.rgb2hex(r, g, b); }

	this.insertBefore = function() {return dojo.dom.insertBefore.apply(dojo.dom, arguments);}
	this.before = this.insertBefore;
	this.insertAfter = function() {return dojo.dom.insertAfter.apply(dojo.dom, arguments);}
	this.after = this.insertAfter
	this.insert = function(){return dojo.dom.insertAtPosition.apply(dojo.dom, arguments);}
	this.insertAtIndex = function(){return dojo.dom.insertAtIndex.apply(dojo.dom, arguments);}
	this.textContent = function () {return dojo.dom.textContent.apply(dojo.dom, arguments);}
	this.renderedTextContent = function () {return dojo.dom.renderedTextContent.apply(dojo.dom, arguments);}
	this.remove = function (node) {return dojo.dom.removeNode.apply(dojo.dom, arguments);}
}


__CPAN_FILE__ src/xml/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.require("dojo.xml.Parse");
dojo.kwCompoundRequire({
	common:		["dojo.xml.domUtil"],
    browser: 	["dojo.xml.htmlUtil"],
    dashboard: 	["dojo.xml.htmlUtil"],
    svg: 		["dojo.xml.svgUtil"]
});
dojo.provide("dojo.xml.*");

__CPAN_FILE__ src/xml/htmlUtil.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.xml.htmlUtil");
dojo.require("dojo.html");
dojo.require("dojo.style");
dojo.require("dojo.dom");

dojo.deprecated("dojo.xml.htmlUtil", "use dojo.html instead", "0.4");

dojo.xml.htmlUtil = new function(){
	this.styleSheet = dojo.style.styleSheet;
	
	this._clobberSelection = function(){return dojo.html.clearSelection.apply(dojo.html, arguments);}
	this.disableSelect = function(){return dojo.html.disableSelection.apply(dojo.html, arguments);}
	this.enableSelect = function(){return dojo.html.enableSelection.apply(dojo.html, arguments);}
	
	this.getInnerWidth = function(){return dojo.style.getInnerWidth.apply(dojo.style, arguments);}
	
	this.getOuterWidth = function(node){
		dojo.unimplemented("dojo.xml.htmlUtil.getOuterWidth");
	}

	this.getInnerHeight = function(){return dojo.style.getInnerHeight.apply(dojo.style, arguments);}

	this.getOuterHeight = function(node){
		dojo.unimplemented("dojo.xml.htmlUtil.getOuterHeight");
	}

	this.getTotalOffset = function(){return dojo.style.getTotalOffset.apply(dojo.style, arguments);}
	this.totalOffsetLeft = function(){return dojo.style.totalOffsetLeft.apply(dojo.style, arguments);}

	this.getAbsoluteX = this.totalOffsetLeft;

	this.totalOffsetTop = function(){return dojo.style.totalOffsetTop.apply(dojo.style, arguments);}
	
	this.getAbsoluteY = this.totalOffsetTop;

	this.getEventTarget = function(){return dojo.html.getEventTarget.apply(dojo.html, arguments);}
	this.getScrollTop = function() {return dojo.html.getScrollTop.apply(dojo.html, arguments);}
	this.getScrollLeft = function() {return dojo.html.getScrollLeft.apply(dojo.html, arguments);}

	this.evtTgt = this.getEventTarget;

	this.getParentOfType = function(){return dojo.html.getParentOfType.apply(dojo.html, arguments);}
	this.getAttribute = function(){return dojo.html.getAttribute.apply(dojo.html, arguments);}
	this.getAttr = function (node, attr) { // for backwards compat (may disappear!!!)
		dojo.deprecated("dojo.xml.htmlUtil.getAttr", "use dojo.xml.htmlUtil.getAttribute instead", "0.4");
		return dojo.xml.htmlUtil.getAttribute(node, attr);
	}
	this.hasAttribute = function(){return dojo.html.hasAttribute.apply(dojo.html, arguments);}

	this.hasAttr = function (node, attr) { // for backwards compat (may disappear!!!)
		dojo.deprecated("dojo.xml.htmlUtil.hasAttr", "use dojo.xml.htmlUtil.hasAttribute instead", "0.4");
		return dojo.xml.htmlUtil.hasAttribute(node, attr);
	}
	
	this.getClass = function(){return dojo.html.getClass.apply(dojo.html, arguments)}
	this.hasClass = function(){return dojo.html.hasClass.apply(dojo.html, arguments)}
	this.prependClass = function(){return dojo.html.prependClass.apply(dojo.html, arguments)}
	this.addClass = function(){return dojo.html.addClass.apply(dojo.html, arguments)}
	this.setClass = function(){return dojo.html.setClass.apply(dojo.html, arguments)}
	this.removeClass = function(){return dojo.html.removeClass.apply(dojo.html, arguments)}

	// Enum type for getElementsByClass classMatchType arg:
	this.classMatchType = {
		ContainsAll : 0, // all of the classes are part of the node's class (default)
		ContainsAny : 1, // any of the classes are part of the node's class
		IsOnly : 2 // only all of the classes are part of the node's class
	}

	this.getElementsByClass = function() {return dojo.html.getElementsByClass.apply(dojo.html, arguments)}
	this.getElementsByClassName = this.getElementsByClass;
	
	this.setOpacity = function() {return dojo.style.setOpacity.apply(dojo.style, arguments)}
	this.getOpacity = function() {return dojo.style.getOpacity.apply(dojo.style, arguments)}
	this.clearOpacity = function() {return dojo.style.clearOpacity.apply(dojo.style, arguments)}
	
	this.gravity = function(){return dojo.html.gravity.apply(dojo.html, arguments)}
	
	this.gravity.NORTH = 1;
	this.gravity.SOUTH = 1 << 1;
	this.gravity.EAST = 1 << 2;
	this.gravity.WEST = 1 << 3;
	
	this.overElement = function(){return dojo.html.overElement.apply(dojo.html, arguments)}

	this.insertCssRule = function(){return dojo.style.insertCssRule.apply(dojo.style, arguments)}
	
	this.insertCSSRule = function(selector, declaration, index){
		dojo.deprecated("dojo.xml.htmlUtil.insertCSSRule", "use dojo.style.insertCssRule instead", "0.4");
		return dojo.xml.htmlUtil.insertCssRule(selector, declaration, index);
	}
	
	this.removeCssRule = function(){return dojo.style.removeCssRule.apply(dojo.style, arguments)}

	this.removeCSSRule = function(index){
		dojo.deprecated("dojo.xml.htmlUtil.removeCSSRule", "use dojo.xml.htmlUtil.removeCssRule instead", "0.4");
		return dojo.xml.htmlUtil.removeCssRule(index);
	}

	this.insertCssFile = function(){return dojo.style.insertCssFile.apply(dojo.style, arguments)}

	this.insertCSSFile = function(URI, doc, checkDuplicates){
		dojo.deprecated("dojo.xml.htmlUtil.insertCSSFile", "use dojo.xml.htmlUtil.insertCssFile instead", "0.4");
		return dojo.xml.htmlUtil.insertCssFile(URI, doc, checkDuplicates);
	}

	this.getBackgroundColor = function() {return dojo.style.getBackgroundColor.apply(dojo.style, arguments)}

	this.getUniqueId = function() { return dojo.dom.getUniqueId(); }

	this.getStyle = function() {return dojo.style.getStyle.apply(dojo.style, arguments)}
}

__CPAN_FILE__ src/xml/Parse.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.xml.Parse");

dojo.require("dojo.dom");

//TODO: determine dependencies
// currently has dependency on dojo.xml.DomUtil nodeTypes constants...

/* generic method for taking a node and parsing it into an object

TODO: WARNING: This comment is wrong!

For example, the following xml fragment

<foo bar="bar">
	<baz xyzzy="xyzzy"/>
</foo>

can be described as:

dojo.???.foo = {}
dojo.???.foo.bar = {}
dojo.???.foo.bar.value = "bar";
dojo.???.foo.baz = {}
dojo.???.foo.baz.xyzzy = {}
dojo.???.foo.baz.xyzzy.value = "xyzzy"

*/
// using documentFragment nomenclature to generalize in case we don't want to require passing a collection of nodes with a single parent
dojo.xml.Parse = function(){

	function getDojoTagName (node) {
		var tagName = node.tagName;
		if (tagName.substr(0,5).toLowerCase() != "dojo:") {
			
			if (tagName.substr(0,4).toLowerCase() == "dojo") {
				// FIXME: this assuumes tag names are always lower case
				return "dojo:" + tagName.substring(4).toLowerCase();
			}
		
			// allow lower-casing
			var djt = node.getAttribute("dojoType") || node.getAttribute("dojotype");
			if (djt) { return "dojo:" + djt.toLowerCase(); }
			
			if (node.getAttributeNS && node.getAttributeNS(dojo.dom.dojoml,"type")) {
				return "dojo:" + node.getAttributeNS(dojo.dom.dojoml,"type").toLowerCase();
			}
			try {
				// FIXME: IE really really doesn't like this, so we squelch
				// errors for it
				djt = node.getAttribute("dojo:type");
			} catch (e) { /* FIXME: log? */ }

			if (djt) { return "dojo:"+djt.toLowerCase(); }
		
			if (!dj_global["djConfig"] || !djConfig["ignoreClassNames"]) {
				// FIXME: should we make this optionally enabled via djConfig?
				var classes = node.className||node.getAttribute("class");
				// FIXME: following line, without check for existence of classes.indexOf
				// breaks firefox 1.5's svg widgets
				if (classes && classes.indexOf && classes.indexOf("dojo-") != -1) {
					var aclasses = classes.split(" ");
					for(var x=0; x<aclasses.length; x++){
						if (aclasses[x].length > 5 && aclasses[x].indexOf("dojo-") >= 0) {
							return "dojo:"+aclasses[x].substr(5).toLowerCase();
						}
					}
				}
			}
		
		}
		return tagName.toLowerCase();
	}

	this.parseElement = function(node, hasParentNodeSet, optimizeForDojoML, thisIdx){

        // if parseWidgets="false" don't search inside this node for widgets
        if (node.getAttribute("parseWidgets") == "false") {
            return {};
        }

		// TODO: make this namespace aware
		var parsedNodeSet = {};

		var tagName = getDojoTagName(node);
		parsedNodeSet[tagName] = [];
		if((!optimizeForDojoML)||(tagName.substr(0,4).toLowerCase()=="dojo")){
			var attributeSet = parseAttributes(node);
			for(var attr in attributeSet){
				if((!parsedNodeSet[tagName][attr])||(typeof parsedNodeSet[tagName][attr] != "array")){
					parsedNodeSet[tagName][attr] = [];
				}
				parsedNodeSet[tagName][attr].push(attributeSet[attr]);
			}
	
			// FIXME: we might want to make this optional or provide cloning instead of
			// referencing, but for now, we include a node reference to allow
			// instantiated components to figure out their "roots"
			parsedNodeSet[tagName].nodeRef = node;
			parsedNodeSet.tagName = tagName;
			parsedNodeSet.index = thisIdx||0;
		}
	
		var count = 0;
		var tcn, i = 0, nodes = node.childNodes;
		while(tcn = nodes[i++]){
			switch(tcn.nodeType){
				case  dojo.dom.ELEMENT_NODE: // element nodes, call this function recursively
					count++;
					var ctn = getDojoTagName(tcn);
					if(!parsedNodeSet[ctn]){
						parsedNodeSet[ctn] = [];
					}
					parsedNodeSet[ctn].push(this.parseElement(tcn, true, optimizeForDojoML, count));
					if(	(tcn.childNodes.length == 1)&&
						(tcn.childNodes.item(0).nodeType == dojo.dom.TEXT_NODE)){
						parsedNodeSet[ctn][parsedNodeSet[ctn].length-1].value = tcn.childNodes.item(0).nodeValue;
					}
					break;
				case  dojo.dom.TEXT_NODE: // if a single text node is the child, treat it as an attribute
					if(node.childNodes.length == 1) {
						parsedNodeSet[tagName].push({ value: node.childNodes.item(0).nodeValue });
					}
					break;
				default: break;
				/*
				case  dojo.dom.ATTRIBUTE_NODE: // attribute node... not meaningful here
					break;
				case  dojo.dom.CDATA_SECTION_NODE: // cdata section... not sure if this would ever be meaningful... might be...
					break;
				case  dojo.dom.ENTITY_REFERENCE_NODE: // entity reference node... not meaningful here
					break;
				case  dojo.dom.ENTITY_NODE: // entity node... not sure if this would ever be meaningful
					break;
				case  dojo.dom.PROCESSING_INSTRUCTION_NODE: // processing instruction node... not meaningful here
					break;
				case  dojo.dom.COMMENT_NODE: // comment node... not not sure if this would ever be meaningful 
					break;
				case  dojo.dom.DOCUMENT_NODE: // document node... not sure if this would ever be meaningful
					break;
				case  dojo.dom.DOCUMENT_TYPE_NODE: // document type node... not meaningful here
					break;
				case  dojo.dom.DOCUMENT_FRAGMENT_NODE: // document fragment node... not meaningful here
					break;
				case  dojo.dom.NOTATION_NODE:// notation node... not meaningful here
					break;
				*/
			}
		}
		//return (hasParentNodeSet) ? parsedNodeSet[node.tagName] : parsedNodeSet;
		return parsedNodeSet;
	}

	/* parses a set of attributes on a node into an object tree */
	function parseAttributes(node) {
		// TODO: make this namespace aware
		var parsedAttributeSet = {};
		var atts = node.attributes;
		// TODO: should we allow for duplicate attributes at this point...
		// would any of the relevant dom implementations even allow this?
		var attnode, i=0;
		while(attnode=atts[i++]) {
			if((dojo.render.html.capable)&&(dojo.render.html.ie)){
				if(!attnode){ continue; }
				if(	(typeof attnode == "object")&&
					(typeof attnode.nodeValue == 'undefined')||
					(attnode.nodeValue == null)||
					(attnode.nodeValue == '')){ 
					continue; 
				}
			}
			var nn = (attnode.nodeName.indexOf("dojo:") == -1) ? attnode.nodeName : attnode.nodeName.split("dojo:")[1];
			parsedAttributeSet[nn] = { 
				value: attnode.nodeValue 
			};
		}
		return parsedAttributeSet;
	}
}

__CPAN_DIR__ src/text
__CPAN_FILE__ src/text/textDirectory.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.text.textDirectory");
dojo.provide("dojo.text.textDirectory.Property");
dojo.provide("dojo.text.textDirectory.tokenise");
dojo.require("dojo.string");

/* adapted from Paul Sowden's iCalendar work */

dojo.textDirectoryTokeniser = function () {}

/*
 * This class parses a single line from a text/directory file
 * and returns an object with four named values; name, group, params
 * and value. name, group and value are strings containing the original
 * tokens unaltered and values is an array containing name/value pairs
 * or a single name token packed into arrays.
 */
dojo.textDirectoryTokeniser.Property = function (line) {
	// split into name/value pair
	var left = dojo.string.trim(line.substring(0, line.indexOf(':')));
	var right = dojo.string.trim(line.substr(line.indexOf(':') + 1));

	// seperate name and paramters	
	var parameters = dojo.string.splitEscaped(left,';');
	this.name = parameters[0]
	parameters.splice(0, 1);

	// parse paramters
	this.params = [];
	for (var i = 0; i < parameters.length; i++) {
		var arr = parameters[i].split("=");
		var key = dojo.string.trim(arr[0].toUpperCase());
		
		if (arr.length == 1) { this.params.push([key]); continue; }
		
		var values = dojo.string.splitEscaped(arr[1],',');
		for (var j = 0; j < values.length; j++) {
			if (dojo.string.trim(values[j]) != '') {
				this.params.push([key, dojo.string.trim(values[j])]);
			}
		}
	}

	// seperate group
	if (this.name.indexOf('.') > 0) {
		var arr = this.name.split('.');
		this.group = arr[0];
		this.name = arr[1];
	}
	
	// don't do any parsing, leave to implementation
	this.value = right;
}


// tokeniser, parses into an array of properties.
dojo.textDirectoryTokeniser.tokenise = function (text) {
	// normlize to one propterty per line and parse
	var nText = dojo.string.normalizeNewlines(text,"\n");
	nText = nText.replace(/\n[ \t]/g, '');
	nText = nText.replace(/\x00/g, '');
		
	var lines = nText.split("\n");
	var properties = []

	for (var i = 0; i < lines.length; i++) {
		if (dojo.string.trim(lines[i]) == '') { continue; }
		var prop = new dojo.textDirectoryTokeniser.Property(lines[i]);
		properties.push(prop);
	}
	return properties;
}

__CPAN_FILE__ src/text/Builder.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.text.Builder");
dojo.require("dojo.string.Builder");

dojo.deprecated("dojo.text.Builder", "use dojo.string.Builder instead", "0.4");

dojo.text.Builder = dojo.string.Builder;

__CPAN_FILE__ src/text/Text.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.deprecated("dojo.text.Text", "replaced by dojo.string", "0.4");
dojo.require("dojo.string");

dojo.text = dojo.string;
dojo.provide("dojo.text.Text");

__CPAN_FILE__ src/text/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: [
		"dojo.text.String",
		"dojo.text.Builder"
	]
});
dojo.provide("dojo.text.*");

__CPAN_FILE__ src/text/String.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.deprecated("dojo.text.String", "replaced by dojo.string", "0.4");
dojo.require("dojo.string");

dojo.text = dojo.string;
dojo.provide("dojo.text.String");

__CPAN_DIR__ src/logging
__CPAN_FILE__ src/logging/Logger.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/*		This is the dojo logging facility, which is imported from nWidgets
		(written by Alex Russell, CLA on file), which is patterned on the
		Python logging module, which in turn has been heavily influenced by
		log4j (execpt with some more pythonic choices, which we adopt as well).

		While the dojo logging facilities do provide a set of familiar
		interfaces, many of the details are changed to reflect the constraints
		of the browser environment. Mainly, file and syslog-style logging
		facilites are not provided, with HTTP POST and GET requests being the
		only ways of getting data from the browser back to a server. Minimal
		support for this (and XML serialization of logs) is provided, but may
		not be of practical use in a deployment environment.

		The Dojo logging classes are agnostic of any environment, and while
		default loggers are provided for browser-based interpreter
		environments, this file and the classes it define are explicitly
		designed to be portable to command-line interpreters and other
		ECMA-262v3 envrionments.

	the logger needs to accomidate:
		log "levels"
		type identifiers
		file?
		message
		tic/toc?

	The logger should ALWAYS record:
		time/date logged
		message
		type
		level
*/
// TODO: conver documentation to javadoc style once we confirm that is our choice
// TODO: define DTD for XML-formatted log messages
// TODO: write XML Formatter class
// TODO: write HTTP Handler which uses POST to send log lines/sections

// Filename:	LogCore.js
// Purpose:		a common logging infrastructure for dojo
// Classes:		dojo.logging, dojo.logging.Logger, dojo.logging.Record, dojo.logging.LogFilter
// Global Objects:	dojo.logging
// Dependencies:	none

dojo.provide("dojo.logging.Logger");
dojo.provide("dojo.log");
dojo.require("dojo.lang");

/*
	A simple data structure class that stores information for and about
	a logged event. Objects of this type are created automatically when
	an event is logged and are the internal format in which information
	about log events is kept.
*/

dojo.logging.Record = function(lvl, msg){
	this.level = lvl;
	this.message = msg;
	this.time = new Date();
	// FIXME: what other information can we receive/discover here?
}

// an empty parent (abstract) class which concrete filters should inherit from.
dojo.logging.LogFilter = function(loggerChain){
	this.passChain = loggerChain || "";
	this.filter = function(record){
		// FIXME: need to figure out a way to enforce the loggerChain
		// restriction
		return true; // pass all records
	}
}

dojo.logging.Logger = function(){
	this.cutOffLevel = 0;
	this.propagate = true;
	this.parent = null;
	// storage for dojo.logging.Record objects seen and accepted by this logger
	this.data = [];
	this.filters = [];
	this.handlers = [];
}

dojo.lang.extend(dojo.logging.Logger, {
	argsToArr: function(args){
		// utility function, reproduced from __util__ here to remove dependency
		var ret = [];
		for(var x=0; x<args.length; x++){
			ret.push(args[x]);
		}
		return ret;
	},

	setLevel: function(lvl){
		this.cutOffLevel = parseInt(lvl);
	},

	isEnabledFor: function(lvl){
		return parseInt(lvl) >= this.cutOffLevel;
	},

	getEffectiveLevel: function(){
		if((this.cutOffLevel==0)&&(this.parent)){
			return this.parent.getEffectiveLevel();
		}
		return this.cutOffLevel;
	},

	addFilter: function(flt){
		this.filters.push(flt);
		return this.filters.length-1;
	},

	removeFilterByIndex: function(fltIndex){
		if(this.filters[fltIndex]){
			delete this.filters[fltIndex];
			return true;
		}
		return false;
	},

	removeFilter: function(fltRef){
		for(var x=0; x<this.filters.length; x++){
			if(this.filters[x]===fltRef){
				delete this.filters[x];
				return true;
			}
		}
		return false;
	},

	removeAllFilters: function(){
		this.filters = []; // clobber all of them
	},

	filter: function(rec){
		for(var x=0; x<this.filters.length; x++){
			if((this.filters[x]["filter"])&&
			   (!this.filters[x].filter(rec))||
			   (rec.level<this.cutOffLevel)){
				return false;
			}
		}
		return true;
	},

	addHandler: function(hdlr){
		this.handlers.push(hdlr);
		return this.handlers.length-1;
	},

	handle: function(rec){
		if((!this.filter(rec))||(rec.level<this.cutOffLevel)){ return false; }
		for(var x=0; x<this.handlers.length; x++){
			if(this.handlers[x]["handle"]){
			   this.handlers[x].handle(rec);
			}
		}
		// FIXME: not sure what to do about records to be propagated that may have
		// been modified by the handlers or the filters at this logger. Should
		// parents always have pristine copies? or is passing the modified record
		// OK?
		// if((this.propagate)&&(this.parent)){ this.parent.handle(rec); }
		return true;
	},

	// the heart and soul of the logging system
	log: function(lvl, msg){
		if(	(this.propagate)&&(this.parent)&&
			(this.parent.rec.level>=this.cutOffLevel)){
			this.parent.log(lvl, msg);
			return false;
		}
		// FIXME: need to call logging providers here!
		this.handle(new dojo.logging.Record(lvl, msg));
		return true;
	},

	// logger helpers
	debug:function(msg){
		return this.logType("DEBUG", this.argsToArr(arguments));
	},

	info: function(msg){
		return this.logType("INFO", this.argsToArr(arguments));
	},

	warning: function(msg){
		return this.logType("WARNING", this.argsToArr(arguments));
	},

	error: function(msg){
		return this.logType("ERROR", this.argsToArr(arguments));
	},

	critical: function(msg){
		return this.logType("CRITICAL", this.argsToArr(arguments));
	},

	exception: function(msg, e, squelch){
		// FIXME: this needs to be modified to put the exception in the msg
		// if we're on Moz, we can get the following from the exception object:
		//		lineNumber
		//		message
		//		fileName
		//		stack
		//		name
		// on IE, we get:
		//		name
		//		message (from MDA?)
		//		number
		//		description (same as message!)
		if(e){
			var eparts = [e.name, (e.description||e.message)];
			if(e.fileName){
				eparts.push(e.fileName);
				eparts.push("line "+e.lineNumber);
				// eparts.push(e.stack);
			}
			msg += " "+eparts.join(" : ");
		}

		this.logType("ERROR", msg);
		if(!squelch){
			throw e;
		}
	},

	logType: function(type, args){
		var na = [dojo.logging.log.getLevel(type)];
		if(typeof args == "array"){
			na = na.concat(args);
		}else if((typeof args == "object")&&(args["length"])){
			na = na.concat(this.argsToArr(args));
			/* for(var x=0; x<args.length; x++){
				na.push(args[x]);
			} */
		}else{
			na = na.concat(this.argsToArr(arguments).slice(1));
			/* for(var x=1; x<arguments.length; x++){
				na.push(arguments[x]);
			} */
		}
		return this.log.apply(this, na);
	}
});

void(function(){
	var ptype = dojo.logging.Logger.prototype;
	ptype.warn = ptype.warning;
	ptype.err = ptype.error;
	ptype.crit = ptype.critical;
})();

// the Handler class
dojo.logging.LogHandler = function(level){
	this.cutOffLevel = (level) ? level : 0;
	this.formatter = null; // FIXME: default formatter?
	this.data = [];
	this.filters = [];
}

dojo.logging.LogHandler.prototype.setFormatter = function(fmtr){
	// FIXME: need to vet that it is indeed a formatter object
	dojo.unimplemented("setFormatter");
}

dojo.logging.LogHandler.prototype.flush = function(){
	dojo.unimplemented("flush");
}

dojo.logging.LogHandler.prototype.close = function(){
	dojo.unimplemented("close");
}

dojo.logging.LogHandler.prototype.handleError = function(){
	dojo.unimplemented("handleError");
}

dojo.logging.LogHandler.prototype.handle = function(record){
	// emits the passed record if it passes this object's filters
	if((this.filter(record))&&(record.level>=this.cutOffLevel)){
		this.emit(record);
	}
}

dojo.logging.LogHandler.prototype.emit = function(record){
	// do whatever is necessaray to actually log the record
	dojo.unimplemented("emit");
}

// set aliases since we don't want to inherit from dojo.logging.Logger
void(function(){ // begin globals protection closure
	var names = [
		"setLevel", "addFilter", "removeFilterByIndex", "removeFilter",
		"removeAllFilters", "filter"
	];
	var tgt = dojo.logging.LogHandler.prototype;
	var src = dojo.logging.Logger.prototype;
	for(var x=0; x<names.length; x++){
		tgt[names[x]] = src[names[x]];
	}
})(); // end globals protection closure

dojo.logging.log = new dojo.logging.Logger();

// an associative array of logger objects. This object inherits from
// a list of level names with their associated numeric levels
dojo.logging.log.levels = [ {"name": "DEBUG", "level": 1},
						   {"name": "INFO", "level": 2},
						   {"name": "WARNING", "level": 3},
						   {"name": "ERROR", "level": 4},
						   {"name": "CRITICAL", "level": 5} ];

dojo.logging.log.loggers = {};

dojo.logging.log.getLogger = function(name){
	if(!this.loggers[name]){
		this.loggers[name] = new dojo.logging.Logger();
		this.loggers[name].parent = this;
	}
	return this.loggers[name];
}

dojo.logging.log.getLevelName = function(lvl){
	for(var x=0; x<this.levels.length; x++){
		if(this.levels[x].level == lvl){
			return this.levels[x].name;
		}
	}
	return null;
}

dojo.logging.log.addLevelName = function(name, lvl){
	if(this.getLevelName(name)){
		this.err("could not add log level "+name+" because a level with that name already exists");
		return false;
	}
	this.levels.append({"name": name, "level": parseInt(lvl)});
	return true;
}

dojo.logging.log.getLevel = function(name){
	for(var x=0; x<this.levels.length; x++){
		if(this.levels[x].name.toUpperCase() == name.toUpperCase()){
			return this.levels[x].level;
		}
	}
	return null;
}

// a default handler class, it simply saves all of the handle()'d records in
// memory. Useful for attaching to with dojo.event.connect()
dojo.logging.MemoryLogHandler = function(level, recordsToKeep, postType, postInterval){
	// mixin style inheritance
	dojo.logging.LogHandler.call(this, level);
	// default is unlimited
	this.numRecords = (typeof djConfig['loggingNumRecords'] != 'undefined') ? djConfig['loggingNumRecords'] : ((recordsToKeep) ? recordsToKeep : -1);
	// 0=count, 1=time, -1=don't post TODO: move this to a better location for prefs
	this.postType = (typeof djConfig['loggingPostType'] != 'undefined') ? djConfig['loggingPostType'] : ( postType || -1);
	// milliseconds for time, interger for number of records, -1 for non-posting,
	this.postInterval = (typeof djConfig['loggingPostInterval'] != 'undefined') ? djConfig['loggingPostInterval'] : ( postType || -1);
	
}
// prototype inheritance
dojo.logging.MemoryLogHandler.prototype = new dojo.logging.LogHandler();

// FIXME
// dojo.inherits(dojo.logging.MemoryLogHandler, 

// over-ride base-class
dojo.logging.MemoryLogHandler.prototype.emit = function(record){
	this.data.push(record);
	if(this.numRecords != -1){
		while(this.data.length>this.numRecords){
			this.data.shift();
		}
	}
}

dojo.logging.logQueueHandler = new dojo.logging.MemoryLogHandler(0,50,0,10000);
// actual logging event handler
dojo.logging.logQueueHandler.emit = function(record){
	// we should probably abstract this in the future
	var logStr = String(dojo.log.getLevelName(record.level)+": "+record.time.toLocaleTimeString())+": "+record.message;
	if(!dj_undef("debug", dj_global)){
		dojo.debug(logStr);
	}else if((typeof dj_global["print"] == "function")&&(!dojo.render.html.capable)){
		print(logStr);
	}
	this.data.push(record);
	if(this.numRecords != -1){
		while(this.data.length>this.numRecords){
			this.data.shift();
		}
	}
}

dojo.logging.log.addHandler(dojo.logging.logQueueHandler);
dojo.log = dojo.logging.log;

__CPAN_FILE__ src/logging/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: ["dojo.logging.Logger", false, false],
	rhino: ["dojo.logging.RhinoLogger"]
});
dojo.provide("dojo.logging.*");

__CPAN_DIR__ src/uuid
__CPAN_FILE__ src/uuid/NameBasedGenerator.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.uuid.NameBasedGenerator");

dojo.uuid.NameBasedGenerator = new function() {

/**
 * This function generates name-based UUIDs, meaning "version 3" 
 * and "version 5" UUIDs.
 *
 * Examples:
 * <pre>
 *   var string = dojo.uuid.NameBasedGenerator.generate();
 *   var string = dojo.uuid.NameBasedGenerator.generate(String);
 *   var uuid   = dojo.uuid.NameBasedGenerator.generate(dojo.uuid.Uuid);
 * </pre>
 *
 * @param	returnType	Optional. The type of instance to return.
 * @return	A newly generated version 3 or version 5 UUID.
 */
	this.generate = function(returnType) {
		dojo.unimplemented('dojo.uuid.NameBasedGenerator.generate');
		
		// FIXME:
		// For an algorithm to generate name-based UUIDs, 
		// see sections 4.3 of RFC 4122:
		//  http://www.ietf.org/rfc/rfc4122.txt
		
		var returnValue = "00000000-0000-0000-0000-000000000000"; // FIXME
		if (returnType && (returnType != String)) {
			returnValue = new returnType(returnValue);
		}
		return returnValue;
	};
}();
__CPAN_FILE__ src/uuid/TimeBasedGenerator.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.uuid.TimeBasedGenerator");
dojo.require("dojo.lang.*");

dojo.uuid.TimeBasedGenerator = new function() {

// --------------------------------------------------
// Public constants
// --------------------------------------------------
	// Number of hours between October 15, 1582 and January 1, 1970:
	this.GREGORIAN_CHANGE_OFFSET_IN_HOURS = 3394248;
	
	// Number of seconds between October 15, 1582 and January 1, 1970:
	//   this.GREGORIAN_CHANGE_OFFSET_IN_SECONDS = 12219292800;	
	
// --------------------------------------------------
// Private variables
// --------------------------------------------------
	var _uuidPseudoNodeString = null;
	var _uuidClockSeqString = null;
	var _dateValueOfPreviousUuid = null;
	var _nextIntraMillisecondIncrement = 0;
	var _cachedMillisecondsBetween1582and1970 = null;
	var _cachedHundredNanosecondIntervalsPerMillisecond = null;
	var _uniformNode = null;
	var HEX_RADIX = 16;

// --------------------------------------------------
// Private functions
// --------------------------------------------------

/**
 * Given an array which holds a 64-bit number broken into 4 16-bit elements,
 * this method carries any excess bits (greater than 16-bits) from each array
 * element into the next.
 *
 * @param	arrayA	An array with 4 elements, each of which is a 16-bit number.
 */
	function _carry(arrayA) {
		arrayA[2] += arrayA[3] >>> 16;
		arrayA[3] &= 0xFFFF;
		arrayA[1] += arrayA[2] >>> 16;
		arrayA[2] &= 0xFFFF;
		arrayA[0] += arrayA[1] >>> 16;
		arrayA[1] &= 0xFFFF;
		dojo.lang.assert((arrayA[0] >>> 16) === 0);
	}

/**
 * Given a floating point number, this method returns an array which holds a
 * 64-bit number broken into 4 16-bit elements.
 *
 * @param	x	A floating point number.
 * @return   An array with 4 elements, each of which is a 16-bit number.
 */
	function _get64bitArrayFromFloat(x) {
		var result = new Array(0, 0, 0, 0);
		result[3] = x % 0x10000;
		x -= result[3];
		x /= 0x10000;
		result[2] = x % 0x10000;
		x -= result[2];
		x /= 0x10000;
		result[1] = x % 0x10000;
		x -= result[1];
		x /= 0x10000;
		result[0] = x;
		return result;
	}

/**
 * Takes two arrays, each of which holds a 64-bit number broken into 4
 * 16-bit elements, and returns a new array that holds a 64-bit number
 * that is the sum of the two original numbers.
 *
 * @param	arrayA	An array with 4 elements, each of which is a 16-bit number.
 * @param	arrayB	An array with 4 elements, each of which is a 16-bit number.
 * @return   An array with 4 elements, each of which is a 16-bit number.
 */
	function _addTwo64bitArrays(arrayA, arrayB) {
		dojo.lang.assertType(arrayA, Array);
		dojo.lang.assertType(arrayB, Array);
		dojo.lang.assert(arrayA.length == 4);
		dojo.lang.assert(arrayB.length == 4);
	
		var result = new Array(0, 0, 0, 0);
		result[3] = arrayA[3] + arrayB[3];
		result[2] = arrayA[2] + arrayB[2];
		result[1] = arrayA[1] + arrayB[1];
		result[0] = arrayA[0] + arrayB[0];
		_carry(result);
		return result;
	}

/**
 * Takes two arrays, each of which holds a 64-bit number broken into 4
 * 16-bit elements, and returns a new array that holds a 64-bit number
 * that is the product of the two original numbers.
 *
 * @param	arrayA	An array with 4 elements, each of which is a 16-bit number.
 * @param	arrayB	An array with 4 elements, each of which is a 16-bit number.
 * @return   An array with 4 elements, each of which is a 16-bit number.
 */
	function _multiplyTwo64bitArrays(arrayA, arrayB) {
		dojo.lang.assertType(arrayA, Array);
		dojo.lang.assertType(arrayB, Array);
		dojo.lang.assert(arrayA.length == 4);
		dojo.lang.assert(arrayB.length == 4);
	
		var overflow = false;
		if (arrayA[0] * arrayB[0] !== 0) { overflow = true; }
		if (arrayA[0] * arrayB[1] !== 0) { overflow = true; }
		if (arrayA[0] * arrayB[2] !== 0) { overflow = true; }
		if (arrayA[1] * arrayB[0] !== 0) { overflow = true; }
		if (arrayA[1] * arrayB[1] !== 0) { overflow = true; }
		if (arrayA[2] * arrayB[0] !== 0) { overflow = true; }
		dojo.lang.assert(!overflow);
	
		var result = new Array(0, 0, 0, 0);
		result[0] += arrayA[0] * arrayB[3];
		_carry(result);
		result[0] += arrayA[1] * arrayB[2];
		_carry(result);
		result[0] += arrayA[2] * arrayB[1];
		_carry(result);
		result[0] += arrayA[3] * arrayB[0];
		_carry(result);
		result[1] += arrayA[1] * arrayB[3];
		_carry(result);
		result[1] += arrayA[2] * arrayB[2];
		_carry(result);
		result[1] += arrayA[3] * arrayB[1];
		_carry(result);
		result[2] += arrayA[2] * arrayB[3];
		_carry(result);
		result[2] += arrayA[3] * arrayB[2];
		_carry(result);
		result[3] += arrayA[3] * arrayB[3];
		_carry(result);
		return result;
	}

/**
 * Pads a string with leading zeros and returns the result.
 * For example:
 * <pre>
 *   result = _padWithLeadingZeros("abc", 6);
 *   dojo.lang.assert(result == "000abc");
 * </pre>
 *
 * @param	string	A string to add padding to.
 * @param	desiredLength	The number of characters the return string should have.
 * @return   A string.
 */
	function _padWithLeadingZeros(string, desiredLength) {
		while (string.length < desiredLength) {
			string = "0" + string;
		}
		return string;
	}

/**
 * Returns a randomly generated 8-character string of hex digits.
 *
 * @return   An 8-character hex string.
 */
	function _generateRandomEightCharacterHexString() {
		// FIXME: This probably isn't a very high quality random number.
	
		// Make random32bitNumber be a randomly generated floating point number
		// between 0 and (4,294,967,296 - 1), inclusive.
		var random32bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 32) );
	
		var eightCharacterString = random32bitNumber.toString(HEX_RADIX);
		while (eightCharacterString.length < 8) {
			eightCharacterString = "0" + eightCharacterString;
		}
		return eightCharacterString;
	}

/**
 * Generates a time-based UUID, meaning a version 1 UUID.  JavaScript
 * code running in a browser doesn't have access to the IEEE 802.3 address
 * of the computer, so if a node value isn't supplied, we generate a random 
 * pseudonode value instead.
 *
 * @param	node	Optional. A 12-character string to use as the node in the new UUID.
 * @return   Returns a 36 character string, which will look something like "b4308fb0-86cd-11da-a72b-0800200c9a66".
 */
	function _generateUuidString(node) {
		dojo.lang.assertType(node, [String, "optional"]);
		if (node) {
			dojo.lang.assert(node.length == 12);
		} else {
			if (_uniformNode) {
				node = _uniformNode;
			} else {
				if (!_uuidPseudoNodeString) {
					var pseudoNodeIndicatorBit = 0x8000;
					var random15bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 15) );
					var leftmost4HexCharacters = (pseudoNodeIndicatorBit | random15bitNumber).toString(HEX_RADIX);
					_uuidPseudoNodeString = leftmost4HexCharacters + _generateRandomEightCharacterHexString();
				}
				node = _uuidPseudoNodeString;
			}
		}
		if (!_uuidClockSeqString) {
			var variantCodeForDCEUuids = 0x8000; // 10--------------, i.e. uses only first two of 16 bits.
			var random14bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 14) );
			_uuidClockSeqString = (variantCodeForDCEUuids | random14bitNumber).toString(HEX_RADIX);
		}
	
		// Maybe we should think about trying to make the code more readable to
		// newcomers by creating a class called "WholeNumber" that encapsulates
		// the methods and data structures for working with these arrays that
		// hold 4 16-bit numbers?  And then these variables below have names
		// like "wholeSecondsPerHour" rather than "arraySecondsPerHour"?
		var now = new Date();
		var millisecondsSince1970 = now.valueOf(); // milliseconds since midnight 01 January, 1970 UTC.
		var nowArray = _get64bitArrayFromFloat(millisecondsSince1970);
		if (!_cachedMillisecondsBetween1582and1970) {
			var arraySecondsPerHour = _get64bitArrayFromFloat(60 * 60);
			var arrayHoursBetween1582and1970 = _get64bitArrayFromFloat(dojo.uuid.TimeBasedGenerator.GREGORIAN_CHANGE_OFFSET_IN_HOURS);
			var arraySecondsBetween1582and1970 = _multiplyTwo64bitArrays(arrayHoursBetween1582and1970, arraySecondsPerHour);
			var arrayMillisecondsPerSecond = _get64bitArrayFromFloat(1000);
			_cachedMillisecondsBetween1582and1970 = _multiplyTwo64bitArrays(arraySecondsBetween1582and1970, arrayMillisecondsPerSecond);
			_cachedHundredNanosecondIntervalsPerMillisecond = _get64bitArrayFromFloat(10000);
		}
		var arrayMillisecondsSince1970 = nowArray;
		var arrayMillisecondsSince1582 = _addTwo64bitArrays(_cachedMillisecondsBetween1582and1970, arrayMillisecondsSince1970);
		var arrayHundredNanosecondIntervalsSince1582 = _multiplyTwo64bitArrays(arrayMillisecondsSince1582, _cachedHundredNanosecondIntervalsPerMillisecond);
	
		if (now.valueOf() == _dateValueOfPreviousUuid) {
			arrayHundredNanosecondIntervalsSince1582[3] += _nextIntraMillisecondIncrement;
			_carry(arrayHundredNanosecondIntervalsSince1582);
			_nextIntraMillisecondIncrement += 1;
			if (_nextIntraMillisecondIncrement == 10000) {
				// If we've gotten to here, it means we've already generated 10,000
				// UUIDs in this single millisecond, which is the most that the UUID
				// timestamp field allows for.  So now we'll just sit here and wait
				// for a fraction of a millisecond, so as to ensure that the next
				// time this method is called there will be a different millisecond
				// value in the timestamp field.
				while (now.valueOf() == _dateValueOfPreviousUuid) {
					now = new Date();
				}
			}
		} else {
			_dateValueOfPreviousUuid = now.valueOf();
			_nextIntraMillisecondIncrement = 1;
		}
	
		var hexTimeLowLeftHalf  = arrayHundredNanosecondIntervalsSince1582[2].toString(HEX_RADIX);
		var hexTimeLowRightHalf = arrayHundredNanosecondIntervalsSince1582[3].toString(HEX_RADIX);
		var hexTimeLow = _padWithLeadingZeros(hexTimeLowLeftHalf, 4) + _padWithLeadingZeros(hexTimeLowRightHalf, 4);
		var hexTimeMid = arrayHundredNanosecondIntervalsSince1582[1].toString(HEX_RADIX);
		hexTimeMid = _padWithLeadingZeros(hexTimeMid, 4);
		var hexTimeHigh = arrayHundredNanosecondIntervalsSince1582[0].toString(HEX_RADIX);
		hexTimeHigh = _padWithLeadingZeros(hexTimeHigh, 3);
		var hyphen = "-";
		var versionCodeForTimeBasedUuids = "1"; // binary2hex("0001")
		var resultUuid = hexTimeLow + hyphen + hexTimeMid + hyphen +
					versionCodeForTimeBasedUuids + hexTimeHigh + hyphen +
					_uuidClockSeqString + hyphen + node;
		resultUuid = resultUuid.toLowerCase();
		return resultUuid;
	}

// --------------------------------------------------
// Public functions
// --------------------------------------------------

/**
 * Sets the 'node' value that will be included in generated UUIDs.
 *
 * @param	node	A 12-character hex string representing a pseudoNode or hardwareNode.
 */
	this.setNode = function(node) {
		dojo.lang.assert((node === null) || (node.length == 12));
		_uniformNode = node;
	};

/**
 * Returns the 'node' value that will be included in generated UUIDs.
 *
 * @return	A 12-character hex string representing a pseudoNode or hardwareNode.
 */
	this.getNode = function() {
		return _uniformNode;
	};

/**
 * This function generates time-based UUIDs, meaning "version 1" UUIDs.
 *
 * For more info, see
 *   http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt
 *   http://www.infonuovo.com/dma/csdocs/sketch/instidid.htm
 *   http://kruithof.xs4all.nl/uuid/uuidgen
 *   http://www.opengroup.org/onlinepubs/009629399/apdxa.htm#tagcjh_20
 *   http://jakarta.apache.org/commons/sandbox/id/apidocs/org/apache/commons/id/uuid/clock/Clock.html
 *
 * Examples:
 * <pre>
 *   var generate = dojo.uuid.TimeBasedGenerator.generate;
 *   var uuid;   // an instance of dojo.uuid.Uuid
 *   var string; // a simple string literal
 *   string = generate();
 *   string = generate(String);
 *   uuid   = generate(dojo.uuid.Uuid);
 *   string = generate("017bf397618a");
 *   string = generate({node: "017bf397618a"});         // hardwareNode
 *   string = generate({node: "f17bf397618a"});         // pseudoNode
 *   string = generate({hardwareNode: "017bf397618a"});
 *   string = generate({pseudoNode:   "f17bf397618a"});
 *   string = generate({node: "017bf397618a", returnType: String});
 *   uuid   = generate({node: "017bf397618a", returnType: dojo.uuid.Uuid});
 *   dojo.uuid.TimeBasedGenerator.setNode("017bf397618a");
 *   string = generate(); // the generated UUID has node == "017bf397618a"
 *   uuid   = generate(dojo.uuid.Uuid); // the generated UUID has node == "017bf397618a"
 * </pre>
 *
 * @param	class	The type of instance to return.
 * @param	node	A 12-character hex string representing a pseudoNode or hardwareNode.
 * @namedParam	node	A 12-character hex string representing a pseudoNode or hardwareNode.
 * @namedParam	hardwareNode	A 12-character hex string containing an IEEE 802.3 network node identificator.
 * @namedParam	pseudoNode	A 12-character hex string representing a pseudoNode.
 * @namedParam	returnType	The type of instance to return.
 * @return	A newly generated version 1 UUID.
 */
	this.generate = function(input) {
		var nodeString = null;
		var returnType = null;
		
		if (input) {
			if (dojo.lang.isObject(input) && !dojo.lang.isBuiltIn(input)) {
				var namedParameters = input;
				dojo.lang.assertValidKeywords(namedParameters, ["node", "hardwareNode", "pseudoNode", "returnType"]);
				var node = namedParameters["node"];
				var hardwareNode = namedParameters["hardwareNode"];
				var pseudoNode = namedParameters["pseudoNode"];
				nodeString = (node || pseudoNode || hardwareNode);
				if (nodeString) {
					var firstCharacter = nodeString.charAt(0);
					var firstDigit = parseInt(firstCharacter, HEX_RADIX);
					if (hardwareNode) {
						dojo.lang.assert((firstDigit >= 0x0) && (firstDigit <= 0x7));
					}
					if (pseudoNode) {
						dojo.lang.assert((firstDigit >= 0x8) && (firstDigit <= 0xF));
					}
				}
				returnType = namedParameters["returnType"];
				dojo.lang.assertType(returnType, [Function, "optional"]);
			} else {
				if (dojo.lang.isString(input)) {
					nodeString = input;
					returnType = null;
				} else {
					if (dojo.lang.isFunction(input)) {
						nodeString = null;
						returnType = input;
					}
				}
			}
			if (nodeString) {
				dojo.lang.assert(nodeString.length == 12);
				var integer = parseInt(nodeString, HEX_RADIX);
				dojo.lang.assert(isFinite(integer));
			}
			dojo.lang.assertType(returnType, [Function, "optional"]);
		}
		
		var uuidString = _generateUuidString(nodeString);
		var returnValue;
		if (returnType && (returnType != String)) {
			returnValue = new returnType(uuidString);
		} else {
			returnValue = uuidString;
		}
		return returnValue;
	};
}();

__CPAN_FILE__ src/uuid/Uuid.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.uuid.Uuid");
dojo.require("dojo.lang.*");

// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
/**
 * The Uuid class offers methods for inspecting existing UUIDs.
 *
 * Examples:
 * <pre>
 *   var uuid;
 *   uuid = new dojo.uuid.Uuid("3b12f1df-5232-4804-897e-917bf397618a");
 *   uuid = new dojo.uuid.Uuid(); // "00000000-0000-0000-0000-000000000000"
 *   uuid = new dojo.uuid.Uuid(dojo.uuid.RandomGenerator);
 *   uuid = new dojo.uuid.Uuid(dojo.uuid.TimeBasedGenerator);
 *
 *   dojo.uuid.Uuid.setGenerator(dojo.uuid.RandomGenerator);
 *   uuid = new dojo.uuid.Uuid();
 *   dojo.lang.assert(!uuid.isEqual(dojo.uuid.Uuid.NIL_UUID));
 * </pre>
 *
 * @scope	public instance constructor
 * @param	uuidString	A 36-character string that conforms to the UUID spec.
 * @param	generator	A UUID generator, such as dojo.uuid.TimeBasedGenerator.
 */
dojo.uuid.Uuid = function(input) {
	this._uuidString = dojo.uuid.Uuid.NIL_UUID;
	if (input) {
		if (dojo.lang.isString(input)) {
			this._uuidString = input.toLowerCase();
			dojo.lang.assert(this.isValid());
		} else {
			if (dojo.lang.isObject(input) && input.generate) {
				var generator = input;
				this._uuidString = generator.generate();
				dojo.lang.assert(this.isValid());
			} else {
				// we got passed something other than a string
				dojo.lang.assert(false, "The dojo.uuid.Uuid() constructor must be initializated with a UUID string.");
			}
		}
	} else {
		var ourGenerator = dojo.uuid.Uuid.getGenerator();
		if (ourGenerator) {
			this._uuidString = ourGenerator.generate();
			dojo.lang.assert(this.isValid());
		}
	}
};

// -------------------------------------------------------------------
// Public constants
// -------------------------------------------------------------------
dojo.uuid.Uuid.NIL_UUID = "00000000-0000-0000-0000-000000000000";
dojo.uuid.Uuid.Version = {
	UNKNOWN: 0,
	TIME_BASED: 1,
	DCE_SECURITY: 2,
	NAME_BASED_MD5: 3,
	RANDOM: 4,
	NAME_BASED_SHA1: 5 };
dojo.uuid.Uuid.Variant = {
	NCS: "0",
	DCE: "10",
	MICROSOFT: "110",
	UNKNOWN: "111" };
dojo.uuid.Uuid.HEX_RADIX = 16;

// -------------------------------------------------------------------
// Public class methods
// -------------------------------------------------------------------
/**
 * Given two UUIDs to compare, this method returns 0, 1, or -1.
 * This method is designed to be used by sorting routines, like
 * the JavaScript built-in Array sort() method.
 * This implementation is intended to match the sample 
 * implementation in IETF RFC 4122: 
 * http://www.ietf.org/rfc/rfc4122.txt
 * 
 * Example:
 * <pre>
 *   var generator = dojo.uuid.TimeBasedGenerator;
 *   var a = new dojo.uuid.Uuid(generator);
 *   var b = new dojo.uuid.Uuid(generator);
 *   var c = new dojo.uuid.Uuid(generator);
 *   var array = new Array(a, b, c);
 *   array.sort(dojo.uuid.Uuid.compare);
 * </pre>
 *
 * @param	uuidOne	A dojo.uuid.Uuid instance, or a string representing a UUID.
 * @param	uuidTwo	A dojo.uuid.Uuid instance, or a string representing a UUID.
 * @return   Returns either 0, 1, or -1.
 */
dojo.uuid.Uuid.compare = function(uuidOne, uuidTwo) {
	var uuidStringOne = uuidOne.toString();
	var uuidStringTwo = uuidTwo.toString();
	if (uuidStringOne > uuidStringTwo) return 1;
	if (uuidStringOne < uuidStringTwo) return -1;
	return 0;
};

/**
 * Sets the default generator, which will be used by the 
 * "new dojo.uuid.Uuid()" constructor if no parameters
 * are passed in.
 *
 * @param	generator	A UUID generator, such as dojo.uuid.TimeBasedGenerator.
 * @return   Returns true or false. True if this UUID is equal to the otherUuid.
 */
dojo.uuid.Uuid.setGenerator = function(generator) {
	dojo.lang.assert(!generator || (dojo.lang.isObject(generator) && generator.generate));
	dojo.uuid.Uuid._ourGenerator = generator;
};

/**
 * Returns the default generator.  See setGenerator().
 *
 * @return   A UUID generator, such as dojo.uuid.TimeBasedGenerator.
 */
dojo.uuid.Uuid.getGenerator = function(generator) {
	return dojo.uuid.Uuid._ourGenerator;
};

// -------------------------------------------------------------------
// Public instance methods
// -------------------------------------------------------------------
/**
 * Returns a 36-character string representing the UUID, such 
 * as "3b12f1df-5232-4804-897e-917bf397618a".
 * 
 * Examples:
 * <pre>
 *   var uuid = new dojo.uuid.Uuid(dojo.uuid.TimeBasedGenerator);
 *   var s;
 *   s = uuid.toString();       //  eb529fec-6498-11d7-b236-000629ba5445
 *   s = uuid.toString('{}');   // {eb529fec-6498-11d7-b236-000629ba5445}
 *   s = uuid.toString('()');   // (eb529fec-6498-11d7-b236-000629ba5445)
 *   s = uuid.toString('""');   // "eb529fec-6498-11d7-b236-000629ba5445"
 *   s = uuid.toString("''");   // 'eb529fec-6498-11d7-b236-000629ba5445'
 *   s = uuid.toString('!-');   //  eb529fec649811d7b236000629ba5445
 *   s = uuid.toString('urn');  //  urn:uuid:eb529fec-6498-11d7-b236-000629ba5445
 * </pre>
 *
 * @param	uuidOne	A dojo.uuid.Uuid instance, or a string representing a UUID.
 * @return   Returns a standard 36-character UUID string, or something similar. 
 */
dojo.uuid.Uuid.prototype.toString = function(format) {
	if (format) {
		switch (format) {
			case '{}':
				return '{' + this._uuidString + '}';
				break;
			case '()':
				return '(' + this._uuidString + ')';
				break;
			case '""':
				return '"' + this._uuidString + '"';
				break;
			case "''":
				return "'" + this._uuidString + "'";
				break;
			case 'urn':
				return 'urn:uuid:' + this._uuidString;
				break;
			case '!-':
				return this._uuidString.split('-').join('');
				break;
			default:
				// we got passed something other than what we expected
				dojo.lang.assert(false, "The toString() method of dojo.uuid.Uuid was passed a bogus format.");
		}
	} else {
		return this._uuidString;
	}
};

/**
 * Compares this UUID to another UUID, and returns 0, 1, or -1.
 * This implementation is intended to match the sample 
 * implementation in IETF RFC 4122: 
 * http://www.ietf.org/rfc/rfc4122.txt
 *
 * @param	otherUuid	A dojo.uuid.Uuid instance, or a string representing a UUID.
 * @return   Returns either 0, 1, or -1.
 */
dojo.uuid.Uuid.prototype.compare = function(otherUuid) {
	return dojo.uuid.Uuid.compare(this, otherUuid);
};

/**
 * Returns true if this UUID is equal to the otherUuid, or
 * false otherwise.
 *
 * @param	otherUuid	A dojo.uuid.Uuid instance, or a string representing a UUID.
 * @return   Returns true or false. True if this UUID is equal to the otherUuid.
 */
dojo.uuid.Uuid.prototype.isEqual = function(otherUuid) {
	return (this.compare(otherUuid) == 0);
};

/**
 * Returns true if the UUID was initialized with a valid value.
 *
 * @return   True if the UUID is valid, or false if it is not.
 */
dojo.uuid.Uuid.prototype.isValid = function() {
	try {
		dojo.lang.assertType(this._uuidString, String);
		dojo.lang.assert(this._uuidString.length == 36);
		dojo.lang.assert(this._uuidString == this._uuidString.toLowerCase());
		var arrayOfParts = this._uuidString.split("-");
		dojo.lang.assert(arrayOfParts.length == 5);
		dojo.lang.assert(arrayOfParts[0].length == 8);
		dojo.lang.assert(arrayOfParts[1].length == 4);
		dojo.lang.assert(arrayOfParts[2].length == 4);
		dojo.lang.assert(arrayOfParts[3].length == 4);
		dojo.lang.assert(arrayOfParts[4].length == 12);
		for (var i in arrayOfParts) {
			var part = arrayOfParts[i];
			var integer = parseInt(part, dojo.uuid.Uuid.HEX_RADIX);
			dojo.lang.assert(isFinite(integer));
		}
		return true;
	} catch (e) {
		return false;
	}
};

/**
 * Returns a variant code that indicates what type of UUID this is.
 * For example:
 * <pre>
 *   var uuid = new dojo.uuid.Uuid("3b12f1df-5232-4804-897e-917bf397618a");
 *   var variant = uuid.getVariant();
 *   dojo.lang.assert(variant == dojo.uuid.Uuid.Variant.DCE);
 * </pre>
 *
 * @return   Returns one of the enumarted dojo.uuid.Uuid.Variant values.
 */
dojo.uuid.Uuid.prototype.getVariant = function() {
	// "3b12f1df-5232-4804-897e-917bf397618a"
	//                     ^
	//                     |
	//         (variant "10__" == DCE)
	var variantCharacter = this._uuidString.charAt(19);
	var variantNumber = parseInt(variantCharacter, dojo.uuid.Uuid.HEX_RADIX);
	dojo.lang.assert((variantNumber >= 0) && (variantNumber <= 16));

	if (!dojo.uuid.Uuid._ourVariantLookupTable) {
		var Variant = dojo.uuid.Uuid.Variant;
		var lookupTable = [];

		lookupTable[0x0] = Variant.NCS;       // 0000
		lookupTable[0x1] = Variant.NCS;       // 0001
		lookupTable[0x2] = Variant.NCS;       // 0010
		lookupTable[0x3] = Variant.NCS;       // 0011

		lookupTable[0x4] = Variant.NCS;       // 0100
		lookupTable[0x5] = Variant.NCS;       // 0101
		lookupTable[0x6] = Variant.NCS;       // 0110
		lookupTable[0x7] = Variant.NCS;       // 0111

		lookupTable[0x8] = Variant.DCE;       // 1000
		lookupTable[0x9] = Variant.DCE;       // 1001
		lookupTable[0xA] = Variant.DCE;       // 1010
		lookupTable[0xB] = Variant.DCE;       // 1011

		lookupTable[0xC] = Variant.MICROSOFT; // 1100
		lookupTable[0xD] = Variant.MICROSOFT; // 1101
		lookupTable[0xE] = Variant.UNKNOWN;   // 1110
		lookupTable[0xF] = Variant.UNKNOWN;   // 1111
		
		dojo.uuid.Uuid._ourVariantLookupTable = lookupTable;
	}

	return dojo.uuid.Uuid._ourVariantLookupTable[variantNumber];
};

/**
 * Returns a version number that indicates what type of UUID this is.
 * For example:
 * <pre>
 *   var uuid = new dojo.uuid.Uuid("b4308fb0-86cd-11da-a72b-0800200c9a66");
 *   var version = uuid.getVersion();
 *   dojo.lang.assert(version == dojo.uuid.Uuid.Version.TIME_BASED);
 * </pre>
 *
 * @return   Returns one of the enumerated dojo.uuid.Uuid.Version values.
 * @throws   Throws an Error if this is not a DCE Variant UUID.
 */
dojo.uuid.Uuid.prototype.getVersion = function() {
	if (!this._versionNumber) {
		var errorMessage = "Called getVersion() on a dojo.uuid.Uuid that was not a DCE Variant UUID.";
		dojo.lang.assert(this.getVariant() == dojo.uuid.Uuid.Variant.DCE, errorMessage);
	
		// "b4308fb0-86cd-11da-a72b-0800200c9a66"
		//                ^
		//                |
		//       (version 1 == TIME_BASED)
		var versionCharacter = this._uuidString.charAt(14);
		this._versionNumber = parseInt(versionCharacter, dojo.uuid.Uuid.HEX_RADIX);
	}
	return this._versionNumber;
};

/**
 * If this is a version 1 UUID (a time-based UUID), this method returns a 
 * 12-character string with the "node" or "pseudonode" portion of the UUID, 
 * which is the rightmost 12 characters.  
 * Throws an Error if this is not a version 1 UUID.
 *
 * @return   Returns a 12-character string, which will look something like "917bf397618a".
 * @throws   Throws an Error if this is not a version 1 UUID.
 */
dojo.uuid.Uuid.prototype.getNode = function() {
	if (!this._nodeString) {
		var errorMessage = "Called getNode() on a dojo.uuid.Uuid that was not a TIME_BASED UUID.";
		dojo.lang.assert(this.getVersion() == dojo.uuid.Uuid.Version.TIME_BASED, errorMessage);

		var arrayOfStrings = this._uuidString.split('-');
		this._nodeString = arrayOfStrings[4];
	}
	return this._nodeString;
};

/**
 * If this is a version 1 UUID (a time-based UUID), this method returns 
 * the timestamp value encoded in the UUID.  The caller can ask for the
 * timestamp to be returned either as a JavaScript Date object or as a 
 * 15-character string of hex digits.
 * Throws an Error if this is not a version 1 UUID.
 *
 * Examples:
 * <pre>
 *   var uuid = new dojo.uuid.Uuid("b4308fb0-86cd-11da-a72b-0800200c9a66");
 *   var date, string, hexString;
 *   date   = uuid.getTimestamp();         // returns a JavaScript Date
 *   date   = uuid.getTimestamp(Date);     // 
 *   string = uuid.getTimestamp(String);   // "Mon, 16 Jan 2006 20:21:41 GMT"
 *   hexString = uuid.getTimestamp("hex"); // "1da86cdb4308fb0"
 * </pre>
 *
 * @return   Returns the timestamp value as a JavaScript Date object or a 15-character string of hex digits.
 * @throws   Throws an Error if this is not a version 1 UUID.
 */
dojo.uuid.Uuid.prototype.getTimestamp = function(returnType) {
	var errorMessage = "Called getTimestamp() on a dojo.uuid.Uuid that was not a TIME_BASED UUID.";
	dojo.lang.assert(this.getVersion() == dojo.uuid.Uuid.Version.TIME_BASED, errorMessage);
	
	if (!returnType) {returnType = null};
	switch (returnType) {
		case "string":
		case String:
			return this.getTimestamp(Date).toUTCString();
			break;
		case "hex":
			// Return a 15-character string of hex digits containing the 
			// timestamp for this UUID, with the high-order bits first.
			if (!this._timestampAsHexString) {
				var arrayOfStrings = this._uuidString.split('-');
				var hexTimeLow = arrayOfStrings[0];
				var hexTimeMid = arrayOfStrings[1];
				var hexTimeHigh = arrayOfStrings[2];
			
				// Chop off the leading "1" character, which is the UUID 
				// version number for time-based UUIDs.
				hexTimeHigh = hexTimeHigh.slice(1);
			
				this._timestampAsHexString = hexTimeHigh + hexTimeMid + hexTimeLow;
				dojo.lang.assert(this._timestampAsHexString.length == 15);
			}
			return this._timestampAsHexString;
			break;
		case null: // no returnType was specified, so default to Date
		case "date":
		case Date:
			// Return a JavaScript Date object. 
			if (!this._timestampAsDate) {
				var GREGORIAN_CHANGE_OFFSET_IN_HOURS = 3394248;
			
				var arrayOfParts = this._uuidString.split('-');
				var timeLow = parseInt(arrayOfParts[0], dojo.uuid.Uuid.HEX_RADIX);
				var timeMid = parseInt(arrayOfParts[1], dojo.uuid.Uuid.HEX_RADIX);
				var timeHigh = parseInt(arrayOfParts[2], dojo.uuid.Uuid.HEX_RADIX);
				var hundredNanosecondIntervalsSince1582 = timeHigh & 0x0FFF;
				hundredNanosecondIntervalsSince1582 <<= 16;
				hundredNanosecondIntervalsSince1582 += timeMid;
				// What we really want to do next is shift left 32 bits, but the 
				// result will be too big to fit in an int, so we'll multiply by 2^32,
				// and the result will be a floating point approximation.
				hundredNanosecondIntervalsSince1582 *= 0x100000000;
				hundredNanosecondIntervalsSince1582 += timeLow;
				var millisecondsSince1582 = hundredNanosecondIntervalsSince1582 / 10000;
			
				// Again, this will be a floating point approximation.
				// We can make things exact later if we need to.
				var secondsPerHour = 60 * 60;
				var hoursBetween1582and1970 = GREGORIAN_CHANGE_OFFSET_IN_HOURS;
				var secondsBetween1582and1970 = hoursBetween1582and1970 * secondsPerHour;
				var millisecondsBetween1582and1970 = secondsBetween1582and1970 * 1000;
				var millisecondsSince1970 = millisecondsSince1582 - millisecondsBetween1582and1970;
			
				this._timestampAsDate = new Date(millisecondsSince1970);
			}
			return this._timestampAsDate;
			break;
		default:
			// we got passed something other than a valid returnType
			dojo.lang.assert(false, "The getTimestamp() method dojo.uuid.Uuid was passed a bogus returnType: " + returnType);
			break;
	}
};

__CPAN_FILE__ src/uuid/RandomGenerator.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.uuid.RandomGenerator");

dojo.uuid.RandomGenerator = new function() {

/**
 * This function generates random UUIDs, meaning "version 4" UUIDs.
 * For example, a typical generated value would be something like
 * "3b12f1df-5232-4804-897e-917bf397618a".
 *
 * Examples:
 * <pre>
 *   var string = dojo.uuid.RandomGenerator.generate();
 *   var string = dojo.uuid.RandomGenerator.generate(String);
 *   var uuid   = dojo.uuid.RandomGenerator.generate(dojo.uuid.Uuid);
 * </pre>
 *
 * @param	returnType	Optional. The type of instance to return.
 * @return	A newly generated version 4 UUID.
 */
	this.generate = function(returnType) {
		dojo.unimplemented('dojo.uuid.RandomGenerator.generate');
		
		// FIXME:
		// For an algorithm to generate a random UUID, see
		// sections 4.4 and 4.5 of RFC 4122:
		//  http://www.ietf.org/rfc/rfc4122.txt
		
		var returnValue = "00000000-0000-0000-0000-000000000000"; // FIXME
		if (returnType && (returnType != String)) {
			returnValue = new returnType(returnValue);
		}
		return returnValue;
	};
}();

__CPAN_FILE__ src/uuid/NilGenerator.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.uuid.NilGenerator");

dojo.uuid.NilGenerator = new function() {

/**
 * This function returns the Nil UUID: 
 * "00000000-0000-0000-0000-000000000000".
 * The Nil UUID is described in section 4.1.7 of
 * RFC 4122: http://www.ietf.org/rfc/rfc4122.txt
 *
 * Examples:
 * <pre>
 *   var string = dojo.uuid.NilGenerator.generate();
 *   var string = dojo.uuid.NilGenerator.generate(String);
 *   var uuid   = dojo.uuid.NilGenerator.generate(dojo.uuid.Uuid);
 * </pre>
 *
 * @param	returnType	Optional. The type of instance to return.
 * @return	The nil UUID.
 */
	this.generate = function(returnType) {
		var returnValue = "00000000-0000-0000-0000-000000000000";
		if (returnType && (returnType != String)) {
			returnValue = new returnType(returnValue);
		}
		return returnValue;
	};
}();
__CPAN_FILE__ src/uuid/__package__.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.kwCompoundRequire({
	common: [
		"dojo.uuid.Uuid",
		"dojo.uuid.LightweightGenerator",
		"dojo.uuid.RandomGenerator",
		"dojo.uuid.TimeBasedGenerator",
		"dojo.uuid.NameBasedGenerator",
		"dojo.uuid.NilGenerator"
	]
});
dojo.provide("dojo.uuid.*");


__CPAN_FILE__ src/uuid/LightweightGenerator.js
/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.uuid.LightweightGenerator");

/**
 * The LightweightGenerator is intended to be small and fast,
 * but not necessarily good.
 * 
 * Small: The LightweightGenerator has a small footprint. 
 * Once comments are stripped, it's only about 25 lines of 
 * code, and it doesn't dojo.require() any other packages.
 *
 * Fast: The LightweightGenerator can generate lots of new 
 * UUIDs fairly quickly (at least, more quickly than the other 
 * dojo UUID generators).
 *
 * Not necessarily good: We use Math.random() as our source
 * of randomness, which may or may not provide much randomness. 
 */
dojo.uuid.LightweightGenerator = new function() {

	var HEX_RADIX = 16;

// --------------------------------------------------
// Private functions
// --------------------------------------------------
	function _generateRandomEightCharacterHexString() {
		// Make random32bitNumber be a randomly generated floating point number
		// between 0 and (4,294,967,296 - 1), inclusive.
		var random32bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 32) );
		var eightCharacterHexString = random32bitNumber.toString(HEX_RADIX);
		while (eightCharacterHexString.length < 8) {
			eightCharacterHexString = "0" + eightCharacterHexString;
		}
		return eightCharacterHexString; // for example: "3B12F1DF"
	}

// --------------------------------------------------
// Public functions
// --------------------------------------------------

/**
 * This function generates random UUIDs, meaning "version 4" UUIDs.
 * For example, a typical generated value would be something like
 * "3b12f1df-5232-4804-897e-917bf397618a".
 *
 * Examples:
 * <pre>
 *   var string = dojo.uuid.LightweightGenerator.generate();
 *   var string = dojo.uuid.LightweightGenerator.generate(String);
 *   var uuid   = dojo.uuid.LightweightGenerator.generate(dojo.uuid.Uuid);
 * </pre>
 *
 * @param	returnType	Optional. The type of instance to return.
 * @return	A newly generated version 4 UUID.
 */
	this.generate = function(returnType) {
		var hyphen = "-";
		var versionCodeForRandomlyGeneratedUuids = "4"; // 8 == binary2hex("0100")
		var variantCodeForDCEUuids = "8"; // 8 == binary2hex("1000")
		var a = _generateRandomEightCharacterHexString();
		var b = _generateRandomEightCharacterHexString();
		b = b.substring(0, 4) + hyphen + versionCodeForRandomlyGeneratedUuids + b.substring(5, 8);
		var c = _generateRandomEightCharacterHexString();
		c = variantCodeForDCEUuids + c.substring(1, 4) + hyphen + c.substring(4, 8);
		var d = _generateRandomEightCharacterHexString();
		var returnValue = a + hyphen + b + hyphen + c + d;
		returnValue = returnValue.toLowerCase();
		if (returnType && (returnType != String)) {
			returnValue = new returnType(returnValue);
		}
		return returnValue;
	};
}();

