/**
 * Hyjax
 * Home's Yielding Javascript Advanced eXtensions
 *  (c) 2006 NEXT CO.,LTD. (http://www.next-group.jp/, http://www.homes.co.jp/)
 */

var Hyjax = {
	Version: '0.1.0',
	PrototypeVersion: '',
	ScriptaculousVersion: '',
	initialize: function() {
		if (typeof Prototype == 'undefined') {
			throw("Hyjax requires prototype.js");
		} else {
			this.PrototypeVersion = parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1]);
			if (this.PrototypeVersion < 1.5) {
				throw("Hyjax requires prototype.js >= 1.5");
			}
		}
		if (typeof Scriptaculous == 'undefined') {
			throw("Hyjax requires scriptaculous.js");
		} else {
			this.ScriptaculousVersion = parseFloat(Scriptaculous.Version.split(".")[0] + "." + Scriptaculous.Version.split(".")[1]);
			if (this.ScriptaculousVersion < 1.6) {
				throw("Hyjax requires scriptaculous.js >= 1.6");
			}
		}
	},
	require: function(libraryName) {
		document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
	},
	load: function() {
		$A(document.getElementsByTagName("script")).findAll( function(s) {
			return (s.src && s.src.match(/hyjax\.js(\?.*)?$/))
		}).each( function(s) {
			var path = s.src.replace(/hyjax\.js(\?.*)?$/,'');
			var includes = s.src.match(/\?.*load=([a-z,]*)/);
			(includes ? includes[1] : 'kernel,effects,components').split(',').each(
				function(include) { Hyjax.require(path+include+'.js') });
		});
	}
}
Hyjax.initialize();

/*------------------------------------------------------------*
   UserAgent
 *------------------------------------------------------------*/
Hyjax.UserAgent = function() {
	if (typeof(navigator) != "object" || !navigator.userAgent) {
		this.unknown = true;
		return;
	}

	var ua = navigator.userAgent;
	var match;

	if (typeof(RegExp) == "undefined") {
		if (ua.indexOf("Opera") >= 0) {
			this.opera = true;
		} else if (ua.indexOf("Netscape") >= 0) {
			this.netscape = true;
		} else if (ua.indexOf("Mozilla/") == 0) {
			this.mozilla = true;
		} else {
			this.unknown = true;
		}
		
		if (ua.indexOf("Gecko/") >= 0) {
			this.gecko = true;
		}
		
		if (ua.indexOf("Win") >= 0) {
			this.windows = true;
		} else if (ua.indexOf("Mac") >= 0) {
			this.mac = true;
		} else if (ua.indexOf("Linux") >= 0) {
			this.linux = true;
		} else if (ua.indexOf("BSD") >= 0) {
			this.bsd = true;
		} else if (ua.indexOf("SunOS") >= 0) {
			this.sunos = true;
		}
		return;
	}

	/* for Trident/Tasman */
	/*@cc_on
	@if (@_jscript)
		function jscriptVersion() {
			switch (@_jscript_version) {
				case 3.0:  return "4.0";
				case 5.0:  return "5.0";
				case 5.1:  return "5.01";
				case 5.5:  return "5.5";
				case 5.6:
					if ("XMLHttpRequest" in window) return "7.0";
					return "6.0";
				default:   return true;
			}
		}
		if (@_win16 || @_win32 || @_win64) {
			this.windows = true;
			this.trident = jscriptVersion();
		} else if (@_mac || navigator.platform.indexOf("Mac") >= 0) {
			// '@_mac' may be 'NaN' even if the platform is Mac,
			// so we check 'navigator.platform', too.
			this.mac = true;
			this.tasman = jscriptVersion();
		}
		if (match = ua.match("MSIE ?(\\d+\\.\\d+)b?;")) {
			this.ie = match[1];
		}
	@else @*/

	/* for AppleWebKit */
	if (match = ua.match("AppleWebKit/(\\d+(\\.\\d+)*)")) {
		this.applewebkit = match[1];
	}

	/* for Gecko */
	else if (typeof(Components) == "object") {
		if (match = ua.match("Gecko/(\\d{8})")) {
			this.gecko = match[1];
		} else if (navigator.product == "Gecko"
				&& (match = navigator.productSub.match("^(\\d{8})$"))) {
			this.gecko = match[1];
		}
	}

	/*@end @*/

	if (typeof(opera) == "object"
			&& (match = ua.match("Opera[/ ](\\d+\\.\\d+)"))) {
		this.opera = match[1];
	} else if (this.ie) {
	} else if (match = ua.match("Safari/(\\d+(\\.\\d+)*)")) {
		this.safari = match[1];
	} else if (match = ua.match("Konqueror/(\\d+(\\.\\d+)*)")) {
		this.konqueror = match[1];
	} else if (ua.indexOf("(compatible;") < 0
			&& (match = ua.match("^Mozilla/(\\d+\\.\\d+)"))) {
		this.mozilla = match[1];
		if (match = ua.match("\\([^(]*rv:(\\d+(\\.\\d+)*).*?\\)"))
			this.mozillarv = match[1];
		if (match = ua.match("Firefox/(\\d+(\\.\\d+)*)")) {
			this.firefox = match[1];
		} else if (match = ua.match("Netscape\\d?/(\\d+(\\.\\d+)*)")) {
			this.netscape = match[1];
		}
	} else {
		this.unknown = true;
	}

	if (ua.indexOf("Win 9x 4.90") >= 0) {
		this.windows = "ME";
	} else if (match = ua.match("Win(dows)? ?(NT ?(\\d+\\.\\d+)?|\\d+|XP|ME|Vista)")) {
		this.windows = match[2];
		if (match[3]) {
			this.winnt = match[3];
		} else switch (match[2]) {
			case "2000":   this.winnt = "5.0";  break;
			case "XP":     this.winnt = "5.1";  break;
			case "Vista":  this.winnt = "6.0";  break;
		}
	} else if (ua.indexOf("Mac") >= 0) {
		this.mac = true;
	} else if (ua.indexOf("Linux") >= 0) {
		this.linux = true;
	} else if (match = ua.match("\\w*BSD")) {
		this.bsd = match[0];
	} else if (ua.indexOf("SunOS") >= 0) {
		this.sunos = true;
	}
}
Hyjax.ua = new Hyjax.UserAgent();

/*------------------------------------------------------------*
   Debugging Tools
 *------------------------------------------------------------*/
Hyjax.StopWatch = Class.create();
Hyjax.StopWatch.prototype = {
	initialize: function() {
		this.start();
	},
	start: function() {
		var dt = new Date();
		this.startTime = dt.getTime();
	},
	stop: function() {
		var dt = new Date();
		this.endTime = dt.getTime();
		return (this.endTime - this.startTime);
	}
}

/*------------------------------------------------------------*
   Hyjax.RGB
 *------------------------------------------------------------*/
Hyjax.RGB = {
	validate: function(rgb) {
		return(/^rgb\(\d+,\s*\d+,\s*\d+\)$/.test(rgb));
	},
	toArray: function(rgb) {
		if (Hyjax.RGB.validate(rgb)) {
			return rgb.substring(4, rgb.indexOf(")")).split(",");
		} else {
			throw("String '"+rgb+"' is not RGB format.");
		}
	},
	toHex: function(rgb) {
		try {
			var rgbArray = Hyjax.RGB.toArray(rgb);
			var r = parseInt(rgbArray[0]);
			var g = parseInt(rgbArray[1]);
			var b = parseInt(rgbArray[2]);
			return "#" + r.toHex(2) + g.toHex(2) + b.toHex(2);
		} catch(e) {
			return null;
		}
	}
}

/*------------------------------------------------------------*
   Hyjax.Color
 *------------------------------------------------------------*/
Hyjax.Color = {
	hex2Array: function (hexColor) {
		var hexArray = new Array(2);
		if (hexColor.length == 4) {
			hexArray[0] = hexColor.substring(1,2).toIntFromHex();
			hexArray[1] = hexColor.substring(2,3).toIntFromHex();
			hexArray[2] = hexColor.substring(3,4).toIntFromHex();
		} else if (hexColor.length == 7) {
			hexArray[0] = hexColor.substring(1,3).toIntFromHex();
			hexArray[1] = hexColor.substring(3,5).toIntFromHex();
			hexArray[2] = hexColor.substring(5,7).toIntFromHex();
		}
		return hexArray;
	},
	array2Hex: function (hexArray) {
		return "#" + hexArray[0].toHex(2) + hexArray[1].toHex(2) + hexArray[2].toHex(2);
	},
	blend: function(hexArray1, hexArray2, fraction) {
		if (fraction > 1 || fraction < 0) fraction = 1;
		
		var hexArray = new Array(2);
		for (var i = 0; i < 3; ++i) {
			hexArray[i] = Math.round((hexArray1[i] * fraction) + (hexArray2[i] * (1 - fraction)));
			if (hexArray[i] > 255) hexArray[i] = 255;
			if (hexArray[i] < 0) hexArray[i] = 0;
		}
		
		return hexArray;
	},
	fraction: 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 = new Array(1);
		var yvalues = new Array(1);
		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;
	}
}

