/* jQuery.nifty */
jQuery.fn.nifty = function(options){
	if((document.getElementById && document.createElement && Array.prototype.push) == false) return;
	
	options = options || "";
	h = (options.indexOf("fixed-height") >= 0) ? this.offsetHeight : 0;
		
	this.each(function(){ 
		var i,top="",bottom="";
		if(options != ""){
		    options=options.replace("left","tl bl");
		    options=options.replace("right","tr br");
		    options=options.replace("top","tr tl");
		    options=options.replace("bottom","br bl");
		    options=options.replace("transparent","alias");
		    if(options.indexOf("tl") >= 0) { top="both"; if(options.indexOf("tr") == -1) top="left"; } else if(options.indexOf("tr") >= 0) top="right";
		    if(options.indexOf("bl") >= 0) { bottom="both"; if(options.indexOf("br") == -1) bottom="left"; } else if(options.indexOf("br") >= 0) bottom="right";
		}
		if(top=="" && bottom=="" && options.indexOf("none") == -1){top="both";bottom="both";}
		
	    // IE Fix
		if(this.currentStyle!=null && this.currentStyle.hasLayout!=null && this.currentStyle.hasLayout==false)
    		jQuery(this).css("display","inline-block");

	    if(top!="") {
			//add top		
			var d=document.createElement("b"),lim=4,border="",p,i,btype="r",bk,color;
			jQuery(d).css("marginLeft","-"+_niftyGP(this,"Left")+"px");
			jQuery(d).css("marginRight","-"+_niftyGP(this,"Right")+"px");
			if(options.indexOf("alias") >= 0 || (color=_niftyBC(this))=="transparent"){
			    color="transparent";bk="transparent"; border=_niftyPBC(this);btype="t";
			    }
			else{
			    bk=_niftyPBC(this); border=_niftyMix(color,bk);
			    }
			jQuery(d).css("background",bk);
			d.className="niftycorners";
			p=_niftyGP(this,"Top");
			if(options.indexOf("small") >= 0){
			    jQuery(d).css("marginBottom",(p-2)+"px");
			    btype+="s"; lim=2;
			    }
			else if(options.indexOf("big") >= 0){
			    jQuery(d).css("marginBottom",(p-10)+"px");
			    btype+="b"; lim=8;
			    }
			else jQuery(d).css("marginBottom",(p-5)+"px");
			for(i=1;i<=lim;i++)
			    jQuery(d).append(CreateStrip(i,top,color,border,btype));
			jQuery(this).css("paddingTop", "0px");
			jQuery(this).prepend(d);				
		}
	    if(bottom!="") {
			//add bottom
			var d=document.createElement("b"),lim=4,border="",p,i,btype="r",bk,color;
			jQuery(d).css("marginLeft","-"+_niftyGP(this,"Left")+"px");
			jQuery(d).css("marginRight","-"+_niftyGP(this,"Right")+"px");
			if(options.indexOf("alias") >= 0 || (color=_niftyBC(this))=="transparent"){ color="transparent";bk="transparent"; border=_niftyPBC(this);btype="t"; } else { bk=_niftyPBC(this); border=_niftyMix(color,bk); }
			jQuery(d).css("background",bk);
			d.className="niftycorners";
			p=_niftyGP(this,"Bottom");
			if(options.indexOf("small") >= 0){
			    jQuery(d).css("marginTop",(p-2)+"px");
			    btype+="s"; lim=2;
			    }
			else if(options.indexOf("big") >= 0){
			    jQuery(d).css("marginTop",(p-10)+"px");
			    btype+="b"; lim=8;
			    }
			else jQuery(d).css("marginTop",(p-5)+"px");
			for(i=lim;i>0;i--)
			    jQuery(d).append(CreateStrip(i,bottom,color,border,btype));
			jQuery(this).css("paddingBottom", "0");
			jQuery(this).append(d);			
		};
	});
   
	if(options.indexOf("height") >= 0)
	{		
		this.each(function(){
	    	if(this.offsetHeight>h) h=this.offsetHeight;
	    	jQuery(this).css("height", "auto");
	
	    	var gap=h-this.offsetHeight;
	    	if(gap>0)
			{
	        	var t=document.createElement("b");t.className="niftyfill";jQuery(t).css("height",gap+"px");
	        	nc=this.lastChild;
	        	nc.className=="niftycorners" ? this.insertBefore(t,nc) : jQuery(this).append(t);
	    	}		
		});
	}
}

function CreateStrip(index,side,color,border,btype){
	var x=document.createElement("b");
	x.className=btype+index;
	jQuery(x).css("backgroundColor", color).css("borderColor", border);
	if(side=="left") jQuery(x).css("borderRightWidth", "0").css("marginRight", "0");
	else if(side=="right") jQuery(x).css("borderLeftWidth", "0").css("marginLeft", "0");
	return(x);
}

function _niftyPBC(x){
	var el=x.parentNode,c;
	while(el.tagName.toUpperCase()!="HTML" && (c=_niftyBC(el))=="transparent")
	    el=el.parentNode;
	if(c=="transparent") c="#FFFFFF";
	return(c);
}

function _niftyBC(x){
	var c=jQuery(x).css("backgroundColor");
	if(c==null || c=="transparent" || c.indexOf("rgba(0, 0, 0, 0)") >= 0) return("transparent");
	if(c.indexOf("rgb") >= 0) {
		var hex="";
		var regexp=/([0-9]+)[, ]+([0-9]+)[, ]+([0-9]+)/;
		var h=regexp.exec(c);
		for(var i=1;i<4;i++){
		    var v=parseInt(h[i]).toString(16);
		    if(v.length==1) hex+="0"+v; else hex+=v;
		}
		c = "#"+hex;	
	}
	return(c);
}