/*------------------------------------------------------------*
   Kernel extention
 *------------------------------------------------------------*/
document.getElementsByClassNameRegExp = function(className, parentElement) {
  var children = ($(parentElement) || document.body).getElementsByTagName('*');
  return $A(children).inject([], function(elements, child) {
    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
      elements.push(child);
    return elements;
  });
}

Object.extend(String.prototype, {
	eqi: function(s) {
		return this.toLowerCase() == s.toLowerCase()
	},
	toIntFromHex: function() {
		return parseInt(this, 16);
	},
	padding: function(chr, digit) {
		var tmp = this;
		for (var i = this.length; i < digit; ++i) {
			tmp = chr + tmp;
		}
		return tmp;
	},
	toLowerCaseWith: function(delimiter) {
		if (typeof(delimiter) == "undefined") {
			delimiter = "-";
		}
		var ret = "";
		for (var i=0; i<this.length; ++i) {
			var chr = this.substring(i,i+1);
			if (/[A-Z]/.test(chr)) {
				ret = ret + delimiter + chr.toLowerCase();
			} else {
				ret = ret + chr;
			}
		}
		return ret;
	},
	sliceBefore: function(needle, alternative) {
		if (needle == "") return alternative;
		var pos = this.indexOf(needle);
		if (pos == -1) {
			return alternative;
		} else {
			return this.slice(0, pos);
		}
	},
	toHexColor: function() {
		var ret = "#ffffff";
		if (this != "" && this != "transparent") {
			if (this.substr(0,4) == "rgb(") {
				ret = Hyjax.RGB.toHex(this);
			} else if (this.length == 4 && this.substring(0,1) == "#") {
				var r = this.substring(1,2);
				var g = this.substring(2,3);
				var b = this.substring(3,4);
				ret = "#" + r + r + g + g + b + b;
			} else {
				ret = this.toString();
			}
		}
		return ret;
	}
});

Object.extend(Number.prototype, {
	toHex: function(digit) {
		var hex = this.toString(16);
		if (digit) hex = hex.padding("0", digit);
		return hex;
	}
});

Hyjax.ElementMethods = {
	findParentNode: function(element, s) {
		pointer = element.parentNode;
		while(!pointer.tagName.eqi(s))
			{
				pointer = pointer.parentNode;
				if(!pointer.tagName) return (false);
			}
		return pointer;
	},
	getStyleStr: function(element, styleName) {
		var style = element.getStyle(styleName);
		if (style == null) style = "";
		return style;
	},
	getStyle2: function(element, styleName) {
		try {
			if (element.currentStyle) {
				var ret = element.currentStyle[styleName];
			} else {
				var original_display = element.style.display;
				if (Hyjax.ua.safari && original_display == "none") {
					element.style.display = "";
				}
				var styleNs = styleName.toLowerCaseWith();
				var ret = document.defaultView.getComputedStyle(element, '').getPropertyValue(styleNS);
				if (Hyjax.ua.safari && original_display == "none") {
					element.style.display = "none";
				}
			}
		} catch(e) {
			// do nothing
		}
		return ret;
	},
	getBoxHeight: function(element) {
		try {
			var boxHeight = element.getStyle("height");
			return parseInt(((boxHeight != null && boxHeight != "auto" && boxHeight.indexOf("%") == -1) ? boxHeight.sliceBefore("px") : element.scrollHeight));
		} catch(e) {
			// do nothing
		}
	},
	getBoxWidth: function(element) {
		try {
			var boxWidth = element.getStyle("width");
			return parseInt(((boxWidth != null && boxWidth != "auto" && boxWidth.indexOf("%") == -1) ? boxWidth.sliceBefore("px") : element.scrollWidth));
		} catch(e) {
			// do nothing
		}
	},
	/*
	setOpacity: function(element, opacity) {
		opacity = (opacity == 1)?0.999:opacity;
		
		if(Hyjax.ua.safari && !element.tagName.eqi("iframe")) {
			// Get array of RGB values
			var rgbArray = Hyjax.RGB.toArray(element.style.backgroundColor);
			
			// Get RGB values
			var red   = parseInt(rgbArray[0]);
			var green = parseInt(rgbArray[1]);
			var blue  = parseInt(rgbArray[2]);
			
			// Safari using RGBA support
			element.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity + ")";
		} else if(typeof(element.style.opacity) != "undefined") {
			// W3C
			element.style.opacity = opacity;
		} else if(typeof(element.style.MozOpacity) != "undefined") {
			// Older Mozilla
			element.style.MozOpacity = opacity;
		} else if(typeof(element.style.filter) != "undefined") {
			// IE
			element.style.filter = "alpha(opacity:" + (opacity * 100) + ")";
		} else if(typeof(element.style.KHTMLOpacity) != "undefined") {
			// Older KHTML Based Browsers
			element.style.KHTMLOpacity = opacity;
		}
	},
	*/
	isAncestor: function(element, target) {
		pointer = target;
		while(pointer.tagName && !pointer.tagName.eqi('body')) {
			if (pointer == element) {
				return true;
			}
			pointer = pointer.parentNode;
			if (!pointer) break;
		}
		return false;
	},
	isDescendant: function(element, target) {
		return Hyjax.ElementMethods.isAncestor(target, element);
	}
}
Object.extend(Element.Methods, Hyjax.ElementMethods);
Element.addMethods();

/*------------------------------------------------------------*
   CurvyCorners
 *------------------------------------------------------------*/