function _niftyGP(x,side){
	var p=jQuery(x).css("padding"+side);
	if(p==null || p.indexOf("px") == -1) return(0);
	return(parseInt(p));
}

function _niftyMix(c1,c2){
	var i,step1,step2,x,y,r=new Array(3);
	c1.length==4 ? step1=1 : step1=2;
	c2.length==4 ? step2=1 : step2=2;
	for(i=0;i<3;i++){
	    x=parseInt(c1.substr(1+step1*i,step1),16);
	    if(step1==1) x=16*x+x;
	    y=parseInt(c2.substr(1+step2*i,step2),16);
	    if(step2==1) y=16*y+y;
	    r[i]=Math.floor((x*50+y*50)/100);
	    r[i]=r[i].toString(16);
	    if(r[i].length==1) r[i]="0"+r[i];
	}
	return("#"+r[0]+r[1]+r[2]);
}
/* Extend $.browser for Chrome */
$.extend($.browser, { chrome : /chrome/.test( navigator.userAgent.toLowerCase() ) });
$.fn.insideHeight = function(){
    var total = 0;
    $('*', $(this)).each(function(){
        var e = $(this);
        if(e.height()) total += e.height();
    });
    return total;
};

// X-Browser HTML5 style form field placeholders

function _setPlaceholders(){
jQuery(function() {
	jQuery.support.placeholder = false;
	test = document.createElement('input');
	if('placeholder' in test) jQuery.support.placeholder = true;
});
jQuery(function(){
    if(jQuery.support.placeholder===true) return;
    var active = document.activeElement;
	$(':text[placeholder], :password[placeholder]').focus(function () {
	    if($(this).is(':password'))
	        $(this).removeClass('hasPlaceholder');
		if ($(this).attr('placeholder') != '' && $(this).val() == $(this).attr('placeholder')) {
			$(this).val('').removeClass('hasPlaceholder');
			if($(this).data('password')) $(this).attr('type', 'password');
		}
	}).blur(function () {
	    if($(this).is(':password') && !$(this).val().length)
	       $(this).addClass('hasPlaceholder').addClass($(this).attr('placeholder').indexOf('Retype')==0 ? 'password retype' : 'password');
		else if ($(this).attr('placeholder') != '' && ($(this).val() == '' || $(this).val() == $(this).attr('placeholder'))) {
			$(this).val($(this).attr('placeholder')).addClass('hasPlaceholder');
		}
	});
	$(':text[placeholder], :password[placeholder]').blur();
	$(active).focus();
	$('form').submit(function () {
		$(this).find('.hasPlaceholder').each(function() { $(this).val(''); });
	});
});
};
_setPlaceholders();

/* jQuery.tools */
(function(c){c.tools=c.tools||{version:{}};c.tools.version.tooltip="1.0.2";var b={toggle:[function(){this.getTip().show()},function(){this.getTip().hide()}],fade:[function(){this.getTip().fadeIn(this.getConf().fadeInSpeed)},function(){this.getTip().fadeOut(this.getConf().fadeOutSpeed)}]};c.tools.addTipEffect=function(d,f,e){b[d]=[f,e]};c.tools.addTipEffect("slideup",function(){var d=this.getConf();var e=d.slideOffset||10;this.getTip().css({opacity:0}).animate({top:"-="+e,opacity:d.opacity},d.slideInSpeed||200).show()},function(){var d=this.getConf();var e=d.slideOffset||10;this.getTip().animate({top:"-="+e,opacity:0},d.slideOutSpeed||200,function(){c(this).hide().animate({top:"+="+(e*2)},0)})});function a(f,e){var d=this;var h=f.next();if(e.tip){if(e.tip.indexOf("#")!=-1){h=c(e.tip)}else{h=f.nextAll(e.tip).eq(0);if(!h.length){h=f.parent().nextAll(e.tip).eq(0)}}}function j(k,l){c(d).bind(k,function(n,m){if(l&&l.call(this)===false&&m){m.proceed=false}});return d}c.each(e,function(k,l){if(c.isFunction(l)){j(k,l)}});var g=f.is("input, textarea");f.bind(g?"focus":"mouseover",function(k){k.target=this;d.show(k);h.hover(function(){d.show()},function(){d.hide()})});f.bind(g?"blur":"mouseout",function(){d.hide()});h.css("opacity",e.opacity);var i=0;c.extend(d,{show:function(q){if(q){f=c(q.target)}clearTimeout(i);if(h.is(":animated")||h.is(":visible")){return d}var o={proceed:true};c(d).trigger("onBeforeShow",o);if(!o.proceed){return d}var n=f.position().top-h.outerHeight();var k=h.outerHeight()+f.outerHeight();var r=e.position[0];if(r=="center"){n+=k/2}if(r=="bottom"){n+=k}var l=f.outerWidth()+h.outerWidth();var m=f.position().left+f.outerWidth();r=e.position[1];if(r=="center"){m-=l/2}if(r=="left"){m-=l}n+=e.offset[0];m+=e.offset[1];h.css({position:"absolute",top:n,left:m});b[e.effect][0].call(d);c(d).trigger("onShow");return d},hide:function(){clearTimeout(i);i=setTimeout(function(){if(!h.is(":visible")){return d}var k={proceed:true};c(d).trigger("onBeforeHide",k);if(!k.proceed){return d}b[e.effect][1].call(d);c(d).trigger("onHide")},e.delay||1);return d},isShown:function(){return h.is(":visible, :animated")},getConf:function(){return e},getTip:function(){return h},getTrigger:function(){return f},onBeforeShow:function(k){return j("onBeforeShow",k)},onShow:function(k){return j("onShow",k)},onBeforeHide:function(k){return j("onBeforeHide",k)},onHide:function(k){return j("onHide",k)}})}c.prototype.tooltip=function(d){var e=this.eq(typeof d=="number"?d:0).data("tooltip");if(e){return e}var f={tip:null,effect:"slideup",delay:30,opacity:1,position:["top","center"],offset:[0,0],api:false};if(c.isFunction(d)){d={onBeforeShow:d}}c.extend(f,d);this.each(function(){e=new a(c(this),f);c(this).data("tooltip",e)});return f.api?e:this}})(jQuery);