Hyjax.CurvyCorners = {
	curvyZIndex: 0,
	curvyCache: null,
	toCurvy: function(element, set_options) {
		
		// initialize options
		var options = {
			tl: 20,
			tr: 20,
			bl: 20,
			br: 20,
			antiAlias: true,
			autoZIndex: false
		}
		Object.extend(options, set_options || {});
		
		// get box values
		var boxHeight = element.getBoxHeight();
		var boxWidth = element.getBoxWidth();
		var borderWidth = parseInt(element.getStyleStr("border-top-width").sliceBefore("px", 0));
		var boxColor = element.getStyleStr("background-color").toHexColor();
		var boxPadding = parseInt(element.getStyleStr("padding-top").sliceBefore("px", 0));
		var boxContent = element.innerHTML;
		var borderColor = element.getStyleStr("border-top-color").toHexColor();
		var borderStyle = element.getStyleStr("border-top-style");
		var borderString = borderWidth + "px " + borderStyle + " " + borderColor;
		var backgroundImage = (element.getStyleStr("background-image") != "none") ? element.getStyleStr("background-image") : "";
		var backgroundRepeat = element.getStyleStr("background-repeat");
		var boxPosition = element.getStyleStr("position");
		var boxPaddingTop = parseInt(element.getStyleStr("padding-top").sliceBefore("px", 0));
		var boxPaddingBottom = parseInt(element.getStyleStr("padding-bottom").sliceBefore("px", 0));
		var boxPaddingLeft = parseInt(element.getStyleStr("padding-left").sliceBefore("px", 0));
		var boxPaddingRight = parseInt(element.getStyleStr("padding-right").sliceBefore("px", 0));
		var boxMarginTop = parseInt(element.getStyleStr("margin-top").sliceBefore("px", 0));
		var boxMarginBottom = parseInt(element.getStyleStr("margin-bottom").sliceBefore("px", 0));

		// set padding top/bottom
		var boxNewPaddingTop = boxPaddingTop;
		var boxNewPaddingBottom = boxPaddingBottom;
		if (boxPaddingTop > topRadius) boxNewPaddingTop = (boxPaddingTop - topRadius);
		if (boxPaddingBottom > bottomRadius) boxNewPaddingBottom = (boxPaddingBottom - bottomRadius);
		element.style.paddingTop = boxNewPaddingTop + "px";
		element.style.paddingBottom = boxNewPaddingBottom + "px";
		
		// fix box width/height
		boxWidth += boxPaddingLeft + boxPaddingRight;
		boxHeight += boxNewPaddingTop + boxNewPaddingBottom;
		
		// make box relative if not already absolute and remove any padding
		if (boxPosition != "absolute") element.style.position = "relative";
		
		// if IE and height and width are not set, we need to set width so that we get positioning
		if (Hyjax.ua.ie && (element.getStyle("width") == null)) {
			element.style.width = "100%";
		}
		
		// get top/bottom container size
		var topRadius = Math.max(options.tl, options.tr);
		var bottomRadius = Math.max(options.bl, options.br);
				
		// create curvy containers
		var topContainer = Hyjax.CurvyCorners.appendCurvyContainer(element, 'top', boxWidth, borderWidth, topRadius, 0);
		var bottomContainer = Hyjax.CurvyCorners.appendCurvyContainer(element, 'bottom', boxWidth, borderWidth, bottomRadius, topRadius);
		
		// fix margin
		element.style.top = topRadius + "px";
		element.style.marginBottom = boxMarginBottom + topRadius + bottomRadius + "px";

		// create curvy corners
		var corner_options = {
			boxColor: boxColor,
			boxHeight: boxHeight,
			boxWidth: boxWidth,
			backgroundImage: backgroundImage,
			backgroundRepeat: backgroundRepeat,
			borderWidth: borderWidth,
			borderString: borderString,
			borderColor: borderColor,
			antiAlias: options.antiAlias
		}
		if (bottomContainer) {
			corner_options.posTop = boxHeight + topRadius;
			corner_options.maxRadius = bottomRadius;
			corner_options.radius = options.bl;
			Hyjax.CurvyCorners.appendCurvyCorner(bottomContainer, 'bottom', 'left', corner_options);
			corner_options.radius = options.br;
			Hyjax.CurvyCorners.appendCurvyCorner(bottomContainer, 'bottom', 'right', corner_options);
			Hyjax.CurvyCorners.fillCurvyCornerGap(bottomContainer, 'bottom', options.bl, options.br, corner_options);
		}
		if (topContainer) {
			corner_options.posTop = 0;
			corner_options.maxRadius = topRadius;
			corner_options.radius = options.tl;
			Hyjax.CurvyCorners.appendCurvyCorner(topContainer, 'top', 'left', corner_options);
			corner_options.radius = options.tr;
			Hyjax.CurvyCorners.appendCurvyCorner(topContainer, 'top', 'right', corner_options);
			Hyjax.CurvyCorners.fillCurvyCornerGap(topContainer, 'top', options.tl, options.tr, corner_options);
			if (backgroundImage) {
				element.style.backgroundPosition = "0px -" + (topRadius - borderWidth) + "px";
			}
		}
		if (options.autoZIndex) element.style.zIndex = Hyjax.CurvyCorners.curvyZIndex++;
	},
	appendCurvyContainer: function(element, position, boxWidth, borderWidth, maxRadius, gapHeight) {
		if (maxRadius) {
			var newContainer = document.createElement("div");
			newContainer.style.width = "100%";
			newContainer.style.fontSize = "1px";
			newContainer.style.overflow = "hidden";
			newContainer.style.position = "absolute";
			newContainer.style.paddingLeft = borderWidth + "px";
			newContainer.style.paddingRight = borderWidth + "px";
			newContainer.style.height = maxRadius + "px";
			newContainer.style[position] = 0 - maxRadius + "px";
			newContainer.style.left = 0 - borderWidth + "px";
			// turn off current boreders if append the containers
			if (position == "top") {
				element.style.borderTopWidth = "0px";
			} else if (position == "bottom") {
				element.style.borderBottomWidth = "0px";
			}
			return element.appendChild(newContainer);
		} else {
			return null;
		}
	},
	appendCurvyCorner: function(element, posVertical, posHorizontal, options) {
		if (options.radius == 0) {
			// need to create a filler div to fill the space
			var newCorner = document.createElement("div");
			newCorner.style.position = "relative";
			newCorner.style.fontSize = "1px";
			newCorner.style.overflow = "hidden";
			newCorner.style.height = options.maxRadius - options.borderWidth + "px";
			if (options.backgroundImage == "") {
				newCorner.style.backgroundColor = options.boxColor;
			} else {
				newCorner.style.backgroundImage = options.backgroundImage;
				newCorner.style.backgroundRepeat = options.backgroundRepeat;
			}
			if (posVertical == "top") {
				newCorner.style.borderTop = options.borderString;
				var bgPosTop = options.posTop + options.posTop + "px";
			} else if (posVertical == "bottom") {
				newCorner.style.borderBottom = options.borderString;
				var bgPosTop = "-" + (options.posTop - options.borderWidth) + "px";
			}
			if (posHorizontal == "left") {
				newCorner.style.marginRight = (options.maxRadius - (options.borderWidth * 2)) + "px";
				newCorner.style.borderLeft = options.borderString;
				newCorner.style.left = -options.borderWidth + "px";
				var bgPosLeft = "0px";
			} else if (posHorizontal == "right") {
				newCorner.style.marginLeft = (options.maxRadius - (options.borderWidth * 2)) + "px";
				newCorner.style.borderRight = options.borderString;
				newCorner.style.left = options.borderWidth + "px";
				var bgPosLeft = "-" + (options.maxRadius - options.borderWidth) + "px";
			}
			newCorner.style.backgroundPosition = bgPosLeft + " " + bgPosTop;

		} else {

			if (Hyjax.CurvyCorners.curvyCache == null) Hyjax.CurvyCorners.curvyCache = new Array();
			var cache_key = options.radius + ":" + options.borderWidth + ":" + options.boxColor + ":" + options.borderColor;
			if (options.backgroundImage) cache_key += ":" + (options.maxRadius - options.radius);
			if (Hyjax.CurvyCorners.curvyCache[cache_key]) {
				// use cache
				var newCorner = Hyjax.CurvyCorners.curvyCache[cache_key].cloneNode(true);
			} else {
				
				// need to create a new corner
				var newCorner = document.createElement("div");
				newCorner.style.height = options.radius + "px";
				newCorner.style.width = options.radius + "px";
				newCorner.style.position = "absolute";
				newCorner.style.fontSize = "1px";
				newCorner.style.overflow = "hidden";
				
				// get border radius
				var borderRadius = parseInt(options.radius - options.borderWidth);
				
				// cycle the x-axis
				for (var intx = 0, j = options.radius; intx < j; ++intx) {
					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 color
					if (y1 > -1) Hyjax.CurvyCorners.drawCurvyLine(newCorner, intx, 0, options.boxColor, 1, (y1+1), options.maxRadius, true, options);
					
					// draw the line
					if (borderRadius != j) {
						// set color array
						var boxColorArray = Hyjax.Color.hex2Array(options.boxColor);
						var borderColorArray = Hyjax.Color.hex2Array(options.borderColor);
						// cycle the y-axis
						for (var inty = (y1 + 1); inty < y2; ++inty) {
							// draw anti-alias pixels
							if (options.antiAlias) {
								// for each of the pixels that need anti aliasing between the foreground and border color draw single pixel divs
								var borderFract = Hyjax.Color.fraction(intx, inty, borderRadius);
								var pixColor = Hyjax.Color.array2Hex(Hyjax.Color.blend(boxColorArray, borderColorArray, borderFract));
								if (options.backgroundImage != "") {
									var showImage = (borderFract >= 0.3);
									Hyjax.CurvyCorners.drawCurvyLine(newCorner, intx, inty, pixColor, 1, 1, options.maxRadius, showImage, options);
								} else {
									Hyjax.CurvyCorners.drawCurvyLine(newCorner, intx, inty, pixColor, 1, 1, options.maxRadius, false, options);
								}
							}
						}
						// draw bar for the border
						if (options.antiAlias) {
							if (y3 >= y2) {
								if (y2 == -1) y2 = 0;
								Hyjax.CurvyCorners.drawCurvyLine(newCorner, intx, y2, options.borderColor, 1, (y3 - y2 + 1), options.maxRadius, false, options);
							}
						} else {
							if (y3 >= y1) {
								Hyjax.CurvyCorners.drawCurvyLine(newCorner, intx, (y1 + 1), options.borderColor, 1, (y3 - y1), options.maxRadius, false, options);
							}
						}
						// set the color for the outside curve
						var outsideColor = options.borderColor;
					} else {
						// set the color for the outside curve
						var outsideColor = options.boxColor;
						var y3 = y1;
					}
					
					// draw anti alias pixels
					if (options.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) {
							var fraction = Hyjax.Color.fraction(intx, inty, j);
							Hyjax.CurvyCorners.drawCurvyLine(newCorner, intx, inty, outsideColor, fraction, 1, options.maxRadius, (options.borderWidth <= 0), options);
						}
					}
				}
				Hyjax.CurvyCorners.curvyCache[cache_key] = newCorner.cloneNode(true);
			}
			
			// need to turn the corner to right direction unless the corner is the bottom right
			if (posVertical == "top" || posHorizontal == "left") {
				for (var t = 0, k = newCorner.childNodes.length; t < k; ++t) {
					
					// get current pix
					var pix = newCorner.childNodes[t];
					
					// get current top and left properties
					var pixTop = parseInt(pix.style.top.sliceBefore("px"));
					var pixLeft = parseInt(pix.style.left.sliceBefore("px"));
					var pixHeight = parseInt(pix.style.height.sliceBefore("px"));
					
					if (posHorizontal == "left") {
						pix.style.left = options.radius - pixLeft - 1 + "px";
						var bgPixPosLeft = "-" + Math.abs(options.radius - pixLeft - 1 - options.borderWidth) + "px";
					} else if (posHorizontal == "right") {
						var bgPixPosLeft = "-" + Math.abs((options.boxWidth - options.radius + options.borderWidth) + pixLeft) + "px";
					}
					if (posVertical == "top") {
						pix.style.top = options.radius - pixHeight - pixTop + "px";
						var bgPixPosTop = "-" + Math.abs(options.radius - pixHeight - pixTop - options.borderWidth) + "px";
					} else if (posVertical == "bottom") {
						var bgPixPosTop = "-" + Math.abs((options.posTop - options.borderWidth + (options.maxRadius - options.radius)) + pixTop) + "px";
					}

					pix.style.backgroundPosition = bgPixPosLeft + " " + bgPixPosTop;
				}
			}
		}
			
		// place the corner on the right place
		if (newCorner.style.position == "absolute") {
			if (posVertical == "top") {
				newCorner.style.top = "0px";
			} else if (posVertical == "bottom") {
				newCorner.style.bottom = "0px";
			}
			if (posHorizontal == "left") {
				newCorner.style.left = "0px";
			} else if (posHorizontal == "right") {
				newCorner.style.right = "0px";
			}
		}

		// draw the rest of the filler divs.
		// need to create a filler divs when two corners have differenct radiuses in either the top or bottom container.
		if (options.radius > 0 && options.radius < options.maxRadius) {
			
			// create a div for the space under the smaller corner
			diffRadius = options.maxRadius - options.radius;
			var newFiller = document.createElement("div");
			newFiller.style.height = diffRadius + "px";
			newFiller.style.width = (options.radius - options.borderWidth) + "px";
			newFiller.style.position = "absolute";
			newFiller.style.fontSize = "1px";
			newFiller.style.overflow = "hidden";
			newFiller.style.backgroundColor = options.boxColor;
			newFiller.style.backgroundImage = options.backgroundImage;
			newFiller.style.backgroundRepeat = options.backgroundRepeat;
			
			// position filler
			if (posVertical == "top") {
				newFiller.style.bottom = "0px";
				var posBgTop = "-" + (options.radius - options.borderWidth) + "px";
			} else if (posVertical == "bottom") {
				newFiller.style.top = "0px";
				var posBgTop = "-" + (options.posTop - options.borderWidth) + "px";
			}
			if (posHorizontal == "left") {
				newFiller.style.left = "0px";
				newFiller.style.borderLeft = options.borderString;
				var posBgLeft = "-" + 0 + "px";
			} else if (posHorizontal == "right") {
				newFiller.style.right = "0px";
				newFiller.style.borderRight = options.borderString;
				var posBgLeft = "-" + (options.boxWidth - options.radius + options.borderWidth) + "px";
			}
			
			if (options.backgroundImage) {
				newFiller.style.backgroundPosition = posBgLeft + " " + posBgTop;
			}
			
			element.appendChild(newFiller);
		}
		element.appendChild(newCorner);
	},
	fillCurvyCornerGap: function(element, posVertical, leftRadius, rightRadius, options) {
		// create the bar to fill the gap between each corner horizontally
		var newFillerBar = document.createElement("div");
		newFillerBar.style.position = "relative";
		newFillerBar.style.fontSize = "1px";
		newFillerBar.style.overflow = "hidden";
		newFillerBar.style.backgroundColor = options.boxColor;
		newFillerBar.style.height = options.maxRadius - options.borderWidth + "px";
		newFillerBar.style.marginLeft = (leftRadius - options.borderWidth) + "px";
		newFillerBar.style.marginRight = (rightRadius - options.borderWidth) + "px";

		if (posVertical == "top") {
			newFillerBar.style.borderTop = options.borderString;
			var bgPos = "-" + Math.abs(leftRadius - options.borderWidth) + "px -" + options.posTop + "px";
		} else if (posVertical == "bottom") {
			newFillerBar.style.borderBottom = options.borderString;
			var bgPos = "-" + Math.abs(leftRadius - options.borderWidth) + "px -" + Math.abs(options.posTop - options.borderWidth) + "px";
		}
		if (options.backgroundImage != "") {
			newFillerBar.style.backgroundImage = options.backgroundImage;
			newFillerBar.style.backgroundRepeat = options.backgroundRepeat;
			newFillerBar.style.backgroundPosition = bgPos;
		}
		element.appendChild(newFillerBar);
	},
	drawCurvyLine: function(element, intx, inty, color, trans, height, maxRadius, showImage, options) {
	
		// create a line
		var pix = document.createElement("div");
		pix.style.height = height + "px";
		pix.style.width = "1px";
		pix.style.position = "absolute";
		pix.style.fontSize = "1px";
		pix.style.overflow = "hidden";
		
		if (showImage && options.backgroundImage != "") {
			pix.style.backgroundImage = options.backgroundImage;
			pix.style.backgroundRepeat = options.backgroundRepeat;
			pix.style.backgroundColor = color;
			var bgPosLeft = -(options.boxWidth - (options.radius - intx) + options.borderWidth);
			var bgPosTop = -((options.posTop + inty + (maxRadius - options.radius)) - options.borderWidth);
			pix.style.backgroundPosition = bgPosLeft + "px " + bgPosTop + "px";
		} else {
			pix.style.backgroundColor = color;
		}
		
		// set opacity
		if (trans < 1) {
			Element.setOpacity(pix, trans);
		}
		
		// set the pix position
		pix.style.top = inty + "px";
		pix.style.left = intx + "px";
		
		element.appendChild(pix);
	}
}
Object.extend(Element.Methods, Hyjax.CurvyCorners);
Element.addMethods();

/*------------------------------------------------------------*
   CurvyCorners Light
 *------------------------------------------------------------*/
Hyjax.CurvyLight = {
	toCurvyLight: function(element, set_options) {
		
		// initialize options
		var options = {
			className: null,
			topHeight: 10,
			bottomHeight: 10,
			topPadding: 0,
			bottomPadding: 0
		}
		Object.extend(options, set_options || {});
		
		if (options.className == null) return;
		
		// iframe back up
		var iframeNodes = element.getElementsByTagName('iframe');

		// get inner div
		for(var i=0; i < element.childNodes.length; ++i) {
			node = element.childNodes[i];
			if (node.tagName && node.tagName.eqi("div")) {
				var inner_div = element.removeChild(node);
				break;
			}
		}
		if (!inner_div) return;
		
		// create top div
		var tl = document.createElement("div");
		var tr = document.createElement("div");
		tl.className = options.className;
		tr.className = options.className;
		tl.style.height = options.topHeight + "px";
		tl.style.fontSize = "1px";
		tl.style.backgroundPosition = "top right";
		tl.style.backgroundRepeat = "no-repeat";
		tr.style.height = options.topHeight + "px";
		tr.style.fontSize = "1px";
		tr.style.backgroundPosition = "top left";		
		tr.style.backgroundRepeat = "no-repeat";
		tr.style.width = options.topHeight + "px";
		tl.appendChild(tr);
		var top_height = options.topHeight + "px";
		
		// create bottom div
		var bl = document.createElement("div");
		var br = document.createElement("div");
		bl.className = options.className;
		br.className = options.className;
		bl.style.height = options.bottomHeight + "px";
		bl.style.fontSize = "1px";
		bl.style.backgroundPosition = "bottom right";
		bl.style.backgroundRepeat = "no-repeat";
		br.style.height = options.bottomHeight + "px";
		br.style.fontSize = "1px";
		br.style.backgroundPosition = "bottom left";		
		br.style.width = options.bottomHeight + "px";
		br.style.backgroundRepeat = "no-repeat";
		bl.appendChild(br);
		var bottom_height = options.bottomHeight + "px";
	
		// modify original div
		var inner_container = document.createElement('div');
		var blw = element.getStyle("border-left-width");
		var blc = element.getStyle("border-left-color");
		var bls = element.getStyle("border-left-style");
		inner_container.style.borderLeft = blw + " " + bls + " " + blc;
		var brw = element.getStyle("border-right-width");
		var brc = element.getStyle("border-right-color");
		var brs = element.getStyle("border-right-style");
		inner_container.style.borderRight = brw + " " + brs + " " + brc;
		inner_container.appendChild(inner_div);
		inner_div.style.paddingTop = options.topPadding + "px";
		inner_div.style.paddingBottom = options.bottomPadding + "px";
		element.style.border = "none";
		
		// insert divs
		element.appendChild(tl);
		element.appendChild(inner_container);
		element.appendChild(bl);

		// return iframe
		var newIframeNodes = element.getElementsByTagName('iframe');
		for(var i=0;i<iframeNodes.length;i++){
			newIframeNodes[i].src = iframeNodes[i].src;
		}
	}
}
Object.extend(Element.Methods, Hyjax.CurvyLight);
Element.addMethods();