/* jModal */
(function($) {
$.fn.jqm=function(o){
var p={
overlay: 50,
overlayClass: 'jqmOverlay',
closeClass: 'jqmClose',
trigger: '.jqModal',
ajax: F,
ajaxText: '',
target: F,
modal: F,
toTop: F,
onShow: F,
onHide: F,
onLoad: F
};
return this.each(function(){if(this._jqm)return H[this._jqm].c=$.extend({},H[this._jqm].c,o);s++;this._jqm=s;
H[s]={c:$.extend(p,$.jqm.params,o),a:F,w:$(this).addClass('jqmID'+s),s:s};
if(p.trigger)$(this).jqmAddTrigger(p.trigger);
});};

$.fn.jqmAddClose=function(e){return hs(this,e,'jqmHide');};
$.fn.jqmAddTrigger=function(e){return hs(this,e,'jqmShow');};
$.fn.jqmShow=function(t){return this.each(function(){t=t||window.event;$.jqm.open(this._jqm,t);});};
$.fn.jqmHide=function(t){return this.each(function(){t=t||window.event;$.jqm.close(this._jqm,t)});};

$.jqm = {
hash:{},
open:function(s,t){var h=H[s],c=h.c,cc='.'+c.closeClass,z=(parseInt(h.w.css('z-index'))),z=(z>0)?z:3000,o=$('<div></div>').css({height:'100%',width:'100%',position:'fixed',left:0,top:0,'z-index':z-1,opacity:c.overlay/100});if(h.a)return F;h.t=t;h.a=true;h.w.css('z-index',z);
 if(c.modal) {if(!A[0])L('bind');A.push(s);}
 else if(c.overlay > 0)h.w.jqmAddClose(o);
 else o=F;

 h.o=(o)?o.addClass(c.overlayClass).prependTo('body'):F;
 //if(ie6){$('html,body').css({height:'100%',width:'100%'});if(o){o=o.css({position:'absolute'})[0];for(var y in {Top:1,Left:1})o.style.setExpression(y.toLowerCase(),"(_=(document.documentElement.scroll"+y+" || document.body.scroll"+y+"))+'px'");}}
 /* IE Fix */
 if(ie6){
     $('html,body').css({height:'100%',width:'100%'});
     if(o){
         o=o.css({position:'absolute'})[0];
         $.each({Top:1,Left:1}, function(y){
            o.style.setExpression(y.toLowerCase(),"(_=(document.documentElement.scroll"+y+" || document.body.scroll"+y+"))+'px'");
         });
    }
 }

 if(c.ajax) {var r=c.target||h.w,u=c.ajax,r=(typeof r == 'string')?$(r,h.w):$(r),u=(u.substr(0,1) == '@')?$(t).attr(u.substring(1)):u;
  r.html(c.ajaxText).load(u,function(){if(c.onLoad)c.onLoad.call(this,h);if(cc)h.w.jqmAddClose($(cc,h.w));e(h);});}
 else if(cc)h.w.jqmAddClose($(cc,h.w));

 if(c.toTop&&h.o)h.w.before('<span id="jqmP'+h.w[0]._jqm+'"></span>').insertAfter(h.o);	
 (c.onShow)?c.onShow(h):h.w.show();e(h);return F;
},
close:function(s){var h=H[s];if(!h.a)return F;h.a=F;
 if(A[0]){A.pop();if(!A[0])L('unbind');}
 if(h.c.toTop&&h.o)$('#jqmP'+h.w[0]._jqm).after(h.w).remove();
 if(h.c.onHide)h.c.onHide(h);else{h.w.hide();if(h.o)h.o.remove();} return F;
},
params:{}};
var s=0,H=$.jqm.hash,A=[],ie6=$.browser.msie&&($.browser.version == "6.0"),F=false,
i=$('<iframe src="javascript:false;document.write(\'\');" class="jqm"></iframe>').css({opacity:0}),
e=function(h){if(ie6)if(h.o)h.o.html('<p style="width:100%;height:100%"/>').prepend(i);else if(!$('iframe.jqm',h.w)[0])h.w.prepend(i); f(h);},
f=function(h){try{$(':input:visible',h.w)[0].focus();}catch(_){}},
L=function(t){$()[t]("keypress",m)[t]("keydown",m)[t]("mousedown",m);},
m=function(e){var h=H[A[A.length-1]],r=(!$(e.target).parents('.jqmID'+h.s)[0]);if(r)f(h);return !r;},
hs=function(w,t,c){return w.each(function(){var s=this._jqm;$(t).each(function() {
    //console.log("this is:", this);
 //if(!this[c]){this[c]=[];$(this).click(function(){for(var i in {jqmShow:1,jqmHide:1})for(var s in this[i])if(H[this[i][s]])H[this[i][s]].w[i](this);return F;});}this[c].push(s);});});};
 //if(!this[c]){this[c]=[];$(this).click(function(){for(var i in ['jqmShow','jqmHide'])for(var s in this[i])if(H[this[i][s]])H[this[i][s]].w[i](this);return F;});}this[c].push(s);});});};
             /* IE fix */
             if(!this[c]){this[c]=[];
                 $(this).click(function(){
                     var m = this;
                     $.each({jqmShow:1,jqmHide:1}, function(i){
                         for(var s in m[i]) if(H[m[i][s]]) H[m[i][s]].w[i](m);
                     });
                    return F;
                 });
              }
              this[c].push(s);
          });
      });
  };
})(jQuery);