/*------------------------------------------------------------*
   ReflectImage
 *------------------------------------------------------------*/
Hyjax.ReflectImage = {
	createReflectImage: function(element, set_options) {
		if (!element.tagName.eqi('img')) return;
		
		// initialize options
		var options = {
			scaleHeight: 0.5,
			opacity: 0.5
		}
		Object.extend(options, set_options || {});

		try {
			var reflectionHeight = Math.floor(element.height * options.scaleHeight);
			var reflectionWidth = element.width;
			var divHeight = Math.floor(element.height * (1 + options.scaleHeight));
			
			// create container and copy original image's classes and styles
			var container = document.createElement('div');
			container.className = element.className;
			container.style.cssText = element.style.cssText;
			element.style.verticalAlign = "bottom";
			
			var isMs = (document.all && !Hyjax.ua.opera);
			if (isMs) {
				var reflection = document.createElement("img");
				
				reflection.src = element.src;
				reflection.style.width = reflectionWidth + "px";
				reflection.style.marginBottom = "-" + (element.height - reflectionHeight) + "px";
				reflection.style.filter = "flipv progid:DXImageTransform.Microsoft.Alpha(opacity=" + (options.opacity * 100) + ", style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy=" + (options.scaleHeight * 100) + ")";
				
				container.style.width = reflectionWidth + "px";
				container.style.height = reflectionHeight + "px";
				element.parentNode.replaceChild(container, element);
				container.appendChild(element);
				container.appendChild(reflection);
			} else {
				var canvas = document.createElement('canvas');
				if (canvas.getContext) {
					var context = canvas.getContext("2d");
					
					canvas.style.height = reflectionHeight + "px";
					canvas.style.width = reflectionWidth + "px";
					canvas.height = reflectionHeight;
					canvas.width = reflectionWidth;
					container.style.width = reflectionWidth + "px";
					container.style.height = divHeight + "px";
					element.parentNode.replaceChild(container, element);
					
					container.appendChild(element);
					container.appendChild(canvas);
					
					context.save();

					context.translate(0, element.height - 1);
					context.scale(1, -1);
					context.drawImage(element, 0, 0, reflectionWidth, element.height);
					context.restore();
					context.globalCompositeOperation = "destination-out";
					var gradient = context.createLinearGradient(0, 0, 0, reflectionHeight);
					gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
					gradient.addColorStop(0, "rgba(255, 255, 255, " + (1 - options.opacity) + ")");
					context.fillStyle = gradient;
					if (navigator.appVersion.indexOf("WebKit") != -1) {
						context.fill();
					} else {
						context.fillRect(0, 0, reflectionWidth, reflectionHeight * 2);
					}
				}
			}
		} catch(e) {
		}
	}
}
Object.extend(Element.Methods, Hyjax.ReflectImage);
Element.addMethods();

/*------------------------------------------------------------*
   EventHandler
 *------------------------------------------------------------*/
Hyjax.EventHandler = {
	obj: new Array(),
	initialize: function() {
		Event.observe(document, 'click', Hyjax.EventHandler.eClick.bind(this));
		Event.observe(document, 'mousemove', this.eMouseMove.bind(this));
		Event.observe(document, 'mousedown', this.eMouseDown.bind(this));
		Event.observe(document, 'mouseup', this.eMouseUp.bind(this));
		Event.observe(document, 'mouseover', this.eMouseOver.bind(this));
		Event.observe(document, 'mouseout', this.eMouseOut.bind(this));
		Event.observe(window, 'load', this.eLoad.bind(this));
		Event.observe(window, 'resize', this.eResize.bind(this));
	},
	node: function(e) {
		var __node = Event.element(e);
		if (!__node.tagName) __node = __node.parentNode;
		return __node;
	},
	cancel: function(e) {
		if (Hyjax.ua.safari) {
			var __node = Hyjax.EventHandler.node(e);
			__node['onclick'] = function() {return false};
		} else {
			Event.stop(e);
		}
	},
	eClick: function(e) {
		var __node = this.node(e);
		if (!document.all) {
			if (__node.tagName.eqi('label')) {
				var __target = __node.attributes.getNamedItem('for');
				if (__target) {
					__node = $(__target.value);
					if (__node.disabled) return false;
					if (Hyjax.ua.safari) {
						if (__node.tagName.eqi('input')) {
							if (__node.type.eqi('checkbox')) __node.checked = !__node.checked;
							if (__node.type.eqi('radio')) __node.checked = true;
						}
					}
				}
			}
		}
		var __ret = this.sendEvent('eClick', __node, e);
		this.prevent(__ret, e);
		return __ret;
	},
	eMouseMove: function(e) {
		var __node = this.node(e);
		var __ret = this.sendEvent('eMouseMove', __node, e);
		this.prevent(__ret, e);
		return __ret;
	},
	eMouseDown: function(e) {
		var __node = this.node(e);
		var __ret = this.sendEvent('eMouseDown', __node, e);
		this.prevent(__ret, e);
		return __ret;
	},
	eMouseUp: function(e) {
		var __node = this.node(e);
		var __ret = this.sendEvent('eMouseUp', __node, e);
		this.prevent(__ret, e);
		return __ret;
	},
	eMouseOver: function(e) {
		var __node = this.node(e);
		var __ret = this.sendEvent('eMouseOver', __node, e);
		this.prevent(__ret, e);
		return __ret;
	},
	eMouseOut: function(e) {
		var __node = this.node(e);
		var __ret = this.sendEvent('eMouseOut', __node, e);
		this.prevent(__ret, e);
		return __ret;
	},
	eChange: function(e) {
		var __node = this.node(e);
		var __ret = this.sendEvent('eChange', __node, e);
		this.prevent(__ret, e);
		return __ret;
	},
	eLoad : function (e) {
		var __ret = true;
		var __res = false;
		for (var i = 0; i < this.obj.length; ++i) {
			if (this.obj[i].eLoad) {
				__res = this.obj[i].eLoad(e);
				__ret = (__ret && __res);
			}
		}
		this.prevent(__ret, e);
		return __ret;
	},
	eResize: function(e) {
		var __ret = true;
		var __res = false;
		for (var i = 0; i < this.obj.length; ++i) {
			if (this.obj[i].eResize) {
				__res = this.obj[i].eResize(e);
				__ret = (__ret && __res);
			}
		}
		this.prevent(__ret, e);
		return __ret;
	},
	sendEvent : function(event_name, node, event) {
		var __ret;
		var __res;
		//var __ret = true;
		//var __res = false;
		for (var i = 0; i < this.obj.length; ++i) {
			if (this.obj[i][event_name]) {
				__res = this.obj[i][event_name](node, event);
				if (typeof __res != 'undefined') {
					if (typeof __ret != 'undefined') {
						__ret = (__ret && __res);
					} else {
						__ret = __res;
					}
				}
			}
		}
		return __ret;
	},
	prevent : function(ret, e) {
		if (typeof ret != 'undefined' && ret == false) {
			this.cancel(e);
		} 
	}, 
	register: function(o) {
		Hyjax.EventHandler.obj.push(o);
	}
}
Hyjax.EventHandler.initialize();

/*------------------------------------------------------------*
   EffectPlanner
 *------------------------------------------------------------*/
Hyjax.EffectPlanner = Class.create();
Hyjax.EffectPlanner.prototype = {
	initialize: function(effects) {
		var plans = [];
		effects.each(function(effect) {
			var next = effect.next;
			var plan = {
				next: (next != undefined) ? ((typeof next == 'function') ? next : function(planner) { planner.invoke(next) }) : undefined,
				options: effect.options || {},
				effects: []
			};
			delete effect.next;
			delete effect.options;

			var afterFinish = plan.options.afterFinish;
			plan.options.afterFinish = function() {
				if(afterFinish) {
					afterFinish.apply(null, arguments);
				}
				if(plan.next) {
					plan.next(this);
				}
				else {
					this.next();
				}
			}.bind(this);

			$H(effect).each(function(set) {
				plan.effects.push([(Hyjax.Effect[set.key] ? Hyjax.Effect[set.key] : Effect[set.key]), set.value]);
				set.value[set.value.length - 1].sync = true;
			});
			plans.push(plan);
		}.bind(this));
		this.plans = plans;
		this.invoke(0);
	},
	invoke: function(i) {
		var plan = this.plans[i];
		if(plan) {
			this.index = i;
			new Effect.Parallel(plan.effects.map(function(effect) {return new effect[0](effect[1][0], effect[1][1], effect[1][2])}), plan.options);
		}
	},
	next: function(nextCount) {
		if(nextCount == undefined) {
			nextCount = 1;
		}
		this.invoke(this.index + nextCount);
	}
};
   
/*------------------------------------------------------------*
   Effects
 *------------------------------------------------------------*/
Hyjax.Effect = new Object();
Hyjax.Effect.Transitions = new Object();

Hyjax.Effect.Transitions.freefall = function(pos) {
	return Math.pow(pos, 3);
}

Hyjax.Effect.Transitions.brake = function(pos) {
	return Math.sqrt(Math.sqrt(pos));
}

Hyjax.Effect.Transitions.rough = function(pos) {
	if (pos <= 0.75) {
		return 1.25*Math.pow(pos, 4);
	} else {
		this.flipper = (this.flipper ? false : true);
		return (this.flipper ? 1.0 : pos);
	}
}

/*------------------------------------------------------------*
   EffectPlans
 *------------------------------------------------------------*/
Hyjax.EffectPlan = new Object();
Hyjax.EffectPlan.Sample = function(element) {
	element = $(element);
	return new Hyjax.EffectPlanner([
		{
			Move: [element, {x: 200, y: 200}]
		},
		{
			Move: [element, {x: 0, y: 300}]
		},
		{
			Move: [element, {x: 300, y: 0}]
		},
		{
			Move: [element, {x: 0, y: -300}]
		},
		{
			Move: [element, {x: -300, y: 0}],
			next: 1
		}
	]);
}

Hyjax.EffectPlan.Sample2 = function(element) {
	element = $(element);
    var colors = { 0: '#FF0000', 1: '#00FF00', 2: '#0000FF', count: 0 };
    var style = element.style;
    var deathCount = 2;
    return new Hyjax.EffectPlanner(
        [
            {
                Appear: [element],
                Move: [element, {x: 0, y: 100}],
                next: function(planner) {
                    if(deathCount--) {
                        planner.next();
                    }
                    else {
                        planner.next(2);
                    }
                }
            },
            {
                Fade: [element],
                Move: [element, {x: 0, y: -100}],
                options: {
                    afterFinish: function() {
                        style.backgroundColor = colors[++colors.count % 3];
                    }
                },
                next: 0
            },
            {
                Fade: [element],
                Move: [element, {x: 500, y: 0}],
                options: {
                    duration: 0.4
                }
            }
        ]
    );
}

/*------------------------------------------------------------*
   Behaviours
 *------------------------------------------------------------*/
Hyjax.Behaviour = new Object();
Hyjax.Behaviour.MagicClass = {
	initialize: function() {
		Hyjax.EventHandler.register(this);
		this.setEnabled(true);
	},
	setEnabled: function(enabled) {
		this.enabled = enabled;
	},
	eLoad: function() {
		if (!this.enabled) return;
		var magicElements = document.getElementsByClassNameRegExp('Hyjax-.*');
		magicElements.each(function(element) {
			var classNames = new Element.classNames(element);
			classNames.each(function(className){
				if (className.match(/^Hyjax-/)) {
					var magicWords = className.split('-');
					magicWords.shift();
					var magicWord = magicWords.shift();
					if (Hyjax.Behaviour.MagicClass[magicWord]) {
						Hyjax.Behaviour.MagicClass[magicWord](this, magicWords);
					}
				}
			}.bind(element));
		});
	},
	CurvyCorners: function(element, args) {
		var options = {
			tl: (args[0] ? args[0] : 20),
			tr: (args[1] ? args[1] : 20),
			bl: (args[2] ? args[2] : 20),
			br: (args[3] ? args[3] : 20)
		}
		element.toCurvy(options);
	},
	CurvyLight: function(element, args) {
		var options = {
			className:     (args[0] ? args[0] : null),
			topHeight:     (args[1] ? args[1] : 10),
			bottomHeight:  (args[2] ? args[2] : 10),
			topPadding:    (args[3] ? args[3] : 0),
			bottomPadding: (args[4] ? args[4] : 0)
		}
		element.toCurvyLight(options);
	},
	ReflectImage: function(element, args) {
		var options = {
			scaleHeight: (args[0] ? parseFloat(args[0]) : 0.5),
			opacity: (args[1] ? parseFloat(args[1]) : 0.5)
		}
		element.createReflectImage(options);
	},
	SWF: function(element, args) {
		var options = {
			swf: args[0],
			id: args[1],
			width: args[2],
			height: args[3],
			version: args[4],
			backgroundColor: args[5]
		}
		var so = new Hyjax.Component.SWFObject(options);
		so.setSwf(element);
	},
	VerticalText: function(element, args) {
		new Hyjax.Component.VerticalText(element);
	}
}
Hyjax.Behaviour.MagicClass.initialize();

Hyjax.Behaviour.PageAnchor = {
	initialize: function() {
		Hyjax.EventHandler.register(this);
		this.setEnabled(true);
		this.setOptions(arguments[1] || {});
	},
	setEnabled: function(enabled) {
		this.enabled = enabled;
	},
	setOptions: function(options) {
		this.options = {
			transition: Hyjax.Effect.Transitions.brake
		}
		Object.extend(this.options, options || {});
	},
	eClick: function(node) {
		if (!this.enabled) return;
		if (Hyjax.ua.safari || Hyjax.ua.konqueror) return;
		if (!node.tagName.eqi('a')) {
			if (node.parentNode.nodeType != 1) return;
			node = node.parentNode;
		}
		if ((node.tagName.eqi('a') && node.href.indexOf('#') != -1) && 
			(node.pathname == location.pathname || '/'+node.pathname == location.pathname) &&
			(node.search == location.search)) {
			var target_name = node.href.slice(node.href.indexOf('#')+1);
			var scr2 = $A(document.getElementsByTagName('a')).find(
				function(alink) {
					return (alink.name == target_name);
				}
			);
			var options = this.options;
			options.afterFinish = function() {window.location.href = node.href};
			if (!scr2) scr2 = document.body;
			new Effect.ScrollTo(scr2, this.options);
			return false;
		}
	}
}
Hyjax.Behaviour.PageAnchor.initialize();

Hyjax.Behaviour.LabelHighlight = {
	initialize: function() {
		Hyjax.EventHandler.register(this);
		this.setEnabled(true);
		this.setOptions(arguments[1] || {});
	},
	setEnabled: function(enabled) {
		this.enabled = enabled;
	},
	setOptions: function(options) {
		this.options = {
			transition: Hyjax.Effect.Transitions.brake
		}
		Object.extend(this.options, options || {});
	},
	eMouseOver: function(node) {
		if (node.tagName.eqi('label')) {
			var options = this.options;
			node.style.cursor = (options.cursor ? options.cursor : (document.all ? 'hand' : 'pointer'));
			if (options.focus_class) {
				this.original_class = node.className;
				node.className = options.focus_class+' '+this.original_class;
			}
		}
	},
	eMouseOut: function(node) {
		if (node.tagName.eqi('label')) {
			var options = this.options;
			if (options.focus_class) {
				node.className = this.original_class;
			}
		}
	}
}
Hyjax.Behaviour.LabelHighlight.initialize();

Hyjax.Behaviour.SyncCheckbox = {
	initialize: function() {
		Hyjax.EventHandler.register(this);
		this.setEnabled(true);
		this.setOptions(arguments[1] || {});
	},
	setEnabled: function(enabled) {
		this.enabled = enabled;
	},
	setOptions: function(options) {
		this.options = {
			transition: Hyjax.Effect.Transitions.brake
		}
		Object.extend(this.options, options || {});
	},
	eLoad: function() {
		var sync_check = new Object();
		var checks = document.getElementsByTagName('input');
		for(var i=0; i<checks.length; ++i) {
			ck = checks[i];
			if (!ck.name || !ck.id) continue;
			if (ck.type.eqi('checkbox')) {
				if (typeof sync_check[ck.name] == 'undefined') {
					sync_check[ck.name] = new Object();
				}
				if (typeof sync_check[ck.name][ck.value] == 'undefined') {
					sync_check[ck.name][ck.value] = new Array();
				}
				sync_check[ck.name][ck.value].push(ck);
			}
		}
		for(sync_check_name in sync_check) {
			for(sync_check_key in sync_check[sync_check_name]) {
				var sync = sync_check[sync_check_name][sync_check_key];
				if (sync.length > 1) {
					new Hyjax.Component.SyncCheckbox(sync);
				}
			}
		}
		/*
		for(var i=0; i<sync_check.length; ++i) {
			var sync_temp = sync_check[i];
			if (sync_temp.length > 0) {
				for(var j=0; j<sync_temp.length; ++j) {
					var sync_grp = sync_temp[j];
					if (sync_grp > 1) {
						new Hyjax.Component.SyncCheckbox(sync_grp);
					}
				}
			}
		}
		*/
	}
}
Hyjax.Behaviour.SyncCheckbox.initialize();