jQuery.extend({
	__stringPrototype: {
		/**
		 * ScriptFragmet, specialChar, and JSONFilter borrowed from Prototype 1.6.0.2
		 */
	 	JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
		ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
		specialChar: {
			'\b': '\\b',
			'\t': '\\t',
			'\n': '\\n',
			'\f': '\\f',
			'\r': '\\r',
			'\\': '\\\\'
		},
	
		/**
		 * Check if the string is blank (white-space only or empty).
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		blank: function(s) {
			return /^\s*$/.test(this.s(s) || ' ');
		},
		/**
		 * Converts a string separated by dashes into a camelCase equivalent.
		 * For instance, 'foo-bar' would be converted to 'fooBar'.
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		camelize: function(s) {
			var a = this.s(s).split('-'), i;
			s = [a[0]];
			for (i=1; i<a.length; i++){
				s.push(a[i].charAt(0).toUpperCase() + a[i].substring(1));
			}
			s = s.join('');
			return this.r(arguments,0,s);
		},
		/**
		 * Capitalizes the first letter of a string and downcases all the others.
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		capitalize: function(s) {
			s = this.s(s);
			s = s.charAt(0).toUpperCase() + s.substring(1).toLowerCase();
			return this.r(arguments,0,s);
		},
		/**
		 * Replaces every instance of the underscore character ("_") by a dash ("-").
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		dasherize: function(s) {
			s = this.s(s).split('_').join('-');
			return this.r(arguments,0,s);
		},
		/**
		 * Check if the string is empty.
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		empty: function(s) {
			return this.s(s) === '';
		},
		/**
		 * Tests whether the end of a string matches pattern.
		 * @param {Object} pattern
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		endsWith: function(pattern, s) {
			s = this.s(s);
			var d = s.length - pattern.length;
			return d >= 0 && s.lastIndexOf(pattern) === d;
		},
		/**
		 * escapeHTML from Prototype-1.6.0.2 -- If it's good enough for Webkit and IE, it's good enough for Gecko!
		 * Converts HTML special characters to their entity equivalents.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		escapeHTML: function(s) {
			s = this.s(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
			return this.r(arguments,0,s);
		},
		/**
		 * evalJSON from Prototype-1.6.0.2
		 * Evaluates the JSON in the string and returns the resulting object. If the optional sanitize parameter
		 * is set to true, the string is checked for possible malicious attempts and eval is not called if one
		 * is detected.
		 * @param {String} s string to be evaluated
		 * @return {Object} evaluated JSON result
		 */
		evalJSON: function(sanitize, s) {
			s = this.s(s);
			var json = this.unfilterJSON(false, s);
			try {
				if (!sanitize || this.isJSON(json)) { return eval('(' + json + ')'); }
			} catch (e) { }
			throw new SyntaxError('Badly formed JSON string: ' + s);
		},
		/**
		 * evalScripts from Prototype-1.6.0.2
		 * Evaluates the content of any script block present in the string. Returns an array containing
		 * the value returned by each script.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		evalScripts: function(s) {
			var scriptTags = this.extractScripts(this.s(s)), results = [];
			if (scriptTags.length > 0) {
				for (var i = 0; i < scriptTags.length; i++) {
					results.push(eval(scriptTags[i]));
				}
			}
			return results;
		},
		/**
		 * extractScripts from Prototype-1.6.0.2
		 * Extracts the content of any script block present in the string and returns them as an array of strings.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		extractScripts: function(s) {
			var matchAll = new RegExp(this.ScriptFragment, 'img'), matchOne = new RegExp(this.ScriptFragment, 'im'), scriptMatches = this.s(s).match(matchAll) || [], scriptTags = [];
			if (scriptMatches.length > 0) {
				for (var i = 0; i < scriptMatches.length; i++) {
					scriptTags.push(scriptMatches[i].match(matchOne)[1] || '');
				}
			}
			return scriptTags;
		},
		/**
		 * Returns a string with all occurances of pattern replaced by either a regular string
		 * or the returned value of a function.  Calls sub internally.
		 * @param {Object} pattern RegEx pattern or string to replace
		 * @param {Object} replacement string or function to replace matched patterns
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 * @see sub
		 */
		gsub: function(pattern, replacement, s) {
			s = this.s(s);
			if (jQuery.isFunction(replacement)) { s = this.sub(pattern, replacement, -1, s); }
			/* if replacement is not a function, do this the easy way; it's quicker */
			else { s = s.split(pattern).join(replacement); }
			return this.r(arguments,2,s);
		},
		/**
		 * Check if the string contains a substring.
		 * @param {Object} pattern RegEx pattern or string to find
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean result
		 */
		include: function(pattern, s) {
			return this.s(s).indexOf(pattern) > -1;
		},
		/**
		 * Returns a debug-oriented version of the string (i.e. wrapped in single or double quotes,
		 * with backslashes and quotes escaped).
		 * @param {Object} useDoubleQuotes escape double-quotes instead of single-quotes
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		inspect: function(useDoubleQuotes, s) {
			s = this.s(s);
			var escapedString;
			try {
				escapedString = this.sub(/[\x00-\x1f\\]/, function(match) {
					var character = jQuery.__stringPrototype.specialChar[match[0]];
					return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
			    }, -1, s);
			} catch(e) { escapedString = s; }
			s = (useDoubleQuotes) ? '"' + escapedString.replace(/"/g, '\\"') + '"' : "'" + escapedString.replace(/'/g, '\\\'') + "'";
			return this.r(arguments,1,s);
		},
		/**
		 * Treats the string as a Prototype-style Template and fills it with objectÕs properties.
		 * @param {Object} obj object of values to replace in string
		 * @param {Object} pattern RegEx pattern for template replacement (default matches Ruby-style '#{attribute}')
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		interpolate: function(obj, pattern, s) {
			s = this.s(s);
			if (!pattern) { pattern = /(\#\{\s*(\w+)\s*\})/; }
			var gpattern = new RegExp(pattern.source, "g");
			var matches = s.match(gpattern), i;
			for (i=0; i<matches.length; i++) {
				s = s.replace(matches[i], obj[matches[i].match(pattern)[2]]);
			}
			return this.r(arguments,2,s);
		},
		/**
		 * isJSON from Prototype-1.6.0.2
		 * Check if the string is valid JSON by the use of regular expressions. This security method is called internally.
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean result
		 */
		isJSON: function(s) {
			s = this.s(s);
			if (this.blank(s)) { return false; }
			s = s.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
			return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(s);
		},
		/**
		 * Evaluates replacement for each match of pattern in string and returns the original string.
		 * Calls sub internally.
		 * @param {Object} pattern RegEx pattern or string to replace
		 * @param {Object} replacement string or function to replace matched patterns
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 * @see sub
		 */
		scan: function(pattern, replacement, s) {
			s = this.s(s);
			this.sub(pattern, replacement, -1, s);
			return this.r(arguments,2,s);
		},
		/**
		 * Tests whether the beginning of a string matches pattern.
		 * @param {Object} pattern
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		startsWith: function(pattern, s) {
			return this.s(s).indexOf(pattern) === 0;
		},
		/**
		 * Trims white space from the beginning and end of a string.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		strip: function(s) {
			s = jQuery.trim(this.s(s));
			return this.r(arguments,0,s);
		},
		/**
		 * Strips a string of anything that looks like an HTML script block.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		stripScripts: function(s) {
			s = this.s(s).replace(new RegExp(this.ScriptFragment, 'img'), '');
			return this.r(arguments,0,s);
		},
		/**
		 * Strips a string of any HTML tags.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		stripTags: function(s) {
			s = this.s(s).replace(/<\/?[^>]+>/gi, '');
			return this.r(arguments,0,s);
		},
		/**
		 * Returns a string with the first count occurances of pattern replaced by either a regular string
		 * or the returned value of a function.
		 * @param {Object} pattern RegEx pattern or string to replace
		 * @param {Object} replacement string or function to replace matched patterns
		 * @param {Integer} count number of (default = 1, -1 replaces all)
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		sub: function(pattern, replacement, count, s) {
			s = this.s(s);
			if (pattern.source && !pattern.global) {
				var patternMods = (pattern.ignoreCase)?"ig":"g";
				patternMods += (pattern.multiline)?"m":"";
				pattern = new RegExp(pattern.source, patternMods);
			}
			var sarray = s.split(pattern), matches = s.match(pattern);
			if (jQuery.browser.msie) {
				if (s.indexOf(matches[0]) == 0) sarray.unshift("");
				if (s.lastIndexOf(matches[matches.length-1]) == s.length - matches[matches.length-1].length) sarray.push("");
			}
			count = (count < 0)?(sarray.length-1):count || 1;
			s = sarray[0];
			for (var i=1; i<sarray.length; i++) {
				if (i <= count) {
					if (jQuery.isFunction(replacement)) {
						s += replacement(matches[i-1] || matches) + sarray[i];
					} else { s += replacement + sarray[i]; }
				} else { s += (matches[i-1] || matches) + sarray[i]; }
			}
			return this.r(arguments,3,s);
		},
		/**
		 * 
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		succ: function(s) {
			s = this.s(s);
			s = s.slice(0, s.length - 1) + String.fromCharCode(s.charCodeAt(s.length - 1) + 1);
			return this.r(arguments,0,s);
		},
		/**
		 * Concatenate count number of copies of s together and return result.
		 * @param {Integer} count Number of times to repeat s
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		times: function(count, s) {
			s = this.s(s);
			var newS = "";
			for (var i=0; i<count; i++) {
				newS += s;
			}
			return this.r(arguments,1,newS);
		},
		/**
		 * Returns a JSON string
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		toJSON: function(s) {
			return this.r(arguments,0,this.inspect(true, this.s(s)));
		},
		/**
		 * Parses a URI-like query string and returns an object composed of parameter/value pairs.
		 * This method is mainly targeted at parsing query strings (hence the default value of '&'
		 * for the seperator argument). For this reason, it does not consider anything that is either
		 * before a question mark (which signals the beginning of a query string) or beyond the hash 
		 * symbol ("#"), and runs decodeURIComponent() on each parameter/value pair.
		 * @param {Object} separator string to separate parameters (default = '&')
		 * @param {Object} s
		 * @return {Object} object
		 */
		toQueryParams: function(separator, s) {
			s = this.s(s);
			var paramsList = s.substring(s.indexOf('?')+1).split('#')[0].split(separator || '&'), params = {}, i, key, value, pair;
			for (i=0; i<paramsList.length; i++) {
				pair = paramsList[i].split('=');
				key = decodeURIComponent(pair[0]);
				value = (pair[1])?decodeURIComponent(pair[1]):undefined;
				if (params[key]) {
					if (typeof params[key] == "string") { params[key] = [params[key]]; }
					params[key].push(value);
				} else { params[key] = value; }
			}
			return params;
		},
		/**
		 * truncate from Prototype-1.6.0.2
		 * Truncates a string to the given length and appends a suffix to it (indicating that it is only an excerpt).
		 * @param {Object} length length of string to truncate to
		 * @param {Object} truncation string to concatenate onto truncated string (default = '...')
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		truncate: function(length, truncation, s) {
			s = this.s(s);
			length = length || 30;
			truncation = (!truncation) ? '...' : truncation;
			s = (s.length > length) ? s.slice(0, length - truncation.length) + truncation : String(s);
			return this.r(arguments,2,s);
		},
		/**
		 * Converts a camelized string into a series of words separated by an underscore ("_").
		 * e.g. $.string('borderBottomWidth').underscore().str = 'border_bottom_width'
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		underscore: function(s) {
			s = this.sub(/[A-Z]/, function(c) { return "_"+c.toLowerCase(); }, -1, this.s(s));
			if (s.charAt(0) == "_") s = s.substring(1);
			return this.r(arguments,0,s);
		},
		/**
		 * unescapeHTML from Prototype-1.6.0.2 -- If it's good enough for Webkit and IE, it's good enough for Gecko!
		 * Strips tags and converts the entity forms of special HTML characters to their normal form.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		unescapeHTML: function(s) {
			s = this.stripTags(this.s(s)).replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
			return this.r(arguments,0,s);
		},
		/**
		 * unfilterJSON from Prototype-1.6.0.2.
		 * @param {Function} filter
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		unfilterJSON: function(filter, s) {
			s = this.s(s);
			filter = filter || this.JSONFilter;
			var filtered = s.match(filter);
			s = (filtered !== null)?filtered[1]:s;
			return this.r(arguments,1,jQuery.trim(s));
		},
	
		/**
		 * Sets .str property and returns $.string object.
		 * @param {String} s string to be evaluated
		 */
		r: function(args, size, s) {
			if (args.length > size || this.str === undefined) {
				return s;
			} else {
				this.str = ''+s;
				return this;
			};
		},
		s: function(s) {
			if (s === '' || s) { return s; }
			if (this.str === '' || this.str) { return this.str; }
			return this;
		}
	},
	string: function(str) {
		if (str === String.prototype) { jQuery.extend(String.prototype, jQuery.__stringPrototype); }
		else { return jQuery.extend({ str: str }, jQuery.__stringPrototype); }
	}
});
jQuery.__stringPrototype.parseQuery = jQuery.__stringPrototype.toQueryParams;