/**
 * イメージボタンに対して、通常のsubmitボタン同様にクリックされたボタンの名前へ値を入れる
 
Hyjax.Behaviour.SubmitTracer = {
	initialize: function() {
		Hyjax.EventHandler.register(this);
		this.setEnabled(true);
	},
	setEnabled: function(enabled) {
		this.enabled = enabled;
	},
	eClick: function(node) {
		if (node.tagName.eqi('input') && (node.type.eqi('submit') || node.type.eqi('image')))
		{
			pointer 		   = node.findParentNode('form');
			pointer.submitName = node.name;
			pointer.submitId   = node.id;
		}
	}
}
Hyjax.Behaviour.SubmitTracer.initialize();
*/
		
/*------------------------------------------------------------*
   Components
 *------------------------------------------------------------*/
Hyjax.Component = new Object();
Hyjax.Component.Accordion = Class.create();
Hyjax.Component.Accordion.prototype = {
	initialize: function(togglers, stretchers, options) {
		Hyjax.EventHandler.register(this);
		this.togglers = togglers;
		this.stretchers = stretchers;
		this.setOptions(options);
	},
	setOptions: function(options) {
		this.options = {
			transition: Hyjax.Effect.Transitions.rough,
			duration: 0.6,
			toggle: 'blind'
		}
		Object.extend(this.options, options || {});
	},
	eClick: function(node) {
		var options = this.options;
		var stretchers = this.stretchers;
		this.togglers.each(function(toggler,i) {
			if (toggler == node) {
				options.clicked_node = node;
				options.target_stretcher = stretchers[i];
				Effect.toggle(stretchers[i], options.toggle, options);
			}
		});
	}
}

Hyjax.Component.SWFObject = Class.create();
Hyjax.Component.SWFObject.prototype = {
	initialize: function(options) {
		this.setOptions(options);
	},
	setOptions: function(options) {
		this.options = {
			swf: null,
			id: "mymovie",
			width: 100,
			height: 100,
			version: 7,
			backgroundColor: "#ffffff"
		}
		Object.extend(this.options, options || {});
	},
	setSwf: function(element) {
		if (typeof SWFObject == 'undefined') {
			throw("Hyjax.Component.SWFObject needs swfobject.js");
		}
		var node = $(element);
		var opt  = this.options;
		var so   = new SWFObject(opt.swf, opt.id, opt.width, opt.height, opt.version, opt.backgroundColor);
		if (opt.params) {
			for (var key in opt.params) {
				so.addParam(key, opt.params[key]);
			}
		}
		var ret  = so.write(node);
		if (!ret) {
			if (opt.onNotInstalled) opt.onNotInstalled();
		} else {
			if (opt.onInstalled) opt.onInstalled();
		}
	}
}

Hyjax.Component.CheckboxAsRadio = Class.create();
Hyjax.Component.CheckboxAsRadio.prototype = {
	initialize: function(check_group, options) {
		Hyjax.EventHandler.register(this);
		this.check_group = check_group;
		this.setOptions(options);
	},
	setOptions: function(options) {
		this.options = {
			enabled_class: '',
			disabled_class: ''
		}
		Object.extend(this.options, options || {});
	},
	eClick: function(node) {
		if(!node.tagName.eqi('input')) return;
		if(node.disabled) return;
		var options = this.options;
		var group_mem = null;
		var is_member = false;
		for(var i=0; i<this.check_group.length; ++i) {
			group_mem = this.check_group[i];
			if(group_mem.indexOf(node) != -1) {
				is_member = true;
				break;
			}
		}
		if (is_member) {
			var checked = false;
			for(var i=0; i<group_mem.length; ++i) {
				if (group_mem[i].checked) {
					checked = true;
					break;
				}
			}
			for(var i=0; i<this.check_group.length; ++i) {
				var target_grp = this.check_group[i];
				if (!checked || (target_grp == group_mem)) {
					enabled = true;
					class_name = options.enabled_class;
				} else {
					enabled = false;
					class_name = options.disabled_class;
				}
				for(var j=0; j<target_grp.length; ++j) {
					var chk = target_grp[j];
					chk.disabled = !enabled;
					if (!enabled && chk.checked) chk.checked = false;
					if (chk.parentNode.tagName.eqi('label')) {
						chk.parentNode.className = class_name;
					}
				}
			}
		}
	}
}

Hyjax.Component.WindowWorkspace = {
	windowCollection: new Array(),
	zhwm: 100,
	zOrder: function(win) {
		win.style.zIndex = this.zhwm++;
	},
	invoke: function(node, options) {
		Hyjax.EventHandler.register(node);
		node.style.position = 'absolute';
		var parent = node.parentNode;
		var node = parent.removeChild(node);
		document.body.insertBefore(node,document.body.lastChild);
		Object.extend(node, Hyjax.Component.BoxWindow);
		node.setOptions(options);
		this.windowCollection.push(node);
	},
	observeShowNearMouse: function(node, observer) {
		Event.observe(observer, 'mousedown', node.showNearMouse.bind(node));
	},
	observeShowRelativeMouse: function(node, observer) {
		Event.observe(observer, 'mousedown', node.showRelativeMouse.bind(node));
	},
    observeShowCenterDisplay: function(node, observer) {
        Event.observe(observer, 'mousedown', node.showCenterDisplay.bind(node));
    },
	closeCollections: function(except) {
		for(var i=0; i<this.windowCollection.length; ++i) {
			var win = this.windowCollection[i];
			if(win != except) {
				win.closeBox();
			}
		}
	}
}

Hyjax.Component.BoxWindow = Class.create();
Hyjax.Component.BoxWindow = {
	setOptions: function(options) {
		this.options = {
			opacity: 1,
			close_another_windows: true,
			close_btn: null,
			grabber: null
		}
		Object.extend(this.options, options || {});
	},
	showBox: function(left, top) {
		this.style.left = left+"px";
		this.style.top = top+"px";
		this.zOrder();
		this.style.visibility = "visible";
		if (this.options.show_effect) {
			if (this.options.close_another_windows) {
				var element = this;
				var options = {
					duration: 0.8,
					queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
				}
			}
			Hyjax.Component.WindowWorkspace.closeCollections(this);
			new this.options.show_effect(this, options);
		} else {
			this.style.display = "block";
			Hyjax.Component.WindowWorkspace.closeCollections(this);
		}
	},
	showScrollBox: function(scrollNode, left, top, width, height) {
		scrollNode.style.width = width+"px";
		scrollNode.style.height = height+"px";
		scrollNode.style.overflow = "auto";
		this.showBox(left, top);
	},
	showNearMouse: function(e) {
		var left = Event.pointerX(e);
		var top  = Event.pointerY(e);
		var node = Event.element(e)
		if (this.options.onShowNearMouse) {
			this.options.onShowNearMouse(node, left, top);
		}
		this.showBox(left, top);
	},
	showRelativeMouse: function(e) {
		var node = Event.element(e)
		if (this.options.onShowRelativeMouse) {
			this.options.onShowRelativeMouse(node);
		}
		var left = Event.pointerX(e) + this.options.leftShift;
		var top  = Event.pointerY(e) + this.options.topShift;
		this.showBox(left, top);
	},
    showCenterDisplay: function(e) {
        var node = Event.element(e)
        if (this.options.onShowCenterDisplay) {
            if(!this.options.onShowCenterDisplay(node)){
                return false;
            }
        }
        var left = 0;
        var top = 0;
        var dw = document.documentElement.clientWidth
              || window.innerWidth
              || 0;
        var dh = document.documentElement.clientHeight
              || window.innerHeight
              || 0;
        var fw = this.options.grabber.getWidth();
        var fh = this.options.grabber.getHeight();
        if (dw - fw > 1) {left = (dw - fw) / 2;}
        if (dh - fh > 1) {top = (dh - fh) / 2;}
        left += (window.pageXOffset
              || document.documentElement.scrollLeft
              || document.body.scrollLeft
              || 0) + this.options.leftShift;
        top += (window.pageYOffset
             || document.documentElement.scrollTop
             || document.body.scrollTop
             || 0) + this.options.topShift;
        this.showBox(left, top);
    },
	closeBox: function() {
		if (this.options.close_effect) {
			var element = this;
			var options = {
				duration: 0.8,
				queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
			}
			new this.options.close_effect(this, options);
		} else {
			this.hide();
		}
	},
	zOrder: function() {
		Hyjax.Component.WindowWorkspace.zOrder(this);
	},
	eClick: function(node) {
		var close = false;
		if ($(this.options.close_btn).isAncestor(node)) {
			close = true;
		} else if (node.isAncestor && node.isAncestor(this)) {
			this.zOrder();
		}
		if (close) {
			this.closeBox();
		}
	},
	eMouseDown: function(node, e) {
		if (!this.options.grabber) return;
		if (!$(this.options.grabber).isAncestor(node)) return;
		if (e.button == 1 || e.which == 1) {
			var left = parseInt(this.getStyle("left"));
			var top  = parseInt(this.getStyle("top"));
			this.dragX = Event.pointerX(e) - left;
			this.dragY = Event.pointerY(e) - top;
			this.dragging = true;
			return false;
		}
	},
	eMouseMove: function(node, e) {
		if (!this.dragging) return;
		if (!this.options.grabber) return;
		if (e.button == 1 || e.which == 1) {
			var x = Event.pointerX(e) - this.dragX;
			var y = Event.pointerY(e) - this.dragY;
			this.style.left = x+'px';
			this.style.top  = y+'px';
			return false;
		}
	},
	eMouseUp: function(node) {
		if (!this.dragging) return;
		if (!this.options.grabber) return;
		this.dragging = false;
	}
}

Hyjax.Component.SyncCheckbox = Class.create();
Hyjax.Component.SyncCheckbox.prototype = {
	initialize: function(sync_checks, options) {
		Hyjax.EventHandler.register(this);
		this.sync_checks = sync_checks;
		this.setOptions(options);
	},
	setOptions: function(options) {
		this.options = {
		}
		Object.extend(this.options, options || {});
	},
	eClick: function(node) {
		if (this.sync_checks.indexOf(node) != -1) {
			var checked = node.checked;
			for(var i=0; i<this.sync_checks.length; ++i) {
				this.sync_checks[i].checked = checked;
			}
		}
	}
}

Hyjax.Component.VerticalText = Class.create();
Hyjax.Component.VerticalText.prototype = {
	initialize: function(node) {
		if(Hyjax.ua.ie){
			node.style.writingMode = 'tb-rl';
		} else {
	        var text = new String(node.innerHTML);
	        var vtext = "";
	        for(var i=0; i<text.length; ++i) {
	                var ch = text.charAt(i);
	                if (ch == 'ー') {ch = '｜'};
	                vtext += ch + "\n";
	        }
	        node.innerHTML = '<pre style="line-height: 1em;">'+vtext+'</pre>';
        }
	}
}

Hyjax.Component.textHint = Class.create();
Hyjax.Component.textHint.prototype = {
	initialize: function(id, options) {
		Hyjax.EventHandler.register(this);
		this.node = $(id);
		Event.observe(this.node, 'focus', this.eFocus.bind(this));
		Event.observe(this.node, 'blur', this.eBlur.bind(this));
		this.setOptions(options);
		this.node.isEmpty = function() {
			var v = this.node.value;
			return (v == '' || v == this.options.hint);
		}.bind(this);
		this.node.setValue = function(v) {
			if (v != this.options.hint && v != '') {
				this.node.value = '';
				this.node.className = this.options.textClass;
			}
			this.node.value = v;
		}.bind(this);
	},
	setOptions: function(options) {
		this.options = {
			hint: '',
			hintClass: '',
			textClass: ''
		}
		Object.extend(this.options, options || {});
	},
	eFocus: function() {
		var node = this.node;
		if (node.value == this.options.hint) {
			node.value = '';
			node.className = this.options.textClass;
		}
	},
	eLoad: function() {
		this.eBlur();
	},
	eBlur: function() {
		var node = this.node;
		if (node.value == '') {
			node.value = this.options.hint;
			node.className = this.options.hintClass;
		} else {
			node.className = this.options.textClass;
		}
	}
}

/**
 *	zip_codeからaddressを取得
 */
/*
Hyjax.Component.ZipToAddress = Class.create();
Hyjax.Component.ZipToAddress.prototype = {
	initialize: function(id, zip1_id, zip2_id,options) {
		Hyjax.EventHandler.register(this);
		this.id = id;
		this.zip1 = $(zip1_id);
		this.zip2 = $(zip2_id);
		this.win  = null;
		this.setOptions(options);
	},
	setOptions: function(options) {
		this.options = {
			name : 'zipAddressWindow',
			settings : 'width=640,height=300,resizable=yes'
		}
		Object.extend(this.options, options || {});
	},
	eClick: function(node) {
		if(node.id.eqi(this.id))
		{
			this.anchor = $(this.id);
			this.post1 = this.zip1.value;
			this.post2 = this.zip2.value;
			if(!this.post1 || !this.post2){
				alert('まず郵便番号を入力してください');
				return (false);
			}	
			this.href = this.anchor.href + "?post1=" + this.post1 + "&post2=" + this.post2;
			this.win = open( this.href, this.options.name , this.options.settings);
			this.win.focus();
				
		}
		return (false);
	}
}*/

Hyjax.Component.EventCanceler = Class.create();
Hyjax.Component.EventCanceler.prototype = {
        initialize: function(node) {
                Hyjax.EventHandler.register(this);
                this.node = $(node);
        },
        eClick: function(node) {
			if (this.node.isAncestor(node)){
				return false;
			}
		},
//        eMouseMove: function(node) {
//			if (this.node.isAncestor(node)){
//				//return false;
//			}
//        },
        eMouseDown: function(node) {
			if (this.node.isAncestor(node)){
				return false;
			}
        },
        eMouseUp: function(node) {
			if (this.node.isAncestor(node)){
				return false;
			}
        },
//        eMouseOver: function(node) {
//			if (this.node.isAncestor(node)){
//				//return false;
//			}
//        },
        eMouseOut: function(node) {
			if (this.node.isAncestor(node)){
				return false;
			}
        }
}

Hyjax.Component.Image = Class.create();

Hyjax.Component.Image.LayerLoader = Class.create();
Hyjax.Component.Image.LayerLoader.prototype = {
	id:null,
	prefix:null,
	initialize: function(id, options){
		this.prefix = id;
		this.options = options;
		Hyjax.EventHandler.register(this);
	},
	eLoad : function (e) {
		for (i = 0; i < document.images.length; ++i) {
			img = document.images[i]
			if (img.id) {
				if (img.id.match(this.prefix)) {
					new Hyjax.Component.Image.Layer(img.id,this.options);
				}
			}
		}
	}
}
Hyjax.Component.Image.Layer = Class.create();
Hyjax.Component.Image.Layer.prototype = {
	src:null,
	node:null,
	frame:null,
	image:null,
	height:0,
	width:0,
	uptop:0,
	downtop:0,
	left:0,
	loaded:false,
	id:'image_layer',
	options:{
		name:null,
		alt:null,
		id:null,
		className:'image-big',
		delay:true
	},
	initialize: function(node,options){
		Object.extend(this.options, options || {});
		this.node = $(node);
		this.setImageSrc();
		if(this.src.indexOf('/data/_default/img/41/') > 0){
			return;
		}
		Hyjax.EventHandler.register(this.node);
		Event.observe(this.node, 'mouseover', this.eMouseOver.bind(this), true);
		Event.observe(this.node, 'mouseout', this.eMouseOut.bind(this), true);
	},
	eMouseOver:function(e){
		if(!this.loaded){
			this.loaded = true;
			this.addImageTag();
			var image = this.image;
			if(image.src == '')image.src = this.src;
			var y = Event.pointerY(e);
			var x = Event.pointerX(e);
			var height = image.height == 0 ? 254 : image.height;
			var width = image.width == 0 ? 254 : image.width;
			this.uptop = y - height-60;
			this.downtop = y + 65;
			this.left = x - width - 70;
		}
		this.show();
	},
	eMouseOut:function(e){
		this.hide();
	},
	addImageTag: function(){
		var image = document.createElement('img');
		id = this.id;
		$(id).appendChild(image);
		var style = image.style;
		var options = this.options;
		if(options.name)image.name = options.name;
		if(options.alt)image.alt = options.alt;
		if(options.id)image.id = options.id;
		image.className = options.className;
		style.display = 'none';
		style.visibility='hidden';
		if(!options.delay)image.src = this.src;
		this.image = image;
		var image = this.image;
		if(image.src == '')image.src = this.src;
		this.resize();
		this.loaded = true;
	},
	resize : function(){
		var image = this.image;
		if(image.width > 254 || image.height > 254){
			if(image.width > image.height){
				ratio = image.height/image.width
				image.width = 254;
				image.height = 254 * ratio;
			}else{
				ratio = image.width/image.height
				image.height = 254;
				image.width = 254 * ratio;
			}
		}
	},
	setImageSrc:function(){
		this.src = this.node.src.replace(/width=\d+/,'width=254').replace(/height=\d+$/,'height=254');
	},
	show : function(){
		var style = this.image.style;
		var scroll = document.body.scrollTop || document.documentElement.scrollTop;
		var top = this.uptop;
		if(scroll > top){
			top = this.downtop;
		}
 		style.display = 'block';
		style.visibility='visible';
		style.position = 'absolute';
		style.left = this.left + 'px';
		style.top = top + 'px';
		this.resize();
	},
	hide : function(){
		var style = this.image.style;
		style.visibility = 'hidden';
 		style.display = 'none';
	}
}