if(typeof(console) !== 'object'){ var console = { log: function(){ } }; }

// Microtemplating
(function(){
  var cache = {}; 
  this.tmpl = function tmpl(str, data){
    // Figure out if we're getting a template, or if we need to
    // load the template - and be sure to cache the result.
    var fn = !/\W/.test(str) ?
      cache[str] = cache[str] ||
        tmpl(document.getElementById(str).innerHTML) :
      // Generate a reusable function that will serve as a template
      // generator (and which will be cached).
      new Function("obj",
        "var p=[],print=function(){p.push.apply(p,arguments);};" +
        // Introduce the data as local variables using with(){}
        "with(obj){p.push('" +
        // Convert the template into pure JavaScript
        str
          .replace(/[\r\t\n]/g, " ")
          .split("<?").join("\t")
          .replace(/((^|\?>)[^\t]*)'/g, "$1\r")
          .replace(/\t=(.*?)\?>/g, "',$1,'")
          .split("\t").join("');")
          .split("?>").join("p.push('")
          .split("\r").join("\\'")
      + "');}return p.join('');");
    // Provide some basic currying to the user
    return data ? fn( data ) : fn;
  };
})();
jQuery.fn.rawElement = function(){
    if(null == this || this.length == 0){ return null; }
    return document.getElementById(this.attr('id'));
}
jQuery.fn.classNames = function() {
    if(null == this){ return [];}
    if($(this).attr('class') == null || $.trim($(this).attr('class')) == ''){ return []; }
    return $.trim($(this).attr('class')).split(/\s/);
};
int_id = function(idname){
    return parseInt($.string(idname).gsub(/[^\d]/, '').str);
};
jQuery.timer = function (interval, callback)
{
	var interval = interval || 100;

	if (!callback)
		return false;

	_timer = function (interval, callback) {
		this.stop = function () {
			clearInterval(self.id);
		};
	
		this.internalCallback = function () {
			callback(self);
		};
	
		this.reset = function (val) {
			if (self.id)
				clearInterval(self.id);
		
			var val = val || 100;
			this.id = setInterval(this.internalCallback, val);
		};
	
		this.interval = interval;
		this.id = setInterval(this.internalCallback, this.interval);
	
		var self = this;
	};

	return new _timer(interval, callback);
};
jQuery.preloadImages = function(){
	
	for(var i=0, images=[]; src=arguments[i]; i++){
	    //console.log("preload image: ", src);
		images.push(new Image());
		images[images.length - 1].src = src;
		//console.log(images[images.length - 1]);
		images[images.length - 1];
	}
};

jQuery.fn.gvform = function(){
    this.each(function(){
        var self = $(this),
            funcs = ['ffirst', 'nthrob', 'bhide', 'aj', 'cpwd', 'revealSelect', 'dirty', 'step'];
        if(self.length == 0 || !self.is('form')){ return; }
        self.ffirst = function(){ 
            if($(':input.ffirst:visible', self).length) $(':input.ffirst:visible', self).focus();
            else if($(':textarea.ffirst:visible', self).length) $(':textarea.ffirst:visible', self).focus();
            else if($(':input:text:first', self).length) $(':input:text:first', self).focus();
            else if($(':textarea:visible:first', self).length) $('textarea:visible:first', self).focus();
        };
        self.nthrob = function(){
            self.submit(function(){ $('img.throb', self).show(); });
        };
        self.bhide = function(){
            self.submit(function(){ $('a.submit', self).hide(); });
        };
        self.aj = function(){
            self.submit(function(){ return false; });
        };
        self.cpwd = function(){
            $(':password:visible', self).attr('value', '');
        };
        self.revealSelect = function(element){
            element.bind('change', function(e){
                var select = $(e.target), form = select.parents('form:first');
                if(form.length){
                    $('.reveal', form).hide().find(':input').attr('disabled', 'disabled');
                    if(select.val() && select.val() != ''){
                        $('#' + select.val() + '.reveal', form).show().find(':input').removeAttr('disabled');
                        $('.noemptyReveal', form).show().find(':input').removeAttr('disabled');
                    } else {
                        $('.noemptyReveal', form).hide().find(':input').attr('disabled', 'disabled');
                    }
                }
            });
        };
        self.dirty = function(element){
            if(element.is('form')){ 
                var form = element;
                if($.browser.msie) element = $(':input', element);
            } else { var form = element.parents('form:first'); }
            if(form.length){
                element.change(function(){
                    $('.clean', form).hide();
                    $('.submit', form).removeClass('disabled');
                });
            }
        };
        function _doStep(s){
            s = $(s), f = s.parents('form:first');
            $.each(s.classNames(), function(j,n){
                if(n.indexOf('sel')===0){
                    var t = parseInt(n.substring(3)), d = $('.step'+t, f);
                    if(s.val().length == 0){
                        if(d.length && !d.hasClass('stepnohide')) d.hide();
                        /*
                        $('.submit', f).addClass('disabled');
                        if(s.parents('fieldset.step').length){
                            $('fieldset.currentStep', f).removeClass('currentStep');
                            s.parents('fieldset.step').addClass('currentStep');
                        }
                        */
                        if(s.hasClass('steplast')) $('.submit', f).addClass('disabled');
                        if(s.parents('fieldset.step').length){
                            $('fieldset.currentStep', f).removeClass('currentStep');
                            s.parents('fieldset.step').addClass('currentStep');
                        }
                    } else {
                        if(d.length){
                            d.show();
                            /*
                            $('.disabled', d).removeClass('disabled');
                            $('fieldset.currentStep', f).removeClass('currentStep');
                            $('.step', d).addClass('currentStep');
                            */
                            $('.disabled', d).removeClass('disabled');
                            if(s.hasClass('steplast')){
                                var b = $('.submit', f);
                                b.removeClass('disabled');
                                $('fieldset.currentStep', f).removeClass('currentStep');
                                b.parents('fieldset.step:first').addClass('currentStep');
                            }
                            if($('fieldset.step', d).length){
                                $('fieldset.currentStep', f).removeClass('currentStep');
                                $('fieldset.step', d).addClass('currentStep');
                            }
                        }
                    }
                    if(s.hasClass('do_paypal'))
                    {
                        Penzu.do_paypal(s);
                    }

                    //s.val()==='' ? $('.step'+t, f).hide() : $('.step'+t, f).show();
                    return false;
                }
            });
        };
        self.step = function(f){
            f = $(f);
            var se = ($.browser.msie && (parseInt($.browser.version) < 9) ? 'click' : 'change');
            $('select.stepper', f).live(se, function(){
                _doStep(this);
            });
            $('input.stepper', f).live('keyup', function(){
                _doStep(this);
            });
        };
        function evalClassNames(element){
            element = $(element);
            $.each(element.classNames(), function(i, name){
                if($.inArray(name, funcs) < 0) return;
                try{
                    if($.isFunction(eval('self.' + name))){
                        eval('self.' + name + '(element);');
                    }
                } catch(ke){}
            });            
        };
        evalClassNames(self);
        $.each($(':input', self), function(j, elem){ evalClassNames(elem); });
    });
};
jQuery.extend({
    dynselects : {}
});

jQuery.fn.dynselect = function(options){
    if((document.getElementById && document.createElement && Array.prototype.push) == false) return;
    options = options || {};
    //console.log("options", options, options.namespace);
    options.onChange = options.onChange || function(val){} ;
    options.namespace = options.namespace || 'dynselect';
    options.elementClass = options.elementClass || 'dynselect';
    options.hoverClass = options.hoverClass || 'dyshover';
    options.selectedClass = options.selectedClass || 'selected';
    options.replacedClass = options.replacedClass || 'replaced';
    options.openClass = options.openClass || 'open';
    
    this.each(function(){
        var self = $(this),
            ul = $(document.createElement('ul')),
            opts = self.attr('options'),
            selected = 0;

        function change(e){
            if($(e.target).is('select')){
                // Fire the callback with the value
                e.preventDefault();
                return options.onChange($(e.target).val());
            }
        }
        function set_option(opt){
            opt = $(opt);
            if(opt.is('li')){
                $(opt).siblings().removeClass(options.selectedClass);
                if(opt.hasClass(options.selectedClass)){
                    opt.parent().hasClass(options.openClass) ? opt.parent().removeClass(options.openClass) : opt.parent().addClass(options.openClass);
                } else {
                    opt.data('select').attr('selectedIndex', opt.data('index'));
                    opt.addClass(options.selectedClass);
                    opt.parent().removeClass(options.openClass);
                    return options.onChange(opt.data('select').val());
                }
            }
        }
        function on_click(e){
            //console.log(options.namespace + '.on_click START');
            var li = $(e.target);
            if(li.is('li')){ set_option(li); }
            //console.log(options.namespace + '.on_click END');
        }

        ul.addClass(options.elementClass);
        if($.browser.msie){
            ul.bind('mouseover.' + options.namespace, function(){ ul.addClass(options.hoverClass); });
            ul.bind('mouseout.' + options.namespace, function(){ul.removeClass(options.hoverClass); });
        }
        self.bind('change.' + options.namespace, function(e){ change(e); });
        for(var i=0; i<opts.length; i++) {
            var li = $(document.createElement('li'));
            li.text(opts[i].text);
            li.data('index', opts[i].index);
            li.data('select', self);
            if(opts[i].selected){ selected = i; }
            if($.browser.msie){
                li.bind('mouseover.' + options.namespace, function(){ li.addClass(options.hoverClass); });
                li.bind('mouseout.' + options.namespace, function(){ li.removeClass(options.hoverClass); });
            }
            ul.append(li);
        }
        ul.bind('click.' + options.namespace, function(e){ on_click(e); });
        ul.children('li:nth-child(' + (selected + 1) + ')').addClass(options.selectedClass);
        self.after(ul);
        // Position of container must be 'relative' in CSS
        ul.css({position: 'absolute', top: self.offset().top - self.parent().offset().top, left: self.offset().left - self.parent().offset().left});
        self.addClass(options.replacedClass);
        jQuery.dynselects[self.attr('id')] = { 
            element : self,
            reset : function(){
                ul.children('li').removeClass(options.selectedClass);
                var fli = ul.children('li:first');
                fli.data('select').attr('selectedIndex', fli.data('index'));
                fli.addClass(options.selectedClass);
                ul.removeClass(options.openClass);
            }
        };
    });
    return this;
};

$.extend({
    postScript : function(url, data, callback){
        $.ajax({
            type: "POST",
            url: url,
            dataType: "script",
            data: data,
            complete: function(req, stat){ if(typeof callback == 'function'){ return callback(req, stat); } }
        });
    },
    getSheetNum : function(href_name) {
    	if (!document.styleSheets) return false;
    	for (var i = 0; i < document.styleSheets.length; i++) { if(document.styleSheets[i].href && document.styleSheets[i].href.toString().match(href_name)) return i; } 
    	return false;
    },
     getCSS : function(rule_name, stylesheet, delete_flag) {
        //console.log("getCSS START", arguments);
     	if(!document.styleSheets){ return false };
     	rule_name = rule_name.toLowerCase(); stylesheet = stylesheet || 0;
     	for (var i = stylesheet; i < document.styleSheets.length; i++) { 
     		var styleSheet = document.styleSheets[i]; css_rules = (document.styleSheets[i].cssRules || document.styleSheets[i].rules);
     		//console.log("STYLESHEET: ", styleSheet);
     		if(!css_rules){ continue;}
     		var j = 0;
     		do {
     			if(css_rules.length && j > css_rules.length + 25){ return false; }
     			try { css_rules[j].selectorText	} catch(err){ continue; }
     			if(css_rules[j].selectorText && css_rules[j].selectorText.toLowerCase() == rule_name) {
     				if(delete_flag == true) {
     					if(document.styleSheets[i].removeRule) document.styleSheets[i].removeRule(j);
     					else if(document.styleSheets[i].deleteRule) document.styleSheets[i].deleteRule(j);
     					return true;
     				}
     				else {return css_rules[j]; }
     			}
     		}
     		while (css_rules[++j]);
     	}
     	return false;
     },
     addCSSRule : function(rule_name, rule_value, stylesheet) {
         rule_name = rule_name.toLowerCase(); stylesheet = stylesheet || 0; rule_value = rule_value || '';
         if (!document.styleSheets || $.getCSS(rule_name, stylesheet)) return false;
         var rule_pos = ((document.styleSheets[stylesheet].cssRules != undefined) ? 
            document.styleSheets[stylesheet].cssRules.length :
            document.styleSheets[stylesheet].rules.length);
         if($.browser.msie && rule_value == ''){ rule_value = '/* empty */'; }
         (typeof(document.styleSheets[stylesheet].insertRule) == 'function') ? 
                document.styleSheets[stylesheet].insertRule(rule_name+' { ' + rule_value + ' }', rule_pos) : 
                document.styleSheets[stylesheet].addRule(rule_name, rule_value, rule_pos);
         var rule_added = $.getCSS(rule_name, stylesheet);
         return $.getCSS(rule_name, stylesheet);
     },
     replaceCSSRule : function(rule_name, rule_value, stylesheet){
         //console.log("replaceCSSRule START", arguments);
         $.getCSS(rule_name, stylesheet, true);
         return $.addCSSRule(rule_name, rule_value, stylesheet);
     },
     addCSSRules : function(json_rules, stylesheet){
         //console.log("addCSSRules START", arguments);
         $.each(json_rules, function(i, rule){
             $.each(rule, function(ruleName, ruleParts){
                 var ruleValue = '';
                 $.each(ruleParts, function(rvName, rvValue){
                     ruleValue += rvName + ': ' + rvValue + '; ';
                 });
                 $.replaceCSSRule(ruleName, ruleValue, stylesheet);
             });
         });
     },
     appendCSS : function(cssurl, options){
         if(cssurl == null || typeof(cssurl) != 'string'){ return; }
         options = options || { };
         options.media = (typeof(options.media) == 'undefined' ? 'screen' : options.media);
         var sheet = document.createElement('link');
         sheet.type = 'text/css';
         sheet.media = options.media;
         sheet.rel = 'stylesheet';
         sheet.href = cssurl;
        $('head').append(sheet);
     },
     appendJS : function(jsurl){
         if(jsurl == null || typeof(jsurl) != 'string'){ return; }
         var js = document.createElement('script');
         js.type = 'text/javascript';
         js.charset = 'utf-8';
         js.src = jsurl;
        $('head').append(js);
     }
     ,isRightClick : function(e){
         if (!e) var e = window.event;
         if (e.which) return (e.which == 3);
     	 else if (e.button) return (e.button == 2);
     }
});
