/* 
 * More info at: http://kevin.vanzonneveld.net/techblog/article/phpjs_licensing/
 * 
 * This is version: 1.16
 * php.js is copyright 2008 Kevin van Zonneveld.
 * 
 * Portions copyright Michael White (http://crestidg.com), _argos, Jonas
 * Raoni Soares Silva (http://www.jsfromhell.com), Legaev Andrey, Ates Goral
 * (http://magnetiq.com), Philip Peterson, Martijn Wieringa, Webtoolkit.info
 * (http://www.webtoolkit.info/), Carlos R. L. Rodrigues
 * (http://www.jsfromhell.com), Ash Searle (http://hexmen.com/blog/),
 * Erkekjetter, marrtins, Alfonso Jimenez (http://www.alfonsojimenez.com),
 * Aman Gupta, Arpad Ray (mailto:arpad@php.net), Karol Kowalski, Mirek Slugen,
 * Thunder.m, Tyler Akins (http://rumkin.com), d3x, mdsjack
 * (http://www.mdsjack.bo.it), Alexander Ermolaev
 * (http://snippets.dzone.com/user/AlexanderErmolaev), Allan Jensen
 * (http://www.winternet.no), Andrea Giammarchi
 * (http://webreflection.blogspot.com), Bayron Guevara, Ben Bryan, Benjamin
 * Lupton, Brad Touesnard, Brett Zamir, Cagri Ekin, Cord, David, David James,
 * DxGx, FGFEmperor, Felix Geisendoerfer (http://www.debuggable.com/felix),
 * FremyCompany, Gabriel Paderni, Leslie Hoare, Lincoln Ramsay, MeEtc
 * (http://yass.meetcweb.com), Mick@el, Nick Callen, Ozh, Pedro Tainha
 * (http://www.pedrotainha.com), Peter-Paul Koch
 * (http://www.quirksmode.org/js/beat.html), Philippe Baumann, Sakimori,
 * Sanjoy Roy, Simon Willison (http://simonwillison.net), Steve Clay, Steve
 * Hilder, Steven Levithan (http://blog.stevenlevithan.com), T0bsn, Thiago
 * Mata (http://thiagomata.blog.com), Tim Wiel, XoraX (http://www.xorax.info),
 * Yannoo, baris ozdil, booeyOH, djmix, duncan, echo is bad, gabriel paderni,
 * ger, john (http://www.jd-tech.net), kenneth, penutbutterjelly, stensi
 * 
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL KEVIN VAN ZONNEVELD BE LIABLE FOR ANY CLAIM, DAMAGES
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */ 


(function(){if(typeof(PHP_JS)=="undefined"){var PHP_JS=function(){if(window==this||!this.init){return new PHP_JS();}else{return this.init();}};}
PHP_JS.prototype={init:function(){},array:function(){return Array.prototype.slice.call(arguments);},array_change_key_case:function(array){var case_fn,tmp_ar=new Object,argc=arguments.length,argv=arguments,key;if(array instanceof Array){return array;}
if(array instanceof Object){if(argc==1||argv[1]=='CASE_LOWER'||argv[1]==0){case_fn="toLowerCase";}else{case_fn="toUpperCase";}
for(var key in array){tmp_ar[key[case_fn]()]=array[key];}
return tmp_ar;}
return false;},array_chunk:function(input,size){for(var x,i=0,c=-1,l=input.length,n=[];i<l;i++){(x=i%size)?n[c][x]=input[i]:n[++c]=[input[i]];}
return n;},array_combine:function(keys,values){var new_array={},keycount=keys.length,i;if(!keys||!values||keys.constructor!==Array||values.constructor!==Array){return false;}
if(keycount!=values.length){return false;}
for(i=0;i<keycount;i++){new_array[keys[i]]=values[i];}
return new_array;},array_count_values:function(array){var tmp_ar=new Object(),key;var countValue=function(value){switch(typeof(value)){case"number":if(Math.floor(value)!=value){return;}
case"string":if(value in this){++this[value];}else{this[value]=1;}}};if(array instanceof Array){array.forEach(countValue,tmp_ar);}else if(array instanceof Object){for(key in array){countValue.call(tmp_ar,array[key]);}}
return tmp_ar;},array_diff:function(array){var arr_dif=[],i=1,argc=arguments.length,argv=arguments,key,key_c,found=false,cntr=0;for(key in array){for(i=1;i<argc;i++){found=false;for(key_c in argv[i]){if(argv[i][key_c]==array[key]){found=true;break;}}
if(!found){arr_dif[cntr]=array[key];cntr++;}}}
return arr_dif;},array_diff_assoc:function(array){var arr_dif={},i=1,argc=arguments.length,argv=arguments,key,key_c,found=false;if(!array||(array.constructor!==Array&&array.constructor!==Array&&typeof array!='object'&&typeof array!='array')){return null;}
for(key in array){for(i=1;i<argc;i++){found=false;if(argv[i][key]){found=true;break;}
if(!found){arr_dif[key]=array[key];}}}
return arr_dif;},array_diff_key:function(object){var tpm_ar=new Object(),argc=arguments.length,argv=arguments,key,argidx,other;for(key in object){tpm_ar[key]=object[key];}
for(argidx=1;argidx<argc;++argidx){other=argv[argidx];if(other instanceof Object){for(key in other){delete tpm_ar[key];}}}
return tpm_ar;},array_fill:function(start_index,num,mixed_val){var key,tmp_arr=new Array();if(!isNaN(start_index)&&!isNaN(num)){for(key=start_index;key<=num;key++){tmp_arr[key]=mixed_val;}}
return tmp_arr;},array_flip:function(trans){var key,tmp_ar={};for(key in trans){tmp_ar[trans[key]]=key;}
return tmp_ar;},array_key_exists:function(key,search){if(!search||(search.constructor!==Array&&search.constructor!==Object)){return false;}
return key in search;},array_keys:function(input,search_value,strict){var tmp_arr=new Array(),strict=!!strict,include=true,cnt=0;for(key in input){include=true;if(search_value!=undefined){if(strict&&input[key]!==search_value){include=false;}else if(input[key]!=search_value){include=false;}}
if(include){tmp_arr[cnt]=key;cnt++;}}
return tmp_arr;},array_map:function(callback){var argc=arguments.length,argv=arguments;var j=argv[1].length,i=0,k=1,m=0;var tmp=[],tmp_ar=[];while(i<j){while(k<argc){tmp[m++]=argv[k++][i];}
m=0;k=1;if(callback){tmp_ar[i++]=callback.apply(null,tmp);}else{tmp_ar[i++]=tmp;}
tmp=[];}
return tmp_ar;},array_pad:function(input,pad_size,pad_value){var pad=[],newArray=[],newLength,i=0;if(input instanceof Array&&!isNaN(pad_size)){newLength=((pad_size<0)?(pad_size*-1):pad_size);if(newLength>input.length){for(i=0;i<(newLength-input.length);i++){newArray[i]=pad_value;}
pad=((pad_size<0)?newArray.concat(input):input.concat(newArray));}else{pad=input;}}
return pad;},array_pop:function(array){if(!array.length){return null;}
return array.pop();},array_product:function(input){var Index=0,Product=1;if(input instanceof Array){while(Index<input.length){Product*=(!isNaN(input[Index])?input[Index]:0);Index++;}}else{Product=null;}
return Product;},array_push:function(array){var i,argv=arguments,argc=argv.length;for(i=1;i<argc;i++){array[array.length++]=argv[i];}
return array.length;},array_rand:function(input,num_req){var Indexes=[];var Ticks=num_req||1;var checkDuplicate=function(input,value){var Exist=false,Index=0;while(Index<input.length){if(input[Index]===value){Exist=true;break;}
Index++;}
return Exist;};if(input instanceof Array&&Ticks<=input.length){while(true){var Rand=Math.floor((Math.random()*input.length));if(Indexes.length===Ticks){break;}
if(!checkDuplicate(Indexes,Rand)){Indexes.push(Rand);}}}else{Indexes=null;}
return((Ticks==1)?Indexes.join():Indexes);},array_reduce:function(a_input,callback){var lon=a_input.length;var res=0,i=0;var tmp=new Array();for(i=0;i<lon;i+=2){tmp[0]=a_input[i];if(a_input[(i+1)]){tmp[1]=a_input[(i+1)];}else{tmp[1]=0;}
res+=callback.apply(null,tmp);tmp=new Array();}
return res;},array_reverse:function(array,preserve_keys){var arr_len=array.length,newkey=0,tmp_ar={};for(var key in array){newkey=arr_len-key-1;tmp_ar[(!!preserve_keys)?newkey:key]=array[newkey];}
return tmp_ar;},array_search:function(needle,haystack,strict){var strict=!!strict;for(var key in haystack){if((strict&&haystack[key]===needle)||(!strict&&haystack[key]==needle)){return key;}}
return false;},array_shift:function(array){var i=0,first_elm=null,cnt=0,tmp_arr={};if(!array||(array.constructor!==Array&&array.constructor!==Object)||!array.length){return null;}
if(array.constructor===Array){first_elm=array[0];for(i=0;i<array.length;i++){array[i]=array[i+1];}
array.length--;}else if(array.constructor===Object){for(var key in array){if(cnt==0){first_elm=array[key];}else{tmp_arr[key]=array[key];}
cnt++;}
array=tmp_arr;}
return first_elm;},array_sum:function(array){var key,sum=0;if(!array||(array.constructor!==Array&&array.constructor!==Object)||!array.length){return null;}
for(var key in array){sum+=array[key];}
return sum;},array_unique:function(array){var p,i,j,tmp_arr=array;for(i=tmp_arr.length;i;){for(p=--i;p>0;){if(tmp_arr[i]===tmp_arr[--p]){for(j=p;--p&&tmp_arr[i]===tmp_arr[p];);i-=tmp_arr.splice(p+1,j-p).length;}}}
return tmp_arr;},array_unshift:function(array){var cnt=0,tot_cnt=0,tmp_arr={},argc=arguments.length,argv=arguments;if(!array||(array.constructor!==Array&&array.constructor!==Array&&typeof array!='object'&&typeof array!='array')){return null;}
for(i=1;i<argc;i++){tmp_arr[cnt]=argv[i];cnt++;tot_cnt++;}
for(var key in array){if(typeof key=='number'&&isFinite(key)){tmp_arr[cnt]=array[key];cnt++;tot_cnt++;}else{tmp_arr[key]=array[key];tot_cnt++;}}
return tot_cnt;},array_values:function(input){var tmp_arr=new Array(),cnt=0;for(key in input){tmp_arr[cnt]=input[key];cnt++;}
return tmp_arr;},compact:function(var_names){var Index=0,Matrix={};var process=function(value){for(var i=0;i<value.length;i++){var key_value=value[i];if(key_value instanceof Array){process(key_value);}else{if(typeof window[key_value]!=='undefined'){Matrix[key_value]=window[key_value];}}}
return true;};process(arguments);return Matrix;},count:function(mixed_var,mode){var key,cnt=0;if(mode=='COUNT_RECURSIVE')mode=1;if(mode!=1)mode=0;for(key in mixed_var){cnt++;if(mode==1&&mixed_var[key]&&(mixed_var[key].constructor===Array||mixed_var[key].constructor===Object)){cnt+=this.count(mixed_var[key],1);}}
return cnt;},end:function(array){var last_elm,key;if(array.constructor===Array){last_elm=array[(array.length-1)];}else{for(key in array){last_elm=array[key];}}
return last_elm;},in_array:function(needle,haystack,strict){var found=false,key,strict=!!strict;for(key in haystack){if((strict&&haystack[key]===needle)||(!strict&&haystack[key]==needle)){found=true;break;}}
return found;},range:function(low,high,step){var matrix=[];var inival,endval,plus;var walker=step||1;var chars=false;if(!isNaN(low)&&!isNaN(high)){inival=low;endval=high;}else if(isNaN(low)&&isNaN(high)){chars=true;inival=low.charCodeAt(0);endval=high.charCodeAt(0);}else{inival=(isNaN(low)?0:low);endval=(isNaN(high)?0:high);}
plus=((inival>endval)?false:true);if(plus){while(inival<=endval){matrix.push(((chars)?String.fromCharCode(inival):inival));inival+=walker;}}else{while(inival>=endval){matrix.push(((chars)?String.fromCharCode(inival):inival));inival-=walker;}}
return matrix;},reset:function(array){var first_elm,key;if(array.constructor===Array){first_elm=array[0];}else{for(key in array){first_elm=array[key];break;}}
return first_elm;},shuffle:function(array){for(var j,x,i=array.length;i;j=parseInt(Math.random()*i),x=array[--i],array[i]=array[j],array[j]=x);return true;},sizeof:function(mixed_var,mode){return this.count(mixed_var,mode);},get_class:function(obj){if(obj instanceof Object&&!(obj instanceof Array)&&!(obj instanceof Function)&&obj.constructor){var arr=obj.constructor.toString().match(/function\s*(\w+)/);if(arr&&arr.length==2){return arr[1];}}
return false;},checkdate:function(month,day,year){var myDate=new Date();myDate.setFullYear(year,(month-1),day);return((myDate.getMonth()+1)==month);},date:function(format,timestamp){var a,jsdate=((timestamp)?new Date(timestamp*1000):new Date());var pad=function(n,c){if((n=n+"").length<c){return new Array(++c-n.length).join("0")+n;}else{return n;}};var txt_weekdays=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var txt_ordin={1:"st",2:"nd",3:"rd",21:"st",22:"nd",23:"rd",31:"st"};var txt_months=["","January","February","March","April","May","June","July","August","September","October","November","December"];var f={d:function(){return pad(f.j(),2);},D:function(){t=f.l();return t.substr(0,3);},j:function(){return jsdate.getDate();},l:function(){return txt_weekdays[f.w()];},N:function(){return f.w()+1;},S:function(){return txt_ordin[f.j()]?txt_ordin[f.j()]:'th';},w:function(){return jsdate.getDay();},z:function(){return(jsdate-new Date(jsdate.getFullYear()+"/1/1"))/864e5>>0;},W:function(){var a=f.z(),b=364+f.L()-a;var nd2,nd=(new Date(jsdate.getFullYear()+"/1/1").getDay()||7)-1;if(b<=2&&((jsdate.getDay()||7)-1)<=2-b){return 1;}else{if(a<=2&&nd>=4&&a>=(6-nd)){nd2=new Date(jsdate.getFullYear()-1+"/12/31");return this.date("W",Math.round(nd2.getTime()/1000));}else{return(1+(nd<=3?((a+nd)/7):(a-(7-nd))/7)>>0);}}},F:function(){return txt_months[f.n()];},m:function(){return pad(f.n(),2);},M:function(){t=f.F();return t.substr(0,3);},n:function(){return jsdate.getMonth()+1;},t:function(){var n;if((n=jsdate.getMonth()+1)==2){return 28+f.L();}else{if(n&1&&n<8||!(n&1)&&n>7){return 31;}else{return 30;}}},L:function(){var y=f.Y();return(!(y&3)&&(y%1e2||!(y%4e2)))?1:0;},Y:function(){return jsdate.getFullYear();},y:function(){return(jsdate.getFullYear()+"").slice(2);},a:function(){return jsdate.getHours()>11?"pm":"am";},A:function(){return f.a().toUpperCase();},B:function(){var off=(jsdate.getTimezoneOffset()+60)*60;var theSeconds=(jsdate.getHours()*3600)+
(jsdate.getMinutes()*60)+
jsdate.getSeconds()+off;var beat=Math.floor(theSeconds/86.4);if(beat>1000)beat-=1000;if(beat<0)beat+=1000;if((String(beat)).length==1)beat="00"+beat;if((String(beat)).length==2)beat="0"+beat;return beat;},g:function(){return jsdate.getHours()%12||12;},G:function(){return jsdate.getHours();},h:function(){return pad(f.g(),2);},H:function(){return pad(jsdate.getHours(),2);},i:function(){return pad(jsdate.getMinutes(),2);},s:function(){return pad(jsdate.getSeconds(),2);},O:function(){var t=pad(Math.abs(jsdate.getTimezoneOffset()/60*100),4);if(jsdate.getTimezoneOffset()>0)t="-"+t;else t="+"+t;return t;},P:function(){var O=f.O();return(O.substr(0,3)+":"+O.substr(3,2));},c:function(){return f.Y()+"-"+f.m()+"-"+f.d()+"T"+f.h()+":"+f.i()+":"+f.s()+f.P();},U:function(){return Math.round(jsdate.getTime()/1000);}};return format.replace(/[\\]?([a-zA-Z])/g,function(t,s){if(t!=s){ret=s;}else if(f[s]){ret=f[s]();}else{ret=s;}
return ret;});},mktime:function(){var no,ma=0,mb=0,i=0,d=new Date(),argv=arguments,argc=argv.length;d.setHours(0,0,0);d.setDate(1);d.setMonth(1);d.setYear(1972);var dateManip={0:function(tt){return d.setHours(tt);},1:function(tt){return d.setMinutes(tt);},2:function(tt){set=d.setSeconds(tt);mb=d.getDate()-1;return set;},3:function(tt){set=d.setMonth(parseInt(tt)-1);ma=d.getFullYear()-1972;return set;},4:function(tt){return d.setDate(tt+mb);},5:function(tt){return d.setYear(tt+ma);}};for(i=0;i<argc;i++){no=parseInt(argv[i]*1);if(no&&isNaN(no)){return false;}else if(no){if(!dateManip[i](no)){return false;}}}
return Math.floor(d.getTime()/1000);},basename:function(path,suffix){var b=path.replace(/^.*[\/\\]/g,'');if(typeof(suffix)=='string'&&b.substr(b.length-suffix.length)==suffix){b=b.substr(0,b.length-suffix.length);}
return b;},dirname:function(path){return path.replace(/\\/g,'/').replace(/\/[^\/]*\/?$/,'');},file:function(url){var req=null;try{req=new ActiveXObject("Msxml2.XMLHTTP");}catch(e){try{req=new ActiveXObject("Microsoft.XMLHTTP");}catch(e){try{req=new XMLHttpRequest();}catch(e){}}}
if(req==null)throw new Error('XMLHttpRequest not supported');req.open("GET",url,false);req.send(null);return req.responseText.split('\n');},file_get_contents:function(url){var req=null;try{req=new ActiveXObject("Msxml2.XMLHTTP");}catch(e){try{req=new ActiveXObject("Microsoft.XMLHTTP");}catch(e){try{req=new XMLHttpRequest();}catch(e){}}}
if(req==null)throw new Error('XMLHttpRequest not supported');req.open("GET",url,false);req.send(null);return req.responseText;},call_user_func_array:function(strFunctionName,arrParam){var strCommand="";var i;strCommand+="return "+strFunctionName+"(";for(i=0;i<arrParam.length;++i){strCommand+="arrParam["+i+"]";if((i+1)!=arrParam.length){strCommand+=",";}}
strCommand+=")";var oFunction=new Function("arrParam",strCommand);return oFunction(arrParam);},function_exists:function(function_name){if(typeof function_name=='string'){return(typeof window[function_name]=='function');}else{return(function_name instanceof Function);}},get_included_files:function(){var cur_file={};cur_file[window.location.href]=1;if(!this.__php_js)this.__php_js={};if(!this.__php_js.includes)this.__php_js.includes=cur_file;var includes=new Array();var i=0;for(var key in this.__php_js.includes){includes[i]=key;i++;}
return includes;},include:function(filename){var js=document.createElement('script');js.setAttribute('type','text/javascript');js.setAttribute('src',filename);js.setAttribute('defer','defer');document.getElementsByTagName('HEAD')[0].appendChild(js);var cur_file={};cur_file[window.location.href]=1;if(!window.php_js)window.php_js={};if(!window.php_js.includes)window.php_js.includes=cur_file;if(!window.php_js.includes[filename]){window.php_js.includes[filename]=1;}else{window.php_js.includes[filename]++;}
return window.php_js.includes[filename];},include_once:function(filename){var cur_file={};cur_file[window.location.href]=1;if(!window.php_js)window.php_js={};if(!window.php_js.includes)window.php_js.includes=cur_file;if(!window.php_js.includes[filename]){if(this.include(filename)){return true;}}else{return true;}},require:function(filename){var js_code=this.file_get_contents(filename);var script_block=document.createElement('script');script_block.type='text/javascript';var client_pc=navigator.userAgent.toLowerCase();if((client_pc.indexOf("msie")!=-1)&&(client_pc.indexOf("opera")==-1)){script_block.text=js_code;}else{script_block.appendChild(document.createTextNode(js_code));}
if(typeof(script_block)!="undefined"){document.getElementsByTagName("head")[0].appendChild(script_block);var cur_file={};cur_file[window.location.href]=1;if(!window.php_js)window.php_js={};if(!window.php_js.includes)window.php_js.includes=cur_file;if(!window.php_js.includes[filename]){window.php_js.includes[filename]=1;}else{return window.php_js.includes[filename]+=1;}}},require_once:function(filename){var cur_file={};cur_file[window.location.href]=1;if(!window.php_js)window.php_js={};if(!window.php_js.includes)window.php_js.includes=cur_file;if(!window.php_js.includes[filename]){if(this.require(filename)){return true;}}else{return true;}},abs:function(mixed_number){return Math.abs(mixed_number)||0;},rand:function(min,max){if(max){return Math.floor(Math.random()*(max-min+1))+min;}else{return Math.floor(Math.random()*(min+1));}},round:function(val,precision){var precision=(this.round.arguments.length>1)?this.round.arguments[1]:0;return Math.round(val*Math.pow(10,precision))/Math.pow(10,precision);},defined:function(constant_name){return(typeof window[constant_name]!=='undefined');},ip2long:function(ip_address){var output=false;if(ip_address.match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)){var parts=ip_address.split('.');var output=0;output=(parts[0]*Math.pow(256,3))+
(parts[1]*Math.pow(256,2))+
(parts[2]*Math.pow(256,1))+
(parts[3]*Math.pow(256,0));}
return output;},long2ip:function(proper_address){var output=false;if(!isNaN(proper_address)&&(proper_address>=0||proper_address<=4294967295)){output=Math.floor(proper_address/Math.pow(256,3))+'.'+
Math.floor((proper_address%Math.pow(256,3))/Math.pow(256,2))+'.'+
Math.floor(((proper_address%Math.pow(256,3))%Math.pow(256,2))/Math.pow(256,1))+'.'+
Math.floor((((proper_address%Math.pow(256,3))%Math.pow(256,2))%Math.pow(256,1))/Math.pow(256,0));}
return output;},setcookie:function(name,value,expires,path,domain,secure){expires instanceof Date?expires=expires.toGMTString():typeof(expires)=='number'&&(expires=(new Date(+(new Date)+expires*1e3)).toGMTString());var r=[name+"="+escape(value)],s,i;for(i in s={expires:expires,path:path,domain:domain}){s[i]&&r.push(i+"="+s[i]);}
return secure&&r.push("secure"),document.cookie=r.join(";"),true;},preg_quote:function(str){return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g,"\\$1");},addslashes:function(str){return str.replace('/(["\'\])/g',"\\$1").replace('/\0/g',"\\0");},bin2hex:function(s){var i,f=s.length,a=[];for(i=0;i<f;i++){a[i]=s.charCodeAt(i).toString(16);}
return a.join('');},chr:function(ascii){return String.fromCharCode(ascii);},count_chars:function(str,mode){var histogram=new Object(),tmp_ar=new Array(),argc=arguments.length,key,i,code,mode;if(argc==1){mode=0;}
mode_even=(mode&1)==0;if(mode_even){for(i=1;i<256;++i){histogram[i]=0;}}
for(i=0;i<str.length;++i){code=str.charCodeAt(i);if(code in histogram){++histogram[code];}else{histogram[code]=1;}}
if(mode>0){for(key in histogram){if(histogram[key]==0!=mode_even){delete histogram[key];}}}
if(mode<3){return histogram;}else{for(key in histogram){tmp_ar.push(String.fromCharCode(key));}
return tmp_ar.join("");}},crc32:function(str){str=this.utf8_encode(str);var table="00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D";var crc=0;var x=0;var y=0;crc=crc^(-1);for(var i=0,iTop=str.length;i<iTop;i++){y=(crc^str.charCodeAt(i))&0xFF;x="0x"+table.substr(y*9,8);crc=(crc>>>8)^x;}
return crc^(-1);},echo:function(){var doc_elem=document.createDocumentFragment();for(i=0;i<this.echo.arguments.length;i++){if(doc_elem.body&&doc_elem.body.innerHTML){doc_elem.body.innerHTML=doc_elem.body.innerHTML+this.echo.arguments[i];}else if(doc_elem.write){doc_elem.write(this.echo.arguments[i]);}}
return null;},explode:function(delimiter,string,limit){var emptyArray={0:''};if(arguments.length<2||typeof arguments[0]=='undefined'||typeof arguments[1]=='undefined')
{return null;}
if(delimiter===''||delimiter===false||delimiter===null)
{return false;}
if(typeof delimiter=='function'||typeof delimiter=='object'||typeof string=='function'||typeof string=='object')
{return emptyArray;}
if(delimiter===true){delimiter='1';}
if(!limit){return string.toString().split(delimiter.toString());}else{var splitted=string.toString().split(delimiter.toString());var partA=splitted.splice(0,limit-1);var partB=splitted.join(delimiter.toString());partA.push(partB);return partA;}},html_entity_decode:function(string){var ret,tarea=document.createElement('textarea');tarea.innerHTML=string;ret=tarea.value;return ret;},htmlentities:function(s){var div=document.createElement('div');var text=document.createTextNode(s);div.appendChild(text);return div.innerHTML;},htmlspecialchars:function(string,quote_style){string=string.toString();string.replace('/&/g','&amp;');string.replace('/</g','&lt;');string.replace('/>/g','&gt;');if(quote_style=='ENT_QUOTES'){string.replace('/"/g','&quot;');string.replace('/\'/g','&#039;');}else if(quote_style!='ENT_NOQUOTES'){string.replace('/"/g','&quot;');}
return string;},htmlspecialchars_decode:function(string,quote_style){string=string.toString();string.replace('/&amp;/g','&');string.replace('/&lt;/g','<');string.replace(/&gt;/g,'>');if(quote_style=='ENT_QUOTES'){string.replace('/&quot;/g','"');string.replace('/&#039;/g','\'');}else if(quote_style!='ENT_NOQUOTES'){string.replace('/&quot;/g','"');}
return string;},implode:function(glue,pieces){return((pieces instanceof Array)?pieces.join(glue):pieces);},join:function(glue,pieces){return this.implode(glue,pieces);},levenshtein:function(str1,str2){var s,l=(s=str1.split("")).length,t=(str2=str2.split("")).length,i,j,m,n;if(!(l||t))return Math.max(l,t);for(var a=[],i=l+1;i;a[--i]=[i]);for(i=t+1;a[0][--i]=i;);for(i=-1,m=s.length;++i<m;){for(j=-1,n=str2.length;++j<n;){a[(i*=1)+1][(j*=1)+1]=Math.min(a[i][j+1]+1,a[i+1][j]+1,a[i][j]+(s[i]!=str2[j]));}}
return a[l][t];},ltrim:function(str,charlist){charlist=!charlist?' \s\xA0':charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g,'\$1');var re=new RegExp('^['+charlist+']+','g');return str.replace(re,'');},md5:function(str){var RotateLeft=function(lValue,iShiftBits){return(lValue<<iShiftBits)|(lValue>>>(32-iShiftBits));};var AddUnsigned=function(lX,lY){var lX4,lY4,lX8,lY8,lResult;lX8=(lX&0x80000000);lY8=(lY&0x80000000);lX4=(lX&0x40000000);lY4=(lY&0x40000000);lResult=(lX&0x3FFFFFFF)+(lY&0x3FFFFFFF);if(lX4&lY4){return(lResult^0x80000000^lX8^lY8);}
if(lX4|lY4){if(lResult&0x40000000){return(lResult^0xC0000000^lX8^lY8);}else{return(lResult^0x40000000^lX8^lY8);}}else{return(lResult^lX8^lY8);}};var F=function(x,y,z){return(x&y)|((~x)&z);};var G=function(x,y,z){return(x&z)|(y&(~z));};var H=function(x,y,z){return(x^y^z);};var I=function(x,y,z){return(y^(x|(~z)));};var FF=function(a,b,c,d,x,s,ac){a=AddUnsigned(a,AddUnsigned(AddUnsigned(F(b,c,d),x),ac));return AddUnsigned(RotateLeft(a,s),b);};var GG=function(a,b,c,d,x,s,ac){a=AddUnsigned(a,AddUnsigned(AddUnsigned(G(b,c,d),x),ac));return AddUnsigned(RotateLeft(a,s),b);};var HH=function(a,b,c,d,x,s,ac){a=AddUnsigned(a,AddUnsigned(AddUnsigned(H(b,c,d),x),ac));return AddUnsigned(RotateLeft(a,s),b);};var II=function(a,b,c,d,x,s,ac){a=AddUnsigned(a,AddUnsigned(AddUnsigned(I(b,c,d),x),ac));return AddUnsigned(RotateLeft(a,s),b);};var ConvertToWordArray=function(str){var lWordCount;var lMessageLength=str.length;var lNumberOfWords_temp1=lMessageLength+8;var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1%64))/64;var lNumberOfWords=(lNumberOfWords_temp2+1)*16;var lWordArray=Array(lNumberOfWords-1);var lBytePosition=0;var lByteCount=0;while(lByteCount<lMessageLength){lWordCount=(lByteCount-(lByteCount%4))/4;lBytePosition=(lByteCount%4)*8;lWordArray[lWordCount]=(lWordArray[lWordCount]|(str.charCodeAt(lByteCount)<<lBytePosition));lByteCount++;}
lWordCount=(lByteCount-(lByteCount%4))/4;lBytePosition=(lByteCount%4)*8;lWordArray[lWordCount]=lWordArray[lWordCount]|(0x80<<lBytePosition);lWordArray[lNumberOfWords-2]=lMessageLength<<3;lWordArray[lNumberOfWords-1]=lMessageLength>>>29;return lWordArray;};var WordToHex=function(lValue){var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;for(lCount=0;lCount<=3;lCount++){lByte=(lValue>>>(lCount*8))&255;WordToHexValue_temp="0"+lByte.toString(16);WordToHexValue=WordToHexValue+WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);}
return WordToHexValue;};var x=Array();var k,AA,BB,CC,DD,a,b,c,d;var S11=7,S12=12,S13=17,S14=22;var S21=5,S22=9,S23=14,S24=20;var S31=4,S32=11,S33=16,S34=23;var S41=6,S42=10,S43=15,S44=21;str=this.utf8_encode(str);x=ConvertToWordArray(str);a=0x67452301;b=0xEFCDAB89;c=0x98BADCFE;d=0x10325476;for(k=0;k<x.length;k+=16){AA=a;BB=b;CC=c;DD=d;a=FF(a,b,c,d,x[k+0],S11,0xD76AA478);d=FF(d,a,b,c,x[k+1],S12,0xE8C7B756);c=FF(c,d,a,b,x[k+2],S13,0x242070DB);b=FF(b,c,d,a,x[k+3],S14,0xC1BDCEEE);a=FF(a,b,c,d,x[k+4],S11,0xF57C0FAF);d=FF(d,a,b,c,x[k+5],S12,0x4787C62A);c=FF(c,d,a,b,x[k+6],S13,0xA8304613);b=FF(b,c,d,a,x[k+7],S14,0xFD469501);a=FF(a,b,c,d,x[k+8],S11,0x698098D8);d=FF(d,a,b,c,x[k+9],S12,0x8B44F7AF);c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);a=FF(a,b,c,d,x[k+12],S11,0x6B901122);d=FF(d,a,b,c,x[k+13],S12,0xFD987193);c=FF(c,d,a,b,x[k+14],S13,0xA679438E);b=FF(b,c,d,a,x[k+15],S14,0x49B40821);a=GG(a,b,c,d,x[k+1],S21,0xF61E2562);d=GG(d,a,b,c,x[k+6],S22,0xC040B340);c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);b=GG(b,c,d,a,x[k+0],S24,0xE9B6C7AA);a=GG(a,b,c,d,x[k+5],S21,0xD62F105D);d=GG(d,a,b,c,x[k+10],S22,0x2441453);c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);b=GG(b,c,d,a,x[k+4],S24,0xE7D3FBC8);a=GG(a,b,c,d,x[k+9],S21,0x21E1CDE6);d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);c=GG(c,d,a,b,x[k+3],S23,0xF4D50D87);b=GG(b,c,d,a,x[k+8],S24,0x455A14ED);a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);d=GG(d,a,b,c,x[k+2],S22,0xFCEFA3F8);c=GG(c,d,a,b,x[k+7],S23,0x676F02D9);b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);a=HH(a,b,c,d,x[k+5],S31,0xFFFA3942);d=HH(d,a,b,c,x[k+8],S32,0x8771F681);c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);a=HH(a,b,c,d,x[k+1],S31,0xA4BEEA44);d=HH(d,a,b,c,x[k+4],S32,0x4BDECFA9);c=HH(c,d,a,b,x[k+7],S33,0xF6BB4B60);b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);d=HH(d,a,b,c,x[k+0],S32,0xEAA127FA);c=HH(c,d,a,b,x[k+3],S33,0xD4EF3085);b=HH(b,c,d,a,x[k+6],S34,0x4881D05);a=HH(a,b,c,d,x[k+9],S31,0xD9D4D039);d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);b=HH(b,c,d,a,x[k+2],S34,0xC4AC5665);a=II(a,b,c,d,x[k+0],S41,0xF4292244);d=II(d,a,b,c,x[k+7],S42,0x432AFF97);c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);b=II(b,c,d,a,x[k+5],S44,0xFC93A039);a=II(a,b,c,d,x[k+12],S41,0x655B59C3);d=II(d,a,b,c,x[k+3],S42,0x8F0CCC92);c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);b=II(b,c,d,a,x[k+1],S44,0x85845DD1);a=II(a,b,c,d,x[k+8],S41,0x6FA87E4F);d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);c=II(c,d,a,b,x[k+6],S43,0xA3014314);b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);a=II(a,b,c,d,x[k+4],S41,0xF7537E82);d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);c=II(c,d,a,b,x[k+2],S43,0x2AD7D2BB);b=II(b,c,d,a,x[k+9],S44,0xEB86D391);a=AddUnsigned(a,AA);b=AddUnsigned(b,BB);c=AddUnsigned(c,CC);d=AddUnsigned(d,DD);}
var temp=WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);return temp.toLowerCase();},md5_file:function(str_filename){return this.md5(this.file_get_contents(str_filename));},nl2br:function(str){return str.replace(/([^>])\n/g,'$1<br />\n');},number_format:function(number,decimals,dec_point,thousands_sep){var n=number,c=isNaN(decimals=Math.abs(decimals))?2:decimals;var d=dec_point==undefined?",":dec_point;var t=thousands_sep==undefined?".":thousands_sep,s=n<0?"-":"";var i=parseInt(n=Math.abs(+n||0).toFixed(c))+"",j=(j=i.length)>3?j%3:0;return s+(j?i.substr(0,j)+t:"")+i.substr(j).replace(/(\d{3})(?=\d)/g,"$1"+t)+(c?d+Math.abs(n-i).toFixed(c).slice(2):"");},ord:function(string){return string.charCodeAt(0);},parse_str:function(str,array){var glue1='=';var glue2='&';var array2=str.split(glue2);var array3=[];for(var x=0;x<array2.length;x++){var tmp=array2[x].split(glue1);array3[unescape(tmp[0])]=unescape(tmp[1]).replace(/[+]/g,' ');}
if(array){array=array3;}else{return array3;}},printf:function(){var ret=this.sprintf.apply(this,arguments);document.write(ret);return ret.length;},rtrim:function(str,charlist){charlist=!charlist?' \s\xA0':charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g,'\$1');var re=new RegExp('['+charlist+']+$','g');return str.replace(re,'');},sha1:function(str){var rotate_left=function(n,s){var t4=(n<<s)|(n>>>(32-s));return t4;};var lsb_hex=function(val){var str="";var i;var vh;var vl;for(i=0;i<=6;i+=2){vh=(val>>>(i*4+4))&0x0f;vl=(val>>>(i*4))&0x0f;str+=vh.toString(16)+vl.toString(16);}
return str;};var cvt_hex=function(val){var str="";var i;var v;for(i=7;i>=0;i--){v=(val>>>(i*4))&0x0f;str+=v.toString(16);}
return str;};var blockstart;var i,j;var W=new Array(80);var H0=0x67452301;var H1=0xEFCDAB89;var H2=0x98BADCFE;var H3=0x10325476;var H4=0xC3D2E1F0;var A,B,C,D,E;var temp;str=this.utf8_encode(str);var str_len=str.length;var word_array=new Array();for(i=0;i<str_len-3;i+=4){j=str.charCodeAt(i)<<24|str.charCodeAt(i+1)<<16|str.charCodeAt(i+2)<<8|str.charCodeAt(i+3);word_array.push(j);}
switch(str_len%4){case 0:i=0x080000000;break;case 1:i=str.charCodeAt(str_len-1)<<24|0x0800000;break;case 2:i=str.charCodeAt(str_len-2)<<24|str.charCodeAt(str_len-1)<<16|0x08000;break;case 3:i=str.charCodeAt(str_len-3)<<24|str.charCodeAt(str_len-2)<<16|str.charCodeAt(str_len-1)<<8|0x80;break;}
word_array.push(i);while((word_array.length%16)!=14)word_array.push(0);word_array.push(str_len>>>29);word_array.push((str_len<<3)&0x0ffffffff);for(blockstart=0;blockstart<word_array.length;blockstart+=16){for(i=0;i<16;i++)W[i]=word_array[blockstart+i];for(i=16;i<=79;i++)W[i]=rotate_left(W[i-3]^W[i-8]^W[i-14]^W[i-16],1);A=H0;B=H1;C=H2;D=H3;E=H4;for(i=0;i<=19;i++){temp=(rotate_left(A,5)+((B&C)|(~B&D))+E+W[i]+0x5A827999)&0x0ffffffff;E=D;D=C;C=rotate_left(B,30);B=A;A=temp;}
for(i=20;i<=39;i++){temp=(rotate_left(A,5)+(B^C^D)+E+W[i]+0x6ED9EBA1)&0x0ffffffff;E=D;D=C;C=rotate_left(B,30);B=A;A=temp;}
for(i=40;i<=59;i++){temp=(rotate_left(A,5)+((B&C)|(B&D)|(C&D))+E+W[i]+0x8F1BBCDC)&0x0ffffffff;E=D;D=C;C=rotate_left(B,30);B=A;A=temp;}
for(i=60;i<=79;i++){temp=(rotate_left(A,5)+(B^C^D)+E+W[i]+0xCA62C1D6)&0x0ffffffff;E=D;D=C;C=rotate_left(B,30);B=A;A=temp;}
H0=(H0+A)&0x0ffffffff;H1=(H1+B)&0x0ffffffff;H2=(H2+C)&0x0ffffffff;H3=(H3+D)&0x0ffffffff;H4=(H4+E)&0x0ffffffff;}
var temp=cvt_hex(H0)+cvt_hex(H1)+cvt_hex(H2)+cvt_hex(H3)+cvt_hex(H4);return temp.toLowerCase();},sha1_file:function(str_filename){var buf=this.file_get_contents(str_filename);return this.sha1(buf);},soundex:function(str){var i,j,l,r,p=isNaN(p)?4:p>10?10:p<4?4:p,m={BFPV:1,CGJKQSXZ:2,DT:3,L:4,MN:5,R:6},r=(s=str.toUpperCase().replace(/[^A-Z]/g,"").split("")).splice(0,1);for(i=-1,l=s.length;++i<l;){for(j in m){if(j.indexOf(s[i])+1&&r[r.length-1]!=m[j]&&r.push(m[j])){break;}}}
return r.length>p&&(r.length=p),r.join("")+(new Array(p-r.length+1)).join("0");},split:function(delimiter,string){return this.explode(delimiter,string);},sprintf:function(){var regex=/%%|%(\d+\$)?([-+#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;var a=arguments,i=0,format=a[i++];var pad=function(str,len,chr,leftJustify){var padding=(str.length>=len)?'':Array(1+len-str.length>>>0).join(chr);return leftJustify?str+padding:padding+str;};var justify=function(value,prefix,leftJustify,minWidth,zeroPad){var diff=minWidth-value.length;if(diff>0){if(leftJustify||!zeroPad){value=pad(value,minWidth,' ',leftJustify);}else{value=value.slice(0,prefix.length)+pad('',diff,'0',true)+value.slice(prefix.length);}}
return value;};var formatBaseX=function(value,base,prefix,leftJustify,minWidth,precision,zeroPad){var number=value>>>0;prefix=prefix&&number&&{'2':'0b','8':'0','16':'0x'}[base]||'';value=prefix+pad(number.toString(base),precision||0,'0',false);return justify(value,prefix,leftJustify,minWidth,zeroPad);};var formatString=function(value,leftJustify,minWidth,precision,zeroPad){if(precision!=null){value=value.slice(0,precision);}
return justify(value,'',leftJustify,minWidth,zeroPad);};var doFormat=function(substring,valueIndex,flags,minWidth,_,precision,type){if(substring=='%%')return'%';var leftJustify=false,positivePrefix='',zeroPad=false,prefixBaseX=false;for(var j=0;flags&&j<flags.length;j++)switch(flags.charAt(j)){case' ':positivePrefix=' ';break;case'+':positivePrefix='+';break;case'-':leftJustify=true;break;case'0':zeroPad=true;break;case'#':prefixBaseX=true;break;}
if(!minWidth){minWidth=0;}else if(minWidth=='*'){minWidth=+a[i++];}else if(minWidth.charAt(0)=='*'){minWidth=+a[minWidth.slice(1,-1)];}else{minWidth=+minWidth;}
if(minWidth<0){minWidth=-minWidth;leftJustify=true;}
if(!isFinite(minWidth)){throw new Error('this.sprintf: (minimum-)width must be finite');}
if(!precision){precision='fFeE'.indexOf(type)>-1?6:(type=='d')?0:void(0);}else if(precision=='*'){precision=+a[i++];}else if(precision.charAt(0)=='*'){precision=+a[precision.slice(1,-1)];}else{precision=+precision;}
var value=valueIndex?a[valueIndex.slice(0,-1)]:a[i++];switch(type){case's':return formatString(String(value),leftJustify,minWidth,precision,zeroPad);case'c':return formatString(String.fromCharCode(+value),leftJustify,minWidth,precision,zeroPad);case'b':return formatBaseX(value,2,prefixBaseX,leftJustify,minWidth,precision,zeroPad);case'o':return formatBaseX(value,8,prefixBaseX,leftJustify,minWidth,precision,zeroPad);case'x':return formatBaseX(value,16,prefixBaseX,leftJustify,minWidth,precision,zeroPad);case'X':return formatBaseX(value,16,prefixBaseX,leftJustify,minWidth,precision,zeroPad).toUpperCase();case'u':return formatBaseX(value,10,prefixBaseX,leftJustify,minWidth,precision,zeroPad);case'i':case'd':{var number=parseInt(+value);var prefix=number<0?'-':positivePrefix;value=prefix+pad(String(Math.abs(number)),precision,'0',false);return justify(value,prefix,leftJustify,minWidth,zeroPad);}
case'e':case'E':case'f':case'F':case'g':case'G':{var number=+value;var prefix=number<0?'-':positivePrefix;var method=['toExponential','toFixed','toPrecision']['efg'.indexOf(type.toLowerCase())];var textTransform=['toString','toUpperCase']['eEfFgG'.indexOf(type)%2];value=prefix+Math.abs(number)[method](precision);return justify(value,prefix,leftJustify,minWidth,zeroPad)[textTransform]();}
default:return substring;}};return format.replace(regex,doFormat);},str_ireplace:function(search,replace,subject){var i;if(!(replace instanceof Array)){replace=new Array(replace);if(search instanceof Array){while(search.length>replace.length){replace[replace.length]=replace[0];}}}
if(!(search instanceof Array))search=new Array(search);while(search.length>replace.length){replace[replace.length]='';}
if(subject instanceof Array){for(k in subject){subject[k]=str_replace(search,replace,subject[k]);}
return subject;}
for(var k=0;k<search.length;k++){reg=new RegExp(search[k],'gi');subject=subject.replace(reg,replace[k]);}
return subject;},str_pad:function(input,pad_length,pad_string,pad_type){var half='',pad_to_go;var str_pad_repeater=function(s,len){var collect='',i;while(collect.length<len)collect+=s;collect=collect.substr(0,len);return collect;};if(pad_type!='STR_PAD_LEFT'&&pad_type!='STR_PAD_RIGHT'&&pad_type!='STR_PAD_BOTH'){pad_type='STR_PAD_RIGHT';}
if((pad_to_go=pad_length-input.length)>0){if(pad_type=='STR_PAD_LEFT'){input=str_pad_repeater(pad_string,pad_to_go)+input;}
else if(pad_type=='STR_PAD_RIGHT'){input=input+str_pad_repeater(pad_string,pad_to_go);}
else if(pad_type=='STR_PAD_BOTH'){half=str_pad_repeater(pad_string,Math.ceil(pad_to_go/2));input=half+input+half;input=input.substr(0,pad_length);}}
return input;},str_repeat:function(input,multiplier){return new Array(multiplier+1).join(input);},str_replace:function(search,replace,subject){var f=search,r=replace,s=subject;var ra=this.is_array(r),sa=this.is_array(s),f=[].concat(f),r=[].concat(r),i=(s=[].concat(s)).length;while(j=0,i--){while(s[i]=s[i].split(f[j]).join(ra?r[j]||"":r[0]),++j in f);}
return sa?s:s[0];},str_rot13:function(str){return str.replace(/[A-Za-z]/g,function(c){return String.fromCharCode((((c=c.charCodeAt(0))&223)-52)%26+(c&32)+65);});},str_split:function(f_string,f_split_length){if(f_split_length==undefined){f_split_length=1;}
if(f_split_length>0){var result=[];while(f_string.length>f_split_length){result[result.length]=f_string.substring(0,f_split_length);f_string=f_string.substring(f_split_length);}
result[result.length]=f_string;return result;}
return false;},strcasecmp:function(f_string1,f_string2){var string1=f_string1.toLowerCase();var string2=f_string2.toLowerCase();if(string1>string2){return 1;}
else if(string1==string2){return 0;}
return-1;},strchr:function(haystack,needle,bool){return this.strstr(haystack,needle,bool);},strcmp:function(str1,str2){var i=size1=size2=0;for(i=0;i<str1.length;++i){size1+=str1.charCodeAt(i);}
for(i=0;i<str2.length;++i){size2+=str2.charCodeAt(i);}
return((size1==size2)?0:((size1>size2)?1:-1));},strip_tags:function(str,allowed_tags){var match='';if(allowed_tags){allowed_tags=allowed_tags.replace(/[\<\> ]+/g,'');;allowed_tags=allowed_tags.replace(/\,/g,'|');}
match='/<\/?(?!(?:'+allowed_tags+')\\b)[^>]+>/gi';alert(match);return str.replace(match,'');},stripos:function(f_haystack,f_needle,f_offset){var haystack=f_haystack.toLowerCase();var needle=f_needle.toLowerCase();var index=0;if(f_offset==undefined){f_offset=0;}
if((index=haystack.indexOf(needle,f_offset))>-1){return index;}
return false;},stripslashes:function(str){return str.replace('/\0/g','0').replace('/\(.)/g','$1');},stristr:function(haystack,needle,bool){var pos=0;pos=haystack.toLowerCase().indexOf(needle.toLowerCase());if(pos==-1){return false;}else{if(bool){return haystack.substr(0,pos);}else{return haystack.slice(pos);}}},strlen:function(string){return(""+string).length;},strnatcmp:function(f_string1,f_string2,f_version){if(f_version==undefined){f_version=false;}
var __strnatcmp_split=function(f_string){var result=new Array();var buffer='';var chr='';var text=true;for(var i=0;i<f_string.length;i++){chr=f_string.substring(i,i+1);if(chr.match(/[0-9]/)){if(text){if(buffer.length>0){result[result.length]=buffer;buffer='';}
text=false;}
buffer+=chr;}else if((text==false)&&(chr=='.')&&(i<(f_string.length-1))&&(f_string.substring(i+1,i+2).match(/[0-9]/))){result[result.length]=buffer;buffer='';}else{if(text==false){if(buffer.length>0){result[result.length]=parseInt(buffer);buffer='';}
text=true;}
buffer+=chr;}}
if(buffer.length>0){if(text){result[result.length]=buffer;}else{result[result.length]=parseInt(buffer);}}
return result;};var array1=__strnatcmp_split(f_string1);var array2=__strnatcmp_split(f_string2);var len=array1.length;var text=true;var result=-1;var r=0;if(len>array2.length){len=array2.length;result=1;}
for(i=0;i<len;i++){if(isNaN(array1[i])){if(isNaN(array2[i])){text=true;if((r=this.strcmp(array1[i],array2[i]))!=0){return r;}}
else if(text){return 1;}else{return-1;}}else if(isNaN(array2[i])){if(text){return-1;}else{return 1;}}else{if(text||f_version){if((r=(array1[i]-array2[i]))!=0){return r;}}else{if((r=this.strcmp(array1[i].toString(),array2[i].toString()))!=0){return r;}}
text=false;}}
return result;},strpbrk:function(haystack,char_list){var lon=haystack.length;var lon_search=char_list.length;var ret=false;var stack='';if(lon>=lon_search){if(lon==lon_search){if(haystack==char_list){ret=haystack;}}else{j=0;i=0;while(i<lon_search&&j<lon&&!ret){if(char_list[i]==haystack[j]){i++;if(i==lon_search)ret=true;}
j++;}
if(ret){for(i=(j-lon_search);i<lon;i++){stack+=haystack[i];}}
if(stack!=''){ret=stack;}}}
return ret;},strpos:function(haystack,needle,offset){var i=haystack.indexOf(needle,offset);return i>=0?i:false;},strrev:function(string){var ret='',i=0;for(i=string.length-1;i>=0;i--){ret+=string.charAt(i);}
return ret;},strripos:function(haystack,needle,offset){var i=haystack.toLowerCase().lastIndexOf(needle.toLowerCase(),offset);return i>=0?i:false;},strrpos:function(haystack,needle,offset){var i=haystack.lastIndexOf(needle,offset);return i>=0?i:false;},strstr:function(haystack,needle,bool){var pos=0;pos=haystack.indexOf(needle);if(pos==-1){return false;}else{if(bool){return haystack.substr(0,pos);}else{return haystack.slice(pos);}}},strtolower:function(str){return str.toLowerCase();},strtoupper:function(str){return str.toUpperCase();},substr:function(f_string,f_start,f_length){if(f_start<0){f_start+=f_string.length;}
if(f_length==undefined){f_length=f_string.length;}else if(f_length<0){f_length+=f_string.length;}else{f_length+=f_start;}
if(f_length<f_start){f_length=f_start;}
return f_string.substring(f_start,f_length);},substr_count:function(haystack,needle,offset,length){var pos=0,cnt=0;if(isNaN(offset))offset=0;if(isNaN(length))length=0;offset--;while((offset=haystack.indexOf(needle,offset+1))!=-1){if(length>0&&(offset+needle.length)>length){return false;}else{cnt++;}}
return cnt;},trim:function(str,charlist){var whitespace;if(!charlist){whitespace=' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';}else{whitespace=charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g,'\$1');}
for(var i=0;i<str.length;i++){if(whitespace.indexOf(str.charAt(i))===-1){str=str.substring(i);break;}}
for(i=str.length-1;i>=0;i--){if(whitespace.indexOf(str.charAt(i))===-1){str=str.substring(0,i+1);break;}}
return whitespace.indexOf(str.charAt(0))===-1?str:'';},ucfirst:function(str){var f=str.charAt(0).toUpperCase();return f+str.substr(1,str.length-1);},ucwords:function(str){return str.replace(/^(.)|\s(.)/g,function($1){return $1.toUpperCase();});},wordwrap:function(str,int_width,str_break,cut){var m=int_width,b=str_break,c=cut;var i,j,l,s,r;if(m<1){return str;}
for(i=-1,l=(r=str.split("\n")).length;++i<l;r[i]+=s){for(s=r[i],r[i]="";s.length>m;r[i]+=s.slice(0,j)+((s=s.slice(j)).length?b:"")){j=c==2||(j=s.slice(0,m+1).match(/\S*(\s)?$/))[1]?m:j.input.length-j[0].length||c==1&&m||j.input.length+(j=s.slice(m).match(/^\S*/)).input.length;}}
return r.join("\n");},base64_decode:function(data){var b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var o1,o2,o3,h1,h2,h3,h4,bits,i=ac=0,dec="",tmp_arr=[];do{h1=b64.indexOf(data.charAt(i++));h2=b64.indexOf(data.charAt(i++));h3=b64.indexOf(data.charAt(i++));h4=b64.indexOf(data.charAt(i++));bits=h1<<18|h2<<12|h3<<6|h4;o1=bits>>16&0xff;o2=bits>>8&0xff;o3=bits&0xff;if(h3==64){tmp_arr[ac++]=String.fromCharCode(o1);}else if(h4==64){tmp_arr[ac++]=String.fromCharCode(o1,o2);}else{tmp_arr[ac++]=String.fromCharCode(o1,o2,o3);}}while(i<data.length);dec=tmp_arr.join('');dec=this.utf8_decode(dec);return dec;},base64_encode:function(data){var b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var o1,o2,o3,h1,h2,h3,h4,bits,i=ac=0,enc="",tmp_arr=[];data=this.utf8_encode(data);do{o1=data.charCodeAt(i++);o2=data.charCodeAt(i++);o3=data.charCodeAt(i++);bits=o1<<16|o2<<8|o3;h1=bits>>18&0x3f;h2=bits>>12&0x3f;h3=bits>>6&0x3f;h4=bits&0x3f;tmp_arr[ac++]=b64.charAt(h1)+b64.charAt(h2)+b64.charAt(h3)+b64.charAt(h4);}while(i<data.length);enc=tmp_arr.join('');switch(data.length%3){case 1:enc=enc.slice(0,-2)+'==';break;case 2:enc=enc.slice(0,-1)+'=';break;}
return enc;},http_build_query:function(formdata,numeric_prefix,arg_separator){var key,use_val,use_key,i=0,tmp_arr=[];if(!arg_separator){arg_separator='&';}
for(key in formdata){use_key=encodeURIComponent(key);use_val=encodeURIComponent((formdata[key].toString()));use_val=use_val.replace(/%20/g,'+');if(numeric_prefix&&!isNaN(key)){use_key=numeric_prefix+i;}
tmp_arr[i]=use_key+'='+use_val;i++;}
return tmp_arr.join(arg_separator);},urldecode:function(str){var ret=str;ret=ret.replace(/\+/g,'%20');ret=decodeURIComponent(ret);ret=ret.toString();return ret;},urlencode:function(str){var ret=str;ret=ret.toString();ret=encodeURIComponent(ret);ret=ret.replace(/%20/g,'+');return ret;},empty:function(mixed_var){return(mixed_var===""||mixed_var===0||mixed_var==="0"||mixed_var===null||mixed_var===false||(is_array(mixed_var)&&mixed_var.length===0));},floatval:function(mixed_var){return(parseFloat(mixed_var)||0);},intval:function(mixed_var,base){var tmp;if(typeof(mixed_var)=='string'){tmp=parseInt(mixed_var*1);if(isNaN(tmp)||!isFinite(tmp)){return 0;}else{return tmp.toString(base||10);}}else if(typeof(mixed_var)=='number'&&isFinite(mixed_var)){return Math.floor(mixed_var);}else{return 0;}},is_array:function(mixed_var){return(mixed_var instanceof Array);},is_null:function(mixed_var){return(mixed_var===null);},is_numeric:function(mixed_var){return!isNaN(mixed_var);},is_object:function(mixed_var){if(mixed_var instanceof Array){return false;}else{return(mixed_var!==null)&&(typeof(mixed_var)=='object');}},is_string:function(mixed_var){return(typeof(mixed_var)=='string');},isset:function(){var a=arguments;var l=a.length;var i=0;while(i!=l){if(typeof(a[i])=='undefined'){return false;}else{i++;}}
return true;},print_r:function(array,return_val){var output="",pad_char=" ",pad_val=4;var formatArray=function(obj,cur_depth,pad_val,pad_char){if(cur_depth>0){cur_depth++;}
var base_pad=repeat_char(pad_val*cur_depth,pad_char);var thick_pad=repeat_char(pad_val*(cur_depth+1),pad_char);var str="";if(obj instanceof Array||obj instanceof Object){str+="Array\n"+base_pad+"(\n";for(var key in obj){if(obj[key]instanceof Array){str+=thick_pad+"["+key+"] => "+formatArray(obj[key],cur_depth+1,pad_val,pad_char);}else{str+=thick_pad+"["+key+"] => "+obj[key]+"\n";}}
str+=base_pad+")\n";}else{str=obj.toString();}
return str;};var repeat_char=function(len,pad_char){var str="";for(var i=0;i<len;i++){str+=pad_char;};return str;};output=formatArray(array,0,pad_val,pad_char);if(return_val!==true){document.write("<pre>"+output+"</pre>");return true;}else{return output;}},serialize:function(inp){var getType=function(inp){var type=typeof inp,match;if(type=='object'&&!inp)
{return'null';}
if(type=="object"){if(!inp.constructor)
{return'object';}
var cons=inp.constructor.toString();if(match=cons.match(/(\w+)\(/)){cons=match[1].toLowerCase();}
var types=["boolean","number","string","array"];for(key in types){if(cons==types[key]){type=types[key];break;}}}
return type;};var type=getType(inp);var val;switch(type){case"undefined":val="N";break;case"boolean":val="b:"+(inp?"1":"0");break;case"number":val=(Math.round(inp)==inp?"i":"d")+":"+inp;break;case"string":val="s:"+inp.length+":\""+inp+"\"";break;case"array":val="a";case"object":if(type=="object"){var objname=inp.constructor.toString().match(/(\w+)\(\)/);if(objname==undefined){return;}
objname[1]=this.serialize(objname[1]);val="O"+objname[1].substring(1,objname[1].length-1);}
var count=0;var vals="";var okey;for(key in inp){okey=(key.match(/^[0-9]+$/)?parseInt(key):key);vals+=this.serialize(okey)+
this.serialize(inp[key]);count++;}
val+=":"+count+":{"+vals+"}";break;}
if(type!="object"&&type!="array")val+=";";return val;},unserialize:function(inp){error=0;if(inp==""||inp.length<2){errormsg="input is too short";return;}
var val,kret,vret,cval;var type=inp.charAt(0);var cont=inp.substring(2);var size=0,divpos=0,endcont=0,rest="",next="";switch(type){case"N":if(inp.charAt(1)!=";"){errormsg="missing ; for null";}
rest=cont;break;case"b":if(!/[01];/.test(cont.substring(0,2))){errormsg="value not 0 or 1, or missing ; for boolean";}
val=(cont.charAt(0)=="1");rest=cont.substring(2);break;case"s":val="";divpos=cont.indexOf(":");if(divpos==-1){errormsg="missing : for string";break;}
size=parseInt(cont.substring(0,divpos));if(size==0){if(cont.length-divpos<4){errormsg="string is too short";break;}
rest=cont.substring(divpos+4);break;}
if((cont.length-divpos-size)<4){errormsg="string is too short";break;}
if(cont.substring(divpos+2+size,divpos+4+size)!="\";"){errormsg="string is too long, or missing \";";}
val=cont.substring(divpos+2,divpos+2+size);rest=cont.substring(divpos+4+size);break;case"i":case"d":var dotfound=0;for(var i=0;i<cont.length;i++){cval=cont.charAt(i);if(isNaN(parseInt(cval))&&!(type=="d"&&cval=="."&&!dotfound++)){endcont=i;break;}}
if(!endcont||cont.charAt(endcont)!=";"){errormsg="missing or invalid value, or missing ; for int/float";}
val=cont.substring(0,endcont);val=(type=="i"?parseInt(val):parseFloat(val));rest=cont.substring(endcont+1);break;case"a":if(cont.length<4){errormsg="array is too short";return;}
divpos=cont.indexOf(":",1);if(divpos==-1){errormsg="missing : for array";return;}
size=parseInt(cont.substring(1*divpos,0));cont=cont.substring(divpos+2);val=new Array();if(cont.length<1){errormsg="array is too short";return;}
for(var i=0;i+1<size*2;i+=2){kret=this.unserialize(cont,1);if(error||kret[0]==undefined||kret[1]==""){errormsg="missing or invalid key, or missing value for array";return;}
vret=this.unserialize(kret[1],1);if(error){errormsg="invalid value for array";return;}
val[kret[0]]=vret[0];cont=vret[1];}
if(cont.charAt(0)!="}"){errormsg="missing ending }, or too many values for array";return;}
rest=cont.substring(1);break;case"O":divpos=cont.indexOf(":");if(divpos==-1){errormsg="missing : for object";return;}
size=parseInt(cont.substring(0,divpos));var objname=cont.substring(divpos+2,divpos+2+size);if(cont.substring(divpos+2+size,divpos+4+size)!="\":"){errormsg="object name is too long, or missing \":";return;}
var objprops=this.unserialize("a:"+cont.substring(divpos+4+size),1);if(error){errormsg="invalid object properties";return;}
rest=objprops[1];var objout="function "+objname+"(){";for(key in objprops[0]){objout+=""+key+"=objprops[0]['"+key+"'];";}
objout+="}val=new "+objname+"();";eval(objout);break;default:errormsg="invalid input type";}
return(arguments.length==1?val:[val,rest]);},var_export:function(mixed_expression,bool_return){var __pad_lines=function(x){return x.split("\n").join("\n  ");};var retstr="";if(mixed_expression instanceof Array){var iret="";for(i in mixed_expression){iret=iret+"\n"+this.var_export(i,true)+" => "+this.var_export(mixed_expression[i],true)+",";}
retstr="array ("+__pad_lines(iret)+"\n)";}else if(mixed_expression===null){retstr="NULL";}else{retstr=(!isNaN(mixed_expression))?mixed_expression:"'"+mixed_expression.replace('/(["\'\])/g',"\\$1").replace('/\0/g',"\\0")+"'";}
if(bool_return!=true){this.echo(retstr);return null;}
else{return retstr;}},utf8_decode:function(str_data){var tmp_arr=[],i=ac=c=c1=c2=0;while(i<str_data.length){c=str_data.charCodeAt(i);if(c<128){tmp_arr[ac++]=String.fromCharCode(c);i++;}else if((c>191)&&(c<224)){c2=str_data.charCodeAt(i+1);tmp_arr[ac++]=String.fromCharCode(((c&31)<<6)|(c2&63));i+=2;}else{c2=str_data.charCodeAt(i+1);c3=str_data.charCodeAt(i+2);tmp_arr[ac++]=String.fromCharCode(((c&15)<<12)|((c2&63)<<6)|(c3&63));i+=3;}}
return tmp_arr.join('');},utf8_encode:function(str_data){str_data=str_data.replace(/\r\n/g,"\n");var tmp_arr=[],ac=0;for(var n=0;n<str_data.length;n++){var c=str_data.charCodeAt(n);if(c<128){tmp_arr[ac++]=String.fromCharCode(c);}else if((c>127)&&(c<2048)){tmp_arr[ac++]=String.fromCharCode((c>>6)|192);tmp_arr[ac++]=String.fromCharCode((c&63)|128);}else{tmp_arr[ac++]=String.fromCharCode((c>>12)|224);tmp_arr[ac++]=String.fromCharCode(((c>>6)&63)|128);tmp_arr[ac++]=String.fromCharCode((c&63)|128);}}
return tmp_arr.join('');}};window.$P=PHP_JS();})();/*!
 * jQuery JavaScript Library v1.3.2
 * http://jquery.com/
 *
 * Copyright (c) 2009 John Resig
 * Dual licensed under the MIT and GPL licenses.
 * http://docs.jquery.com/License
 *
 * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
 * Revision: 6246
 */
(function(){

var 
	// Will speed up references to window, and allows munging its name.
	window = this,
	// Will speed up references to undefined, and allows munging its name.
	undefined,
	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,
	// Map over the $ in case of overwrite
	_$ = window.$,

	jQuery = window.jQuery = window.$ = function( selector, context ) {
		// The jQuery object is actually just the init constructor 'enhanced'
		return new jQuery.fn.init( selector, context );
	},

	// A simple way to check for HTML strings or ID strings
	// (both of which we optimize for)
	quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
	// Is it a simple selector
	isSimple = /^.[^:#\[\.,]*$/;

jQuery.fn = jQuery.prototype = {
	init: function( selector, context ) {
		// Make sure that a selection was provided
		selector = selector || document;

		// Handle $(DOMElement)
		if ( selector.nodeType ) {
			this[0] = selector;
			this.length = 1;
			this.context = selector;
			return this;
		}
		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			var match = quickExpr.exec( selector );

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] )
					selector = jQuery.clean( [ match[1] ], context );

				// HANDLE: $("#id")
				else {
					var elem = document.getElementById( match[3] );

					// Handle the case where IE and Opera return items
					// by name instead of ID
					if ( elem && elem.id != match[3] )
						return jQuery().find( selector );

					// Otherwise, we inject the element directly into the jQuery object
					var ret = jQuery( elem || [] );
					ret.context = document;
					ret.selector = selector;
					return ret;
				}

			// HANDLE: $(expr, [context])
			// (which is just equivalent to: $(content).find(expr)
			} else
				return jQuery( context ).find( selector );

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) )
			return jQuery( document ).ready( selector );

		// Make sure that old selector state is passed along
		if ( selector.selector && selector.context ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return this.setArray(jQuery.isArray( selector ) ?
			selector :
			jQuery.makeArray(selector));
	},

	// Start with an empty selector
	selector: "",

	// The current version of jQuery being used
	jquery: "1.3.2",

	// The number of elements contained in the matched element set
	size: function() {
		return this.length;
	},

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		return num === undefined ?

			// Return a 'clean' array
			Array.prototype.slice.call( this ) :

			// Return just the object
			this[ num ];
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems, name, selector ) {
		// Build a new jQuery matched element set
		var ret = jQuery( elems );

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;

		ret.context = this.context;

		if ( name === "find" )
			ret.selector = this.selector + (this.selector ? " " : "") + selector;
		else if ( name )
			ret.selector = this.selector + "." + name + "(" + selector + ")";

		// Return the newly-formed element set
		return ret;
	},

	// Force the current matched set of elements to become
	// the specified array of elements (destroying the stack in the process)
	// You should use pushStack() in order to do this, but maintain the stack
	setArray: function( elems ) {
		// Resetting the length to 0, then using the native Array push
		// is a super-fast way to populate an object with array-like properties
		this.length = 0;
		Array.prototype.push.apply( this, elems );

		return this;
	},

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},

	// Determine the position of an element within
	// the matched set of elements
	index: function( elem ) {
		// Locate the position of the desired element
		return jQuery.inArray(
			// If it receives a jQuery object, the first element is used
			elem && elem.jquery ? elem[0] : elem
		, this );
	},

	attr: function( name, value, type ) {
		var options = name;

		// Look for the case where we're accessing a style value
		if ( typeof name === "string" )
			if ( value === undefined )
				return this[0] && jQuery[ type || "attr" ]( this[0], name );

			else {
				options = {};
				options[ name ] = value;
			}

		// Check to see if we're setting style values
		return this.each(function(i){
			// Set all the styles
			for ( name in options )
				jQuery.attr(
					type ?
						this.style :
						this,
					name, jQuery.prop( this, options[ name ], type, i, name )
				);
		});
	},

	css: function( key, value ) {
		// ignore negative width and height values
		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
			value = undefined;
		return this.attr( key, value, "curCSS" );
	},

	text: function( text ) {
		if ( typeof text !== "object" && text != null )
			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );

		var ret = "";

		jQuery.each( text || this, function(){
			jQuery.each( this.childNodes, function(){
				if ( this.nodeType != 8 )
					ret += this.nodeType != 1 ?
						this.nodeValue :
						jQuery.fn.text( [ this ] );
			});
		});

		return ret;
	},

	wrapAll: function( html ) {
		if ( this[0] ) {
			// The elements to wrap the target around
			var wrap = jQuery( html, this[0].ownerDocument ).clone();

			if ( this[0].parentNode )
				wrap.insertBefore( this[0] );

			wrap.map(function(){
				var elem = this;

				while ( elem.firstChild )
					elem = elem.firstChild;

				return elem;
			}).append(this);
		}

		return this;
	},

	wrapInner: function( html ) {
		return this.each(function(){
			jQuery( this ).contents().wrapAll( html );
		});
	},

	wrap: function( html ) {
		return this.each(function(){
			jQuery( this ).wrapAll( html );
		});
	},

	append: function() {
		return this.domManip(arguments, true, function(elem){
			if (this.nodeType == 1)
				this.appendChild( elem );
		});
	},

	prepend: function() {
		return this.domManip(arguments, true, function(elem){
			if (this.nodeType == 1)
				this.insertBefore( elem, this.firstChild );
		});
	},

	before: function() {
		return this.domManip(arguments, false, function(elem){
			this.parentNode.insertBefore( elem, this );
		});
	},

	after: function() {
		return this.domManip(arguments, false, function(elem){
			this.parentNode.insertBefore( elem, this.nextSibling );
		});
	},

	end: function() {
		return this.prevObject || jQuery( [] );
	},

	// For internal use only.
	// Behaves like an Array's method, not like a jQuery method.
	push: [].push,
	sort: [].sort,
	splice: [].splice,

	find: function( selector ) {
		if ( this.length === 1 ) {
			var ret = this.pushStack( [], "find", selector );
			ret.length = 0;
			jQuery.find( selector, this[0], ret );
			return ret;
		} else {
			return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
				return jQuery.find( selector, elem );
			})), "find", selector );
		}
	},

	clone: function( events ) {
		// Do the clone
		var ret = this.map(function(){
			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
				// IE copies events bound via attachEvent when
				// using cloneNode. Calling detachEvent on the
				// clone will also remove the events from the orignal
				// In order to get around this, we use innerHTML.
				// Unfortunately, this means some modifications to
				// attributes in IE that are actually only stored
				// as properties will not be copied (such as the
				// the name attribute on an input).
				var html = this.outerHTML;
				if ( !html ) {
					var div = this.ownerDocument.createElement("div");
					div.appendChild( this.cloneNode(true) );
					html = div.innerHTML;
				}

				return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
			} else
				return this.cloneNode(true);
		});

		// Copy the events from the original to the clone
		if ( events === true ) {
			var orig = this.find("*").andSelf(), i = 0;

			ret.find("*").andSelf().each(function(){
				if ( this.nodeName !== orig[i].nodeName )
					return;

				var events = jQuery.data( orig[i], "events" );

				for ( var type in events ) {
					for ( var handler in events[ type ] ) {
						jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
					}
				}

				i++;
			});
		}

		// Return the cloned set
		return ret;
	},

	filter: function( selector ) {
		return this.pushStack(
			jQuery.isFunction( selector ) &&
			jQuery.grep(this, function(elem, i){
				return selector.call( elem, i );
			}) ||

			jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
				return elem.nodeType === 1;
			}) ), "filter", selector );
	},

	closest: function( selector ) {
		var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
			closer = 0;

		return this.map(function(){
			var cur = this;
			while ( cur && cur.ownerDocument ) {
				if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
					jQuery.data(cur, "closest", closer);
					return cur;
				}
				cur = cur.parentNode;
				closer++;
			}
		});
	},

	not: function( selector ) {
		if ( typeof selector === "string" )
			// test special case where just one selector is passed in
			if ( isSimple.test( selector ) )
				return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
			else
				selector = jQuery.multiFilter( selector, this );

		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
		return this.filter(function() {
			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
		});
	},

	add: function( selector ) {
		return this.pushStack( jQuery.unique( jQuery.merge(
			this.get(),
			typeof selector === "string" ?
				jQuery( selector ) :
				jQuery.makeArray( selector )
		)));
	},

	is: function( selector ) {
		return !!selector && jQuery.multiFilter( selector, this ).length > 0;
	},

	hasClass: function( selector ) {
		return !!selector && this.is( "." + selector );
	},

	val: function( value ) {
		if ( value === undefined ) {			
			var elem = this[0];

			if ( elem ) {
				if( jQuery.nodeName( elem, 'option' ) )
					return (elem.attributes.value || {}).specified ? elem.value : elem.text;
				
				// We need to handle select boxes special
				if ( jQuery.nodeName( elem, "select" ) ) {
					var index = elem.selectedIndex,
						values = [],
						options = elem.options,
						one = elem.type == "select-one";

					// Nothing was selected
					if ( index < 0 )
						return null;

					// Loop through all the selected options
					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
						var option = options[ i ];

						if ( option.selected ) {
							// Get the specifc value for the option
							value = jQuery(option).val();

							// We don't need an array for one selects
							if ( one )
								return value;

							// Multi-Selects return an array
							values.push( value );
						}
					}

					return values;				
				}

				// Everything else, we just grab the value
				return (elem.value || "").replace(/\r/g, "");

			}

			return undefined;
		}

		if ( typeof value === "number" )
			value += '';

		return this.each(function(){
			if ( this.nodeType != 1 )
				return;

			if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
					jQuery.inArray(this.name, value) >= 0);

			else if ( jQuery.nodeName( this, "select" ) ) {
				var values = jQuery.makeArray(value);

				jQuery( "option", this ).each(function(){
					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
						jQuery.inArray( this.text, values ) >= 0);
				});

				if ( !values.length )
					this.selectedIndex = -1;

			} else
				this.value = value;
		});
	},

	html: function( value ) {
		return value === undefined ?
			(this[0] ?
				this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
				null) :
			this.empty().append( value );
	},

	replaceWith: function( value ) {
		return this.after( value ).remove();
	},

	eq: function( i ) {
		return this.slice( i, +i + 1 );
	},

	slice: function() {
		return this.pushStack( Array.prototype.slice.apply( this, arguments ),
			"slice", Array.prototype.slice.call(arguments).join(",") );
	},

	map: function( callback ) {
		return this.pushStack( jQuery.map(this, function(elem, i){
			return callback.call( elem, i, elem );
		}));
	},

	andSelf: function() {
		return this.add( this.prevObject );
	},

	domManip: function( args, table, callback ) {
		if ( this[0] ) {
			var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
				scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
				first = fragment.firstChild;

			if ( first )
				for ( var i = 0, l = this.length; i < l; i++ )
					callback.call( root(this[i], first), this.length > 1 || i > 0 ?
							fragment.cloneNode(true) : fragment );
		
			if ( scripts )
				jQuery.each( scripts, evalScript );
		}

		return this;
		
		function root( elem, cur ) {
			return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
				(elem.getElementsByTagName("tbody")[0] ||
				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
				elem;
		}
	}
};

// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;

function evalScript( i, elem ) {
	if ( elem.src )
		jQuery.ajax({
			url: elem.src,
			async: false,
			dataType: "script"
		});

	else
		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );

	if ( elem.parentNode )
		elem.parentNode.removeChild( elem );
}

function now(){
	return +new Date;
}

jQuery.extend = jQuery.fn.extend = function() {
	// copy reference to target object
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;
		target = arguments[1] || {};
		// skip the boolean and the target
		i = 2;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction(target) )
		target = {};

	// extend jQuery itself if only one argument is passed
	if ( length == i ) {
		target = this;
		--i;
	}

	for ( ; i < length; i++ )
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null )
			// Extend the base object
			for ( var name in options ) {
				var src = target[ name ], copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy )
					continue;

				// Recurse if we're merging object values
				if ( deep && copy && typeof copy === "object" && !copy.nodeType )
					target[ name ] = jQuery.extend( deep, 
						// Never move original objects, clone them
						src || ( copy.length != null ? [ ] : { } )
					, copy );

				// Don't bring in undefined values
				else if ( copy !== undefined )
					target[ name ] = copy;

			}

	// Return the modified object
	return target;
};

// exclude the following css properties to add px
var	exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
	// cache defaultView
	defaultView = document.defaultView || {},
	toString = Object.prototype.toString;

jQuery.extend({
	noConflict: function( deep ) {
		window.$ = _$;

		if ( deep )
			window.jQuery = _jQuery;

		return jQuery;
	},

	// See test/unit/core.js for details concerning isFunction.
	// Since version 1.3, DOM methods and functions like alert
	// aren't supported. They return false on IE (#2968).
	isFunction: function( obj ) {
		return toString.call(obj) === "[object Function]";
	},

	isArray: function( obj ) {
		return toString.call(obj) === "[object Array]";
	},

	// check if an element is in a (or is an) XML document
	isXMLDoc: function( elem ) {
		return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
			!!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
	},

	// Evalulates a script in a global context
	globalEval: function( data ) {
		if ( data && /\S/.test(data) ) {
			// Inspired by code by Andrea Giammarchi
			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
			var head = document.getElementsByTagName("head")[0] || document.documentElement,
				script = document.createElement("script");

			script.type = "text/javascript";
			if ( jQuery.support.scriptEval )
				script.appendChild( document.createTextNode( data ) );
			else
				script.text = data;

			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
			// This arises when a base node is used (#2709).
			head.insertBefore( script, head.firstChild );
			head.removeChild( script );
		}
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
	},

	// args is for internal usage only
	each: function( object, callback, args ) {
		var name, i = 0, length = object.length;

		if ( args ) {
			if ( length === undefined ) {
				for ( name in object )
					if ( callback.apply( object[ name ], args ) === false )
						break;
			} else
				for ( ; i < length; )
					if ( callback.apply( object[ i++ ], args ) === false )
						break;

		// A special, fast, case for the most common use of each
		} else {
			if ( length === undefined ) {
				for ( name in object )
					if ( callback.call( object[ name ], name, object[ name ] ) === false )
						break;
			} else
				for ( var value = object[0];
					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
		}

		return object;
	},

	prop: function( elem, value, type, i, name ) {
		// Handle executable functions
		if ( jQuery.isFunction( value ) )
			value = value.call( elem, i );

		// Handle passing in a number to a CSS property
		return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
			value + "px" :
			value;
	},

	className: {
		// internal only, use addClass("class")
		add: function( elem, classNames ) {
			jQuery.each((classNames || "").split(/\s+/), function(i, className){
				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
					elem.className += (elem.className ? " " : "") + className;
			});
		},

		// internal only, use removeClass("class")
		remove: function( elem, classNames ) {
			if (elem.nodeType == 1)
				elem.className = classNames !== undefined ?
					jQuery.grep(elem.className.split(/\s+/), function(className){
						return !jQuery.className.has( classNames, className );
					}).join(" ") :
					"";
		},

		// internal only, use hasClass("class")
		has: function( elem, className ) {
			return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
		}
	},

	// A method for quickly swapping in/out CSS properties to get correct calculations
	swap: function( elem, options, callback ) {
		var old = {};
		// Remember the old values, and insert the new ones
		for ( var name in options ) {
			old[ name ] = elem.style[ name ];
			elem.style[ name ] = options[ name ];
		}

		callback.call( elem );

		// Revert the old values
		for ( var name in options )
			elem.style[ name ] = old[ name ];
	},

	css: function( elem, name, force, extra ) {
		if ( name == "width" || name == "height" ) {
			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];

			function getWH() {
				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;

				if ( extra === "border" )
					return;

				jQuery.each( which, function() {
					if ( !extra )
						val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
					if ( extra === "margin" )
						val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
					else
						val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
				});
			}

			if ( elem.offsetWidth !== 0 )
				getWH();
			else
				jQuery.swap( elem, props, getWH );

			return Math.max(0, Math.round(val));
		}

		return jQuery.curCSS( elem, name, force );
	},

	curCSS: function( elem, name, force ) {
		var ret, style = elem.style;

		// We need to handle opacity special in IE
		if ( name == "opacity" && !jQuery.support.opacity ) {
			ret = jQuery.attr( style, "opacity" );

			return ret == "" ?
				"1" :
				ret;
		}

		// Make sure we're using the right name for getting the float value
		if ( name.match( /float/i ) )
			name = styleFloat;

		if ( !force && style && style[ name ] )
			ret = style[ name ];

		else if ( defaultView.getComputedStyle ) {

			// Only "float" is needed here
			if ( name.match( /float/i ) )
				name = "float";

			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();

			var computedStyle = defaultView.getComputedStyle( elem, null );

			if ( computedStyle )
				ret = computedStyle.getPropertyValue( name );

			// We should always get a number back from opacity
			if ( name == "opacity" && ret == "" )
				ret = "1";

		} else if ( elem.currentStyle ) {
			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
				return letter.toUpperCase();
			});

			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];

			// From the awesome hack by Dean Edwards
			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

			// If we're not dealing with a regular pixel number
			// but a number that has a weird ending, we need to convert it to pixels
			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
				// Remember the original values
				var left = style.left, rsLeft = elem.runtimeStyle.left;

				// Put in the new values to get a computed value out
				elem.runtimeStyle.left = elem.currentStyle.left;
				style.left = ret || 0;
				ret = style.pixelLeft + "px";

				// Revert the changed values
				style.left = left;
				elem.runtimeStyle.left = rsLeft;
			}
		}

		return ret;
	},

	clean: function( elems, context, fragment ) {
		context = context || document;

		// !context.createElement fails in IE with an error but returns typeof 'object'
		if ( typeof context.createElement === "undefined" )
			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;

		// If a single string is passed in and it's a single tag
		// just do a createElement and skip the rest
		if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
			var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
			if ( match )
				return [ context.createElement( match[1] ) ];
		}

		var ret = [], scripts = [], div = context.createElement("div");

		jQuery.each(elems, function(i, elem){
			if ( typeof elem === "number" )
				elem += '';

			if ( !elem )
				return;

			// Convert html string into DOM nodes
			if ( typeof elem === "string" ) {
				// Fix "XHTML"-style tags in all browsers
				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
						all :
						front + "></" + tag + ">";
				});

				// Trim whitespace, otherwise indexOf won't work as expected
				var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();

				var wrap =
					// option or optgroup
					!tags.indexOf("<opt") &&
					[ 1, "<select multiple='multiple'>", "</select>" ] ||

					!tags.indexOf("<leg") &&
					[ 1, "<fieldset>", "</fieldset>" ] ||

					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
					[ 1, "<table>", "</table>" ] ||

					!tags.indexOf("<tr") &&
					[ 2, "<table><tbody>", "</tbody></table>" ] ||

				 	// <thead> matched above
					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||

					!tags.indexOf("<col") &&
					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||

					// IE can't serialize <link> and <script> tags normally
					!jQuery.support.htmlSerialize &&
					[ 1, "div<div>", "</div>" ] ||

					[ 0, "", "" ];

				// Go to html and back, then peel off extra wrappers
				div.innerHTML = wrap[1] + elem + wrap[2];

				// Move to the right depth
				while ( wrap[0]-- )
					div = div.lastChild;

				// Remove IE's autoinserted <tbody> from table fragments
				if ( !jQuery.support.tbody ) {

					// String was a <table>, *may* have spurious <tbody>
					var hasBody = /<tbody/i.test(elem),
						tbody = !tags.indexOf("<table") && !hasBody ?
							div.firstChild && div.firstChild.childNodes :

						// String was a bare <thead> or <tfoot>
						wrap[1] == "<table>" && !hasBody ?
							div.childNodes :
							[];

					for ( var j = tbody.length - 1; j >= 0 ; --j )
						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
							tbody[ j ].parentNode.removeChild( tbody[ j ] );

					}

				// IE completely kills leading whitespace when innerHTML is used
				if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
					div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
				
				elem = jQuery.makeArray( div.childNodes );
			}

			if ( elem.nodeType )
				ret.push( elem );
			else
				ret = jQuery.merge( ret, elem );

		});

		if ( fragment ) {
			for ( var i = 0; ret[i]; i++ ) {
				if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
				} else {
					if ( ret[i].nodeType === 1 )
						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
					fragment.appendChild( ret[i] );
				}
			}
			
			return scripts;
		}

		return ret;
	},

	attr: function( elem, name, value ) {
		// don't set attributes on text and comment nodes
		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
			return undefined;

		var notxml = !jQuery.isXMLDoc( elem ),
			// Whether we are setting (or getting)
			set = value !== undefined;

		// Try to normalize/fix the name
		name = notxml && jQuery.props[ name ] || name;

		// Only do all the following if this is a node (faster for style)
		// IE elem.getAttribute passes even for style
		if ( elem.tagName ) {

			// These attributes require special treatment
			var special = /href|src|style/.test( name );

			// Safari mis-reports the default selected property of a hidden option
			// Accessing the parent's selectedIndex property fixes it
			if ( name == "selected" && elem.parentNode )
				elem.parentNode.selectedIndex;

			// If applicable, access the attribute via the DOM 0 way
			if ( name in elem && notxml && !special ) {
				if ( set ){
					// We can't allow the type property to be changed (since it causes problems in IE)
					if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
						throw "type property can't be changed";

					elem[ name ] = value;
				}

				// browsers index elements by id/name on forms, give priority to attributes.
				if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
					return elem.getAttributeNode( name ).nodeValue;

				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
				if ( name == "tabIndex" ) {
					var attributeNode = elem.getAttributeNode( "tabIndex" );
					return attributeNode && attributeNode.specified
						? attributeNode.value
						: elem.nodeName.match(/(button|input|object|select|textarea)/i)
							? 0
							: elem.nodeName.match(/^(a|area)$/i) && elem.href
								? 0
								: undefined;
				}

				return elem[ name ];
			}

			if ( !jQuery.support.style && notxml &&  name == "style" )
				return jQuery.attr( elem.style, "cssText", value );

			if ( set )
				// convert the value to a string (all browsers do this but IE) see #1070
				elem.setAttribute( name, "" + value );

			var attr = !jQuery.support.hrefNormalized && notxml && special
					// Some attributes require a special call on IE
					? elem.getAttribute( name, 2 )
					: elem.getAttribute( name );

			// Non-existent attributes return null, we normalize to undefined
			return attr === null ? undefined : attr;
		}

		// elem is actually elem.style ... set the style

		// IE uses filters for opacity
		if ( !jQuery.support.opacity && name == "opacity" ) {
			if ( set ) {
				// IE has trouble with opacity if it does not have layout
				// Force it by setting the zoom level
				elem.zoom = 1;

				// Set the alpha filter to set the opacity
				elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
					(parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
			}

			return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
				(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
				"";
		}

		name = name.replace(/-([a-z])/ig, function(all, letter){
			return letter.toUpperCase();
		});

		if ( set )
			elem[ name ] = value;

		return elem[ name ];
	},

	trim: function( text ) {
		return (text || "").replace( /^\s+|\s+$/g, "" );
	},

	makeArray: function( array ) {
		var ret = [];

		if( array != null ){
			var i = array.length;
			// The window, strings (and functions) also have 'length'
			if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
				ret[0] = array;
			else
				while( i )
					ret[--i] = array[i];
		}

		return ret;
	},

	inArray: function( elem, array ) {
		for ( var i = 0, length = array.length; i < length; i++ )
		// Use === because on IE, window == document
			if ( array[ i ] === elem )
				return i;

		return -1;
	},

	merge: function( first, second ) {
		// We have to loop this way because IE & Opera overwrite the length
		// expando of getElementsByTagName
		var i = 0, elem, pos = first.length;
		// Also, we need to make sure that the correct elements are being returned
		// (IE returns comment nodes in a '*' query)
		if ( !jQuery.support.getAll ) {
			while ( (elem = second[ i++ ]) != null )
				if ( elem.nodeType != 8 )
					first[ pos++ ] = elem;

		} else
			while ( (elem = second[ i++ ]) != null )
				first[ pos++ ] = elem;

		return first;
	},

	unique: function( array ) {
		var ret = [], done = {};

		try {

			for ( var i = 0, length = array.length; i < length; i++ ) {
				var id = jQuery.data( array[ i ] );

				if ( !done[ id ] ) {
					done[ id ] = true;
					ret.push( array[ i ] );
				}
			}

		} catch( e ) {
			ret = array;
		}

		return ret;
	},

	grep: function( elems, callback, inv ) {
		var ret = [];

		// Go through the array, only saving the items
		// that pass the validator function
		for ( var i = 0, length = elems.length; i < length; i++ )
			if ( !inv != !callback( elems[ i ], i ) )
				ret.push( elems[ i ] );

		return ret;
	},

	map: function( elems, callback ) {
		var ret = [];

		// Go through the array, translating each of the items to their
		// new value (or values).
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			var value = callback( elems[ i ], i );

			if ( value != null )
				ret[ ret.length ] = value;
		}

		return ret.concat.apply( [], ret );
	}
});

// Use of jQuery.browser is deprecated.
// It's included for backwards compatibility and plugins,
// although they should work to migrate away.

var userAgent = navigator.userAgent.toLowerCase();

// Figure out what browser is being used
jQuery.browser = {
	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
	safari: /webkit/.test( userAgent ),
	opera: /opera/.test( userAgent ),
	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
};

jQuery.each({
	parent: function(elem){return elem.parentNode;},
	parents: function(elem){return jQuery.dir(elem,"parentNode");},
	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
	children: function(elem){return jQuery.sibling(elem.firstChild);},
	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
}, function(name, fn){
	jQuery.fn[ name ] = function( selector ) {
		var ret = jQuery.map( this, fn );

		if ( selector && typeof selector == "string" )
			ret = jQuery.multiFilter( selector, ret );

		return this.pushStack( jQuery.unique( ret ), name, selector );
	};
});

jQuery.each({
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function(name, original){
	jQuery.fn[ name ] = function( selector ) {
		var ret = [], insert = jQuery( selector );

		for ( var i = 0, l = insert.length; i < l; i++ ) {
			var elems = (i > 0 ? this.clone(true) : this).get();
			jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
			ret = ret.concat( elems );
		}

		return this.pushStack( ret, name, selector );
	};
});

jQuery.each({
	removeAttr: function( name ) {
		jQuery.attr( this, name, "" );
		if (this.nodeType == 1)
			this.removeAttribute( name );
	},

	addClass: function( classNames ) {
		jQuery.className.add( this, classNames );
	},

	removeClass: function( classNames ) {
		jQuery.className.remove( this, classNames );
	},

	toggleClass: function( classNames, state ) {
		if( typeof state !== "boolean" )
			state = !jQuery.className.has( this, classNames );
		jQuery.className[ state ? "add" : "remove" ]( this, classNames );
	},

	remove: function( selector ) {
		if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
			// Prevent memory leaks
			jQuery( "*", this ).add([this]).each(function(){
				jQuery.event.remove(this);
				jQuery.removeData(this);
			});
			if (this.parentNode)
				this.parentNode.removeChild( this );
		}
	},

	empty: function() {
		// Remove element nodes and prevent memory leaks
		jQuery(this).children().remove();

		// Remove any remaining nodes
		while ( this.firstChild )
			this.removeChild( this.firstChild );
	}
}, function(name, fn){
	jQuery.fn[ name ] = function(){
		return this.each( fn, arguments );
	};
});

// Helper function used by the dimensions and offset modules
function num(elem, prop) {
	return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
}
var expando = "jQuery" + now(), uuid = 0, windowData = {};

jQuery.extend({
	cache: {},

	data: function( elem, name, data ) {
		elem = elem == window ?
			windowData :
			elem;

		var id = elem[ expando ];

		// Compute a unique ID for the element
		if ( !id )
			id = elem[ expando ] = ++uuid;

		// Only generate the data cache if we're
		// trying to access or manipulate it
		if ( name && !jQuery.cache[ id ] )
			jQuery.cache[ id ] = {};

		// Prevent overriding the named cache with undefined values
		if ( data !== undefined )
			jQuery.cache[ id ][ name ] = data;

		// Return the named cache data, or the ID for the element
		return name ?
			jQuery.cache[ id ][ name ] :
			id;
	},

	removeData: function( elem, name ) {
		elem = elem == window ?
			windowData :
			elem;

		var id = elem[ expando ];

		// If we want to remove a specific section of the element's data
		if ( name ) {
			if ( jQuery.cache[ id ] ) {
				// Remove the section of cache data
				delete jQuery.cache[ id ][ name ];

				// If we've removed all the data, remove the element's cache
				name = "";

				for ( name in jQuery.cache[ id ] )
					break;

				if ( !name )
					jQuery.removeData( elem );
			}

		// Otherwise, we want to remove all of the element's data
		} else {
			// Clean up the element expando
			try {
				delete elem[ expando ];
			} catch(e){
				// IE has trouble directly removing the expando
				// but it's ok with using removeAttribute
				if ( elem.removeAttribute )
					elem.removeAttribute( expando );
			}

			// Completely remove the data cache
			delete jQuery.cache[ id ];
		}
	},
	queue: function( elem, type, data ) {
		if ( elem ){
	
			type = (type || "fx") + "queue";
	
			var q = jQuery.data( elem, type );
	
			if ( !q || jQuery.isArray(data) )
				q = jQuery.data( elem, type, jQuery.makeArray(data) );
			else if( data )
				q.push( data );
	
		}
		return q;
	},

	dequeue: function( elem, type ){
		var queue = jQuery.queue( elem, type ),
			fn = queue.shift();
		
		if( !type || type === "fx" )
			fn = queue[0];
			
		if( fn !== undefined )
			fn.call(elem);
	}
});

jQuery.fn.extend({
	data: function( key, value ){
		var parts = key.split(".");
		parts[1] = parts[1] ? "." + parts[1] : "";

		if ( value === undefined ) {
			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);

			if ( data === undefined && this.length )
				data = jQuery.data( this[0], key );

			return data === undefined && parts[1] ?
				this.data( parts[0] ) :
				data;
		} else
			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
				jQuery.data( this, key, value );
			});
	},

	removeData: function( key ){
		return this.each(function(){
			jQuery.removeData( this, key );
		});
	},
	queue: function(type, data){
		if ( typeof type !== "string" ) {
			data = type;
			type = "fx";
		}

		if ( data === undefined )
			return jQuery.queue( this[0], type );

		return this.each(function(){
			var queue = jQuery.queue( this, type, data );
			
			 if( type == "fx" && queue.length == 1 )
				queue[0].call(this);
		});
	},
	dequeue: function(type){
		return this.each(function(){
			jQuery.dequeue( this, type );
		});
	}
});/*!
 * Sizzle CSS Selector Engine - v0.9.3
 *  Copyright 2009, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
(function(){

var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
	done = 0,
	toString = Object.prototype.toString;

var Sizzle = function(selector, context, results, seed) {
	results = results || [];
	context = context || document;

	if ( context.nodeType !== 1 && context.nodeType !== 9 )
		return [];
	
	if ( !selector || typeof selector !== "string" ) {
		return results;
	}

	var parts = [], m, set, checkSet, check, mode, extra, prune = true;
	
	// Reset the position of the chunker regexp (start from head)
	chunker.lastIndex = 0;
	
	while ( (m = chunker.exec(selector)) !== null ) {
		parts.push( m[1] );
		
		if ( m[2] ) {
			extra = RegExp.rightContext;
			break;
		}
	}

	if ( parts.length > 1 && origPOS.exec( selector ) ) {
		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
			set = posProcess( parts[0] + parts[1], context );
		} else {
			set = Expr.relative[ parts[0] ] ?
				[ context ] :
				Sizzle( parts.shift(), context );

			while ( parts.length ) {
				selector = parts.shift();

				if ( Expr.relative[ selector ] )
					selector += parts.shift();

				set = posProcess( selector, set );
			}
		}
	} else {
		var ret = seed ?
			{ expr: parts.pop(), set: makeArray(seed) } :
			Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
		set = Sizzle.filter( ret.expr, ret.set );

		if ( parts.length > 0 ) {
			checkSet = makeArray(set);
		} else {
			prune = false;
		}

		while ( parts.length ) {
			var cur = parts.pop(), pop = cur;

			if ( !Expr.relative[ cur ] ) {
				cur = "";
			} else {
				pop = parts.pop();
			}

			if ( pop == null ) {
				pop = context;
			}

			Expr.relative[ cur ]( checkSet, pop, isXML(context) );
		}
	}

	if ( !checkSet ) {
		checkSet = set;
	}

	if ( !checkSet ) {
		throw "Syntax error, unrecognized expression: " + (cur || selector);
	}

	if ( toString.call(checkSet) === "[object Array]" ) {
		if ( !prune ) {
			results.push.apply( results, checkSet );
		} else if ( context.nodeType === 1 ) {
			for ( var i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
					results.push( set[i] );
				}
			}
		} else {
			for ( var i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
					results.push( set[i] );
				}
			}
		}
	} else {
		makeArray( checkSet, results );
	}

	if ( extra ) {
		Sizzle( extra, context, results, seed );

		if ( sortOrder ) {
			hasDuplicate = false;
			results.sort(sortOrder);

			if ( hasDuplicate ) {
				for ( var i = 1; i < results.length; i++ ) {
					if ( results[i] === results[i-1] ) {
						results.splice(i--, 1);
					}
				}
			}
		}
	}

	return results;
};

Sizzle.matches = function(expr, set){
	return Sizzle(expr, null, null, set);
};

Sizzle.find = function(expr, context, isXML){
	var set, match;

	if ( !expr ) {
		return [];
	}

	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
		var type = Expr.order[i], match;
		
		if ( (match = Expr.match[ type ].exec( expr )) ) {
			var left = RegExp.leftContext;

			if ( left.substr( left.length - 1 ) !== "\\" ) {
				match[1] = (match[1] || "").replace(/\\/g, "");
				set = Expr.find[ type ]( match, context, isXML );
				if ( set != null ) {
					expr = expr.replace( Expr.match[ type ], "" );
					break;
				}
			}
		}
	}

	if ( !set ) {
		set = context.getElementsByTagName("*");
	}

	return {set: set, expr: expr};
};

Sizzle.filter = function(expr, set, inplace, not){
	var old = expr, result = [], curLoop = set, match, anyFound,
		isXMLFilter = set && set[0] && isXML(set[0]);

	while ( expr && set.length ) {
		for ( var type in Expr.filter ) {
			if ( (match = Expr.match[ type ].exec( expr )) != null ) {
				var filter = Expr.filter[ type ], found, item;
				anyFound = false;

				if ( curLoop == result ) {
					result = [];
				}

				if ( Expr.preFilter[ type ] ) {
					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );

					if ( !match ) {
						anyFound = found = true;
					} else if ( match === true ) {
						continue;
					}
				}

				if ( match ) {
					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
						if ( item ) {
							found = filter( item, match, i, curLoop );
							var pass = not ^ !!found;

							if ( inplace && found != null ) {
								if ( pass ) {
									anyFound = true;
								} else {
									curLoop[i] = false;
								}
							} else if ( pass ) {
								result.push( item );
								anyFound = true;
							}
						}
					}
				}

				if ( found !== undefined ) {
					if ( !inplace ) {
						curLoop = result;
					}

					expr = expr.replace( Expr.match[ type ], "" );

					if ( !anyFound ) {
						return [];
					}

					break;
				}
			}
		}

		// Improper expression
		if ( expr == old ) {
			if ( anyFound == null ) {
				throw "Syntax error, unrecognized expression: " + expr;
			} else {
				break;
			}
		}

		old = expr;
	}

	return curLoop;
};

var Expr = Sizzle.selectors = {
	order: [ "ID", "NAME", "TAG" ],
	match: {
		ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
		CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
		TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
		PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
	},
	attrMap: {
		"class": "className",
		"for": "htmlFor"
	},
	attrHandle: {
		href: function(elem){
			return elem.getAttribute("href");
		}
	},
	relative: {
		"+": function(checkSet, part, isXML){
			var isPartStr = typeof part === "string",
				isTag = isPartStr && !/\W/.test(part),
				isPartStrNotTag = isPartStr && !isTag;

			if ( isTag && !isXML ) {
				part = part.toUpperCase();
			}

			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
				if ( (elem = checkSet[i]) ) {
					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}

					checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
						elem || false :
						elem === part;
				}
			}

			if ( isPartStrNotTag ) {
				Sizzle.filter( part, checkSet, true );
			}
		},
		">": function(checkSet, part, isXML){
			var isPartStr = typeof part === "string";

			if ( isPartStr && !/\W/.test(part) ) {
				part = isXML ? part : part.toUpperCase();

				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
					var elem = checkSet[i];
					if ( elem ) {
						var parent = elem.parentNode;
						checkSet[i] = parent.nodeName === part ? parent : false;
					}
				}
			} else {
				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
					var elem = checkSet[i];
					if ( elem ) {
						checkSet[i] = isPartStr ?
							elem.parentNode :
							elem.parentNode === part;
					}
				}

				if ( isPartStr ) {
					Sizzle.filter( part, checkSet, true );
				}
			}
		},
		"": function(checkSet, part, isXML){
			var doneName = done++, checkFn = dirCheck;

			if ( !part.match(/\W/) ) {
				var nodeCheck = part = isXML ? part : part.toUpperCase();
				checkFn = dirNodeCheck;
			}

			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
		},
		"~": function(checkSet, part, isXML){
			var doneName = done++, checkFn = dirCheck;

			if ( typeof part === "string" && !part.match(/\W/) ) {
				var nodeCheck = part = isXML ? part : part.toUpperCase();
				checkFn = dirNodeCheck;
			}

			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
		}
	},
	find: {
		ID: function(match, context, isXML){
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				return m ? [m] : [];
			}
		},
		NAME: function(match, context, isXML){
			if ( typeof context.getElementsByName !== "undefined" ) {
				var ret = [], results = context.getElementsByName(match[1]);

				for ( var i = 0, l = results.length; i < l; i++ ) {
					if ( results[i].getAttribute("name") === match[1] ) {
						ret.push( results[i] );
					}
				}

				return ret.length === 0 ? null : ret;
			}
		},
		TAG: function(match, context){
			return context.getElementsByTagName(match[1]);
		}
	},
	preFilter: {
		CLASS: function(match, curLoop, inplace, result, not, isXML){
			match = " " + match[1].replace(/\\/g, "") + " ";

			if ( isXML ) {
				return match;
			}

			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
				if ( elem ) {
					if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
						if ( !inplace )
							result.push( elem );
					} else if ( inplace ) {
						curLoop[i] = false;
					}
				}
			}

			return false;
		},
		ID: function(match){
			return match[1].replace(/\\/g, "");
		},
		TAG: function(match, curLoop){
			for ( var i = 0; curLoop[i] === false; i++ ){}
			return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
		},
		CHILD: function(match){
			if ( match[1] == "nth" ) {
				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);

				// calculate the numbers (first)n+(last) including if they are negative
				match[2] = (test[1] + (test[2] || 1)) - 0;
				match[3] = test[3] - 0;
			}

			// TODO: Move to normal caching system
			match[0] = done++;

			return match;
		},
		ATTR: function(match, curLoop, inplace, result, not, isXML){
			var name = match[1].replace(/\\/g, "");
			
			if ( !isXML && Expr.attrMap[name] ) {
				match[1] = Expr.attrMap[name];
			}

			if ( match[2] === "~=" ) {
				match[4] = " " + match[4] + " ";
			}

			return match;
		},
		PSEUDO: function(match, curLoop, inplace, result, not){
			if ( match[1] === "not" ) {
				// If we're dealing with a complex expression, or a simple one
				if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
					match[3] = Sizzle(match[3], null, null, curLoop);
				} else {
					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
					if ( !inplace ) {
						result.push.apply( result, ret );
					}
					return false;
				}
			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
				return true;
			}
			
			return match;
		},
		POS: function(match){
			match.unshift( true );
			return match;
		}
	},
	filters: {
		enabled: function(elem){
			return elem.disabled === false && elem.type !== "hidden";
		},
		disabled: function(elem){
			return elem.disabled === true;
		},
		checked: function(elem){
			return elem.checked === true;
		},
		selected: function(elem){
			// Accessing this property makes selected-by-default
			// options in Safari work properly
			elem.parentNode.selectedIndex;
			return elem.selected === true;
		},
		parent: function(elem){
			return !!elem.firstChild;
		},
		empty: function(elem){
			return !elem.firstChild;
		},
		has: function(elem, i, match){
			return !!Sizzle( match[3], elem ).length;
		},
		header: function(elem){
			return /h\d/i.test( elem.nodeName );
		},
		text: function(elem){
			return "text" === elem.type;
		},
		radio: function(elem){
			return "radio" === elem.type;
		},
		checkbox: function(elem){
			return "checkbox" === elem.type;
		},
		file: function(elem){
			return "file" === elem.type;
		},
		password: function(elem){
			return "password" === elem.type;
		},
		submit: function(elem){
			return "submit" === elem.type;
		},
		image: function(elem){
			return "image" === elem.type;
		},
		reset: function(elem){
			return "reset" === elem.type;
		},
		button: function(elem){
			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
		},
		input: function(elem){
			return /input|select|textarea|button/i.test(elem.nodeName);
		}
	},
	setFilters: {
		first: function(elem, i){
			return i === 0;
		},
		last: function(elem, i, match, array){
			return i === array.length - 1;
		},
		even: function(elem, i){
			return i % 2 === 0;
		},
		odd: function(elem, i){
			return i % 2 === 1;
		},
		lt: function(elem, i, match){
			return i < match[3] - 0;
		},
		gt: function(elem, i, match){
			return i > match[3] - 0;
		},
		nth: function(elem, i, match){
			return match[3] - 0 == i;
		},
		eq: function(elem, i, match){
			return match[3] - 0 == i;
		}
	},
	filter: {
		PSEUDO: function(elem, match, i, array){
			var name = match[1], filter = Expr.filters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			} else if ( name === "contains" ) {
				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
			} else if ( name === "not" ) {
				var not = match[3];

				for ( var i = 0, l = not.length; i < l; i++ ) {
					if ( not[i] === elem ) {
						return false;
					}
				}

				return true;
			}
		},
		CHILD: function(elem, match){
			var type = match[1], node = elem;
			switch (type) {
				case 'only':
				case 'first':
					while (node = node.previousSibling)  {
						if ( node.nodeType === 1 ) return false;
					}
					if ( type == 'first') return true;
					node = elem;
				case 'last':
					while (node = node.nextSibling)  {
						if ( node.nodeType === 1 ) return false;
					}
					return true;
				case 'nth':
					var first = match[2], last = match[3];

					if ( first == 1 && last == 0 ) {
						return true;
					}
					
					var doneName = match[0],
						parent = elem.parentNode;
	
					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
						var count = 0;
						for ( node = parent.firstChild; node; node = node.nextSibling ) {
							if ( node.nodeType === 1 ) {
								node.nodeIndex = ++count;
							}
						} 
						parent.sizcache = doneName;
					}
					
					var diff = elem.nodeIndex - last;
					if ( first == 0 ) {
						return diff == 0;
					} else {
						return ( diff % first == 0 && diff / first >= 0 );
					}
			}
		},
		ID: function(elem, match){
			return elem.nodeType === 1 && elem.getAttribute("id") === match;
		},
		TAG: function(elem, match){
			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
		},
		CLASS: function(elem, match){
			return (" " + (elem.className || elem.getAttribute("class")) + " ")
				.indexOf( match ) > -1;
		},
		ATTR: function(elem, match){
			var name = match[1],
				result = Expr.attrHandle[ name ] ?
					Expr.attrHandle[ name ]( elem ) :
					elem[ name ] != null ?
						elem[ name ] :
						elem.getAttribute( name ),
				value = result + "",
				type = match[2],
				check = match[4];

			return result == null ?
				type === "!=" :
				type === "=" ?
				value === check :
				type === "*=" ?
				value.indexOf(check) >= 0 :
				type === "~=" ?
				(" " + value + " ").indexOf(check) >= 0 :
				!check ?
				value && result !== false :
				type === "!=" ?
				value != check :
				type === "^=" ?
				value.indexOf(check) === 0 :
				type === "$=" ?
				value.substr(value.length - check.length) === check :
				type === "|=" ?
				value === check || value.substr(0, check.length + 1) === check + "-" :
				false;
		},
		POS: function(elem, match, i, array){
			var name = match[2], filter = Expr.setFilters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			}
		}
	}
};

var origPOS = Expr.match.POS;

for ( var type in Expr.match ) {
	Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
}

var makeArray = function(array, results) {
	array = Array.prototype.slice.call( array );

	if ( results ) {
		results.push.apply( results, array );
		return results;
	}
	
	return array;
};

// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
try {
	Array.prototype.slice.call( document.documentElement.childNodes );

// Provide a fallback method if it does not work
} catch(e){
	makeArray = function(array, results) {
		var ret = results || [];

		if ( toString.call(array) === "[object Array]" ) {
			Array.prototype.push.apply( ret, array );
		} else {
			if ( typeof array.length === "number" ) {
				for ( var i = 0, l = array.length; i < l; i++ ) {
					ret.push( array[i] );
				}
			} else {
				for ( var i = 0; array[i]; i++ ) {
					ret.push( array[i] );
				}
			}
		}

		return ret;
	};
}

var sortOrder;

if ( document.documentElement.compareDocumentPosition ) {
	sortOrder = function( a, b ) {
		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
		if ( ret === 0 ) {
			hasDuplicate = true;
		}
		return ret;
	};
} else if ( "sourceIndex" in document.documentElement ) {
	sortOrder = function( a, b ) {
		var ret = a.sourceIndex - b.sourceIndex;
		if ( ret === 0 ) {
			hasDuplicate = true;
		}
		return ret;
	};
} else if ( document.createRange ) {
	sortOrder = function( a, b ) {
		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
		aRange.selectNode(a);
		aRange.collapse(true);
		bRange.selectNode(b);
		bRange.collapse(true);
		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
		if ( ret === 0 ) {
			hasDuplicate = true;
		}
		return ret;
	};
}

// Check to see if the browser returns elements by name when
// querying by getElementById (and provide a workaround)
(function(){
	// We're going to inject a fake input element with a specified name
	var form = document.createElement("form"),
		id = "script" + (new Date).getTime();
	form.innerHTML = "<input name='" + id + "'/>";

	// Inject it into the root element, check its status, and remove it quickly
	var root = document.documentElement;
	root.insertBefore( form, root.firstChild );

	// The workaround has to do additional checks after a getElementById
	// Which slows things down for other browsers (hence the branching)
	if ( !!document.getElementById( id ) ) {
		Expr.find.ID = function(match, context, isXML){
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
			}
		};

		Expr.filter.ID = function(elem, match){
			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
			return elem.nodeType === 1 && node && node.nodeValue === match;
		};
	}

	root.removeChild( form );
})();

(function(){
	// Check to see if the browser returns only elements
	// when doing getElementsByTagName("*")

	// Create a fake element
	var div = document.createElement("div");
	div.appendChild( document.createComment("") );

	// Make sure no comments are found
	if ( div.getElementsByTagName("*").length > 0 ) {
		Expr.find.TAG = function(match, context){
			var results = context.getElementsByTagName(match[1]);

			// Filter out possible comments
			if ( match[1] === "*" ) {
				var tmp = [];

				for ( var i = 0; results[i]; i++ ) {
					if ( results[i].nodeType === 1 ) {
						tmp.push( results[i] );
					}
				}

				results = tmp;
			}

			return results;
		};
	}

	// Check to see if an attribute returns normalized href attributes
	div.innerHTML = "<a href='#'></a>";
	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
			div.firstChild.getAttribute("href") !== "#" ) {
		Expr.attrHandle.href = function(elem){
			return elem.getAttribute("href", 2);
		};
	}
})();

if ( document.querySelectorAll ) (function(){
	var oldSizzle = Sizzle, div = document.createElement("div");
	div.innerHTML = "<p class='TEST'></p>";

	// Safari can't handle uppercase or unicode characters when
	// in quirks mode.
	if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
		return;
	}
	
	Sizzle = function(query, context, extra, seed){
		context = context || document;

		// Only use querySelectorAll on non-XML documents
		// (ID selectors don't work in non-HTML documents)
		if ( !seed && context.nodeType === 9 && !isXML(context) ) {
			try {
				return makeArray( context.querySelectorAll(query), extra );
			} catch(e){}
		}
		
		return oldSizzle(query, context, extra, seed);
	};

	Sizzle.find = oldSizzle.find;
	Sizzle.filter = oldSizzle.filter;
	Sizzle.selectors = oldSizzle.selectors;
	Sizzle.matches = oldSizzle.matches;
})();

if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
	var div = document.createElement("div");
	div.innerHTML = "<div class='test e'></div><div class='test'></div>";

	// Opera can't find a second classname (in 9.6)
	if ( div.getElementsByClassName("e").length === 0 )
		return;

	// Safari caches class attributes, doesn't catch changes (in 3.2)
	div.lastChild.className = "e";

	if ( div.getElementsByClassName("e").length === 1 )
		return;

	Expr.order.splice(1, 0, "CLASS");
	Expr.find.CLASS = function(match, context, isXML) {
		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
			return context.getElementsByClassName(match[1]);
		}
	};
})();

function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	var sibDir = dir == "previousSibling" && !isXML;
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];
		if ( elem ) {
			if ( sibDir && elem.nodeType === 1 ){
				elem.sizcache = doneName;
				elem.sizset = i;
			}
			elem = elem[dir];
			var match = false;

			while ( elem ) {
				if ( elem.sizcache === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 && !isXML ){
					elem.sizcache = doneName;
					elem.sizset = i;
				}

				if ( elem.nodeName === cur ) {
					match = elem;
					break;
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	var sibDir = dir == "previousSibling" && !isXML;
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];
		if ( elem ) {
			if ( sibDir && elem.nodeType === 1 ) {
				elem.sizcache = doneName;
				elem.sizset = i;
			}
			elem = elem[dir];
			var match = false;

			while ( elem ) {
				if ( elem.sizcache === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 ) {
					if ( !isXML ) {
						elem.sizcache = doneName;
						elem.sizset = i;
					}
					if ( typeof cur !== "string" ) {
						if ( elem === cur ) {
							match = true;
							break;
						}

					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
						match = elem;
						break;
					}
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

var contains = document.compareDocumentPosition ?  function(a, b){
	return a.compareDocumentPosition(b) & 16;
} : function(a, b){
	return a !== b && (a.contains ? a.contains(b) : true);
};

var isXML = function(elem){
	return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
		!!elem.ownerDocument && isXML( elem.ownerDocument );
};

var posProcess = function(selector, context){
	var tmpSet = [], later = "", match,
		root = context.nodeType ? [context] : context;

	// Position selectors must be done after the filter
	// And so must :not(positional) so we move all PSEUDOs to the end
	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
		later += match[0];
		selector = selector.replace( Expr.match.PSEUDO, "" );
	}

	selector = Expr.relative[selector] ? selector + "*" : selector;

	for ( var i = 0, l = root.length; i < l; i++ ) {
		Sizzle( selector, root[i], tmpSet );
	}

	return Sizzle.filter( later, tmpSet );
};

// EXPOSE
jQuery.find = Sizzle;
jQuery.filter = Sizzle.filter;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;

Sizzle.selectors.filters.hidden = function(elem){
	return elem.offsetWidth === 0 || elem.offsetHeight === 0;
};

Sizzle.selectors.filters.visible = function(elem){
	return elem.offsetWidth > 0 || elem.offsetHeight > 0;
};

Sizzle.selectors.filters.animated = function(elem){
	return jQuery.grep(jQuery.timers, function(fn){
		return elem === fn.elem;
	}).length;
};

jQuery.multiFilter = function( expr, elems, not ) {
	if ( not ) {
		expr = ":not(" + expr + ")";
	}

	return Sizzle.matches(expr, elems);
};

jQuery.dir = function( elem, dir ){
	var matched = [], cur = elem[dir];
	while ( cur && cur != document ) {
		if ( cur.nodeType == 1 )
			matched.push( cur );
		cur = cur[dir];
	}
	return matched;
};

jQuery.nth = function(cur, result, dir, elem){
	result = result || 1;
	var num = 0;

	for ( ; cur; cur = cur[dir] )
		if ( cur.nodeType == 1 && ++num == result )
			break;

	return cur;
};

jQuery.sibling = function(n, elem){
	var r = [];

	for ( ; n; n = n.nextSibling ) {
		if ( n.nodeType == 1 && n != elem )
			r.push( n );
	}

	return r;
};

return;

window.Sizzle = Sizzle;

})();
/*
 * A number of helper functions used for managing events.
 * Many of the ideas behind this code originated from
 * Dean Edwards' addEvent library.
 */
jQuery.event = {

	// Bind an event to an element
	// Original by Dean Edwards
	add: function(elem, types, handler, data) {
		if ( elem.nodeType == 3 || elem.nodeType == 8 )
			return;

		// For whatever reason, IE has trouble passing the window object
		// around, causing it to be cloned in the process
		if ( elem.setInterval && elem != window )
			elem = window;

		// Make sure that the function being executed has a unique ID
		if ( !handler.guid )
			handler.guid = this.guid++;

		// if data is passed, bind to handler
		if ( data !== undefined ) {
			// Create temporary function pointer to original handler
			var fn = handler;

			// Create unique handler function, wrapped around original handler
			handler = this.proxy( fn );

			// Store data in unique handler
			handler.data = data;
		}

		// Init the element's event structure
		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
				// Handle the second event of a trigger and when
				// an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
					jQuery.event.handle.apply(arguments.callee.elem, arguments) :
					undefined;
			});
		// Add elem as a property of the handle function
		// This is to prevent a memory leak with non-native
		// event in IE.
		handle.elem = elem;

		// Handle multiple events separated by a space
		// jQuery(...).bind("mouseover mouseout", fn);
		jQuery.each(types.split(/\s+/), function(index, type) {
			// Namespaced event handlers
			var namespaces = type.split(".");
			type = namespaces.shift();
			handler.type = namespaces.slice().sort().join(".");

			// Get the current list of functions bound to this event
			var handlers = events[type];
			
			if ( jQuery.event.specialAll[type] )
				jQuery.event.specialAll[type].setup.call(elem, data, namespaces);

			// Init the event handler queue
			if (!handlers) {
				handlers = events[type] = {};

				// Check for a special event handler
				// Only use addEventListener/attachEvent if the special
				// events handler returns false
				if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
					// Bind the global event handler to the element
					if (elem.addEventListener)
						elem.addEventListener(type, handle, false);
					else if (elem.attachEvent)
						elem.attachEvent("on" + type, handle);
				}
			}

			// Add the function to the element's handler list
			handlers[handler.guid] = handler;

			// Keep track of which events have been used, for global triggering
			jQuery.event.global[type] = true;
		});

		// Nullify elem to prevent memory leaks in IE
		elem = null;
	},

	guid: 1,
	global: {},

	// Detach an event or set of events from an element
	remove: function(elem, types, handler) {
		// don't do events on text and comment nodes
		if ( elem.nodeType == 3 || elem.nodeType == 8 )
			return;

		var events = jQuery.data(elem, "events"), ret, index;

		if ( events ) {
			// Unbind all events for the element
			if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
				for ( var type in events )
					this.remove( elem, type + (types || "") );
			else {
				// types is actually an event object here
				if ( types.type ) {
					handler = types.handler;
					types = types.type;
				}

				// Handle multiple events seperated by a space
				// jQuery(...).unbind("mouseover mouseout", fn);
				jQuery.each(types.split(/\s+/), function(index, type){
					// Namespaced event handlers
					var namespaces = type.split(".");
					type = namespaces.shift();
					var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");

					if ( events[type] ) {
						// remove the given handler for the given type
						if ( handler )
							delete events[type][handler.guid];

						// remove all handlers for the given type
						else
							for ( var handle in events[type] )
								// Handle the removal of namespaced events
								if ( namespace.test(events[type][handle].type) )
									delete events[type][handle];
									
						if ( jQuery.event.specialAll[type] )
							jQuery.event.specialAll[type].teardown.call(elem, namespaces);

						// remove generic event handler if no more handlers exist
						for ( ret in events[type] ) break;
						if ( !ret ) {
							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
								if (elem.removeEventListener)
									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
								else if (elem.detachEvent)
									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
							}
							ret = null;
							delete events[type];
						}
					}
				});
			}

			// Remove the expando if it's no longer used
			for ( ret in events ) break;
			if ( !ret ) {
				var handle = jQuery.data( elem, "handle" );
				if ( handle ) handle.elem = null;
				jQuery.removeData( elem, "events" );
				jQuery.removeData( elem, "handle" );
			}
		}
	},

	// bubbling is internal
	trigger: function( event, data, elem, bubbling ) {
		// Event object or event type
		var type = event.type || event;

		if( !bubbling ){
			event = typeof event === "object" ?
				// jQuery.Event object
				event[expando] ? event :
				// Object literal
				jQuery.extend( jQuery.Event(type), event ) :
				// Just the event type (string)
				jQuery.Event(type);

			if ( type.indexOf("!") >= 0 ) {
				event.type = type = type.slice(0, -1);
				event.exclusive = true;
			}

			// Handle a global trigger
			if ( !elem ) {
				// Don't bubble custom events when global (to avoid too much overhead)
				event.stopPropagation();
				// Only trigger if we've ever bound an event for it
				if ( this.global[type] )
					jQuery.each( jQuery.cache, function(){
						if ( this.events && this.events[type] )
							jQuery.event.trigger( event, data, this.handle.elem );
					});
			}

			// Handle triggering a single element

			// don't do events on text and comment nodes
			if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
				return undefined;
			
			// Clean up in case it is reused
			event.result = undefined;
			event.target = elem;
			
			// Clone the incoming data, if any
			data = jQuery.makeArray(data);
			data.unshift( event );
		}

		event.currentTarget = elem;

		// Trigger the event, it is assumed that "handle" is a function
		var handle = jQuery.data(elem, "handle");
		if ( handle )
			handle.apply( elem, data );

		// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
		if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
			event.result = false;

		// Trigger the native events (except for clicks on links)
		if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
			this.triggered = true;
			try {
				elem[ type ]();
			// prevent IE from throwing an error for some hidden elements
			} catch (e) {}
		}

		this.triggered = false;

		if ( !event.isPropagationStopped() ) {
			var parent = elem.parentNode || elem.ownerDocument;
			if ( parent )
				jQuery.event.trigger(event, data, parent, true);
		}
	},

	handle: function(event) {
		// returned undefined or false
		var all, handlers;

		event = arguments[0] = jQuery.event.fix( event || window.event );
		event.currentTarget = this;
		
		// Namespaced event handlers
		var namespaces = event.type.split(".");
		event.type = namespaces.shift();

		// Cache this now, all = true means, any handler
		all = !namespaces.length && !event.exclusive;
		
		var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");

		handlers = ( jQuery.data(this, "events") || {} )[event.type];

		for ( var j in handlers ) {
			var handler = handlers[j];

			// Filter the functions by class
			if ( all || namespace.test(handler.type) ) {
				// Pass in a reference to the handler function itself
				// So that we can later remove it
				event.handler = handler;
				event.data = handler.data;

				var ret = handler.apply(this, arguments);

				if( ret !== undefined ){
					event.result = ret;
					if ( ret === false ) {
						event.preventDefault();
						event.stopPropagation();
					}
				}

				if( event.isImmediatePropagationStopped() )
					break;

			}
		}
	},

	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),

	fix: function(event) {
		if ( event[expando] )
			return event;

		// store a copy of the original event object
		// and "clone" to set read-only properties
		var originalEvent = event;
		event = jQuery.Event( originalEvent );

		for ( var i = this.props.length, prop; i; ){
			prop = this.props[ --i ];
			event[ prop ] = originalEvent[ prop ];
		}

		// Fix target property, if necessary
		if ( !event.target )
			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either

		// check if target is a textnode (safari)
		if ( event.target.nodeType == 3 )
			event.target = event.target.parentNode;

		// Add relatedTarget, if necessary
		if ( !event.relatedTarget && event.fromElement )
			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;

		// Calculate pageX/Y if missing and clientX/Y available
		if ( event.pageX == null && event.clientX != null ) {
			var doc = document.documentElement, body = document.body;
			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
		}

		// Add which for key events
		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
			event.which = event.charCode || event.keyCode;

		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
		if ( !event.metaKey && event.ctrlKey )
			event.metaKey = event.ctrlKey;

		// Add which for click: 1 == left; 2 == middle; 3 == right
		// Note: button is not normalized, so don't use it
		if ( !event.which && event.button )
			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));

		return event;
	},

	proxy: function( fn, proxy ){
		proxy = proxy || function(){ return fn.apply(this, arguments); };
		// Set the guid of unique handler to the same of original handler, so it can be removed
		proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
		// So proxy can be declared as an argument
		return proxy;
	},

	special: {
		ready: {
			// Make sure the ready event is setup
			setup: bindReady,
			teardown: function() {}
		}
	},
	
	specialAll: {
		live: {
			setup: function( selector, namespaces ){
				jQuery.event.add( this, namespaces[0], liveHandler );
			},
			teardown:  function( namespaces ){
				if ( namespaces.length ) {
					var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
					
					jQuery.each( (jQuery.data(this, "events").live || {}), function(){
						if ( name.test(this.type) )
							remove++;
					});
					
					if ( remove < 1 )
						jQuery.event.remove( this, namespaces[0], liveHandler );
				}
			}
		}
	}
};

jQuery.Event = function( src ){
	// Allow instantiation without the 'new' keyword
	if( !this.preventDefault )
		return new jQuery.Event(src);
	
	// Event object
	if( src && src.type ){
		this.originalEvent = src;
		this.type = src.type;
	// Event type
	}else
		this.type = src;

	// timeStamp is buggy for some events on Firefox(#3843)
	// So we won't rely on the native value
	this.timeStamp = now();
	
	// Mark it as fixed
	this[expando] = true;
};

function returnFalse(){
	return false;
}
function returnTrue(){
	return true;
}

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
	preventDefault: function() {
		this.isDefaultPrevented = returnTrue;

		var e = this.originalEvent;
		if( !e )
			return;
		// if preventDefault exists run it on the original event
		if (e.preventDefault)
			e.preventDefault();
		// otherwise set the returnValue property of the original event to false (IE)
		e.returnValue = false;
	},
	stopPropagation: function() {
		this.isPropagationStopped = returnTrue;

		var e = this.originalEvent;
		if( !e )
			return;
		// if stopPropagation exists run it on the original event
		if (e.stopPropagation)
			e.stopPropagation();
		// otherwise set the cancelBubble property of the original event to true (IE)
		e.cancelBubble = true;
	},
	stopImmediatePropagation:function(){
		this.isImmediatePropagationStopped = returnTrue;
		this.stopPropagation();
	},
	isDefaultPrevented: returnFalse,
	isPropagationStopped: returnFalse,
	isImmediatePropagationStopped: returnFalse
};
// Checks if an event happened on an element within another element
// Used in jQuery.event.special.mouseenter and mouseleave handlers
var withinElement = function(event) {
	// Check if mouse(over|out) are still within the same parent element
	var parent = event.relatedTarget;
	// Traverse up the tree
	while ( parent && parent != this )
		try { parent = parent.parentNode; }
		catch(e) { parent = this; }
	
	if( parent != this ){
		// set the correct event type
		event.type = event.data;
		// handle event if we actually just moused on to a non sub-element
		jQuery.event.handle.apply( this, arguments );
	}
};
	
jQuery.each({ 
	mouseover: 'mouseenter', 
	mouseout: 'mouseleave'
}, function( orig, fix ){
	jQuery.event.special[ fix ] = {
		setup: function(){
			jQuery.event.add( this, orig, withinElement, fix );
		},
		teardown: function(){
			jQuery.event.remove( this, orig, withinElement );
		}
	};			   
});

jQuery.fn.extend({
	bind: function( type, data, fn ) {
		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
			jQuery.event.add( this, type, fn || data, fn && data );
		});
	},

	one: function( type, data, fn ) {
		var one = jQuery.event.proxy( fn || data, function(event) {
			jQuery(this).unbind(event, one);
			return (fn || data).apply( this, arguments );
		});
		return this.each(function(){
			jQuery.event.add( this, type, one, fn && data);
		});
	},

	unbind: function( type, fn ) {
		return this.each(function(){
			jQuery.event.remove( this, type, fn );
		});
	},

	trigger: function( type, data ) {
		return this.each(function(){
			jQuery.event.trigger( type, data, this );
		});
	},

	triggerHandler: function( type, data ) {
		if( this[0] ){
			var event = jQuery.Event(type);
			event.preventDefault();
			event.stopPropagation();
			jQuery.event.trigger( event, data, this[0] );
			return event.result;
		}		
	},

	toggle: function( fn ) {
		// Save reference to arguments for access in closure
		var args = arguments, i = 1;

		// link all the functions, so any of them can unbind this click handler
		while( i < args.length )
			jQuery.event.proxy( fn, args[i++] );

		return this.click( jQuery.event.proxy( fn, function(event) {
			// Figure out which function to execute
			this.lastToggle = ( this.lastToggle || 0 ) % i;

			// Make sure that clicks stop
			event.preventDefault();

			// and execute the function
			return args[ this.lastToggle++ ].apply( this, arguments ) || false;
		}));
	},

	hover: function(fnOver, fnOut) {
		return this.mouseenter(fnOver).mouseleave(fnOut);
	},

	ready: function(fn) {
		// Attach the listeners
		bindReady();

		// If the DOM is already ready
		if ( jQuery.isReady )
			// Execute the function immediately
			fn.call( document, jQuery );

		// Otherwise, remember the function for later
		else
			// Add the function to the wait list
			jQuery.readyList.push( fn );

		return this;
	},
	
	live: function( type, fn ){
		var proxy = jQuery.event.proxy( fn );
		proxy.guid += this.selector + type;

		jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );

		return this;
	},
	
	die: function( type, fn ){
		jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
		return this;
	}
});

function liveHandler( event ){
	var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
		stop = true,
		elems = [];

	jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
		if ( check.test(fn.type) ) {
			var elem = jQuery(event.target).closest(fn.data)[0];
			if ( elem )
				elems.push({ elem: elem, fn: fn });
		}
	});

	elems.sort(function(a,b) {
		return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
	});
	
	jQuery.each(elems, function(){
		if ( this.fn.call(this.elem, event, this.fn.data) === false )
			return (stop = false);
	});

	return stop;
}

function liveConvert(type, selector){
	return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
}

jQuery.extend({
	isReady: false,
	readyList: [],
	// Handle when the DOM is ready
	ready: function() {
		// Make sure that the DOM is not already loaded
		if ( !jQuery.isReady ) {
			// Remember that the DOM is ready
			jQuery.isReady = true;

			// If there are functions bound, to execute
			if ( jQuery.readyList ) {
				// Execute all of them
				jQuery.each( jQuery.readyList, function(){
					this.call( document, jQuery );
				});

				// Reset the list of functions
				jQuery.readyList = null;
			}

			// Trigger any bound ready events
			jQuery(document).triggerHandler("ready");
		}
	}
});

var readyBound = false;

function bindReady(){
	if ( readyBound ) return;
	readyBound = true;

	// Mozilla, Opera and webkit nightlies currently support this event
	if ( document.addEventListener ) {
		// Use the handy event callback
		document.addEventListener( "DOMContentLoaded", function(){
			document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
			jQuery.ready();
		}, false );

	// If IE event model is used
	} else if ( document.attachEvent ) {
		// ensure firing before onload,
		// maybe late but safe also for iframes
		document.attachEvent("onreadystatechange", function(){
			if ( document.readyState === "complete" ) {
				document.detachEvent( "onreadystatechange", arguments.callee );
				jQuery.ready();
			}
		});

		// If IE and not an iframe
		// continually check to see if the document is ready
		if ( document.documentElement.doScroll && window == window.top ) (function(){
			if ( jQuery.isReady ) return;

			try {
				// If IE is used, use the trick by Diego Perini
				// http://javascript.nwbox.com/IEContentLoaded/
				document.documentElement.doScroll("left");
			} catch( error ) {
				setTimeout( arguments.callee, 0 );
				return;
			}

			// and execute any waiting functions
			jQuery.ready();
		})();
	}

	// A fallback to window.onload, that will always work
	jQuery.event.add( window, "load", jQuery.ready );
}

jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
	"mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
	"change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){

	// Handle event binding
	jQuery.fn[name] = function(fn){
		return fn ? this.bind(name, fn) : this.trigger(name);
	};
});

// Prevent memory leaks in IE
// And prevent errors on refresh with events like mouseover in other browsers
// Window isn't included so as not to unbind existing unload events
jQuery( window ).bind( 'unload', function(){ 
	for ( var id in jQuery.cache )
		// Skip the window
		if ( id != 1 && jQuery.cache[ id ].handle )
			jQuery.event.remove( jQuery.cache[ id ].handle.elem );
}); 
(function(){

	jQuery.support = {};

	var root = document.documentElement,
		script = document.createElement("script"),
		div = document.createElement("div"),
		id = "script" + (new Date).getTime();

	div.style.display = "none";
	div.innerHTML = '   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';

	var all = div.getElementsByTagName("*"),
		a = div.getElementsByTagName("a")[0];

	// Can't get basic test support
	if ( !all || !all.length || !a ) {
		return;
	}

	jQuery.support = {
		// IE strips leading whitespace when .innerHTML is used
		leadingWhitespace: div.firstChild.nodeType == 3,
		
		// Make sure that tbody elements aren't automatically inserted
		// IE will insert them into empty tables
		tbody: !div.getElementsByTagName("tbody").length,
		
		// Make sure that you can get all elements in an <object> element
		// IE 7 always returns no results
		objectAll: !!div.getElementsByTagName("object")[0]
			.getElementsByTagName("*").length,
		
		// Make sure that link elements get serialized correctly by innerHTML
		// This requires a wrapper element in IE
		htmlSerialize: !!div.getElementsByTagName("link").length,
		
		// Get the style information from getAttribute
		// (IE uses .cssText insted)
		style: /red/.test( a.getAttribute("style") ),
		
		// Make sure that URLs aren't manipulated
		// (IE normalizes it by default)
		hrefNormalized: a.getAttribute("href") === "/a",
		
		// Make sure that element opacity exists
		// (IE uses filter instead)
		opacity: a.style.opacity === "0.5",
		
		// Verify style float existence
		// (IE uses styleFloat instead of cssFloat)
		cssFloat: !!a.style.cssFloat,

		// Will be defined later
		scriptEval: false,
		noCloneEvent: true,
		boxModel: null
	};
	
	script.type = "text/javascript";
	try {
		script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
	} catch(e){}

	root.insertBefore( script, root.firstChild );
	
	// Make sure that the execution of code works by injecting a script
	// tag with appendChild/createTextNode
	// (IE doesn't support this, fails, and uses .text instead)
	if ( window[ id ] ) {
		jQuery.support.scriptEval = true;
		delete window[ id ];
	}

	root.removeChild( script );

	if ( div.attachEvent && div.fireEvent ) {
		div.attachEvent("onclick", function(){
			// Cloning a node shouldn't copy over any
			// bound event handlers (IE does this)
			jQuery.support.noCloneEvent = false;
			div.detachEvent("onclick", arguments.callee);
		});
		div.cloneNode(true).fireEvent("onclick");
	}

	// Figure out if the W3C box model works as expected
	// document.body must exist before we can do this
	jQuery(function(){
		var div = document.createElement("div");
		div.style.width = div.style.paddingLeft = "1px";

		document.body.appendChild( div );
		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
		document.body.removeChild( div ).style.display = 'none';
	});
})();

var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";

jQuery.props = {
	"for": "htmlFor",
	"class": "className",
	"float": styleFloat,
	cssFloat: styleFloat,
	styleFloat: styleFloat,
	readonly: "readOnly",
	maxlength: "maxLength",
	cellspacing: "cellSpacing",
	rowspan: "rowSpan",
	tabindex: "tabIndex"
};
jQuery.fn.extend({
	// Keep a copy of the old load
	_load: jQuery.fn.load,

	load: function( url, params, callback ) {
		if ( typeof url !== "string" )
			return this._load( url );

		var off = url.indexOf(" ");
		if ( off >= 0 ) {
			var selector = url.slice(off, url.length);
			url = url.slice(0, off);
		}

		// Default to a GET request
		var type = "GET";

		// If the second parameter was provided
		if ( params )
			// If it's a function
			if ( jQuery.isFunction( params ) ) {
				// We assume that it's the callback
				callback = params;
				params = null;

			// Otherwise, build a param string
			} else if( typeof params === "object" ) {
				params = jQuery.param( params );
				type = "POST";
			}

		var self = this;

		// Request the remote document
		jQuery.ajax({
			url: url,
			type: type,
			dataType: "html",
			data: params,
			complete: function(res, status){
				// If successful, inject the HTML into all the matched elements
				if ( status == "success" || status == "notmodified" )
					// See if a selector was specified
					self.html( selector ?
						// Create a dummy div to hold the results
						jQuery("<div/>")
							// inject the contents of the document in, removing the scripts
							// to avoid any 'Permission Denied' errors in IE
							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))

							// Locate the specified elements
							.find(selector) :

						// If not, just inject the full result
						res.responseText );

				if( callback )
					self.each( callback, [res.responseText, status, res] );
			}
		});
		return this;
	},

	serialize: function() {
		return jQuery.param(this.serializeArray());
	},
	serializeArray: function() {
		return this.map(function(){
			return this.elements ? jQuery.makeArray(this.elements) : this;
		})
		.filter(function(){
			return this.name && !this.disabled &&
				(this.checked || /select|textarea/i.test(this.nodeName) ||
					/text|hidden|password|search/i.test(this.type));
		})
		.map(function(i, elem){
			var val = jQuery(this).val();
			return val == null ? null :
				jQuery.isArray(val) ?
					jQuery.map( val, function(val, i){
						return {name: elem.name, value: val};
					}) :
					{name: elem.name, value: val};
		}).get();
	}
});

// Attach a bunch of functions for handling common AJAX events
jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
	jQuery.fn[o] = function(f){
		return this.bind(o, f);
	};
});

var jsc = now();

jQuery.extend({
  
	get: function( url, data, callback, type ) {
		// shift arguments if data argument was ommited
		if ( jQuery.isFunction( data ) ) {
			callback = data;
			data = null;
		}

		return jQuery.ajax({
			type: "GET",
			url: url,
			data: data,
			success: callback,
			dataType: type
		});
	},

	getScript: function( url, callback ) {
		return jQuery.get(url, null, callback, "script");
	},

	getJSON: function( url, data, callback ) {
		return jQuery.get(url, data, callback, "json");
	},

	post: function( url, data, callback, type ) {
		if ( jQuery.isFunction( data ) ) {
			callback = data;
			data = {};
		}

		return jQuery.ajax({
			type: "POST",
			url: url,
			data: data,
			success: callback,
			dataType: type
		});
	},

	ajaxSetup: function( settings ) {
		jQuery.extend( jQuery.ajaxSettings, settings );
	},

	ajaxSettings: {
		url: location.href,
		global: true,
		type: "GET",
		contentType: "application/x-www-form-urlencoded",
		processData: true,
		async: true,
		/*
		timeout: 0,
		data: null,
		username: null,
		password: null,
		*/
		// Create the request object; Microsoft failed to properly
		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
		// This function can be overriden by calling jQuery.ajaxSetup
		xhr:function(){
			return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
		},
		accepts: {
			xml: "application/xml, text/xml",
			html: "text/html",
			script: "text/javascript, application/javascript",
			json: "application/json, text/javascript",
			text: "text/plain",
			_default: "*/*"
		}
	},

	// Last-Modified header cache for next request
	lastModified: {},

	ajax: function( s ) {
		// Extend the settings, but re-extend 's' so that it can be
		// checked again later (in the test suite, specifically)
		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));

		var jsonp, jsre = /=\?(&|$)/g, status, data,
			type = s.type.toUpperCase();

		// convert data if not already a string
		if ( s.data && s.processData && typeof s.data !== "string" )
			s.data = jQuery.param(s.data);

		// Handle JSONP Parameter Callbacks
		if ( s.dataType == "jsonp" ) {
			if ( type == "GET" ) {
				if ( !s.url.match(jsre) )
					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
			} else if ( !s.data || !s.data.match(jsre) )
				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
			s.dataType = "json";
		}

		// Build temporary JSONP function
		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
			jsonp = "jsonp" + jsc++;

			// Replace the =? sequence both in the query string and the data
			if ( s.data )
				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
			s.url = s.url.replace(jsre, "=" + jsonp + "$1");

			// We need to make sure
			// that a JSONP style response is executed properly
			s.dataType = "script";

			// Handle JSONP-style loading
			window[ jsonp ] = function(tmp){
				data = tmp;
				success();
				complete();
				// Garbage collect
				window[ jsonp ] = undefined;
				try{ delete window[ jsonp ]; } catch(e){}
				if ( head )
					head.removeChild( script );
			};
		}

		if ( s.dataType == "script" && s.cache == null )
			s.cache = false;

		if ( s.cache === false && type == "GET" ) {
			var ts = now();
			// try replacing _= if it is there
			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
			// if nothing was replaced, add timestamp to the end
			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
		}

		// If data is available, append data to url for get requests
		if ( s.data && type == "GET" ) {
			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;

			// IE likes to send both get and post data, prevent this
			s.data = null;
		}

		// Watch for a new set of requests
		if ( s.global && ! jQuery.active++ )
			jQuery.event.trigger( "ajaxStart" );

		// Matches an absolute URL, and saves the domain
		var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );

		// If we're requesting a remote document
		// and trying to load JSON or Script with a GET
		if ( s.dataType == "script" && type == "GET" && parts
			&& ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){

			var head = document.getElementsByTagName("head")[0];
			var script = document.createElement("script");
			script.src = s.url;
			if (s.scriptCharset)
				script.charset = s.scriptCharset;

			// Handle Script loading
			if ( !jsonp ) {
				var done = false;

				// Attach handlers for all browsers
				script.onload = script.onreadystatechange = function(){
					if ( !done && (!this.readyState ||
							this.readyState == "loaded" || this.readyState == "complete") ) {
						done = true;
						success();
						complete();

						// Handle memory leak in IE
						script.onload = script.onreadystatechange = null;
						head.removeChild( script );
					}
				};
			}

			head.appendChild(script);

			// We handle everything using the script element injection
			return undefined;
		}

		var requestDone = false;

		// Create the request object
		var xhr = s.xhr();

		// Open the socket
		// Passing null username, generates a login popup on Opera (#2865)
		if( s.username )
			xhr.open(type, s.url, s.async, s.username, s.password);
		else
			xhr.open(type, s.url, s.async);

		// Need an extra try/catch for cross domain requests in Firefox 3
		try {
			// Set the correct header, if data is being sent
			if ( s.data )
				xhr.setRequestHeader("Content-Type", s.contentType);

			// Set the If-Modified-Since header, if ifModified mode.
			if ( s.ifModified )
				xhr.setRequestHeader("If-Modified-Since",
					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );

			// Set header so the called script knows that it's an XMLHttpRequest
			xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");

			// Set the Accepts header for the server, depending on the dataType
			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
				s.accepts[ s.dataType ] + ", */*" :
				s.accepts._default );
		} catch(e){}

		// Allow custom headers/mimetypes and early abort
		if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
			// Handle the global AJAX counter
			if ( s.global && ! --jQuery.active )
				jQuery.event.trigger( "ajaxStop" );
			// close opended socket
			xhr.abort();
			return false;
		}

		if ( s.global )
			jQuery.event.trigger("ajaxSend", [xhr, s]);

		// Wait for a response to come back
		var onreadystatechange = function(isTimeout){
			// The request was aborted, clear the interval and decrement jQuery.active
			if (xhr.readyState == 0) {
				if (ival) {
					// clear poll interval
					clearInterval(ival);
					ival = null;
					// Handle the global AJAX counter
					if ( s.global && ! --jQuery.active )
						jQuery.event.trigger( "ajaxStop" );
				}
			// The transfer is complete and the data is available, or the request timed out
			} else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
				requestDone = true;

				// clear poll interval
				if (ival) {
					clearInterval(ival);
					ival = null;
				}

				status = isTimeout == "timeout" ? "timeout" :
					!jQuery.httpSuccess( xhr ) ? "error" :
					s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
					"success";

				if ( status == "success" ) {
					// Watch for, and catch, XML document parse errors
					try {
						// process the data (runs the xml through httpData regardless of callback)
						data = jQuery.httpData( xhr, s.dataType, s );
					} catch(e) {
						status = "parsererror";
					}
				}

				// Make sure that the request was successful or notmodified
				if ( status == "success" ) {
					// Cache Last-Modified header, if ifModified mode.
					var modRes;
					try {
						modRes = xhr.getResponseHeader("Last-Modified");
					} catch(e) {} // swallow exception thrown by FF if header is not available

					if ( s.ifModified && modRes )
						jQuery.lastModified[s.url] = modRes;

					// JSONP handles its own success callback
					if ( !jsonp )
						success();
				} else
					jQuery.handleError(s, xhr, status);

				// Fire the complete handlers
				complete();

				if ( isTimeout )
					xhr.abort();

				// Stop memory leaks
				if ( s.async )
					xhr = null;
			}
		};

		if ( s.async ) {
			// don't attach the handler to the request, just poll it instead
			var ival = setInterval(onreadystatechange, 13);

			// Timeout checker
			if ( s.timeout > 0 )
				setTimeout(function(){
					// Check to see if the request is still happening
					if ( xhr && !requestDone )
						onreadystatechange( "timeout" );
				}, s.timeout);
		}

		// Send the data
		try {
			xhr.send(s.data);
		} catch(e) {
			jQuery.handleError(s, xhr, null, e);
		}

		// firefox 1.5 doesn't fire statechange for sync requests
		if ( !s.async )
			onreadystatechange();

		function success(){
			// If a local callback was specified, fire it and pass it the data
			if ( s.success )
				s.success( data, status );

			// Fire the global callback
			if ( s.global )
				jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
		}

		function complete(){
			// Process result
			if ( s.complete )
				s.complete(xhr, status);

			// The request was completed
			if ( s.global )
				jQuery.event.trigger( "ajaxComplete", [xhr, s] );

			// Handle the global AJAX counter
			if ( s.global && ! --jQuery.active )
				jQuery.event.trigger( "ajaxStop" );
		}

		// return XMLHttpRequest to allow aborting the request etc.
		return xhr;
	},

	handleError: function( s, xhr, status, e ) {
		// If a local callback was specified, fire it
		if ( s.error ) s.error( xhr, status, e );

		// Fire the global callback
		if ( s.global )
			jQuery.event.trigger( "ajaxError", [xhr, s, e] );
	},

	// Counter for holding the number of active queries
	active: 0,

	// Determines if an XMLHttpRequest was successful or not
	httpSuccess: function( xhr ) {
		try {
			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
			return !xhr.status && location.protocol == "file:" ||
				( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
		} catch(e){}
		return false;
	},

	// Determines if an XMLHttpRequest returns NotModified
	httpNotModified: function( xhr, url ) {
		try {
			var xhrRes = xhr.getResponseHeader("Last-Modified");

			// Firefox always returns 200. check Last-Modified date
			return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
		} catch(e){}
		return false;
	},

	httpData: function( xhr, type, s ) {
		var ct = xhr.getResponseHeader("content-type"),
			xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
			data = xml ? xhr.responseXML : xhr.responseText;

		if ( xml && data.documentElement.tagName == "parsererror" )
			throw "parsererror";
			
		// Allow a pre-filtering function to sanitize the response
		// s != null is checked to keep backwards compatibility
		if( s && s.dataFilter )
			data = s.dataFilter( data, type );

		// The filter can actually parse the response
		if( typeof data === "string" ){

			// If the type is "script", eval it in global context
			if ( type == "script" )
				jQuery.globalEval( data );

			// Get the JavaScript object, if JSON is used.
			if ( type == "json" )
				data = window["eval"]("(" + data + ")");
		}
		
		return data;
	},

	// Serialize an array of form elements or a set of
	// key/values into a query string
	param: function( a ) {
		var s = [ ];

		function add( key, value ){
			s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
		};

		// If an array was passed in, assume that it is an array
		// of form elements
		if ( jQuery.isArray(a) || a.jquery )
			// Serialize the form elements
			jQuery.each( a, function(){
				add( this.name, this.value );
			});

		// Otherwise, assume that it's an object of key/value pairs
		else
			// Serialize the key/values
			for ( var j in a )
				// If the value is an array then the key names need to be repeated
				if ( jQuery.isArray(a[j]) )
					jQuery.each( a[j], function(){
						add( j, this );
					});
				else
					add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );

		// Return the resulting serialization
		return s.join("&").replace(/%20/g, "+");
	}

});
var elemdisplay = {},
	timerId,
	fxAttrs = [
		// height animations
		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
		// width animations
		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
		// opacity animations
		[ "opacity" ]
	];

function genFx( type, num ){
	var obj = {};
	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
		obj[ this ] = type;
	});
	return obj;
}

jQuery.fn.extend({
	show: function(speed,callback){
		if ( speed ) {
			return this.animate( genFx("show", 3), speed, callback);
		} else {
			for ( var i = 0, l = this.length; i < l; i++ ){
				var old = jQuery.data(this[i], "olddisplay");
				
				this[i].style.display = old || "";
				
				if ( jQuery.css(this[i], "display") === "none" ) {
					var tagName = this[i].tagName, display;
					
					if ( elemdisplay[ tagName ] ) {
						display = elemdisplay[ tagName ];
					} else {
						var elem = jQuery("<" + tagName + " />").appendTo("body");
						
						display = elem.css("display");
						if ( display === "none" )
							display = "block";
						
						elem.remove();
						
						elemdisplay[ tagName ] = display;
					}
					
					jQuery.data(this[i], "olddisplay", display);
				}
			}

			// Set the display of the elements in a second loop
			// to avoid the constant reflow
			for ( var i = 0, l = this.length; i < l; i++ ){
				this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
			}
			
			return this;
		}
	},

	hide: function(speed,callback){
		if ( speed ) {
			return this.animate( genFx("hide", 3), speed, callback);
		} else {
			for ( var i = 0, l = this.length; i < l; i++ ){
				var old = jQuery.data(this[i], "olddisplay");
				if ( !old && old !== "none" )
					jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
			}

			// Set the display of the elements in a second loop
			// to avoid the constant reflow
			for ( var i = 0, l = this.length; i < l; i++ ){
				this[i].style.display = "none";
			}

			return this;
		}
	},

	// Save the old toggle function
	_toggle: jQuery.fn.toggle,

	toggle: function( fn, fn2 ){
		var bool = typeof fn === "boolean";

		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
			this._toggle.apply( this, arguments ) :
			fn == null || bool ?
				this.each(function(){
					var state = bool ? fn : jQuery(this).is(":hidden");
					jQuery(this)[ state ? "show" : "hide" ]();
				}) :
				this.animate(genFx("toggle", 3), fn, fn2);
	},

	fadeTo: function(speed,to,callback){
		return this.animate({opacity: to}, speed, callback);
	},

	animate: function( prop, speed, easing, callback ) {
		var optall = jQuery.speed(speed, easing, callback);

		return this[ optall.queue === false ? "each" : "queue" ](function(){
		
			var opt = jQuery.extend({}, optall), p,
				hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
				self = this;
	
			for ( p in prop ) {
				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
					return opt.complete.call(this);

				if ( ( p == "height" || p == "width" ) && this.style ) {
					// Store display property
					opt.display = jQuery.css(this, "display");

					// Make sure that nothing sneaks out
					opt.overflow = this.style.overflow;
				}
			}

			if ( opt.overflow != null )
				this.style.overflow = "hidden";

			opt.curAnim = jQuery.extend({}, prop);

			jQuery.each( prop, function(name, val){
				var e = new jQuery.fx( self, opt, name );

				if ( /toggle|show|hide/.test(val) )
					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
				else {
					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
						start = e.cur(true) || 0;

					if ( parts ) {
						var end = parseFloat(parts[2]),
							unit = parts[3] || "px";

						// We need to compute starting value
						if ( unit != "px" ) {
							self.style[ name ] = (end || 1) + unit;
							start = ((end || 1) / e.cur(true)) * start;
							self.style[ name ] = start + unit;
						}

						// If a +=/-= token was provided, we're doing a relative animation
						if ( parts[1] )
							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;

						e.custom( start, end, unit );
					} else
						e.custom( start, val, "" );
				}
			});

			// For JS strict compliance
			return true;
		});
	},

	stop: function(clearQueue, gotoEnd){
		var timers = jQuery.timers;

		if (clearQueue)
			this.queue([]);

		this.each(function(){
			// go in reverse order so anything added to the queue during the loop is ignored
			for ( var i = timers.length - 1; i >= 0; i-- )
				if ( timers[i].elem == this ) {
					if (gotoEnd)
						// force the next step to be the last
						timers[i](true);
					timers.splice(i, 1);
				}
		});

		// start the next in the queue if the last step wasn't forced
		if (!gotoEnd)
			this.dequeue();

		return this;
	}

});

// Generate shortcuts for custom animations
jQuery.each({
	slideDown: genFx("show", 1),
	slideUp: genFx("hide", 1),
	slideToggle: genFx("toggle", 1),
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" }
}, function( name, props ){
	jQuery.fn[ name ] = function( speed, callback ){
		return this.animate( props, speed, callback );
	};
});

jQuery.extend({

	speed: function(speed, easing, fn) {
		var opt = typeof speed === "object" ? speed : {
			complete: fn || !fn && easing ||
				jQuery.isFunction( speed ) && speed,
			duration: speed,
			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
		};

		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
			jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;

		// Queueing
		opt.old = opt.complete;
		opt.complete = function(){
			if ( opt.queue !== false )
				jQuery(this).dequeue();
			if ( jQuery.isFunction( opt.old ) )
				opt.old.call( this );
		};

		return opt;
	},

	easing: {
		linear: function( p, n, firstNum, diff ) {
			return firstNum + diff * p;
		},
		swing: function( p, n, firstNum, diff ) {
			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
		}
	},

	timers: [],

	fx: function( elem, options, prop ){
		this.options = options;
		this.elem = elem;
		this.prop = prop;

		if ( !options.orig )
			options.orig = {};
	}

});

jQuery.fx.prototype = {

	// Simple function for setting a style value
	update: function(){
		if ( this.options.step )
			this.options.step.call( this.elem, this.now, this );

		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );

		// Set display property to block for height/width animations
		if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
			this.elem.style.display = "block";
	},

	// Get the current size
	cur: function(force){
		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
			return this.elem[ this.prop ];

		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
	},

	// Start an animation from one number to another
	custom: function(from, to, unit){
		this.startTime = now();
		this.start = from;
		this.end = to;
		this.unit = unit || this.unit || "px";
		this.now = this.start;
		this.pos = this.state = 0;

		var self = this;
		function t(gotoEnd){
			return self.step(gotoEnd);
		}

		t.elem = this.elem;

		if ( t() && jQuery.timers.push(t) && !timerId ) {
			timerId = setInterval(function(){
				var timers = jQuery.timers;

				for ( var i = 0; i < timers.length; i++ )
					if ( !timers[i]() )
						timers.splice(i--, 1);

				if ( !timers.length ) {
					clearInterval( timerId );
					timerId = undefined;
				}
			}, 13);
		}
	},

	// Simple 'show' function
	show: function(){
		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
		this.options.show = true;

		// Begin the animation
		// Make sure that we start at a small width/height to avoid any
		// flash of content
		this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());

		// Start by showing the element
		jQuery(this.elem).show();
	},

	// Simple 'hide' function
	hide: function(){
		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
		this.options.hide = true;

		// Begin the animation
		this.custom(this.cur(), 0);
	},

	// Each step of an animation
	step: function(gotoEnd){
		var t = now();

		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
			this.now = this.end;
			this.pos = this.state = 1;
			this.update();

			this.options.curAnim[ this.prop ] = true;

			var done = true;
			for ( var i in this.options.curAnim )
				if ( this.options.curAnim[i] !== true )
					done = false;

			if ( done ) {
				if ( this.options.display != null ) {
					// Reset the overflow
					this.elem.style.overflow = this.options.overflow;

					// Reset the display
					this.elem.style.display = this.options.display;
					if ( jQuery.css(this.elem, "display") == "none" )
						this.elem.style.display = "block";
				}

				// Hide the element if the "hide" operation was done
				if ( this.options.hide )
					jQuery(this.elem).hide();

				// Reset the properties, if the item has been hidden or shown
				if ( this.options.hide || this.options.show )
					for ( var p in this.options.curAnim )
						jQuery.attr(this.elem.style, p, this.options.orig[p]);
					
				// Execute the complete function
				this.options.complete.call( this.elem );
			}

			return false;
		} else {
			var n = t - this.startTime;
			this.state = n / this.options.duration;

			// Perform the easing function, defaults to swing
			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
			this.now = this.start + ((this.end - this.start) * this.pos);

			// Perform the next step of the animation
			this.update();
		}

		return true;
	}

};

jQuery.extend( jQuery.fx, {
	speeds:{
		slow: 600,
 		fast: 200,
 		// Default speed
 		_default: 400
	},
	step: {

		opacity: function(fx){
			jQuery.attr(fx.elem.style, "opacity", fx.now);
		},

		_default: function(fx){
			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
				fx.elem.style[ fx.prop ] = fx.now + fx.unit;
			else
				fx.elem[ fx.prop ] = fx.now;
		}
	}
});
if ( document.documentElement["getBoundingClientRect"] )
	jQuery.fn.offset = function() {
		if ( !this[0] ) return { top: 0, left: 0 };
		if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
		var box  = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
			clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
			top  = box.top  + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
			left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
		return { top: top, left: left };
	};
else 
	jQuery.fn.offset = function() {
		if ( !this[0] ) return { top: 0, left: 0 };
		if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
		jQuery.offset.initialized || jQuery.offset.initialize();

		var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
			doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
			body = doc.body, defaultView = doc.defaultView,
			prevComputedStyle = defaultView.getComputedStyle(elem, null),
			top = elem.offsetTop, left = elem.offsetLeft;

		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
			computedStyle = defaultView.getComputedStyle(elem, null);
			top -= elem.scrollTop, left -= elem.scrollLeft;
			if ( elem === offsetParent ) {
				top += elem.offsetTop, left += elem.offsetLeft;
				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
					top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
					left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
				prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
			}
			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
				top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
				left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
			prevComputedStyle = computedStyle;
		}

		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
			top  += body.offsetTop,
			left += body.offsetLeft;

		if ( prevComputedStyle.position === "fixed" )
			top  += Math.max(docElem.scrollTop, body.scrollTop),
			left += Math.max(docElem.scrollLeft, body.scrollLeft);

		return { top: top, left: left };
	};

jQuery.offset = {
	initialize: function() {
		if ( this.initialized ) return;
		var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
			html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';

		rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
		for ( prop in rules ) container.style[prop] = rules[prop];

		container.innerHTML = html;
		body.insertBefore(container, body.firstChild);
		innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;

		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);

		innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);

		body.style.marginTop = '1px';
		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
		body.style.marginTop = bodyMarginTop;

		body.removeChild(container);
		this.initialized = true;
	},

	bodyOffset: function(body) {
		jQuery.offset.initialized || jQuery.offset.initialize();
		var top = body.offsetTop, left = body.offsetLeft;
		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
			top  += parseInt( jQuery.curCSS(body, 'marginTop',  true), 10 ) || 0,
			left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
		return { top: top, left: left };
	}
};


jQuery.fn.extend({
	position: function() {
		var left = 0, top = 0, results;

		if ( this[0] ) {
			// Get *real* offsetParent
			var offsetParent = this.offsetParent(),

			// Get correct offsets
			offset       = this.offset(),
			parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();

			// Subtract element margins
			// note: when an element has margin: auto the offsetLeft and marginLeft 
			// are the same in Safari causing offset.left to incorrectly be 0
			offset.top  -= num( this, 'marginTop'  );
			offset.left -= num( this, 'marginLeft' );

			// Add offsetParent borders
			parentOffset.top  += num( offsetParent, 'borderTopWidth'  );
			parentOffset.left += num( offsetParent, 'borderLeftWidth' );

			// Subtract the two offsets
			results = {
				top:  offset.top  - parentOffset.top,
				left: offset.left - parentOffset.left
			};
		}

		return results;
	},

	offsetParent: function() {
		var offsetParent = this[0].offsetParent || document.body;
		while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
			offsetParent = offsetParent.offsetParent;
		return jQuery(offsetParent);
	}
});


// Create scrollLeft and scrollTop methods
jQuery.each( ['Left', 'Top'], function(i, name) {
	var method = 'scroll' + name;
	
	jQuery.fn[ method ] = function(val) {
		if (!this[0]) return null;

		return val !== undefined ?

			// Set the scroll offset
			this.each(function() {
				this == window || this == document ?
					window.scrollTo(
						!i ? val : jQuery(window).scrollLeft(),
						 i ? val : jQuery(window).scrollTop()
					) :
					this[ method ] = val;
			}) :

			// Return the scroll offset
			this[0] == window || this[0] == document ?
				self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
					jQuery.boxModel && document.documentElement[ method ] ||
					document.body[ method ] :
				this[0][ method ];
	};
});
// Create innerHeight, innerWidth, outerHeight and outerWidth methods
jQuery.each([ "Height", "Width" ], function(i, name){

	var tl = i ? "Left"  : "Top",  // top or left
		br = i ? "Right" : "Bottom", // bottom or right
		lower = name.toLowerCase();

	// innerHeight and innerWidth
	jQuery.fn["inner" + name] = function(){
		return this[0] ?
			jQuery.css( this[0], lower, false, "padding" ) :
			null;
	};

	// outerHeight and outerWidth
	jQuery.fn["outer" + name] = function(margin) {
		return this[0] ?
			jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
			null;
	};
	
	var type = name.toLowerCase();

	jQuery.fn[ type ] = function( size ) {
		// Get window width or height
		return this[0] == window ?
			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
			document.body[ "client" + name ] :

			// Get document width or height
			this[0] == document ?
				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
				Math.max(
					document.documentElement["client" + name],
					document.body["scroll" + name], document.documentElement["scroll" + name],
					document.body["offset" + name], document.documentElement["offset" + name]
				) :

				// Get or set width or height on the element
				size === undefined ?
					// Get width or height on the element
					(this.length ? jQuery.css( this[0], type ) : null) :

					// Set the width or height on the element (default to pixels if value is unitless)
					this.css( type, typeof size === "string" ? size : size + "px" );
	};

});
})();
jQuery.fn.rotate = function(angle,whence) {
    var p = this.get(0);

    // we store the angle inside the image tag for persistence
    if (!whence) {
        p.angle = ((p.angle==undefined?0:p.angle) + angle) % 360;
    } else {
        p.angle = angle;
    }

    if (p.angle >= 0) {
        var rotation = Math.PI * p.angle / 180;
    } else {
        var rotation = Math.PI * (360+p.angle) / 180;
    }
    var costheta = Math.cos(rotation);
    var sintheta = Math.sin(rotation);

    if (document.all && !window.opera) {
        var canvas = document.createElement('img');

        canvas.src = p.src;
        canvas.height = p.height;
        canvas.width = p.width;

        canvas.style.filter = "progid:DXImageTransform.Microsoft.Matrix(M11="+costheta+",M12="+(-sintheta)+",M21="+sintheta+",M22="+costheta+",SizingMethod='auto expand')";
    } else {
        var canvas = document.createElement('canvas');
        if (!p.oImage) {
            canvas.oImage = new Image();
            canvas.oImage.src = p.src;
        } else {
            canvas.oImage = p.oImage;
        }

        canvas.style.width = canvas.width = Math.abs(costheta*canvas.oImage.width) + Math.abs(sintheta*canvas.oImage.height);
        canvas.style.height = canvas.height = Math.abs(costheta*canvas.oImage.height) + Math.abs(sintheta*canvas.oImage.width);

        var context = canvas.getContext('2d');
        context.save();
        if (rotation <= Math.PI/2) {
            context.translate(sintheta*canvas.oImage.height,0);
        } else if (rotation <= Math.PI) {
            context.translate(canvas.width,-costheta*canvas.oImage.height);
        } else if (rotation <= 1.5*Math.PI) {
            context.translate(-costheta*canvas.oImage.width,canvas.height);
        } else {
            context.translate(0,-sintheta*canvas.oImage.width);
        }
        context.rotate(rotation);
        context.drawImage(canvas.oImage, 0, 0, canvas.oImage.width, canvas.oImage.height);
        context.restore();
    }
    canvas.id = p.id;
    canvas.angle = p.angle;
    p.parentNode.replaceChild(canvas, p);
};

jQuery.fn.rotateRight = function(angle) {
    this.rotate(angle==undefined?90:angle);
};

jQuery.fn.rotateLeft = function(angle) {
    this.rotate(angle==undefined?-90:-angle);
};

(function ($) {
    
$.fn.simpleSpy = function (limit, interval) {
    limit = limit || 4;
    interval = interval || 4000;
    
    return this.each(function () {
        // 1. setup
            // capture a cache of all the list items
            // chomp the list down to limit li elements
        var $list = $(this),
            items = [], // uninitialised
            currentItem = limit,
            total = 0, // initialise later on
            //height = $list.find('> li:first > div:first').height() + 10;
						height = 60;
            //console.log($list.html());
        // capture the cache
        $list.find('> li').each(function () {
            items.push('<li>' + $(this).html() + '</li>');
        });
        
        total = items.length;
        
        $list.wrap('<div class="spyWrapper" />').parent().css({ height : height * limit });
        $list.find('> li').filter(':gt(' + (limit - 1) + ')').remove();

        // 2. effect        
        function spy() {
            // insert a new item with opacity and height of zero
            var $insert = $(items[currentItem]).css({
                height : 0,
                opacity : 0,
                display : 'none'
            }).prependTo($list);
                        
            // fade the LAST item out
            $list.find('> li:last').animate({ opacity : 0}, 1000, function () {
                // increase the height of the NEW first item
                $insert.animate({ height : height }, 1000).animate({ opacity : 1 }, 1000);
                
                // AND at the same time - decrease the height of the LAST item
                // $(this).animate({ height : 0 }, 1000, function () {
                    // finally fade the first item in (and we can remove the last)
                    $(this).remove();
                 //});
            });
            
            currentItem++;
            if (currentItem >= total) {
                currentItem = 0;
            }
            
            setTimeout(spy, interval)
        }
        
        spy();
    });
};
    
})(jQuery);

/*
    http://www.JSON.org/json2.js
    2008-09-01

    Public Domain.

    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

    See http://www.JSON.org/js.html

    This file creates a global JSON object containing two methods: stringify
    and parse.

        JSON.stringify(value, replacer, space)
            value       any JavaScript value, usually an object or array.

            replacer    an optional parameter that determines how object
                        values are stringified for objects. It can be a
                        function or an array of strings.

            space       an optional parameter that specifies the indentation
                        of nested structures. If it is omitted, the text will
                        be packed without extra whitespace. If it is a number,
                        it will specify the number of spaces to indent at each
                        level. If it is a string (such as '\t' or '&nbsp;'),
                        it contains the characters used to indent at each level.

            This method produces a JSON text from a JavaScript value.

            When an object value is found, if the object contains a toJSON
            method, its toJSON method will be called and the result will be
            stringified. A toJSON method does not serialize: it returns the
            value represented by the name/value pair that should be serialized,
            or undefined if nothing should be serialized. The toJSON method
            will be passed the key associated with the value, and this will be
            bound to the object holding the key.

            For example, this would serialize Dates as ISO strings.

                Date.prototype.toJSON = function (key) {
                    function f(n) {
                        // Format integers to have at least two digits.
                        return n < 10 ? '0' + n : n;
                    }

                    return this.getUTCFullYear()   + '-' +
                         f(this.getUTCMonth() + 1) + '-' +
                         f(this.getUTCDate())      + 'T' +
                         f(this.getUTCHours())     + ':' +
                         f(this.getUTCMinutes())   + ':' +
                         f(this.getUTCSeconds())   + 'Z';
                };

            You can provide an optional replacer method. It will be passed the
            key and value of each member, with this bound to the containing
            object. The value that is returned from your method will be
            serialized. If your method returns undefined, then the member will
            be excluded from the serialization.

            If the replacer parameter is an array of strings, then it will be used to
            select the members to be serialized. It filters the results such
            that only members with keys listed in the replacer array are
            stringified.

            Values that do not have JSON representations, such as undefined or
            functions, will not be serialized. Such values in objects will be
            dropped; in arrays they will be replaced with null. You can use
            a replacer function to replace those with JSON values.
            JSON.stringify(undefined) returns undefined.

            The optional space parameter produces a stringification of the
            value that is filled with line breaks and indentation to make it
            easier to read.

            If the space parameter is a non-empty string, then that string will
            be used for indentation. If the space parameter is a number, then
            the indentation will be that many spaces.

            Example:

            text = JSON.stringify(['e', {pluribus: 'unum'}]);
            // text is '["e",{"pluribus":"unum"}]'


            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'

            text = JSON.stringify([new Date()], function (key, value) {
                return this[key] instanceof Date ?
                    'Date(' + this[key] + ')' : value;
            });
            // text is '["Date(---current time---)"]'


        JSON.parse(text, reviver)
            This method parses a JSON text to produce an object or array.
            It can throw a SyntaxError exception.

            The optional reviver parameter is a function that can filter and
            transform the results. It receives each of the keys and values,
            and its return value is used instead of the original value.
            If it returns what it received, then the structure is not modified.
            If it returns undefined then the member is deleted.

            Example:

            // Parse the text. Values that look like ISO date strings will
            // be converted to Date objects.

            myData = JSON.parse(text, function (key, value) {
                var a;
                if (typeof value === 'string') {
                    a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
                    if (a) {
                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                            +a[5], +a[6]));
                    }
                }
                return value;
            });

            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
                var d;
                if (typeof value === 'string' &&
                        value.slice(0, 5) === 'Date(' &&
                        value.slice(-1) === ')') {
                    d = new Date(value.slice(5, -1));
                    if (d) {
                        return d;
                    }
                }
                return value;
            });


    This is a reference implementation. You are free to copy, modify, or
    redistribute.

    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html

    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.
*/

/*jslint evil: true */

/*global JSON */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", call,
    charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes,
    getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length,
    parse, propertyIsEnumerable, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/

// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (!this.JSON) {
    JSON = {};
}
(function () {

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 ? '0' + n : n;
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function (key) {

            return this.getUTCFullYear()   + '-' +
                 f(this.getUTCMonth() + 1) + '-' +
                 f(this.getUTCDate())      + 'T' +
                 f(this.getUTCHours())     + ':' +
                 f(this.getUTCMinutes())   + ':' +
                 f(this.getUTCSeconds())   + 'Z';
        };

        String.prototype.toJSON =
        Number.prototype.toJSON =
        Boolean.prototype.toJSON = function (key) {
            return this.valueOf();
        };
    }

    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        gap,
        indent,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        rep;


    function quote(string) {

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.

        escapeable.lastIndex = 0;
        return escapeable.test(string) ?
            '"' + string.replace(escapeable, function (a) {
                var c = meta[a];
                if (typeof c === 'string') {
                    return c;
                }
                return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"' :
            '"' + string + '"';
    }


    function str(key, holder) {

// Produce a string from holder[key].

        var i,          // The loop counter.
            k,          // The member key.
            v,          // The member value.
            length,
            mind = gap,
            partial,
            value = holder[key];

// If the value has a toJSON method, call it to obtain a replacement value.

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }

// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.

        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }

// What happens next depends on the value's type.

        switch (typeof value) {
        case 'string':
            return quote(value);

        case 'number':

// JSON numbers must be finite. Encode non-finite numbers as null.

            return isFinite(value) ? String(value) : 'null';

        case 'boolean':
        case 'null':

// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.

            return String(value);

// If the type is 'object', we might be dealing with an object or an array or
// null.

        case 'object':

// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.

            if (!value) {
                return 'null';
            }

// Make an array to hold the partial results of stringifying this object value.

            gap += indent;
            partial = [];

// If the object has a dontEnum length property, we'll treat it as an array.

            if (typeof value.length === 'number' &&
                    !value.propertyIsEnumerable('length')) {

// The object is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.

                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || 'null';
                }

// Join all of the elements together, separated with commas, and wrap them in
// brackets.

                v = partial.length === 0 ? '[]' :
                    gap ? '[\n' + gap +
                            partial.join(',\n' + gap) + '\n' +
                                mind + ']' :
                          '[' + partial.join(',') + ']';
                gap = mind;
                return v;
            }

// If the replacer is an array, use it to select the members to be stringified.

            if (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    k = rep[i];
                    if (typeof k === 'string') {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            } else {

// Otherwise, iterate through all of the keys in the object.

                for (k in value) {
                    if (Object.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            }

// Join all of the member texts together, separated with commas,
// and wrap them in braces.

            v = partial.length === 0 ? '{}' :
                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
                        mind + '}' : '{' + partial.join(',') + '}';
            gap = mind;
            return v;
        }
    }

// If the JSON object does not yet have a stringify method, give it one.

    if (typeof JSON.stringify !== 'function') {
        JSON.stringify = function (value, replacer, space) {

// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.

            var i;
            gap = '';
            indent = '';

// If the space parameter is a number, make an indent string containing that
// many spaces.

            if (typeof space === 'number') {
                for (i = 0; i < space; i += 1) {
                    indent += ' ';
                }

// If the space parameter is a string, it will be used as the indent string.

            } else if (typeof space === 'string') {
                indent = space;
            }

// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                     typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }

// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.

            return str('', {'': value});
        };
    }


// If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== 'function') {
        JSON.parse = function (text, reviver) {

// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.

            var j;

            function walk(holder, key) {

// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.

                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }


// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.

            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

            if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

                j = eval('(' + text + ')');

// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.

                return typeof reviver === 'function' ?
                    walk({'': j}, '') : j;
            }

// If the text is not JSON parseable, then a SyntaxError is thrown.

            throw new SyntaxError('JSON.parse');
        };
    }
})();
/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-12-20 08:46:55 -0600 (Thu, 20 Dec 2007) $
 * $Rev: 4259 $
 *
 * Version: 1.2
 *
 * Requires: jQuery 1.2+
 */

(function($){
	
$.dimensions = {
	version: '1.2'
};

// Create innerHeight, innerWidth, outerHeight and outerWidth methods
$.each( [ 'Height', 'Width' ], function(i, name){
	
	// innerHeight and innerWidth
	$.fn[ 'inner' + name ] = function() {
		if (!this[0]) return;
		
		var torl = name == 'Height' ? 'Top'    : 'Left',  // top or left
		    borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right
		
		return this.is(':visible') ? this[0]['client' + name] : num( this, name.toLowerCase() ) + num(this, 'padding' + torl) + num(this, 'padding' + borr);
	};
	
	// outerHeight and outerWidth
	$.fn[ 'outer' + name ] = function(options) {
		if (!this[0]) return;
		
		var torl = name == 'Height' ? 'Top'    : 'Left',  // top or left
		    borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right
		
		options = $.extend({ margin: false }, options || {});
		
		var val = this.is(':visible') ? 
				this[0]['offset' + name] : 
				num( this, name.toLowerCase() )
					+ num(this, 'border' + torl + 'Width') + num(this, 'border' + borr + 'Width')
					+ num(this, 'padding' + torl) + num(this, 'padding' + borr);
		
		return val + (options.margin ? (num(this, 'margin' + torl) + num(this, 'margin' + borr)) : 0);
	};
});

// Create scrollLeft and scrollTop methods
$.each( ['Left', 'Top'], function(i, name) {
	$.fn[ 'scroll' + name ] = function(val) {
		if (!this[0]) return;
		
		return val != undefined ?
		
			// Set the scroll offset
			this.each(function() {
				this == window || this == document ?
					window.scrollTo( 
						name == 'Left' ? val : $(window)[ 'scrollLeft' ](),
						name == 'Top'  ? val : $(window)[ 'scrollTop'  ]()
					) :
					this[ 'scroll' + name ] = val;
			}) :
			
			// Return the scroll offset
			this[0] == window || this[0] == document ?
				self[ (name == 'Left' ? 'pageXOffset' : 'pageYOffset') ] ||
					$.boxModel && document.documentElement[ 'scroll' + name ] ||
					document.body[ 'scroll' + name ] :
				this[0][ 'scroll' + name ];
	};
});

$.fn.extend({
	position: function() {
		var left = 0, top = 0, elem = this[0], offset, parentOffset, offsetParent, results;
		
		if (elem) {
			// Get *real* offsetParent
			offsetParent = this.offsetParent();
			
			// Get correct offsets
			offset       = this.offset();
			parentOffset = offsetParent.offset();
			
			// Subtract element margins
			offset.top  -= num(elem, 'marginTop');
			offset.left -= num(elem, 'marginLeft');
			
			// Add offsetParent borders
			parentOffset.top  += num(offsetParent, 'borderTopWidth');
			parentOffset.left += num(offsetParent, 'borderLeftWidth');
			
			// Subtract the two offsets
			results = {
				top:  offset.top  - parentOffset.top,
				left: offset.left - parentOffset.left
			};
		}
		
		return results;
	},
	
	offsetParent: function() {
		var offsetParent = this[0].offsetParent;
		while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') )
			offsetParent = offsetParent.offsetParent;
		return $(offsetParent);
	}
});

function num(el, prop) {
	return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0;
};

})(jQuery);/**
* hoverIntent is similar to jQuery's built-in "hover" function except that
* instead of firing the onMouseOver event immediately, hoverIntent checks
* to see if the user's mouse has slowed down (beneath the sensitivity
* threshold) before firing the onMouseOver event.
* 
* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
* 
* hoverIntent is currently available for use in all personal or commercial 
* projects under both MIT and GPL licenses. This means that you can choose 
* the license that best suits your project, and use it accordingly.
* 
* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions
* $("ul li").hoverIntent( showNav , hideNav );
* 
* // advanced usage receives configuration object only
* $("ul li").hoverIntent({
*	sensitivity: 7, // number = sensitivity threshold (must be 1 or higher)
*	interval: 100,   // number = milliseconds of polling interval
*	over: showNav,  // function = onMouseOver callback (required)
*	timeout: 0,   // number = milliseconds delay before onMouseOut function call
*	out: hideNav    // function = onMouseOut callback (required)
* });
* 
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne <brian@cherne.net>
*/
(function($) {
	$.fn.hoverIntent = function(f,g) {
		// default configuration options
		var cfg = {
			sensitivity: 7,
			interval: 100,
			timeout: 0
		};
		// override configuration options with user supplied object
		cfg = $.extend(cfg, g ? { over: f, out: g } : f );

		// instantiate variables
		// cX, cY = current X and Y position of mouse, updated by mousemove event
		// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
		var cX, cY, pX, pY;

		// A private function for getting mouse position
		var track = function(ev) {
			cX = ev.pageX;
			cY = ev.pageY;
		};

		// A private function for comparing current and previous mouse position
		var compare = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			// compare mouse positions to see if they've crossed the threshold
			if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
				$(ob).unbind("mousemove",track);
				// set hoverIntent state to true (so mouseOut can be called)
				ob.hoverIntent_s = 1;
				return cfg.over.apply(ob,[ev]);
			} else {
				// set previous coordinates for next time
				pX = cX; pY = cY;
				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
				ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
			}
		};

		// A private function for delaying the mouseOut function
		var delay = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			ob.hoverIntent_s = 0;
			return cfg.out.apply(ob,[ev]);
		};

		// A private function for handling mouse 'hovering'
		var handleHover = function(e) {
			// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
			while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
			if ( p == this ) { return false; }

			// copy objects to be passed into t (required for event object to be passed in IE)
			var ev = jQuery.extend({},e);
			var ob = this;

			// cancel hoverIntent timer if it exists
			if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

			// else e.type == "onmouseover"
			if (e.type == "mouseover") {
				// set "previous" X and Y position based on initial entry point
				pX = ev.pageX; pY = ev.pageY;
				// update "current" X and Y position based on mousemove
				$(ob).bind("mousemove",track);
				// start polling interval (self-calling timeout) to compare mouse coordinates over time
				if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}

			// else e.type == "onmouseout"
			} else {
				// unbind expensive mousemove event
				$(ob).unbind("mousemove",track);
				// if hoverIntent state is true, then call the mouseOut function after the specified delay
				if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
			}
		};

		// bind the function to the two event listeners
		return this.mouseover(handleHover).mouseout(handleHover);
	};
})(jQuery);/*
 * Facebox (for jQuery)
 * version: 1.2 (05/05/2008)
 * @requires jQuery v1.2 or later
 *
 * Examples at http://famspam.com/facebox/
 *
 * Licensed under the MIT:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ]
 *
 * Usage:
 *  
 *  jQuery(document).ready(function() {
 *    jQuery('a[rel*=facebox]').facebox() 
 *  })
 *
 *  <a href="#terms" rel="facebox">Terms</a>
 *    Loads the #terms div in the box
 *
 *  <a href="terms.html" rel="facebox">Terms</a>
 *    Loads the terms.html page in the box
 *
 *  <a href="terms.png" rel="facebox">Terms</a>
 *    Loads the terms.png image in the box
 *
 *
 *  You can also use it programmatically:
 * 
 *    jQuery.facebox('some html')
 *
 *  The above will open a facebox with "some html" as the content.
 *    
 *    jQuery.facebox(function($) { 
 *      $.get('blah.html', function(data) { $.facebox(data) })
 *    })
 *
 *  The above will show a loading screen before the passed function is called,
 *  allowing for a better ajaxy experience.
 *
 *  The facebox function can also display an ajax page or image:
 *  
 *    jQuery.facebox({ ajax: 'remote.html' })
 *    jQuery.facebox({ image: 'dude.jpg' })
 *
 *  Want to close the facebox?  Trigger the 'close.facebox' document event:
 *
 *    jQuery(document).trigger('close.facebox')
 *
 *  Facebox also has a bunch of other hooks:
 *
 *    loading.facebox
 *    beforeReveal.facebox
 *    reveal.facebox (aliased as 'afterReveal.facebox')
 *    init.facebox
 *
 *  Simply bind a function to any of these hooks:
 *
 *   $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... })
 *
 */
(function($) {
  $.facebox = function(data, klass) {
    $.facebox.loading()

    if (data.ajax) fillFaceboxFromAjax(data.ajax)
    else if (data.image) fillFaceboxFromImage(data.image)
    else if (data.div) fillFaceboxFromHref(data.div)
    else if ($.isFunction(data)) data.call($)
    else $.facebox.reveal(data, klass)
  }

  /*
   * Public, $.facebox methods
   */

  $.extend($.facebox, {
    settings: {
      opacity      : 0,
      overlay      : true,
      loadingImage : '/facebox/loading.gif',
      closeImage   : '/facebox/closelabel.gif',
      imageTypes   : [ 'png', 'jpg', 'jpeg', 'gif' ],
      faceboxHtml  : '\
    <div id="facebox" style="display:none;"> \
      <div class="popup"> \
        <table> \
          <tbody> \
            <tr> \
              <td class="tl"/><td class="b"/><td class="tr"/> \
            </tr> \
            <tr> \
              <td class="b"/> \
              <td class="body"> \
                <div class="content"> \
                </div> \
				<div class="footer"> \
                  <a href="#" class="close"> \
                    <img src="/facebox/closelabel.gif" title="close" class="close_image" /> \
                  </a> \
                </div> \
              </td> \
              <td class="b"/> \
            </tr> \
            <tr> \
              <td class="bl"/><td class="b"/><td class="br"/> \
            </tr> \
          </tbody> \
        </table> \
      </div> \
    </div>'
    },

    loading: function() {
      init()
      if ($('#facebox .loading').length == 1) return true
      showOverlay()

      $('#facebox .content').empty()
      $('#facebox .body').children().hide().end().
        append('<div class="loading"><img src="'+$.facebox.settings.loadingImage+'"/></div>')

      $('#facebox').css({
        top:	getPageScroll()[1] + (getPageHeight() / 10),
        left:	385.5
      }).fadeIn(300)

      $(document).bind('keydown.facebox', function(e) {
        if (e.keyCode == 27) $.facebox.close()
        return true
      })
      $(document).trigger('loading.facebox')
    },

    reveal: function(data, klass) {
      $(document).trigger('beforeReveal.facebox')
      if (klass) $('#facebox .content').addClass(klass)
      $('#facebox .content').append(data)
      $('#facebox .loading').remove()
      $('#facebox .body').children().fadeIn('normal')
      $('#facebox').css('left', $(window).width() / 2 - ($('#facebox table').width() / 2))
      $(document).trigger('reveal.facebox').trigger('afterReveal.facebox')
    },

    close: function() {
      $(document).trigger('close.facebox')
      return false
    }
  })

  /*
   * Public, $.fn methods
   */

  $.fn.facebox = function(settings) {

    init(settings)

    function clickHandler() {
      $.facebox.loading(true)

      // support for rel="facebox.inline_popup" syntax, to add a class
      // also supports deprecated "facebox[.inline_popup]" syntax
      var klass = this.rel.match(/facebox\[?\.(\w+)\]?/)
      if (klass) klass = klass[1]

      fillFaceboxFromHref(this.href, klass)
      return false
    }

    return this.click(clickHandler)
  }

  /*
   * Private methods
   */

  // called one time to setup facebox on this page
  function init(settings) {
    if ($.facebox.settings.inited) return true
    else $.facebox.settings.inited = true

    $(document).trigger('init.facebox')
    makeCompatible()

    var imageTypes = $.facebox.settings.imageTypes.join('|')
    $.facebox.settings.imageTypesRegexp = new RegExp('\.' + imageTypes + '$', 'i')

    if (settings) $.extend($.facebox.settings, settings)
    $('body').append($.facebox.settings.faceboxHtml)

    var preload = [ new Image(), new Image() ]
    preload[0].src = $.facebox.settings.closeImage
    preload[1].src = $.facebox.settings.loadingImage

    $('#facebox').find('.b:first, .bl, .br, .tl, .tr').each(function() {
      preload.push(new Image())
      preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1')
    })

    $('#facebox .close').click($.facebox.close)
    $('#facebox .close_image').attr('src', $.facebox.settings.closeImage)
  }
  
  // getPageScroll() by quirksmode.com
  function getPageScroll() {
    var xScroll, yScroll;
    if (self.pageYOffset) {
      yScroll = self.pageYOffset;
      xScroll = self.pageXOffset;
    } else if (document.documentElement && document.documentElement.scrollTop) {	 // Explorer 6 Strict
      yScroll = document.documentElement.scrollTop;
      xScroll = document.documentElement.scrollLeft;
    } else if (document.body) {// all other Explorers
      yScroll = document.body.scrollTop;
      xScroll = document.body.scrollLeft;	
    }
    return new Array(xScroll,yScroll) 
  }

  // Adapted from getPageSize() by quirksmode.com
  function getPageHeight() {
    var windowHeight
    if (self.innerHeight) {	// all except Explorer
      windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
      windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { // other Explorers
      windowHeight = document.body.clientHeight;
    }	
    return windowHeight
  }

  // Backwards compatibility
  function makeCompatible() {
    var $s = $.facebox.settings

    $s.loadingImage = $s.loading_image || $s.loadingImage
    $s.closeImage = $s.close_image || $s.closeImage
    $s.imageTypes = $s.image_types || $s.imageTypes
    $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml
  }

  // Figures out what you want to display and displays it
  // formats are:
  //     div: #id
  //   image: blah.extension
  //    ajax: anything else
  function fillFaceboxFromHref(href, klass) {
    // div
    if (href.match(/#/)) {
      var url    = window.location.href.split('#')[0]
      var target = href.replace(url,'')
      $.facebox.reveal($(target).clone().show(), klass)

    // image
    } else if (href.match($.facebox.settings.imageTypesRegexp)) {
      fillFaceboxFromImage(href, klass)
    // ajax
    } else {
      fillFaceboxFromAjax(href, klass)
    }
  }

  function fillFaceboxFromImage(href, klass) {
    var image = new Image()
    image.onload = function() {
      $.facebox.reveal('<div class="image"><img src="' + image.src + '" /></div>', klass)
    }
    image.src = href
  }

  function fillFaceboxFromAjax(href, klass) {
    $.get(href, function(data) { $.facebox.reveal(data, klass) })
  }

  function skipOverlay() {
    return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null 
  }

  function showOverlay() {
    if (skipOverlay()) return

    if ($('facebox_overlay').length == 0) 
      $("body").append('<div id="facebox_overlay" class="facebox_hide"></div>')

    $('#facebox_overlay').hide().addClass("facebox_overlayBG")
      .css('opacity', $.facebox.settings.opacity)
      .click(function() { $(document).trigger('close.facebox') })
      .show()
    return false
  }

  function hideOverlay() {
    if (skipOverlay()) return

    $('#facebox_overlay').fadeOut(100, function(){
      $("#facebox_overlay").removeClass("facebox_overlayBG")
      $("#facebox_overlay").addClass("facebox_hide") 
      $("#facebox_overlay").remove()
    })
    
    return false
  }

  /*
   * Bindings
   */

  $(document).bind('close.facebox', function() {
    $(document).unbind('keydown.facebox')
    $('#facebox').fadeOut(function() {
      $('#facebox .content').removeClass().addClass('content')
      hideOverlay()
      $('#facebox .loading').remove()
    })
  })

})(jQuery);
(function($) {
	$.fn.ellipsis = function(enableUpdating){
		var s = document.documentElement.style;
		if (!('textOverflow' in s || 'OTextOverflow' in s)) {
			return this.each(function(){
				var el = $(this);
				if(el.css("overflow") == "hidden"){
					var originalText = el.html();
					var w = el.width();
					
					var t = $(this.cloneNode(true)).hide().css({
                        'position': 'absolute',
                        'width': 'auto',
                        'overflow': 'visible',
                        'max-width': 'inherit'
                    });
					el.after(t);
					
					var text = originalText;
					while(text.length > 0 && t.width() > el.width()){
						text = text.substr(0, text.length - 1);
						t.html(text + "...");
					}
					el.html(t.html());
					
					t.remove();
					
					if(enableUpdating == true){
						var oldW = el.width();
						setInterval(function(){
							if(el.width() != oldW){
								oldW = el.width();
								el.html(originalText);
								el.ellipsis();
							}
						}, 200);
					}
				}
			});
		} else return this;
	};
})(jQuery);/*
 * mbox (for facebox)
 * version: 1.0 (01/27/2009)
 * @requires facebox v1.2 or later
 *
 * Copyright 2009 sendme Inc.
 *
 * Usage:
 *  
 *  jQuery(document).ready(function() {
 *    jQuery('a[rel*=mbox]').mbox() 
 *  })
 *
 *  <a href="#terms" rel="mbox">Terms</a>
 *    Loads the #terms div in the box
 *
 */

jQuery(document).ready(function() {
    $('a[rel*=mbox]').mbox() 
});

(function($) {
  $.mbox = function(data) {
	if (data.url) {
		var newURL = this.makeMboxURL(data.url);
		jQuery.facebox({ ajax: newURL });
	} else if (data.parts) {
		jQuery.facebox(data.parts.join(''));
	} else {
		jQuery.facebox(data);
	}
  }	

  $.extend($.mbox, {
	  loadingSettings: {
		  html  : '\
			<table> \
			  <tbody> \
				<tr> \
				  <td colspan="3" class="mboxHorizontalEdge"/> \
			    </tr> \
				<tr> \
				  <td class="mboxVerticalEdge"/> \
				  <td class="body"> \
					<div>\
					  <div id="mboxFrame"> \
						<center> \
                          <div valign="middle" class="mboxLoading"> \
							<img id="mboxLoadingSpinner" src="http://cache.mbuzzy.com/cache/4.1.8.7/images/spinner_lg.gif"/> \
						  </div> \
						</center> \
					  </div>\
					</div> \
 				  </td>\
				  <td class="mboxVerticalEdge"/> \
				</tr> \
				<tr> \
				  <td colspan="3" class="mboxHorizontalEdge"/> \
				</tr> \
			  </tbody> \
			</table> '
	  },

	  loading: function() {
		if ($('#facebox .mboxLoading').length == 0) {
			$.mbox.load($.mbox.loadingSettings.html);
		}
	  },

	  load:  function(data) {
		if ($.mbox.isVisible()) {
			if (data.parts) {
				$('#mboxWindowFrame').html(data.parts.join(''));
			} else {
				$('#mboxWindowFrame').html(data);
			}
		} else {
			$.mbox(data);
		}
	  },

      close: function() {
		if ($.mbox.isVisible()) {
			jQuery(document).trigger('close.facebox');
		}
	  },

      bindOnClose: function(callback) {
		jQuery(document).bind('close.facebox',callback);
	  },

      unbindOnClose: function(callback) {
		jQuery(document).unbind('close.facebox',callback);
	  },

	  enableDoButton: function() {
		$('#mboxDoBtn').addClass("mboxDoBtnEnabled");
		$('#mboxDoBtn').removeClass("mboxDoBtnDisabled");
	  },

	  disableDoButton: function() {
		$('#mboxDoBtn').addClass("mboxDoBtnEnabled");
		$('#mboxDoBtn').removeClass("mboxDoBtnDisabled");
	  },

	  isVisible: function() {
		if ($('#mboxWindowFrame').is(':visible')) {
			return true;
		} else {
			return false;
		}
	  }
  })

  $.extend($.facebox, {
	settings: {
      opacity      : 0.4,
      overlay      : true,
      loadingImage : 'http://cache.mbuzzy.com/cache/4.1.8.7/images/spinner_lg.gif',
      closeImage : 'http://cache.mbuzzy.com/cache/4.1.8.7/images/invis.gif',
      imageTypes   : [ 'png', 'jpg', 'jpeg', 'gif' ],
      faceboxHtml  : '\
    <div id="facebox" style="display:none;"> \
      <div id="mboxWindowFrame" class="popup content"> \
      </div> \
    </div>'
    }
  })


  $.fn.mbox = function(settings) {

	function clickHandler() {
		var newUrl = jQuery.makeMboxURL(this.href);
		jQuery.facebox({ ajax: newUrl })
		return false;
	}

	return this.click(clickHandler)
  }

  $.makeMboxURL = function(href) {
		var hrefParts = href.split('#');
		var url = hrefParts[0];
		var urlParts = url.split('?');
		var	newUrl = urlParts[0] + "?tt=lb";
		if (urlParts[1]) {
			newUrl += "&" + urlParts[1];
		}
		if (hrefParts[1]) {
			newUrl += "#" + hrefParts[1];
		}
		return newUrl;
  }

})(jQuery);
mjaxAPIInternal = {
    maxNestedPostToServer: 3,
	repostData: null,

	postToServer: function(payload,internalResponseHandler,opaqueData,customHandler,nestingLevel,isOpenMboxRequest) {
		this.repostData = { "isOpenMbox": isOpenMboxRequest, "originalPayload": payload, "originalInternalResponseHandler": internalResponseHandler, "opaqueData": opaqueData, "customHandler": customHandler, "nestingLevel": nestingLevel  };
		$.post("/mjax/index.php", payload, function(response) {
			internalResponseHandler(response[0],opaqueData,customHandler);
		},"json");
	},

	mjaxRepost: function(repostData) {
		repostData.nestingLevel++;
		if (repostData.nestingLevel < this.maxNestedPostToServer) {
			this.postToServer(repostData.originalPayload,repostData.originalInternalResponseHandler,repostData.opaqueData,repostData.customHandler,repostData.nestingLevel,null);
		}
	},

	mjaxPost: function(app,action,sendData,sendUI,internalResponseHandler,opaqueData,customHandler) {
        $("#ajaxLatch").val('latched');
        var isOpenMboxRequest = 0;
		if (sendUI['default'] && (sendUI['default']['action'] == "openMbox")) {
			isOpenMboxRequest = 1;
			jQuery.mbox.loading();
		}
		if (sendUI['default'] && sendUI['default']['data'] && opaqueData) {
			sendUI['default']['data']['opaque'] = opaqueData;
		} else {
			sendUI['default']['data']['opaque'] = null;
		}
		var payload = { "app": app, "action": action, "data": sendData , "ui": sendUI }
		var payloadArray = new Array(payload);
		var sendPayload = JSON.stringify(payloadArray);
		this.postToServer(sendPayload,internalResponseHandler,opaqueData,customHandler,0,isOpenMboxRequest);
        $("#ajaxLatch").val('unlatched');
	}

};

mjaxAPI = {
	loginRepostData: null,
	sendUI: {"default" :{ "data": { "opaque" : null }}},
	
	//
	// Registration APIs
	//
	doQuickReg: function(regUsername,regPassword,regEmail,regMobile,opaqueData,customHandler) {
		var sendData = { "regUsername": regUsername, "regPassword": regPassword, "regEmail": regEmail, "regMobile": regMobile }
		mjaxAPIInternal.mjaxPost('mbuzzy','register',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	checkUsername: function(username, opaque, responseHandler) {
	    var sendData = {username: username};
	    mjaxAPIInternal.mjaxPost('mbuzzy','checkUsername',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaque,responseHandler);
        },

    // Simple registration (homepage)
    //    
    registerUser: function(args,
                           opaque,
                           responseHandler)
    {
        var sendData = {type: args.type,
                        username: args.userInfo.username,
                        password: args.userInfo.password,
                        email: args.userInfo.email,
                        mobile: args.userInfo.mobile,
                        gender: args.userInfo.gender,
                        birthMonth: args.userInfo.birthMonth,
                        birthDay: args.userInfo.birthDay,
                        birthYear: args.userInfo.birthYear,
                        zipcode: args.userInfo.zipcode};
        
		mjaxAPIInternal.mjaxPost("mbuzzy",
                                 "registerUser",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);        
    },

	//
	// Buzzstream APIs
	//	
	getBuzzstreamProfileEvents: function(uid,lastEventID,opaqueData,customHandler) {
		var sendData = { "uid": uid, "eventType": "profile", "afterEventID": lastEventID };
		mjaxAPIInternal.mjaxPost('buzzstream','getEvents',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler);
	},

    getProfileBuzzStreamEvents: function(sendData,
                                         opaque, 
                                         responseHandler)
    {
		mjaxAPIInternal.mjaxPost("buzzStream",
                                 "getProfileEvents",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler)        
    },
    
    getMyBuzzStreamEvents: function(sendData,
                                    opaque,
                                    responseHandler)
    {
		mjaxAPIInternal.mjaxPost("buzzstream",
                                 "getMyEvents",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler)        
    },
    
    getHomeBuzzStreamEvents: function(sendData,
                                      opaque,
                                      responseHandler)
    {
		mjaxAPIInternal.mjaxPost("buzzStream",
                                 "getHomeEvents",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);                        
    },
    
    getBuzzStreamComments: function(eventID,
                                    opaque,
                                    responseHandler)
    {
		var sendData = {eventID: eventID};
		mjaxAPIInternal.mjaxPost("buzzstream",
                                 "getComments",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);                                        
    },
                                    
	//
	// Comment APIs
	//	
	addProfileComment: function(uid,comment,opaqueData,customHandler) {
		var sendData = { "commentType": "profile", "refID": uid, "comment": comment }
		mjaxAPIInternal.mjaxPost('comment','addComment',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	addObjectComment: function(objectID,
                               message,
                               opaque,
                               responseHandler) {
		var sendData = {commentType: "object", 
                        refID: objectID, 
                        comment: message};
		mjaxAPIInternal.mjaxPost("comment",
                                 "addComment",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
	},
        
	addBuzzStreamComment: function(eventID,
                                   message,
                                   opaque,
                                   responseHandler) {
		var sendData = {commentType: "buzzStream", 
                        refID: eventID, 
                        comment: message};
		mjaxAPIInternal.mjaxPost("comment",
                                 "addComment",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
	},
    
    acceptComment: function(commentID,
                            opaque,
                            responseHandler)
    {
        var sendData = {commentID: commentID};
		mjaxAPIInternal.mjaxPost("comment",
                                 "acceptComment",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
    },
    
    removeComment: function(commentID,
                            opaque,
                            responseHandler)
    {
        var sendData = {commentID: commentID};
		mjaxAPIInternal.mjaxPost("comment",
                                 "removeComment",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
    },
    
    getProfileChat: function(profileUsername1,
                             profileUsername2,   
                             limit,
                             page,
                             opaque,
                             responseHandler)
    {
        var sendData = {profileUsername1: profileUsername1,
                        profileUsername2: profileUsername2,
                        limit: limit,
                        page: page};
                    
		mjaxAPIInternal.mjaxPost("comment",
                                 "getProfileChat",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);        
    },
    
    getPendingComments: function(limit,
                                 page,   
                                 opaque,
                                 responseHandler)
    {
        var sendData = {limit: limit,
                        page: page};
	    mjaxAPIInternal.mjaxPost("comment",
                                 "getPendingComments",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
    },    
	
	//
	// Crush APIs
	//	
	addCrush: function(uid,message,opaqueData,customHandler) {
		var sendData = { "uid": uid, "message": message };
		mjaxAPIInternal.mjaxPost('crush','addCrush',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler);
	},
    
    getCrushes: function(type,
                         limit,
                         page,   
                         opaque,
                         responseHandler)
    {
        var sendData = {type: type,
                        limit: limit,
                        page: page};
	    mjaxAPIInternal.mjaxPost("crush",
                                 "getCrushes",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
    },
    
    getCrush: function(anonCrushID,
                       opaque,
                       responseHandler)
    {
        var sendData = {anonCrushID: anonCrushID};
	    mjaxAPIInternal.mjaxPost("crush",
                                 "getCrush",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
    },     
    
    requestIdentity: function(anonCrushID,
                              opaque,
                              responseHandler)
    {
        var sendData = {anonCrushID: anonCrushID};        
		mjaxAPIInternal.mjaxPost("crush",
                                 "requestIdentity",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
    },
        
    revealIdentity: function(anonCrushID,
                             opaque,
                             responseHandler)
    {
        var sendData = {anonCrushID: anonCrushID};
		mjaxAPIInternal.mjaxPost("crush",
                                 "revealIdentity",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
    },
    
    withdrawCrush: function(anonCrushID,
                            opaque,
                            responseHandler)
    {
        var sendData = {anonCrushID: anonCrushID};        
		mjaxAPIInternal.mjaxPost("crush",
                                 "withdrawCrush",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
    },          

	//
	// Favorites APIs
	//	
	addFavoriteItem: function(itemType,itemID,opaqueData,customHandler) {
		var sendData = { "favValue": itemID, "favType": itemType}
		mjaxAPIInternal.mjaxPost('favorites','addFavorite',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	addFavoriteText: function(text,opaqueData,customHandler) {
		var sendData = { "favName": text, "favType": "txt" }
		mjaxAPIInternal.mjaxPost('favorites','addFavorite',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	editFavoriteText: function(id,text,opaqueData,customHandler) {
		var sendData = { "id": id, "favName": text }
		mjaxAPIInternal.mjaxPost('favorites','editFavorite',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	removeFavorite: function(id,opaqueData,customHandler) {
		var sendData = { "id": id }
		mjaxAPIInternal.mjaxPost('favorites','removeFavorite',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	removeFavoriteItem: function(itemType,itemID,opaqueData,customHandler) {
		var sendData = { "favValue": itemID, "favType": itemType}
		mjaxAPIInternal.mjaxPost('favorites','removeFavorite',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},


	//
	// Friends APIs
	//
    acceptFriend: function(fromUsername,
                           opaque,
                           responseHandler)
    {
        var sendData = {fromUsername: fromUsername};
		mjaxAPIInternal.mjaxPost("friends",
                                 "acceptFriend",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
    },
    
    acceptRelationship: function(fromUsername,
                                 opaque,
                                 responseHandler)
    {
        var sendData = {fromUsername: fromUsername};
		mjaxAPIInternal.mjaxPost("friends",
                                 "acceptRelationship",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);        
    },    
    	
	addFriend: function(uid,message,opaqueData,customHandler) {
		var sendData = { "uid": uid, "message": message }
		mjaxAPIInternal.mjaxPost('friends','addFriend',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	changeRelationship: function(friendname,relationID,message,opaqueData,customHandler) {
		var sendData = { "changeUsername": friendname, "changeStatusTo": relationID, "message": message };
		mjaxAPIInternal.mjaxPost('friends','changeRelationship',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler);
	},

	changeRelationshipStatus: function(friendname,relationID,opaqueData,customHandler) {
		var sendData = { "changeUsername": friendname, "changeStatusTo": relationID }
		mjaxAPIInternal.mjaxPost('friends','changeRelationshipStatus',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},
    
    declineFriend: function(fromUsername,
                            opaque,
                            responseHandler)
    {
		var sendData = {fromUsername: fromUsername};
		mjaxAPIInternal.mjaxPost("friends",
                                 "declineFriend",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);        
    },
    
    declineRelationship: function(fromUsername,
                                  opaque,
                                  responseHandler)
    {
		var sendData = {fromUsername: fromUsername};
		mjaxAPIInternal.mjaxPost("friends",
                                 "declineRelationship",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);   
    },
    
    getFriends: function(type,
                         limit,
                         page,
                         opaque,
                         responseHandler)
    {
        var sendData = {type: type,
                        limit: limit,
                        page: page};
   	    mjaxAPIInternal.mjaxPost("friends",
                                 "getFriends",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
	},
    
    getRelationships: function(type,
                               limit,
                               page,
                               opaque,
                               responseHandler)
    {
        var sendData = {type: type,
                        limit: limit,
                        page: page};
   	    mjaxAPIInternal.mjaxPost("friends",
                                 "getRelationships",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
	},              

	getMyRelationships: function(view,opaqueData,customHandler) {
		var sendData = { "view": view }
		mjaxAPIInternal.mjaxPost('friends','getMyRelationships',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},
    
    getIgnoredUsers: function(limit,
                              page,
                              opaque,
                              responseHandler)
    {
        var sendData = {limit: limit,
                        page: page};
		mjaxAPIInternal.mjaxPost("friends",
                                 "getIgnoredUsers",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
    },

	ignoreUsername: function(uid,anonCrushID,opaqueData,customHandler) {
		var sendData = {uid: uid,
                        anonCrushID: anonCrushID};
		mjaxAPIInternal.mjaxPost('friends','ignoreUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler);
	},
    
	removeFriend: function(uid,opaqueData,customHandler) {
		var sendData = { "uid": uid }
		mjaxAPIInternal.mjaxPost('friends','removeFriend',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	setTopFriends: function(newTopFriends,opaqueData,customHandler) {
		var sendData = { "newTopFriends": newTopFriends }
		mjaxAPIInternal.mjaxPost('friends','setTopFriends',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	subscribeUser: function(uid,opaqueData,customHandler) {
		var sendData = { "uid": uid }
		mjaxAPIInternal.mjaxPost('friends','subscribeUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	unignoreUsername: function(uid,anonCrushID,opaqueData,customHandler) {
		var sendData = {uid: uid,
                        anonCrushID: anonCrushID};
		mjaxAPIInternal.mjaxPost('friends','unignoreUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler);
	},

	unsubscribeUser: function(uid,opaqueData,customHandler) {
		var sendData = { "uid": uid }
		mjaxAPIInternal.mjaxPost('friends','unsubscribeUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},
    
    getAddressBook: function(providerID,
                             username,
                             password,
                             importID,
                             limit,
                             page,
                             opaque,
                             responseHandler)
    {
		var sendData = {providerID: providerID,
                        importID: importID,
                        username: username,
                        password: password,
                        limit: limit,
                        page: page};
		mjaxAPIInternal.mjaxPost("friends",
                                 "getAddressBook",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);
    },
    
    sendInvite: function(providerID,
                         importID,
                         contacts,
                         addresses,
                         subject,
                         message,
                         notifyMe,
                         opaque,
                         responseHandler)
    {
		var sendData = {providerID: providerID,
                        importID: importID,
                        contacts: contacts,
                        addresses: addresses,
                        subject: subject,
                        message: message,
                        notifyMe: notifyMe};
		mjaxAPIInternal.mjaxPost("friends",
                                 "sendInvite",
                                 sendData,
                                 this.sendUI,
                                 mjaxAPI.responseHandlerWrapper,
                                 opaque,
                                 responseHandler);        
    },

	//
	// Funding APIs
	//	
	myFundingOptions: function(fundingSourceID,fundingOfferClass,referer,returnURL,opaqueData,customHandler) {
		var sendData = { "fundingSourceID": fundingSourceID, "foc": fundingOfferClass, "referer": referer, "returnURL": returnURL }
		mjaxAPIInternal.mjaxPost('funding','myFundingOptions',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	myFundingOffers: function(mobile,fundingOfferKey,fundingOfferClass,referer,returnURL,opaqueData,customHandler) {
		var sendData = { "mobile": mobile, "offerKey": fundingOfferKey, "foc": fundingOfferClass, "referer": referer, "returnURL": returnURL }
		mjaxAPIInternal.mjaxPost('funding','myFundingOffers',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	pcMobileBilling: function(mobile,rememberMobile,tandc,fundingSourceID,fundingOfferKey,fundingOfferClass,referer,returnURL,opaqueData,customHandler) {
		var sendData = {"mobile": mobile, "rememberMobile": rememberMobile, "tandc": tandc, "fundingSourceID": fundingSourceID, "offerKey": fundingOfferKey, "foc": fundingOfferClass, "referer": referer, "returnURL": returnURL }
		mjaxAPIInternal.mjaxPost('funding','pcMobileBilling',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	shoutOutzPCPSMS: function(mobile,rememberMobile,offerKey,fundingOfferClass,referer,returnURL,opaqueData,customHandler) {
		var sendData = { "rememberMobile": rememberMobile, "offerKey": offerKey, "mobile": mobile, "foc": fundingOfferClass, "referer": referer, "returnURL": returnURL }
		mjaxAPIInternal.mjaxPost('funding','shoutOutzPCPSMS',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	shoutOutzEnterPIN: function(mobile,pin,referer,returnURL,buySessionID,offerKey,opaqueData,customHandler) {
		var sendData = { "mode": "PINEntered", "offerKey": offerKey, "mobile": mobile, "pin": pin, "buySessionID": buySessionID, "referer": referer, "returnURL": returnURL }
		mjaxAPIInternal.mjaxPost('funding','shoutOutzPCPSMS',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	shoutOutzCheckReplyY: function(mobile,buySessionID,offerKey,referer,returnURL,opaqueData,customHandler) {
		var sendData = { "mode": "checkReplyY", "mobile": mobile, "buySessionID": buySessionID, "offerKey": offerKey, "referer": referer, "returnURL": returnURL }
		mjaxAPIInternal.mjaxPost('funding','shoutOutzPCPSMS',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},


	//
	// Inventory APIs 
	//	
	getAssets: function(uid,type,page,limit,numberOfPages,shared,opaqueData,customHandler) {
		var sendData = { "uid": uid, "type": type, "page": page, "limit": limit, "numberOfPages": numberOfPages, "shared":shared }
		mjaxAPIInternal.mjaxPost('inventory','getAssets',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	sendToPhone: function(type,id,mobile,device,opaqueData,customHandler) {
		var sendData = { "mobile": mobile, 'device': device, 'type':type, 'id':id }
		mjaxAPIInternal.mjaxPost('inventory','sendToPhone',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	uploadDone: function(opaqueUploadID,shared,opaqueData,customHandler) {
		var locationHref = mbuzzy.common.urlEncode(location.href);
		var sendData = { "opaqueUploadID": opaqueUploadID, 'locationHref':locationHref, "shared":shared }
		mjaxAPIInternal.mjaxPost('inventory','uploadDone',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},
    
	//
	// mbuzzy APIs (general/non app specific)
	//	
	changePassword: function(oldPassword,newPassword,confirmNewPassword,opaqueData,customHandler) {
		var sendData = { "oldPassword": oldPassword, "newPassword":newPassword, "confirmNewPassword":confirmNewPassword }
		mjaxAPIInternal.mjaxPost('mbuzzy','changePassword',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	loginUser: function(uid,pw,opaqueData,customHandler) {
		var sendData = { "uid": uid, "pw": pw }
		mjaxAPIInternal.mjaxPost('mbuzzy','login',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	logoutUser: function(opaqueData,customHandler) {
		var sendData = null;
		mjaxAPIInternal.mjaxPost('mbuzzy','logout',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	getPhoneInfo: function(opaqueData,customHandler) {
		var sendData = null
		mjaxAPIInternal.mjaxPost('mbuzzy','getPhoneInfo',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	mbuzzy2go: function(mobile,opaqueData,customHandler) {
		var sendData = { "mobile": mobile }
		mjaxAPIInternal.mjaxPost('mbuzzy','mbuzzy2go',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	phoneSetup: function(opaqueData,customHandler) {
		var sendData = { "mode": "deviceDetection" };
		mjaxAPIInternal.mjaxPost('mbuzzy','phoneSetup',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	phoneSetupLinkClicked: function(opaqueData,customHandler) {
		var sendData = { "mode": "checkLinkClicked" };
		mjaxAPIInternal.mjaxPost('mbuzzy','phoneSetup',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	phoneSetupNoSMS: function(opaqueData,customHandler) {
		var sendData = { "mode": "NoSMS" };
		mjaxAPIInternal.mjaxPost('mbuzzy','phoneSetup',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	phoneSetupPINEntry: function(pin,opaqueData,customHandler) {
		var sendData = { "mode": "PINEntry", "pin": pin };
		mjaxAPIInternal.mjaxPost('mbuzzy','phoneSetup',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	phoneSetupSetRingtone: function(title,artist,opaqueData,customHandler) {
		var sendData = { "title": title, "artist": artist };
		mjaxAPIInternal.mjaxPost('mbuzzy','phoneSetupSetRingtone',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	phoneSetupSendSMS: function(mobile,opaqueData,customHandler) {
		var sendData = { "mode": "sendSMS", "mobile": mobile };
		mjaxAPIInternal.mjaxPost('mbuzzy','phoneSetup',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	phoneSetupSetDevice: function(deviceID,opaqueData,customHandler) {
		var sendData = { "mode": "setDevice", "deviceID": deviceID };
		mjaxAPIInternal.mjaxPost('mbuzzy','phoneSetup',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},


	//
	// Messaging APIs
	//	
	buzzUser: function(uid,iconID,message,opaqueData,customHandler) {
		var sendData = { "uid": uid, "iconID":iconID, "message": message }
		mjaxAPIInternal.mjaxPost('messaging','buzzUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	newMessage: function(toUid,anonCrushID,subject,message,addRecipientsToFriendsList,attachmentType,attachmentID,opaqueData,customHandler) {
		var sendData = { "toUid": toUid, "anonCrushID": anonCrushID, "addRecipientsToFriendsList":addRecipientsToFriendsList, "message":message, "subject": subject, 'attachmentType':attachmentType, 'attachmentID':attachmentID}
	mjaxAPIInternal.mjaxPost('messaging','newMessage',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	sendMessage: function(toUid,recipients,subject,message,addRecipientsToFriendsList,attachmentType,attachmentID,opaqueData,customHandler) {
		var sendData = { "toUid": toUid, "recipients": recipients, "addRecipientsToFriendsList":addRecipientsToFriendsList, "message":message, "subject": subject, 'attachmentType':attachmentType, 'attachmentID':attachmentID}
		mjaxAPIInternal.mjaxPost('messaging','newMessage',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},


	//
	// Open mbox APIs
	//	
	open: {
		sendUI: {"default" :{ "action": "openMbox", "data": { "opaque": null} }},
		
		//
		// Crush open mbox APIs
		//	
		addCrush: function(uid,opaqueData,customHandler) {
			var sendData = { "uid": uid }
			mjaxAPIInternal.mjaxPost('crush','addCrush',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		//
		// Friends open mbox APIs
		//	
		addFriend: function(uid,opaqueData,customHandler) {
			var sendData = { "uid": uid }
			mjaxAPIInternal.mjaxPost('friends','addFriend',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		changeRelationship: function(friendname,opaqueData,customHandler) {
			var sendData = { "changeUsername": friendname }
			mjaxAPIInternal.mjaxPost('friends','changeRelationship',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},
        
		ignoreUsername: function(uid,anonCrushID,opaqueData,customHandler) {
			var sendData = {uid: uid,
                            anonCrushID: anonCrushID};
			mjaxAPIInternal.mjaxPost('friends','ignoreUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler);
		},

		removeFriend: function(uid,opaqueData,customHandler) {
			var sendData = { "uid": uid }
			mjaxAPIInternal.mjaxPost('friends','removeFriend',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		subscribeUser: function(uid,opaqueData,customHandler) {
			var sendData = { "uid": uid }
			mjaxAPIInternal.mjaxPost('friends','subscribeUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		unignoreUsername: function(uid,anonCrushID,opaqueData,customHandler) {
			var sendData = {uid: uid,
                            anonCrushID: anonCrushID};
			mjaxAPIInternal.mjaxPost('friends','unignoreUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler);
		},

		unsubscribeUser: function(uid,opaqueData,customHandler) {
			var sendData = { "uid": uid }
			mjaxAPIInternal.mjaxPost('friends','unsubscribeUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		//
		// Funding open mbox APIs
		//	
		myFundingOptions: function(referer,returnURL,fundingOfferClass,opaqueData,customHandler) {
			var sendData = { "foc": fundingOfferClass, "referer": referer, "returnURL": returnURL }
			mjaxAPIInternal.mjaxPost('funding','myFundingOptions',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

        buyCoinzMessages: function(resultStatus,offer,r,opaqueData,customHandler) {
            var sendData = { "resultStatus": resultStatus, "offer": offer , "r": r };
            mjaxAPIInternal.mjaxPost('funding','buyCoinzMessages',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
        },


		//
		// inventory open mbox APIs
		//
		editItem: function(itemID,opaqueData,customHandler) {
			var locationHref = mbuzzy.common.urlEncode(location.href);
			var sendData = { "itemID": itemID, 'locationHref':locationHref }
			mjaxAPIInternal.mjaxPost('inventory','editItem',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},
		
		sendToPhone: function(type,id,opaqueData,customHandler) {
			var sendData = { 'type': type, 'id':id }
			mjaxAPIInternal.mjaxPost('inventory','sendToPhone',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

        moveProfileImage: function(method,opaqueData,customHandler) {
            var sendData = { 'method': method }
			mjaxAPIInternal.mjaxPost('inventory','moveProfileImage',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
        },

		//
		// secret stash open mbox APIs
		//
		editSecretStashPrice: function(secretStashID,newSecretStash,elementID,opaqueData,customHandler) {
            var sendData = { 'secretStashID':secretStashID , 'newSecretStash':newSecretStash, 'elementID':elementID };                    
			mjaxAPIInternal.mjaxPost('secretStash','editSecretStashPrice',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		//
		// mbuzzy (general/non app specific) open mbox APIs
		//	
		changePassword: function(opaqueData,customHandler) {
			var sendData = null;
			mjaxAPIInternal.mjaxPost('mbuzzy','changePassword',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		loginUser: function(opaqueData,customHandler) {
			var sendData = null;
			mjaxAPIInternal.mjaxPost('mbuzzy','login',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		mbuzzy2go: function(opaqueData,customHandler) {
			var sendData = null;
			mjaxAPIInternal.mjaxPost('mbuzzy','mbuzzy2go',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		phoneSetup: function(opaqueData,customHandler) {
			var sendData = null;
			mjaxAPIInternal.mjaxPost('mbuzzy','phoneSetup',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		//
		// Messaging open mbox APIs
		//	
		buzzUser: function(uid,opaqueData,customHandler) {
			var sendData = { "uid": uid }
			mjaxAPIInternal.mjaxPost('messaging','buzzUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		messageAttachMedia: function(opaqueData,customHandler) {
			var sendData = null;
			mjaxAPIInternal.mjaxPost('messaging','attachMedia',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		draftMessage: function(draftHashKey,opaqueData,customHandler) {
			var sendData = {'draftHashKey':draftHashKey};
			mjaxAPIInternal.mjaxPost('messaging','newMessage',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		newMessage: function(uid,anonCrushID,subject,message,attachmentType,attachmentID,opaqueData,customHandler) {
			var sendData = {toUid: uid, anonCrushID: anonCrushID , 'message':message, 'subject': subject, 'attachmentType':attachmentType, 'attachmentID':attachmentID};
			mjaxAPIInternal.mjaxPost('messaging','newMessage',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},
        
        
		//
		// Profile open mbox APIs
		//	
		setProfilePictures: function(opaqueData,customHandler) {
			var sendData = null;
			mjaxAPIInternal.mjaxPost('profile','setProfilePictures',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		//
		// Rate open mbox APIs
		//	
		rateUser: function(uid,opaqueData,customHandler) {
			var sendData = { "uid": uid }
			mjaxAPIInternal.mjaxPost('rate','rateUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		//
		// Upload open mbox APIs
		//	
		uploadDisabled: function(opaqueData,customHandler) {
			var sendData = null
			mjaxAPIInternal.mjaxPost('upload','uploadDisabled',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

		//
		// Shopping APIs 
		//	
		buyVirtualGood: function(uid,virtualGoodRefKey,returnURL,cost,shoutOutDescription,opaqueData,customHandler) {
			var sendData = { "uid": uid, "virtualGoodRefKey": virtualGoodRefKey, "returnURL": returnURL,"cost":cost,"shoutOutDescription":shoutOutDescription }
			mjaxAPIInternal.mjaxPost('shopping','buyVirtualGood',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},

        //
        //Shout Out APIs
        //
        getMoreCoinsShoutOut: function(uid,description,numDays,returnURL,opaqueData,customHandler) {
			var sendData = { "uid": uid, "description": description,"numDays":numDays, "returnURL": returnURL }
			mjaxAPIInternal.mjaxPost('userShoutOut','getMoreCoins',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
		},


        //Free coins
        openFreeCoinsAlert: function(credit, reason,opaqueData,customHandler){
            var sendData = { "credit": credit, "reason":reason};
            mjaxAPIInternal.mjaxPost('homepage','openFreeCoinsAlert',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler);
        },

        //Bookmark
        openAddBookmarkAlert: function(opaqueData,customHandler){
            mjaxAPIInternal.mjaxPost('homepage','openAddBookmarkAlert',null,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler);
        }

	},

	// 
	// Profile APIs
	//
    getEmoticons: function(opaque, responseHandler)
    {
		mjaxAPIInternal.mjaxPost('profile', 'getEmoticons', null, this.sendUI, mjaxAPI.responseHandlerWrapper, opaque, responseHandler);
    },

	setExtendedProfileInfo: function(jobTypeID,ethnicityID,bodyTypeID,heightFeet,heightInches,maritalStatusID,sexualOrientationID,religionID,smokeID,drinkID,childrenID,educationID,hairColor,eyeColor,weight,opaqueData,customHandler) {
		var sendData = { "jobTypeID": jobTypeID, "ethnicityID": ethnicityID, "bodyTypeID": bodyTypeID, "heightFeet": heightFeet, "heightInches": heightInches, "maritalStatusID": maritalStatusID, "sexualOrientationID": sexualOrientationID, "religionID": religionID, "smokeID": smokeID, "drinkID": drinkID, "childrenID": childrenID, "educationID": educationID, "hairColor": hairColor, "eyeColor": eyeColor, "weight": weight}
		mjaxAPIInternal.mjaxPost('profile','setExtendedProfileInfo',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},
    
	setMood: function(moodID,emoticonID,opaqueData,customHandler) {
		var sendData = { "moodID": moodID, "emoticonID": emoticonID }
		mjaxAPIInternal.mjaxPost('profile','setMood',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	setProfileFavorites: function(bands,books,movies,opaqueData,customHandler) {
		var sendData = { "bands": bands, "movies": movies, "books": books }
		mjaxAPIInternal.mjaxPost('profile','setProfileFavorites',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	setProfileInfo: function(gender,bDayDay,bDayMonth,bDayYear,city,state,country,zip,aboutMe,opaqueData,customHandler) {
		var sendData = { "gender": gender, "bDayDay": bDayDay, "bDayMonth": bDayMonth, "bDayYear": bDayYear, "city": city, "state": state, "country": country, "zip": zip, "aboutMe": aboutMe }
		mjaxAPIInternal.mjaxPost('profile','setProfileInfo',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	setProfilePictures: function(oids,opaqueData,customHandler) {
		var sendData = { "oids": oids }
		mjaxAPIInternal.mjaxPost('profile','setProfilePictures',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	setProfileCustomStyle: function(color1,color2,color3,opaqueData,customHandler) {
		var sendData = { "styleID": "custom", "customColor1": color1,"customColor2": color2, "customColor3": color3 }
		mjaxAPIInternal.mjaxPost('profile','setProfileStyle',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	setProfileStyle: function(styleID,opaqueData,customHandler) {
		var sendData = { "styleID": styleID }
		mjaxAPIInternal.mjaxPost('profile','setProfileStyle',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	setRightNow: function(rightNowAction,opaqueData,customHandler) {
		var sendData = { "rightNowAction": rightNowAction }
		mjaxAPIInternal.mjaxPost('profile','setRightNow',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	//
	// Rate APIs
	//	
	rateUser: function(uid,ratingID,opaqueData,customHandler) {
		var sendData = { "uid": uid, "ratingID": ratingID }
		mjaxAPIInternal.mjaxPost('rate','rateUser',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},

	//
	// Shopping APIs 
	//	
	buyVirtualGood: function(uid,virtualGoodRefKey,message,senderPrivacy,returnURL,opaqueData,customHandler) {
		var sendData = { "uid": uid, "virtualGoodRefKey": virtualGoodRefKey, "message": message, "senderPrivacy": senderPrivacy, "returnURL": returnURL}
		mjaxAPIInternal.mjaxPost('shopping','buyVirtualGood',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
	},


    responseHandlerWrapper: function(response,opaqueData,customHandler) {
		var status;
		var uiDefault;
		var uiActionDefault;
		var data;
		if (response) {
			if (response.ui && response.ui.action && (response.ui.action['default'])) {	
				uiActionDefault = response.ui.action['default'];
			}
			if (response.status == "LOGIN_REQUIRED") {
				mjaxAPI.loginRedirect();
				return;
			} else if (response.status != "SUCCESS") {
				status = response.status;
			} else if (((response.app == 'mbuzzy') && (response.action == 'login') && (mjaxAPI.loginRepostData)) && (uiActionDefault != 'openMbox')) {
				var localLoginRepostData = mjaxAPI.loginRepostData;
				jQuery(document).bind('close.facebox', mjaxAPI.postLoginMboxCloseHandler); 
				if (!localLoginRepostData.isOpenMbox) {
					jQuery(document).trigger('close.facebox');
				} else {
					mjaxAPIInternal.mjaxRepost(localLoginRepostData);
				}
				return;
			} 
			if (response.ui && response.ui['default']) {
				uiDefault = response.ui['default'];
			}
			if (response.data) {
				data = response.data;
			}
		}
		if ((uiActionDefault == 'openMbox') && uiDefault) {
			jQuery.mbox.load(uiDefault);
			uiDefault = null;
		}
		if (typeof customHandler == 'function') {

			var handlerData = { "ui": uiDefault, "data": data, "status": status, "opaqueData": opaqueData};
			customHandler(handlerData);
		}
	},

	postLoginMboxCloseHandler: function(event) {
		jQuery(document).unbind('close.facebox', mjaxAPI.postLoginMboxCloseHandler); 
		refresh();
	},


	mboxCloseHandler: function(event) {
		mjaxAPI.loginRepostData = null;
		mjaxAPIInternal.repostData = null;
		jQuery(document).unbind('close.facebox', mjaxAPI.mboxCloseHandler); 
	},

	loginRedirect: function(event) {
		this.loginRepostData = mjaxAPIInternal.repostData;
		mjaxAPI.open.loginUser();
		jQuery(document).bind('close.facebox', mjaxAPI.mboxCloseHandler); 
	},

    //Secret Stash APIs
    updateSecretStashDescription: function(secretStashID,description,opaqueData,customHandler) {
		var sendData = { "secretStashID": secretStashID, "description": description };
		mjaxAPIInternal.mjaxPost('secretStash','updateDescription',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler);
	},

    editSecretStashPrice: function(secretStashID,price,elementID,opaqueData,customHandler) {
        var sendData = { 'secretStashID': secretStashID, 'price':price, 'elementID':elementID };
        mjaxAPIInternal.mjaxPost('secretStash','editSecretStashPrice',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler)
    },

    rateSecretStash: function(secretStashID,purchaserUserID,secretStashPurchaseID,rating,opaqueData,customHandler) {
		var sendData = { "secretStashID": secretStashID, "purchaserUserID": purchaserUserID, "secretStashPurchaseID": secretStashPurchaseID, "rating": rating };
		mjaxAPIInternal.mjaxPost('secretStash','rateSecretStash',sendData,this.sendUI,mjaxAPI.responseHandlerWrapper,opaqueData,customHandler);
	}

};
 
mbuzzy =
{
	/**
	 * Post form data
	 */
	postForm: function(form,
					   target,
					   reporter)
	{
		if (form)
		{
			YAHOO.util.Connect.setForm(form);
		}
					
		YAHOO.util.Connect.asyncRequest('GET', 
									    target, 
		{ 
		    success: function(request)
 		    {
		        if (request.responseText !== undefined)										  
			    {
			        request.argument(request.responseText);
			    }
		    },																   

	        failure: function(request)
		    {
			    // FIXME: provide feedback!
	            //
		    },
																   
		    timeout: 5000,  // request timeout 5 sec!
		    argument: reporter
		});
	}
};

/**
 * Generic polling engine.
 * FIXME: Restructure as class!
 */
mbuzzyPoll = 
{
	getTarget: null,
	reporter: null,	

	normalTimeout: null,
	errorTimeout: null,
	
	currentPoll: null,
	currentTimer: null,
	expediteTimer: false,
	
	setTimer: function(timeout)
	{
       mbuzzyPoll.currentPoll = null;
  	   mbuzzyPoll.currentTimer = setTimeout("mbuzzyPoll.invoke();", timeout);
	},

	/**
	 * (reporter) signature is (responseText)
	 */
	invoke: function()
	{
		if (mbuzzyPoll.currentPoll == null) 
		{
			mbuzzyPoll.currentPoll = YAHOO.util.Connect.asyncRequest('GET',mbuzzyPoll.getTarget(), 
			{ 
				success: function(request)
				{
			       	mbuzzyPoll.setTimer((mbuzzyPoll.expediteTimer ? 0 : mbuzzyPoll.normalTimeout));
				   	mbuzzyPoll.expediteTimer = false;																       				   

				   	if (request.responseText !== undefined)
			   	   	{
			   	   		mbuzzyPoll.reporter(request.responseText);																   	   
		   	   		}
			   	},																   

				failure: function(request)
				{
					// What to do here?
					// Just cleanup and try again?
					//																   
					mbuzzyPoll.setTimer(mbuzzyPoll.errorTimeout);
			   	},
					
				argument: [mbuzzyPoll.normalTimeout, mbuzzyPoll.errorTimeout, mbuzzyPoll.reporter],
			    timeout: 10000	// request timeout 10 sec!
			});
		} 
	},

	/**
	 *
	 */
	expeditePoll: function() 
	{
		if (mbuzzyPoll.currentPoll == null)
		{
			// No active poll in-progress,
			// manually fire poll command!
			//				
			if (mbuzzyPoll.currentTimer != null)
			{
				clearTimeout(mbuzzyPoll.currentTimer);
				mbuzzyPoll.invoke();				
			}
		}
		else
		{
			mbuzzyPoll.expediteTimer = true;
		}
	}
};if(jQuery)(
	function($){
		$.extend($.fn,{
			hideSpinner:function() {
				$(this).each(function() {
					$(this).css('visibility','visible');
					$(this).parent().find('.spinner').hide();
				});
			},

			showSpinner:function(overlay) {
				$(this).each(function() {
					var myParent = $(this).parent();
					if (!$(myParent).hasClass('.spinner_wrapper')) {
						$(this).wrap('<div class="spinner_wrapper" style="position: relative; float:left"></div>');
						var spinnerImage;
						if ($(this).hasClass('darkSpinner')) {
							spinnerImage = 'spinner_dark_sm.gif';
						} else {
							spinnerImage = 'spinner_sm.gif';
						}
						var mySpinnerWrapper = $(this).parent();
						var needToRehideIt = false;
						var height = $(mySpinnerWrapper).outerHeight();
						var width = $(mySpinnerWrapper).outerWidth();
						var spinnerTop = Math.floor(height/2 - 10);
						if (spinnerTop < 0) { spinnerTop = 0; }
						var spinnerLeft = Math.floor(width/2 - 10);
						if (spinnerLeft < 0) { spinnerLeft = 0; }
						var marginTop = $(this).css('margin-top');
						if (!marginTop) {
							marginTop = "0";
						}
						var marginLeft = $(this).css('margin-left');
						if (!marginLeft) {
							marginLeft = "0";
						}
						$(mySpinnerWrapper).prepend('<div class="spinner" align="center" valign="middle" style="vertical-align:middle; background-image: URL(\'/images/'+spinnerImage+'\'); position: absolute; top: '+spinnerTop+'px; left: '+spinnerLeft+'px; width:20px; height: 20px; z-index:10000; display: none; margin-top: '+marginTop+'px; margin-left: '+marginLeft+'px;"></div>');
						var float = $(this).css('float');
						if (float == "right") {
							$(mySpinnerWrapper).css('float','right');
						}
					}
					$(myParent).find('.spinner').show();
					if (!overlay) {
						$(this).css('visibility','hidden');
					}
				});
			}

	})
})(jQuery);
if(jQuery)(
	function($){
		$.extend($.fn,{
			zIndexFix: function(zNumber) {	
				if ($.browser.msie) {
					var zIndexNumber = zNumber;
					$(this).each(function() {
						$(this).css('zIndex', zIndexNumber);
						zIndexNumber -= 10;
					});
				}
			},
			zIndexIncrementRecursive: function(zNumber) {	
				if ($.browser.msie) {
					$(this).each(function() {
						$(this).css('zIndex', zNumber);
						$(this).children().zIndexIncrementRecursive(zNumber+10);
					});
				}
			}
		})
	}
)(jQuery);


jQuery.fn.accessNews = function(settings) {
    settings = jQuery.extend({
        newsHeadline: "",
        /*newsSpeed: "normal"*/
        newsSpeed: 50
    }, settings);
    return this.each(function(i) {
        aNewsSlider.itemWidth = 565;
        aNewsSlider.init(settings,this);
    });
};
var aNewsSlider = {
    itemWidth: 0,
    init: function(s,p) {
        var parentID = $(p).attr('id');
        jQuery(".messaging").css("display","none");
        itemLength = jQuery(".item",p).length;
		if (itemLength) {
			newsContainerWidth = itemLength * aNewsSlider.itemWidth;
			jQuery("#"+parentID+" .container").css("width",newsContainerWidth + "px");

            animateLeft = parseInt(jQuery("#"+parentID+" .container").css("left")) - (aNewsSlider.itemWidth * 1);
            if (animateLeft + parseInt(jQuery("#"+parentID+" .container").width()) > 0) {
                jQuery('#'+parentID+' .streamRightOff').hide();
                jQuery('#'+parentID+' .streamRightOn').show();
            } else {
                jQuery('#'+parentID+' .streamRightOn').hide();
                jQuery('#'+parentID+' .streamRightOff').show();
            }
		}else{
            jQuery('#'+parentID+' .streamRightOn').hide();
            jQuery('#'+parentID+' .streamRightOff').show();
        }

        animating = false;
        jQuery(".next",p).click(function() {
           if (animating == false) {
                animating = true;
                animateLeft = parseInt(jQuery(".container",p).css("left")) - (aNewsSlider.itemWidth * 1);
                if (animateLeft + parseInt(jQuery(".container",p).css("width")) > 0) {
                    jQuery('#'+parentID+' .streamLeftOff').hide();
                    jQuery('#'+parentID+' .streamLeftOn').show();
                    jQuery(".container",p).animate({left: animateLeft}, s.newsSpeed, function() {
                        jQuery(this).css("left",animateLeft);
                        if (parseInt(jQuery(".container",p).css("left")) + parseInt(jQuery(".container",p).css("width")) 
													<= aNewsSlider.itemWidth * 1) {
                        } else {
                            jQuery('#'+parentID+' .streamLeftOff').hide();
                            jQuery('#'+parentID+' .streamLeftOn').show();
						}
                        animating = false;
                    });
                } else {
                    animating = false;
                }
            }
            return false;
        });
        jQuery(".prev",p).click(function() {
            if (animating == false) {
                animating = true;
                animateLeft = parseInt(jQuery(".container",p).css("left")) + (aNewsSlider.itemWidth * 1);
                if ((animateLeft + parseInt(jQuery(".container",p).css("width"))) <= parseInt(jQuery(".container",p).css("width"))) {
					jQuery('#'+parentID+' .streamRightOff').hide();
                    jQuery('#'+parentID+' .streamRightOn').show();
                    jQuery(".container",p).animate({left: animateLeft}, s.newsSpeed, function() {
                        jQuery(this).css("left",animateLeft);
                        if (parseInt(jQuery(".container",p).css("left")) == 0) {
							jQuery('#'+parentID+' .streamLeftOn').hide();
                            jQuery('#'+parentID+' .streamLeftOff').show();
                        } else {
                            jQuery('#'+parentID+' .streamRightOff').hide();
                            jQuery('#'+parentID+' .streamRightOn').show();
						}
                        animating = false;
                    });
                } else {
                    animating = false;
                }
            }
            return false;
        });
    },
    vAll: function(s,p) {
        var parentID = $(p).attr('id');
        var o = p;
        while (p) {
            p = p.parentNode;
            if (jQuery(p).attr("class") != undefined && jQuery(p).attr("class").indexOf("news_slider") != -1) {
                break;
            }
        }
        if (jQuery(o).text().indexOf("View All") != -1) {
            jQuery('#'+parentID+' .streamRightOn').hide();
            jQuery('#'+parentID+' .streamRightOff').show();
            jQuery('#'+parentID+' .streamLeftOn').hide();
            jQuery('#'+parentID+' .streamLeftOff').show();
            jQuery(o).text("View Less");
            jQuery(".container",p).css("left","0px").css("width",aNewsSlider.itemWidth * 1 + "px");
        } else {
            jQuery(o).text("View All");
            aNewsSlider.init(s,p);
        }
    }
};
$(function() 
{
    // style array affecting the mini profile
		// [stylesArray][0] - .mini_catHeader
		// [stylesArray][1] - .mini_profileHeaders
		// [stylesArray][2] - .mini_bottomCorner
		// [stylesArray][3] - .miniLinks anchor color
		// [stylesArray][4] - #mini_profileGallery img (border)
		var stylesArray = new Array("ED9C1C", "99BBCC", "FFFFFF", "379AC5", "CCCCCC");
		
    mbuzzy.bubble = 
    {
		spanClear: function(miniProfile,
                            thenWhat)
		{
			var clearMarkup = false;
            
			// swap back to default styles
			$(miniProfile).find('.mini_catHeader').css('backgroundColor', [stylesArray][0]); 
			$(miniProfile).find('.miniLinks > a').css('color', [stylesArray][3]); 
			$(miniProfile).find('.mini_profileHeaders').css('backgroundColor', [stylesArray][1]); 
		    $(miniProfile).find('.mini_bottomCorner').css('backgroundColor', [stylesArray][2]); 
					
			$(miniProfile).find('img[name=miniUserPic]').attr('src', 'http://cache.mbuzzy.com/cache/4.1.8.7/images/spinner_lg.gif');
			$(miniProfile).find('.miniLinks > a').unbind("click", null).removeAttr('href');

			var spanArray = new Array('miniUserName', 
                                      'miniUserGender',
                                      'miniUserAge',
                                      'miniUserCity',
                                      'miniUserState',
                                      'RightNow');
					
			$(spanArray).each(function(i) 
            {
				$(miniProfile).find('span[name='+spanArray[i]+']').html("");
			});

			clearMarkup = true;
					
			var nextAction = thenWhat;

			if(clearMarkup) 
            {	
				if(nextAction == "thenShow") 
                {
					mbuzzy.bubble.spanSwap(miniProfile);
				}
			}
		},
				
		spanSwap: function(miniProfile)
        {
						
						// swap the styles color
						/*
						-color1: 
							mini_catHeader, miniLinks
						
						-color2: 
							mini_profileHeaders
							
						-color3:
							mini_bottomCorner
						*/

			$(miniProfile).find('.mini_catHeader').css('backgroundColor', miniUserStyleOne); 
			$(miniProfile).find('.miniLinks > a').css('color', miniUserStyleOne); 
			$(miniProfile).find('.mini_profileHeaders').css('backgroundColor', miniUserStyleTwo); 
			$(miniProfile).find('.mini_bottomCorner').css('backgroundColor', miniUserStyleThree); 
						
			if (typeof(miniUserName) == "string") 
            {
				$(miniProfile).find('span[name=miniUserName]').html(miniUserName);
							
				// add visit profile link
				$(miniProfile).find('a[name=miniViewProfileLink]').attr('href', 'http://www.mbuzzy.com/showProfile.php?uid='+miniUserName+'');
							
				// add send message link
				$(miniProfile).find('a[name=miniSendMessageLink]')
                              .click(function(event)
                                     {
                                         event.preventDefault();
                                         messaging.openNewMessage(miniUserName);
                                     })
                              .attr("href", "#");
                             
				// add add as friend link
				$(miniProfile).find('a[name=miniAddAsFriendLink]')
                              .click(function(event)
                                     {
                                         event.preventDefault();
                                         friends.openAddFriend(miniUserName);
                                     })       
                              .attr("href", "#");
							
			    // add send IM link
				$(miniProfile).find('a[name=miniSendIMLink]')
                              .click(function(event)
                                     {
                                         event.preventDefault();
                                         openTheTab(miniUserName);
                                     })
                              .attr("href", "#");
			}
			else 
            {
				$(miniProfile).find('span[name=miniUserName]').html("");
			}
						
			if (miniUserOnline)
			{
				$(miniProfile).find('span[name=miniOnlineStatus]').html("online");
			}
			else
			{
				$(miniProfile).find('span[name=miniOnlineStatus]').html("offline");
			}
						
			if (typeof miniUserInChatRoom == "string")
			{	
				$(miniProfile).find('a[name=miniJoinInChatLink]')
							  .attr('href', "http://www.mbuzzy.com/chatRoom.php?crk="+miniUserInChatRoom+"");
			}
						
			if (miniUserGender)
			{
			    $(miniProfile).find('span[name=miniUserGender]').html(miniUserGender);
			}
			else
			{
				$(miniProfile).find('span[name=miniUserGender]').html("");
			}
						
			if (miniUserAge)
			{
			    $(miniProfile).find('span[name=miniUserAge]').html(miniUserAge);
			}
			else
			{
				$(miniProfile).find('span[name=miniUserAge]').html("");
			}
						
			if (typeof miniUserCity == 'undefined') 
			{
			}
			else 
            {
				$(miniProfile).find('span[name=miniUserCity]').html(miniUserCity);
			}
            
			$(miniProfile).find('span[name=miniUserState]').html(miniUserState);
						
			if (miniUserRightNow)
			{
				$(miniProfile).find('span[name=miniUserRightNow]').html(miniUserRightNow['action']);
			}
			else
			{
				$(miniProfile).find('span[name=miniUserRightNow]').html("");
			}
						
			$(miniProfile).find('img[name=miniUserPic]').attr('src', miniUserPic);
						
		},
							
		placeBox: function(w, pw, h, t, b, l, r, dw, dh)
		{
					
					var boxWidth = 338;
					var boxHeight = 230;
					
					var boxCoordinates = new Object();
					//sets the direction of the slide top for top down and bottom for bottom up
					boxCoordinates.upDown = "top";
					
					if( t <= (boxHeight + h))
					{
						boxCoordinates.upDown = "bottom";
					}
					
					if (r < (boxWidth - w)/2 )
					{
						boxCoordinates.left = (boxWidth - ((boxWidth - w)/2));
						boxCoordinates.rightMost = true;
					}
					else
					{
						if(pw == w) {
							boxCoordinates.left = (boxWidth - w)/2;
						}
						else {
							boxCoordinates.left = ((boxWidth - pw) - w)/2;
						}
						boxCoordinates.rightMost = false;
					}
					
					return boxCoordinates;
		},
        
		initBubble: function($this)
        {
        	return;
		    var x;
			var y;
			var offX;
					var offY;
					var distance;
					var rightMostBox;
					var hideDelayTimer = null;

					var beingShown = false;
					var shown = false;
					var trigger = $('.trigger', $this);
                    
//					var coordinates = $('.coordinates', $this);
					var popupMiniProfile = $('.popupMiniProfile', $this);

					var friendsThumbInfo = $('.friendsThumbInfo > a', $this);
					var content = $('.popupMiniProfile', $this);
					var info = $('.popupMiniProfile', $this).css('opacity', 0);
					
					var leftPos = 0;
					var rightPos = 0;
					var boxUpDown;
					
					var time = 400;
					var hideDelay = 250;
					
					$([trigger.get(0), info.get(0)])
					.hoverIntent({
						sensitivity: 7, // number = sensitivity threshold (must be 1 or higher)
						interval: 1000,   // number = milliseconds of polling interval
						over: showPopup,  // function = onMouseOver callback (required)
						timeout: 500,   // number = milliseconds delay before onMouseOut function call
						out: hidePopup    // function = onMouseOut callback (required)																						 
					});
					
					$(popupMiniProfile).hoverIntent(stayOnPopup, leavePopup);
					
            function stayOnPopup()
            {						
			    $([trigger.get(0), info.get(0)]).trigger("mouseover");
			};

			function leavePopup()
            {
				$([trigger.get(0), info.get(0)]).trigger("mouseout");	
			};
			
			// Marco- taking this out because its causing Issue 3539
			// when we re-enable miniProfile we will need to figure this out.		
			//$(friendsThumbInfo).hoverIntent(friendOnPopup, friendLeavePopup);
					
            function friendOnPopup()
            {
				$([trigger.get(0), info.get(0)]).trigger("mouseover");
			};
			
            function friendLeavePopup()
            {
				$([trigger.get(0), info.get(0)]).trigger("mouseout");	
			};
					
		    function showPopup()
            {
				triggerMouseOver($(this));
							
							if (hideDelayTimer) clearTimeout(hideDelayTimer);
							if (beingShown || shown) {
									// don't trigger the animation again
									return;
							} else {
									// reset position of info box
									beingShown = true;
									var travelTop = trigger.parent().height();
									
									distance = 20;
									
                                    var miniProfile = $(content).find(".miniWrapper");
                                    if (!miniProfile.length)
                                    {
                                        miniProfile = $(content).html($(".templates .miniWrapper").clone(true).show()).find(".miniWrapper");
                                    }

									mbuzzy.bubble.spanClear(miniProfile.get(0),
                                                            "thenShow");
                                    
//									$('.miniWrapper').appendTo($(content)).css({display: 'block'});
									$(content).css({display: 'block'});
									
									var bgURL = 'url("/images/mp_bg_full.png")';
									var cssObject;
                                    
                                    var popup = $(content);
									
									if(boxUpDown == "top") {
										
										// get the proper background piece for the miniWrapper
										
										popup.find('.mini_catHeader').css("marginTop", "7px");
										popup.find('.mini_absolute').css("top", "4px");
										
										if(rightMostBox) {
											popup.find('.miniWrapper').css ({
																						 
												backgroundImage: bgURL,
												backgroundPosition: 'top right'
											});
										}
										else {
											popup.find('.miniWrapper').css ({
												backgroundImage: bgURL,
												backgroundPosition: 'top center'
											});
										}
										
										//position the box accordingly
										info.css({
												top: -215,
												left: leftPos,
												display: 'block'
										}).animate({
												top: '-=' + distance + 'px',
												opacity: 1
										}, time, 'linear', function() {
												beingShown = false;
												shown = true;
										});
									}									
									else if(boxUpDown == "bottom") 
                                    {										
										popup.find('.mini_catHeader').css("marginTop", "21px");
										popup.find('.mini_absolute').css("top", "4px");
										
										// get the proper background piece for the miniWrapper
										if(rightMostBox) {
											popup.find('.miniWrapper').css ({
												backgroundImage: bgURL,
												backgroundPosition: 'bottom right'
											});
										}
										else {
											popup.find('.miniWrapper').css ({
												backgroundImage: bgURL,
												backgroundPosition: 'bottom'
											});
										}
										//position the box accordingly
										info.css({
												top: travelTop + 15,
												left: leftPos,
												display: 'block'
										}).animate({
												top: '-=' + distance + 'px',
												opacity: 1
										}, time, 'linear', function() {
												beingShown = false;
												shown = true;
										});
									}
							}

							return false;
			}; // end showPopup
										
			function hidePopup()
            {
							if (hideDelayTimer) clearTimeout(hideDelayTimer);
							hideDelayTimer = setTimeout(function () {
									hideDelayTimer = null;
									
									if(boxUpDown == "top")
									{
										info.animate({
												top: '-=' + distance + 'px',
												opacity: 0
										}, time, 'swing', function () {
												shown = false;
												info.css('display', 'none');
										});
										
//										mbuzzy.bubble.spanClear("thenHide");
									}
									
									else if(boxUpDown == "bottom") {
										info.animate({
											top: '+=' + distance + 'px',
											opacity: 0
											}, time, 'swing', function () {
													shown = false;
													info.css('display', 'none');
											});
//										mbuzzy.bubble.spanClear("thenHide");
									}
										
							}, hideDelay);

							return false;
			};// hidePopup
					
			function triggerMouseOver($this)
            {					
						var width = $this.outerWidth();
						var parentWidth = $this.parent().outerWidth();
						var height = $this.parent().outerHeight();
						var scrollTop = Number($(document).scrollTop());
						var scrollLeft = Number($(document).scrollLeft());
						var docWidth = Number($(window).width());
						var docHeight = Number($(window).height());
						var winRight = scrollLeft + docWidth;
						var winBottom = scrollTop + docHeight;
						var space = new Object();
						space.top = $this.offset().top - scrollTop;
						space.bottom = docHeight - (($this.offset().top + height) - scrollTop);
						space.left = $this.offset().left - scrollLeft;
						space.right = docWidth - (($this.offset().left + width) - scrollLeft);
						
						var boxPos = mbuzzy.bubble.placeBox(width, parentWidth, height, space.top, space.bottom, space.left, space.right, 
																	docWidth, docHeight);
						leftPos = -(boxPos.left);
						travelPos = height;
						boxUpDown = boxPos.upDown;
						rightMostBox = boxPos.rightMost;
			};
				
			function triggerMouseOut()
            {				
			}
					
		}// end initBubble
    };
				
});

$(function() {
		   
		// let's claculate the css position of the breakout pages tab tail since the tab can grow based on the number of items
			if($('.settings_navigation_item').length > 0) {
				var tabMinWidth = Number(100);
				var tabWidth = Number($('.settings_navigation_item').width());
				if(tabWidth > tabMinWidth) {
					var tailLeftPos = Math.round(tabWidth / 2) - 5;
					$('.settings_navigation_item_tail').css('left', tailLeftPos+'px');	
				}
				
			}
					 
		// check the browser and assign the reset z-index if IE
		if ( $.browser.msie ) {
			// The z-index fix was IE7 specific, IE8 seemingly takes cares of this problem
			// so we should be aware of these kind of conditional statements further on.
 			if ( $.browser.version == "7.0" ) {
								
				$('.stats').zIndexFix(10000);
				
				$('#emoticonID > div').zIndexFix(20000);
				
				$('.hasTray > div').zIndexFix(30000);
				
				$('#talkBox > div').zIndexFix(40000);
				
				$('.actionPopUp2 > div').zIndexFix(50000);
				
				$('.s_buzzItem > div').zIndexFix(50000);
			}
		}
		
		// bubble info is triggered by default for any pages that has user profile info
		$('.bubbleInfo').each(function () {
			mbuzzy.bubble.initBubble($(this));       
       	});
		
			var viewTray = false;
			$('a').click(function(event) {
				if(viewTray) {										
					$('.showTray').fadeOut().css("height", "0");
					viewTray = false;
				}
			});
			
			// remove the last bottom border in the info panel and for the last item of a list
			$('.chartsTop:last').css("border", "none"); 
			$('.chartsNew:last').css("border", "none"); 
			
			// remove last bottom border for breakout pages last item
			$('.dataContainer > ul > li:last').css("borderBottom", "none");
			$(' div.settingsAccountHolder:last').css("borderBottom", "none");
			$(' .inbox_tableRow:last > .inbox_ContentRow').css("borderBottom", "none");

			$('.display_helpItem').hover(
				function(){$(this).css("backgroundColor", "#f3f3f3")},
				function(){$(this).css("backgroundColor", "#ffffff")}
			);
			
			// profile pictures gallery style functionality
			$('.profileThumbs').click(function(event) {
				event.preventDefault();
				var bigProfileImage = $(this).attr('m');
				$('#profileSlider')
				.animate({
					"opacity" : 0,
					"duration" : 1000
				}, function() {
					$(this)
					.html("<img src='"+bigProfileImage+"' width='242' height='242' border=0>")
					.animate({
						"opacity" : 1,
						"duration" : 3000				 
					});
				});
			});
		
		// end profile pics logic
		
		// end save comment code 
			
		$('.streamLinksActive').hide();
		$('.streamLinks > li:first > a.streamLinksTrigger').css("display", "none");
		$('.streamLinks > li:first > a.streamLinksActive').css("display", "block");
		$('.streamLinksTrigger').click( function(event) {
				//event.preventDefault();
				$('.streamLinksActive').css("display", "none");
				$('.streamLinksTrigger').css("display", "block");
				$(this).css("display", "none").siblings('.streamLinksActive').css("display", "block");
			}
		);
		
		// end streamLinks javascript css
		
		// add slider functionality to given block(s)
		$(".news_slider").accessNews();

		// end slider functionality
		
		// set the default page number to 1			 
		var currentPage = Number(1);
		// set the default stream to all
		var currentStreamType = new Array(0,3);

/**
 * FIXME: This is a hack to work-around a js referencing error.
 *        The variable below "moreLeft" is NOT defined in this module and breaks if you don't
 *        include the corresponding tpl that creates it!
 *        mjax.js was originally used only for profile page.
 *        However, it has since be leveraged for just about all our ajax-based pages because
 *        it has some useful common code/functionallity.
 *        
 *        This gigantic file should be broken up into it's constituent parts immediately so
 *        that we can selectively include only what we want.
 */
	if (myGroup == "slideAndHide")	
	{
		
        var lastInSetPage = 0;
        sliderInProgress = 0;

		// next and previous buttons logic
		$(".next").click(function () {
            // Block concurrent slide requests
            //
            if (!sliderInProgress) {
                //var parentID  = $(this).parents('div:first').attr('id');    
                var parentID = $(this).parents('.news_slider').attr('id');
                currentPage = parseInt($('#' + parentID + ' .currentSlide').val());
                currentPage = parseInt(currentPage) + 1;
                $('#' + parentID + ' .currentSlide').val(currentPage);
                var nextPage = currentPage + 1;
                var nextPageString = parentID + '_' + nextPage + '';
                var cachedPage = $('#' + parentID + ' > div.news_items > div.container').find("div[id='" + nextPageString + "']");
                
                if ($(cachedPage).html() !== null) {
                }
                else {
                    lastInSet = parseInt($('#' + parentID + ' .lastSlide').val());                    
                    lastInSetPage = lastInSet;
                    if (nextPage > lastInSetPage) {
                        // do nothing there is no more
                        $('#'+parentID+' .streamRightOn').hide();
                        $('#'+parentID+' .streamRightOff').show();
                    }
                    else {
                        var opaqueData = {
                            itemID: parentID
                        };

                        $('#'+parentID+' .streamButtons').showSpinner(false);
                        var sharedType = $('#'+parentID).find('.sharedType').val();
                        streamType = $('#' + parentID + ' .streamType').val();
                        var currentStreamType = getStreamType(streamType);
                        mjaxAPI.getAssets(userName, currentStreamType, nextPage, 5, 1, sharedType, opaqueData, getAssetsResponseHandler);
                    }
                }
            }
            
			return false;
		});
		
		$(".prev").click(function () {

            var parentID = $(this).parents('.news_slider').attr('id');

            // Block concurrent slide requests
            //
            if (!sliderInProgress) {
                currentPage = parseInt($('#' + parentID + ' .currentSlide').val());
                currentPage = parseInt(currentPage) - 1;
                $('#' + parentID + ' .currentSlide').val(currentPage);
                lastInSetPage = parseInt($('#' + parentID + ' .lastSlide').val());
                if (lastInSetPage > 0) {
                    if (currentPage < lastInSetPage) {
                        $('#'+parentID+' .streamRightOff').hide();
                        $('#'+parentID+' .streamRightOn').show();
                    }
                    
                }
            }

			return false;
		});
	}
		
		// end next and previous buttons logic
		
		// photos + videos stream box links logic
		// goals outlined below
		// 1- ensure that a new stream is requested before sending a request to the server
		// 2- get the stream type of the newly requested one
		// 3- clear out the current stream
		// 4- implement the new stream

		
		// 1- ensure that a new stream is requested before sending a request to the server
		$(".streamLinksTrigger > a").click(function(event) {
			event.preventDefault();
			var clickedStream = $(this).text();
			var clickedStreamType = getStreamType(clickedStream);

            var parentID = $(this).parents('.news_slider').attr('id');
            currentStreamTypeVal = $('#' + parentID + ' .streamType').val();
            var currentStreamType = getStreamType(currentStreamTypeVal);
        
			if(clickedStreamType != currentStreamType) {

                //reset the page
				currentPage = Number(1);
				$('#' + parentID + ' .currentSlide').val(currentPage);
                $('#' + parentID + ' .streamType').val(clickedStream);
                currentStreamType = clickedStreamType;
                var sharedType = $('#'+parentID).find('.sharedType').val();

				// 3- clear out the current stream
				$('#'+parentID+' > div.news_items > div.container')
				.animate({"opacity" : 0, "duration" : 50},
					 function() {
						$(this).empty();
						$(this).html('<div id="newsItemsSpinner" style="width: 575px; height: 130px; text-align: center; float:left;"><center><img src="images/spinner_lg.gif" style="position:relative; top:43px;"/></center></div>').animate({"opacity": 1, "duration": 50});
						var opaqueData = { itemID: parentID, newStream: true };
						mjaxAPI.getAssets(userName,currentStreamType,0,5,2,sharedType,opaqueData, getAssetsResponseHandler);
					 }
				);
			}
			
		});

		// end photos + videos stream box links logic
		
		
		// showing and hiding tray logic
		var trayContainer;
		var trayHeight;
		if(typeof blockedUser != 'undefined') {
			trayHeight = 190;
		}
		else{
			trayHeight = 230;
		}
		
		$('.inputTrigger').click(function(event) {
			if (!isAuthState) {
				mbuzzy.common.openLoginUser();
			} else {
				viewTray = true;
				trayContainer = $(this).attr('name');
				$('.'+trayContainer+'').animate({height: trayHeight+50+"px"}).animate({height: trayHeight+"px"}, "fast", 
				function() {$('.addCommentTextarea', this).focus();});
			
				if ($('.addCommentTextarea').length > 0) {	
					if ($('.addCommentTextarea').val().length > 0) {
						$('.charCounter').text(1000 - Number($('.addCommentTextarea').val().length) );
					}
					else {
						$('.charCounter').text("1000");
					}
				}
			}	
		});
		
		// ending tray logic
		
		// track text area changes 
		// 1- enable/disable the save button based on character count
		// 2- empty the container when the cancel button is clicked and close the tray
		// 3- save what was type in the text area and send it to the proper markup
		// 4- infuse the response from the call to the div with the proper markup around
		
		// 1- enable/disable logic
		$('.addCommentTextarea').keyup(function(e) {		
			var $thisKey = e.keyCode;													 
			var commentLength = $(this).val().length;
			var limit = 1000;
			if (commentLength > limit) {
				$(this).val($(this).val().substring(0,limit));
			} else {
				$('.charCounter').text(Number(parseInt(limit) - parseInt(commentLength)));
				if (commentLength >= 2) {
					$('#saveCommentButtonDisabled').hide();
					$('#saveCommentButtonEnabled').show();
				} else if(commentLength < 2) {
					$('#saveCommentButtonEnabled').hide();
					$('#saveCommentButtonDisabled').show();
				}
			}	
		});
		// end enable/disable
		
		// 2- cancel and save logic
		
		// end cancel and save logic
		
		
		// end text area changes code
		
		/* 
			this code would be only useful sitewide , if any other visual design regarding displaying a comment list or
			 adding a new one is uniform accros the site. The profile is a special case but for the sake of consistency
			 we should strive to define a format that can translate to many pages.
		*/
		// adding and saving a new comment for all pages (besides the profile) class names are important
			 $('.objectCommentBtn').click(
					function(event) {
						event.preventDefault();
						var currentButton = $(this).attr('name').split('_');
						
						var commentAction = currentButton[0];
						var commentContainer = currentButton[1];
						
						switch(commentAction) {
							case 'save':
								var newMessage = $('textarea[name='+commentContainer+']').val().substring(0,1000);
								$('#objectCommentButtons').showSpinner();
								mjaxAPI.addObjectComment(objectID,newMessage,{objectComment : true},addObjectCommentResponseHandler);
								$('textarea[name='+commentContainer+']').val("")
								$('.charCounter').text(Number(1000));
							break;
							
							case 'cancel': 
								$('#saveCommentButtonEnabled').hide();
								$('#saveCommentButtonDisabled').show();
								$('textarea[name='+commentContainer+']').val("");
								$('.charCounter').text(Number(1000));
							break;
							
							default:
							break;
						}
						return false;
					}
				);
			 
		
		function addObjectCommentResponseHandler(objectCommentsResponse) {
			var appendMarkup = "";
			var status = objectCommentsResponse.status;
			$('#objectCommentButtons').hideSpinner();
			if(status) {
				$(objectCommentsResponse.ui).appendTo($('.objectCommentStream'));
			} else {
				// append the response to the bottom of the comments stream
				$(objectCommentsResponse.ui).appendTo($('.objectCommentStream'));
				
				// add bubbleInfo functionality to new comment
				var lastBubbler = $('div.bubbleInfo').find(':last');		
				mbuzzy.bubble.initBubble(lastBubbler);
				
				// update the comment count
				$('.objectCommentCount').html(Number($('.objectCommentCount').html()) + 1);
			}
		}
		
		function getAssetsResponseHandler(assetsResponse) {
            
            $(".news_slider .streamButtons").hideSpinner();
			
            var parentID;
			var isNewStream;

			if (assetsResponse.opaqueData) {
				parentID = assetsResponse.opaqueData.itemID;
				isNewStream = assetsResponse.opaqueData.newStream;
			} 

			if (isNewStream) {
			    $('#'+parentID+' .streamLeftOn').hide();
                $('#'+parentID+' .streamLeftOff').show(); 

				$('#'+parentID+' > div.news_items > div.container ').css("left","0px");
				$('#'+parentID+' > div.news_items > div.container ').css("width","1130px");
				if (assetsResponse.ui.parts) {
					$('#'+parentID+' > div.news_items > div.container ').html(assetsResponse.ui.parts.join());
				} else {
					$('#'+parentID+' > div.news_items > div.container ').html(assetsResponse.ui);
				}
				if(moreLeft) {
		            $('#'+parentID+' .streamRightOff').hide();
                    $('#'+parentID+' .streamRightOn').show();
				} else {
					$('#'+parentID+' .streamRightOn').hide();
                    $('#'+parentID+' .streamRightOff').show();
				}
			} else {
				if (assetsResponse.ui.parts) {
					$('#'+parentID+' > div.news_items > div.container').append(assetsResponse.ui.parts.join());
				} else {
					$('#'+parentID+' > div.news_items > div.container').append(assetsResponse.ui);
				}
                $('#'+parentID+' .streamRightOff').hide();
                $('#'+parentID+' .streamRightOn').show();

                $('#'+parentID+' .streamLeftOff').hide();
                $('#'+parentID+' .streamLeftOn').show();
			}
            
			$('#'+parentID+'').accessNews();
		}
        
        function getStreamType(streamValue) {
            switch(streamValue) {
				case 'All' :
					streamType = new Array(0,3);
					break;
				case 'Photos' :
					streamType = '0';
					break;
				case 'Videos' :
					streamType = '3';
					break;
				default :
					streamType = new Array(0,3);
					break;
			}
            return streamType;
        }
});
inventory = {

	openSendToPhone: function(type,id) {
		mjaxAPI.open.sendToPhone(type,id);
	},

	sendToPhone: function(type,id) {
		var mobile = $("#sendToPhoneMobileNumber").val();
		var device = $("#sendToPhoneDevice").val();
		if (mobile.length > 0) {
			$(".sendToPhoneError").hide();
			mjaxAPI.sendToPhone(type,id,mobile,device,null,inventory.sendToPhoneResponseHandler);
		} else {
			$("#sendToPhoneErrorMobileNumberMissing").show();
		}
	},

	sendToPhoneResponseHandler: function(response) {
		if (response.status) {
			$(".sendToPhoneError").hide();
			if (response.status == "MISSING_MOBILE") {
				$("#sendToPhoneErrorMobileNumberMissing").show();
			} else if (response.status == "INVALID_MOBILE") {
				$("#sendToPhoneErrorMobileInvalid").show();
			} else if (response.status == "UNSUPPORTED_CARRIER") {
				$("#sendToPhoneErrorUnsupportedCarrier").show();
			}
		} else if (response.ui) {
			jQuery.mbox.load(response.ui);
		} else {
			jQuery.mbox.close();
		}
	},

	openEditItem: function(itemID) {
		mjaxAPI.open.editItem(itemID,null,null);
	}

};
$(function()
{
friends = 
{    
    openAddFriend: function(username) {
	    mjaxAPI.open.addFriend(username,null,null);
    },

    addFriend: function(username) {
		$('#mboxDoBtn').showSpinner();
	    mjaxAPI.addFriend(username,$('#addAsFriendMessageText').val(),null,friends.addFriendResponseHandler); 
	    return false;
    },

    addFriendResponseHandler: function(response) {
		//display error div.
	    if ((response.status == "ADD_FRIEND_REQUEST_SENT") && response.ui) {
			$('#mboxDoBtn').hideSpinner();
		    jQuery.mbox.load(response.ui);
	    } else {
		    jQuery.mbox.close();
	    }
	    $('#profileActionAddFriend').hide();
	    $('#profileActionRequestPending').show();
    },

    openRemoveFriend: function(username) {
	    mjaxAPI.open.removeFriend(username,null,null);
    },

    removeFriend: function(username) {
		$('#mboxDoBtn').showSpinner();
	    mjaxAPI.removeFriend(username,null,friends.removeFriendResponseHandler); 
    	return false;
    },

    removeFriendResponseHandler: function(response) {
	    jQuery.mbox.close();
    	$('#profileActionAddFriend').show();
    	$('#profileActionRemoveFriend').hide();
    },

    openIgnoreUsername: function(username) {
	    mjaxAPI.open.ignoreUsername(username,null,null);
    },

    ignoreUsername: function(username) {
		$('#mboxDoBtn').showSpinner();
	    mjaxAPI.ignoreUsername(username,null,null,friends.ignoreUsernameResponseHandler); 
    	return false;
    },

    ignoreUsernameResponseHandler: function(response) {
	    //display error div.
    	if (response.status && response.ui) {
			$('#mboxDoBtn').hideSpinner();
	    	jQuery.mbox.load(response.ui);
    	} else {
	    	jQuery.mbox.close();
		    $('#profileActionBlockUser').hide();
		    $('#profileActionUnblockUser').show();
    	}
    },

    openUnignoreUsername: function(username) {
	    mjaxAPI.open.unignoreUsername(username,null,null);
    },

    unignoreUsername: function(username) {
		$('#mboxDoBtn').showSpinner();
	    mjaxAPI.unignoreUsername(username,null,null,friends.unignoreUsernameResponseHandler); 
    	return false;
    },

    unignoreUsernameResponseHandler: function(response) {
	    jQuery.mbox.close();
	    $('#profileActionBlockUser').show();
	    $('#profileActionUnblockUser').hide();
    },

    openChangeRelationship: function(username,closeHandler) {
	    mjaxAPI.open.changeRelationship(username,null,null);
		jQuery.mbox.bindOnClose(closeHandler);
    },

    changeRelationshipStatus: function(username) {
	    mjaxAPI.changeRelationshipStatus(username,$('#changeRelationshipRelationID').val(),null,friends.changeRelationshipStatusResponseHandler); 
    	return false;
    },

    changeRelationship: function(username) {
		$('#mboxDoBtn').showSpinner();
	    mjaxAPI.changeRelationship(username,$('#changeRelationshipRelationID').val(),$('#changeRelationhipsMessageText').val(),null,friends.changeRelationshipResponseHandler); 
    	return false;
    },

    changeRelationshipResponseHandler: function(response) {
		//display error div.
	    if ((response.status) && response.ui) {
			$('#mboxDoBtn').hideSpinner();
    		jQuery.mbox.load(response.ui);
	    } else {
		    jQuery.mbox.close();
    	}
    },

    changeRelationshipStatusResponseHandler: function(response) {
		//display error div.
	    if ((response.status == "UPGRADE_WITH_BREAKUP_LIST") && response.ui) {
		    $('#upgradeWithBreakupList').html(response.ui);
    		$('#upgradeWithBreakupList').show();
	    } else {
    		$('#upgradeWithBreakupList').hide();
	    }
    },

    openSubscribeUser: function(username) {
	    mjaxAPI.open.subscribeUser(username,null,null);
    },

    subscribeUser: function(username) {
		$('#mboxDoBtn').showSpinner();
	    mjaxAPI.subscribeUser(username,null,friends.subscribeUserResponseHandler); 
    	return false;
    },

    subscribeUserResponseHandler: function(response) {
	    //display error div.
    	if (response.status && response.ui) {
			$('#mboxDoBtn').hideSpinner();
	    	jQuery.mbox.load(response.ui);
    	} else {
	    	jQuery.mbox.close();
		    $('#profileActionSubscribeUser').hide();
    		$('#profileActionUnsubscribeUser').show();
	    }
    },

    openUnsubscribeUser: function(username) {
	    mjaxAPI.open.unsubscribeUser(username,null,null);
    },

    unsubscribeUser: function(username) {
		$('#mboxDoBtn').showSpinner();
	    mjaxAPI.unsubscribeUser(username,null,friends.unsubscribeUserResponseHandler); 
    	return false;
    },

    unsubscribeUserResponseHandler: function(response) {
	    jQuery.mbox.close();
    	$('#profileActionSubscribeUser').show();
	    $('#profileActionUnsubscribeUser').hide();
    }
};



});
messaging = {
	canBuzzUser:false,
	selectedBuzzUserIcon: null,

openBuzzUser: function(username) {
	mjaxAPI.open.buzzUser(username,null,null);
},

selectBuzzUserIcon: function(iter, iconID) {
    for(var i = 0; i < 12; i++) {
        if(i == iter) {
            $('#buzzIcon' + i).addClass('mboxBuzzUserIconsClick');
            $('#buzzIcon' + i).removeClass('mboxBuzzUserIconsRollover');
			messaging.selectedBuzzUSerIcon = iconID;
			messaging.buzzUserEnableButtons();
        } else {
            $('#buzzIcon' + i).addClass('mboxBuzzUserIconsRollover');
            $('#buzzIcon' + i).removeClass('mboxBuzzUserIconsClick');
        }
    }
},

buzzUserTypeMessage: function() {
	var limit = 1000;
	if ($('#buzzUserMessageText').val().length > limit) {
		$('#buzzUserMessageText').val($('#buzzUserMessageText').val().substring(0,limit));
	}
	messaging.buzzUserEnableButtons();
},

buzzUserEnableButtons: function() {
	messaging.canBuzzUser = true;

	if ($('#buzzUserMessageText').val() == "") {
		messaging.canBuzzUser = false;
	} else if ($('#buzzUserMessageText').val().length > 1000) {
		messaging.canBuzzUser = false;
	}
	
	if (messaging.selectedBuzzUSerIcon == null) {
		messaging.canBuzzUser = false;
	}
	if (messaging.canBuzzUser) {
		jQuery.mbox.enableDoButton();
	} else {
		jQuery.mbox.disableDoButton();
	}
},

buzzUser: function(buzzeeusername) {
	$("#buzzError").hide()
	if(!$("#buzzUserMessageText").val()) {
		$("#buzzError").show()
	} else {
		if (messaging.canBuzzUser) {
			$('#mboxDoBtn').showSpinner();
			mjaxAPI.buzzUser(buzzeeusername,messaging.selectedBuzzUSerIcon,$('#buzzUserMessageText').val(),null,messaging.buzzUserResponseHandler); 
			return false;
		} else {
			return false;
		}
	}
},

buzzUserResponseHandler: function(response) {
	if (response.status) {
		$('#mboxDoBtn').hideSpinner();
		if ((response.status == "INVALID_USERNAME") || (response.status == "INTERNAL_SERVER_ERROR")) {
			$("#internalError").show();
		} else {
			$("#operationBlocked").show();
		}
	} else {
		jQuery.mbox.close();
	}
},

openAddCrush: function(username) {
	mjaxAPI.open.addCrush(username,null,null);
},

addCrush: function(username) {
	$('#mboxDoBtn').showSpinner();
	mjaxAPI.addCrush(username,$('#addCrushMessageText').val(),null,messaging.addCrushResponseHandler); 
	return false;
},

addCrushResponseHandler: function(response) {
	if ((response.status) && response.ui) {
		$('#mboxDoBtn').hideSpinner();
		jQuery.mbox.load(response.ui);
	} else {
		jQuery.mbox.close();
	}
},

openNewCrushMessage: function(anonCrushID)
{
	mjaxAPI.open.newMessage(null,
                            anonCrushID, 
                            null, 
                            null, 
                            null, 
                            null);
},

newCrushMessage: function(anonCrushID)
{
	$('#mboxDoBtn').showSpinner();
    mjaxAPI.newMessage(null, 
                       anonCrushID,
                       $('#newMessageSubject').val(),
                       $('#newMessageText').val(),
                       0,
                       null,
                       null,
                       null,
                       messaging.newMessageResponseHandler);
},

openNewMessage: function(username,subject,message,attachmentType,attachmentID) {
	mjaxAPI.open.newMessage(username,null,subject,message,attachmentType,attachmentID,null,null);
},

newMessageLengthCheck: function(messageElID, countElId) {
	var limit = 1000;
	if ($('#'+messageElID).val().length > limit) {
		$('#'+messageElID).val($('#'+messageElID).val().substring(0,limit));
	} else {
		$('#'+countElId).val(limit - $('#'+messageElID).val().length);
	}
},

newMessage: function(username) {
	$('#mboxDoBtn').showSpinner();
	mjaxAPI.newMessage(username,null,$('#newMessageSubject').val(),$('#newMessageText').val(),0,$('#newMessageAttachmentType').val(),$('#newMessageAttachmentID').val(),null,messaging.newMessageResponseHandler);
},

newMessageResponseHandler: function(response) {
	if ((response.status) && response.ui) {
		$('#mboxDoBtn').hideSpinner();
		jQuery.mbox.load(response.ui);
	} else {
		jQuery.mbox.close();
	}
},

sendMessage: function() {
	$('#mboxDoBtn').showSpinner();
	mjaxAPI.sendMessage($('#newMessageSendToUsername').val(),$('#newMessageRecipients').val(),$('#newMessageSubject').val(),$('#newMessageText').val(),0,$('#newMessageAttachmentType').val(),$('#newMessageAttachmentID').val(),null,messaging.sendMessageResponseHandler);
},

sendMessageResponseHandler: function(response) {
	if (response.status && !response.ui) {
		$('#mboxDoBtn').hideSpinner();
		if (response.status == "EMAIL_QUOTA_REACHED") {
			$('#emailQuotaReached').show();
		} else if (response.status == "CAN_NOT_RECEIVE_EMAIL") {
			$('#canNotReveiceEmail').show();
		} else if (response.status == "USER_EMAIL_DISABLED") {
			$('#userEmailDisabled').show();
		}
	} else if (response.ui) {
		jQuery.mbox.load(response.ui);
	} else {
		jQuery.mbox.close();
	}
}


};

mbuzzy.funding = {

	pcMobileBillingSubmitMobile: function(fundingSourceID,fundingOfferKey,fundingOfferClass,referer,returnURL) {
		if (!$('#pcMobileBillingNumber').val()) {
			$('#pcMobileBillingAcceptTandC').hide();
			$('#pcMobileBillingNumberMissing').show();
			return;
		}
		tandc = $('#pcMobileBillingTandC:checked').val();
		if (!tandc) {
			$('#pcMobileBillingNumberMissing').hide();
			$('#pcMobileBillingAcceptTandC').show();
			return;
		}
		rememberMobile = $('#pcMobileBillingRememberMobile:checked').val();
		mjaxAPI.pcMobileBilling($('#pcMobileBillingNumber').val(),rememberMobile,tandc,fundingSourceID,fundingOfferKey,fundingOfferClass,referer,returnURL,null,mbuzzy.funding.pcMobileBillingResponseHandler);
	},

	pcMobileBillingResponseHandler: function(response) {
		if (response.ui) {
			$('#mboxDoBtn').hideSpinner();
			if (response.ui.parts) {
				jQuery.mbox.load(response.ui.parts.join(''));
			} else {
				jQuery.mbox.load(response.ui);
			}
		} else if ((response.data) && response.data.redir) {
			window.location = response.data.redir;
		} else if ((response.data) && response.data.fundingHandler) {
			if (response.data.fundingHandlerType == 'javaScriptFunction') {
				mbuzzy.funding[response.data.fundingHandler](response.data);
			} else if (response.data.fundingHandlerType == 'url') {
				window.location = response.data.fundingHandler + '?m='+response.data.mobile+'&rfr='+response.data.referer+'&r='+response.data.returnURL;
			}
		}
	},

	pcMobileBillingHandler: function(data) {
		mjaxAPI.pcMobileBilling(data.mobile,data.rememberMobile,data.tandc,data.fundingSourceID,data.fundingOfferKey,data.fundingOfferClass,data.referer,data.returnURL,null,mbuzzy.funding.pcMobileBillingResponseHandler);
	},
	
	shoutOutzPCPSMSHandler: function(data) {
		mjaxAPI.shoutOutzPCPSMS(data.mobile,data.rememberMobile,data.fundingOfferKey,data.fundingOfferClass,data.referer,data.returnURL,null,mbuzzy.funding.pcMobileBillingResponseHandler);
	},
	
	shoutOutzEnterPINSubmit: function(mobile,referer,returnURL,buySessionID,offerKey) {
		mjaxAPI.shoutOutzEnterPIN(mobile,$('#shoutOutzPIN').val(),referer,returnURL,buySessionID,offerKey,null,mbuzzy.funding.pcMobileBillingResponseHandler)
	},

	chooseFundingOption: function(fundingOfferClass,referer,returnURL) {
		fundingSourceID = $('input:radio[name=fundingSourceID]:checked').val();
		mjaxAPI.myFundingOptions(fundingSourceID,fundingOfferClass,referer,returnURL,null,mbuzzy.funding.pcMobileBillingResponseHandler)
	},

	chooseFundingOffer: function(mobile,fundingOfferClass,referer,returnURL) {
		fundingOfferKey = $('input:radio[name=fundingOfferKey]:checked').val();
		mjaxAPI.myFundingOffers(mobile,fundingOfferKey,fundingOfferClass,referer,returnURL,null,mbuzzy.funding.pcMobileBillingResponseHandler)
	},

	shoutOutzReplyYIntervalID: 0,
	shoutOutzReplyYIntervalCount: 0,
	shoutOutzReplyYIntervalMaxCount: 120,
	shoutOutzReplyYInterval: 10000,

	shoutOutzReplyYStopChecking: function() {
		jQuery.mbox.unbindOnClose(mbuzzy.funding.shoutOutzReplyYStopChecking);	
		clearInterval(mbuzzy.funding.shoutOutzReplyYIntervalID);
	},

	shoutOutzReplyYStartChecking: function(mobile,buySessionID,offerKey,referer,returnURL) {
		if (mbuzzy.funding.shoutOutzReplyYIntervalID) {
			mbuzzy.funding.shoutOutzReplyYStopChecking();
		}
		jQuery.mbox.bindOnClose(mbuzzy.funding.shoutOutzReplyYStopChecking);	
		mbuzzy.funding.shoutOutzReplyYIntervalID = setInterval('mbuzzy.funding.shoutOutzReplyYIsReplyYReceived(\''+mobile+'\',\''+buySessionID+'\',\''+offerKey+'\',\''+referer+'\',\''+returnURL+'\')',10000);
	},

	shoutOutzReplyYIsReplyYReceived: function(mobile,buySessionID,offerKey,referer,returnURL) {
		if (mbuzzy.funding.shoutOutzReplyYIntervalCount < mbuzzy.funding.shoutOutzReplyYIntervalMaxCount) {
			mjaxAPI.shoutOutzCheckReplyY(mobile,buySessionID,offerKey,referer,returnURL,null,mbuzzy.funding.shoutOutzReplyYResponseHandler);		
			mbuzzy.funding.shoutOutzReplyYIntervalCount++;
		}
	},

	shoutOutzReplyYResponseHandler: function(response) {
		if (response.ui) {
			mbuzzy.funding.shoutOutzReplyYStopChecking();
			if (response.ui.parts) {
				jQuery.mbox.load(response.ui.parts.join(''));
			} else {
				jQuery.mbox.load(response.ui);
			}
		}
	},

	fundingResultOnClose: function() {
		jQuery.mbox.unbindOnClose(mbuzzy.funding.fundingResultClose);	
		refresh();
	},

    buyCoinzMessageOpen: function(resultStatus,offer,r) {
        mjaxAPI.open.buyCoinzMessages(resultStatus,offer,r,null,null);
    }

};

$(function()
{
	mbuzzy.common = {

		initEditHover: function () {
			
			$('.editHoverView').hover(
				function() {
					$(this).css("backgroundImage", "url('http://cache.mbuzzy.com/cache/4.1.8.7/images/editProfHoverBg.png')");
					$('.profileEditLink > a > img', this).attr('src', 'http://cache.mbuzzy.com/cache/4.1.8.7/images/edit_icon_hover.png');
					
					$(this).css("paddingTop", "4px").css("paddingBottom", "4px");
					$(this).find('div.topContainer').css("display", "block");
					$(this).find('div.bottomContainer').css("display", "block");
				},
				function() {
					
					$(this).css("backgroundImage", "none");
					$(this).find('div.topContainer').css("display", "none");
					$(this).find('div.bottomContainer').css("display", "none");
					
					$('.profileEditLink > a > img', this).attr('src', 'http://cache.mbuzzy.com/cache/4.1.8.7/images/edit_icon.png');
				}
			);
		},

		textareaLengthCheck: function(textareaID,lengthLeftID,limit) {
			if ($(''+textareaID+'').val().length > limit) {
				$(''+textareaID+'').val($(''+textareaID+'').val().substring(0,limit));
			} else {
				$(''+lengthLeftID+'').val(limit - $(''+textareaID+'').val().length);
			}
		},

		getCheckedRadioButtonValue: function(radioGroup) {
			for (var i=0; i<radioGroup.length;i++) {
				if (radioGroup[i].checked) {
					return radioGroup[i].value;
				} else {
				}
			}
		},

		toggleViewEdit: function(elementID,level) {
			if ($('#'+elementID+'_view').is(':visible')) {
				if (level == "field") {
					$('.inlineFieldEditor').hide();
					$('.inlineFieldViewer').show();
				} else {
					$('.c_inlineEditor').hide();
					$('.c_inlineViewer').show();
					$('.inlineEditor').hide();
					$('.inlineViewer').show();
				}
				$('#'+elementID+'_view').hide();
				$('#'+elementID+'_edit').show();
			} else {
				$('#'+elementID+'_view').show();
				$('#'+elementID+'_edit').hide();
			}
		},

		editInlineResponseHandler: function(response) {
			$('.inlineDoButton').hideSpinner();
			if (response.opaqueData.elementID && response.ui) {
				if (response.ui.parts) {
					$('#'+response.opaqueData.elementID+'').html('');
					$('#'+response.opaqueData.elementID+'').append(response.ui.parts.join(''));
				} else {
					$('#'+response.opaqueData.elementID+'').html(response.ui);
				}
				mbuzzy.common.initEditHover();
			}
		},

        editInlineResponseHandlerUserData: function(response) {
            var registerBirthdateErrorElement = document.getElementById('registerBirthdateError');
            if ((response['status']=='MUST_BE_OVER_13')&&(registerBirthdateErrorElement)) {
                $('.inlineDoButton').hideSpinner();
                registerBirthdateErrorElement.style.display = 'block';
            } else {
                mbuzzy.common.editInlineResponseHandler(response);
            }
        },

		myPage: null,

		// Common entrypoint for user login.
		// Primary purpose is to provide shared error handling...
		// However, in practice, may not be doable as login context 
		// tends to be different.
		// NOTE: You can call mjaxAPI.loginUser() directly for complete control.
		//
		openLoginUser: function(opaque) {
			var opaqueData = null;
			if (opaque) {
				opaqueData = opaque;
			}
			mjaxAPI.open.loginUser(opaqueData,null);
		},

        mjaxLoginKeyPressHandler: function(event)
        {
            if ((event.keyCode && (event.keyCode == 13)) ||
                (event.which && (event.which == 13)))
            {
                event.preventDefault();
                mbuzzy.common.loginUser();
            }
        },

        loginPageKeyPressHandler: function(event)
        {
            if ((event.keyCode && (event.keyCode == 13)) ||
                (event.which && (event.which == 13)))
            {
                event.preventDefault();
                $('#loginForm').submit();
            }
        },


		loginUser: function(caller) {
			var username;
			var password;
			var opaque = null;
			if (caller == "header") {
				var loginForm = $("#header .loginForm");
				opaque = {'username':loginForm.find(".username").val(),'caller':'header'};
				username = loginForm.find(".username").val();
				password = loginForm.find(".password").val();
			} else {
				opaque = {'caller':'lightbox'};
				$('#mboxLoginUserButton').showSpinner();
				username = $('#loginUsername').val();
				password = $('#loginPassword').val();
			}
			mjaxAPI.loginUser(username,
							  password,
							  opaque,
							  mbuzzy.common.loginUserResponseHandler);
		},

		loginUserResponseHandler: function(response) {
			if (response.status) {
				if (response.status == "CHANGE_PASSWORD") {
					mjaxAPI.open.changePassword();
				} else {
					if (response.opaqueData && response.opaqueData.caller == "header") {
                        $("#header .loginForm .actionHolder").hideSpinner();
						$("#header .loginForm").hide();
						$("#header .notSignedIn").show();
						var opaqueData = {'username': response.opaqueData.username, 'previousStatus':response.status};
						mjaxAPI.open.loginUser(opaqueData);
					} else {
						$('#mboxLoginUserButton').hideSpinner();
						if (response.status == "LOGIN_FAILED") {
							$('#loginFailed').show();
						} else if (response.status == "ALREADY_LOGGED_IN") {
							$('#alreadyLoggedIn').show();
						}
					}
				}
			} else {
                if (response.data && response.data.redir) {
                    window.location = response.data.redir;
                } else {
                    refresh();
                }
			}
		},

		loginChangePassword: function() {
			if ($('#changePasswordOldPassword').val().length == 0) {
				$('#changePasswordMissingOldPassword').show();
			} else if ($('#changePasswordNewPassword').val().length == 0) {
				$('#changePasswordMissingNewPassword').show();
			} else if ($('#changePasswordConfirmNewPassword').val().length == 0) {
				$('#changePasswordMissingConfirmNewPassword').show();
			} else if ($('#changePasswordNewPassword').val() != $('#changePasswordConfirmNewPassword').val()) {
				$('#changePasswordNewPasswordMissmatch').show();
			} else if ($('#changePasswordNewPassword').val().length < 6) {
				$('#changePasswordNewPasswordTooShort').show();
			} else if ($('#changePasswordNewPassword').val().length > 12) {
				$('#changePasswordNewPasswordTooLong').show();
			} else {
				mjaxAPI.changePassword($('#changePasswordOldPassword').val(),$('#changePasswordNewPassword').val(),$('#changePasswordConfirmNewPassword').val(),null,mbuzzy.common.loginChangePasswordResponseHandler);
			}

		},

		loginChangePasswordResponseHandler: function(response) {
			if (response.status == "OLD_PASSWORD_MISSING") {
				$('#changePasswordMissingOldPassword').show();
			} else if (response.status == "OLD_PASSWORD_INCORRECT") {
				$('#changePasswordBadOldPassword').show();
			} else if (response.status == "NEW_PASSWORD_MISSING") {
				$('#changePasswordMissingNewPassword').show();
			} else if (response.status == "CONFIRM_NEW_PASSWORD_MISSING") {
				$('#changePasswordMissingConfirmNewPassword').show();
			} else if (response.status == "NEW_PASSWORD_MISSMATCH") {
				$('#changePasswordNewPasswordMissmatch').show();
			} else if (response.status == "NEW_PASSWORD_TOO_SHORT") {
				$('#changePasswordNewPasswordTooShort').show();
			} else if (response.status == "NEW_PASSWORD_TOO_LONG") {
				$('#changePasswordNewPasswordTooLong').show();
			} else if (response.status == "NEW_PASSWORD_INVALID") {
				$('#changePasswordNewPasswordInvalid').show();
			} else {
				refresh();
			}

		},

		registerUserHandler: function(event) 
        {
			// Reset errors on page
			//        
			$(".registerError").hide();
			
			var validateInput = function()
			{
				var errors = 0
				var username;
				var password;
				var email;  
				var mobile;
				var gender;
				var birthMonth;
                var birthDay;
                var birthYear;
				var zipcode;
				
				if (!(username = $("#registerUsername").val())) 
				{
					$("#registerUsernameError").text("Provide a username").show();
					errors++;
				}
				
				if (!(password = $("#registerPassword").val())) 
				{
					$("#registerPasswordError").text("Provide a password").show();
					errors++;
				}           
				
				if (!(email = $("#registerEmail").val()))
				{
					$("#registerEmailError").text("Provide your email address").show();
					errors++;
				}
				
				if (!(mobile = $("#registerMobile").val()))
				{
					$("#registerMobileError").text("Provide your mobile number").show();
					errors++;
				}
				
				if (!(gender = $("#registerGender").val()))
				{
					$("#registerGenderError").text("Select your gender").show();
					errors++;
				}
                
				if (!(zipcode = $("#registerZipcode").val()))
				{
					$("#registerZipcodeError").text("Provide your zipcode").show();
					errors++;
				}
                
				if (!(birthMonth = $("#registerBirthMonth").val()) ||
					!(birthDay = $("#registerBirthDay").val()) ||
					!(birthYear = $("#registerBirthYear").val()))
				{
					$("#registerBirthdateError").text("Provide month, day and year you were born").show();
					errors++;
				}
                
				return (errors ? false : 
						{username: username,
						 password: password,
						 email: email,
						 mobile: mobile,
						 gender: gender,
						 birthMonth: birthMonth,
						 birthDay: birthDay,
						 birthYear: birthYear,
						 zipcode: zipcode});
			};
			
			var responseHandler = function(response)
			{
				function handleErrors(containerID,
									  errors)
				{
					if (errors)
					{
						var prefix = "";
						var message = "";
						var error = null;
                        
						for (error in errors)
						{
							message += (prefix+errors[error]);
							prefix = ", ";
						}
                        
						if (message && (message != ""))
						{
							$("#"+containerID).text(message).show();
						}
					}
				}
                
                $("#registerSubmit").hideSpinner();
                
                switch (response.status)
                {
                case "REGISTER_FAILURE":
					handleErrors("registerUsernameError", response.data.errors.username);
					handleErrors("registerPasswordError", response.data.errors.password);
					handleErrors("registerEmailError", response.data.errors.email);
					handleErrors("registerMobileError", response.data.errors.mobile);
					handleErrors("registerBirthdateError", response.data.errors.birthdate);
                    
                    break;

                case "INTERNAL_ERROR":
                    // FIXME: What do we do here?
                    break;
                    
                default:
					window.location = response.data.nextURL;
                    break;
				}
			};
            
			if (userInfo = validateInput())
			{
                $(event.currentTarget).showSpinner(false);
                
				mjaxAPI.registerUser({type: "simple",
									  userInfo: userInfo},
									 null,
									 responseHandler);
			}
		},


		openPhoneSetup: function() {
			mjaxAPI.open.phoneSetup(null,null);
			jQuery.mbox.bindOnClose(mbuzzy.common.phoneSetupCloseHandler);
		},

		phoneSetupCloseHandler: function() {
			var opaqueData = {'elementID':'profilePhone'};
			mjaxAPI.getPhoneInfo(opaqueData,mbuzzy.common.editInlineResponseHandler);
			jQuery.mbox.unbindOnClose(mbuzzy.common.phoneSetupCloseHandler);
		},

		phoneSetupEditPhone: function() {
			mjaxAPI.phoneSetup(null,mbuzzy.common.phoneSetupResponseHandler);
		},

		phoneSetupSendSMS: function() {
			if ($('#phoneSetupMobileNumber').val().length > 0) {
				$('.inlineDoButton').showSpinner();
				mjaxAPI.phoneSetupSendSMS($('#phoneSetupMobileNumber').val(),null,mbuzzy.common.phoneSetupResponseHandler);
			}
		},

		phoneSetupPINEntry: function() {
			if ($('#phoneSetupPIN').val().length > 0) {
				$('.inlineDoButton').showSpinner();
				$('#phoneSetupNoSMS').css('visibility','hidden');
				mbuzzy.common.phoneSetupLinkClickedStopChecking();
				mjaxAPI.phoneSetupPINEntry($('#phoneSetupPIN').val(),null,mbuzzy.common.phoneSetupResponseHandler);
			}
		},

		phoneSetupNoSMS: function() {
			$('.inlineDoButton').showSpinner();
			mbuzzy.common.phoneSetupLinkClickedStopChecking();
			mjaxAPI.phoneSetupNoSMS(null,mbuzzy.common.phoneSetupResponseHandler);
		},

		phoneSetupCanNotClickLink: function() {
			$('#phoneSetupWaitForLinkClick').hide();
			$('#phoneSetupEnterPIN').show();
			mbuzzy.common.phoneSetupLinkClickedStopChecking();
		},

		phoneSetupChangeManuf: function() {
			var manufID = $('#phoneSetupManufSelect').val();
			$('.phoneSetupPhoneSelector').hide();
			$('#phoneSetupPhoneSelect_'+manufID+'').show();
			$('#phoneSetupSelectedPhone').hide();
			$('#phoneSetupSelectedPhoneImage').attr('src','http://cache.mbuzzy.com/cache/4.1.8.7/images/invis.gif');
		},

		phoneSetupSelectedDeviceID: 0,

		phoneSetupPhoneClicked: function(deviceID, deviceImageURL) {
			if (deviceID && deviceID != '' && deviceID != 0) {
				mbuzzy.common.phoneSetupSelectedDeviceID = deviceID;
				$('#phoneSetupSelectedPhoneImage').attr('src',deviceImageURL);
				$('#phoneSetupSelectedPhone').show();
				jQuery.mbox.enableDoButton();
			} else {
				mbuzzy.common.phoneSetupSelectedDeviceID = '0';
				$('#phoneSetupSelectedPhone').hide();
				jQuery.mbox.disableDoButton();
			}
		},

		phoneSetupSetDevice: function() {
			if (mbuzzy.common.phoneSetupSelectedDeviceID) {
				$('.inlineDoButton').showSpinner();
				mjaxAPI.phoneSetupSetDevice(mbuzzy.common.phoneSetupSelectedDeviceID,null,mbuzzy.common.phoneSetupResponseHandler);
			}
		},

		phoneSetupLinkClickedIntervalID: 0,
		phoneSetupLinkClickedIntervalCount: 0,
		phoneSetupLinkClickedIntervalMaxCount: 30,
		phoneSetupLinkClickedInterval: 10000,

		phoneSetupLinkClickedStopChecking: function() {
			jQuery.mbox.unbindOnClose(mbuzzy.common.phoneSetupLinkClickedStopChecking);	
			clearInterval(mbuzzy.common.phoneSetupLinkClickedIntervalID);
		},

		phoneSetupLinkClickedStartChecking: function() {
			if (mbuzzy.common.phoneSetupLinkClickedIntervalID) {
				mbuzzy.common.phoneSetupLinkClickedStopChecking();
			}
			jQuery.mbox.bindOnClose(mbuzzy.common.phoneSetupLinkClickedStopChecking);	
			mbuzzy.common.phoneSetupLinkClickedIntervalID = setInterval("mbuzzy.common.phoneSetupIsLinkClicked()",10000);
		},

		phoneSetupIsLinkClicked: function() {
			if (mbuzzy.common.phoneSetupLinkClickedIntervalCount < mbuzzy.common.phoneSetupLinkClickedIntervalMaxCount) {
				mjaxAPI.phoneSetupLinkClicked(null,mbuzzy.common.phoneSetupLinkClickedResponseHandler);		
				mbuzzy.common.phoneSetupLinkClickedIntervalCount++;
			}
		},

		phoneSetupLinkClickedResponseHandler: function(response) {
			if (response.ui) {
				mbuzzy.common.phoneSetupLinkClickedStopChecking();
				if (response.ui.parts) {
					jQuery.mbox.load(response.ui.parts.join(''));
				} else {
					jQuery.mbox.load(response.ui);
				}
			}
		},

		phoneSetupResponseHandler: function(response) {
			$('.inlineDoButton').hideSpinner();
			if (response.ui) {
				if (response.ui.parts) {
					jQuery.mbox.load(response.ui.parts.join(''));
				} else {
					jQuery.mbox.load(response.ui);
				}
			} else {
				jQuery.mbox.close();
			}
		},

		phoneSetupSetRingtone: function() {
			$('.inlineDoButton').showSpinner();
			var opaqueData = {'elementID':'phoneSetupRingtone'};
			mjaxAPI.phoneSetupSetRingtone($('#phoneSetupRingtoneTitleText').val(),$('#phoneSetupRingtoneArtistText').val(),opaqueData,mbuzzy.common.editInlineResponseHandler);

		},
		
		urlEncode: function(str) {
			str = escape(str);
			str = str.replace('+', '%2B');
			str = str.replace('%20', '+');
			str = str.replace('*', '%2A');
			str = str.replace('/', '%2F');
			str = str.replace('@', '%40');
			return str;
		},
		
		// simple function to hide and show two stacked containers
		displayHideContainers: function(hideItem, showItem) {
			$(''+hideItem+'').slideUp("fast");
			$(''+showItem+'').slideDown("slow");
		},

		openMbuzzy2go: function() {
			mjaxAPI.open.mbuzzy2go();
		},

		mbuzzy2go: function() {
			var mobile = $("#mbuzzy2goMobileNumber").val();
			if (mobile.length > 0) {
				$(".mbuzzy2goError").hide();
				mjaxAPI.mbuzzy2go(mobile,null,mbuzzy.common.mbuzzy2goResponseHandler);
			} else {
				$("#mbuzzy2goErrorMobileNumberMissing").show();
			}
		},

		mbuzzy2goResponseHandler: function(response) {
			if (response.status) {
				$(".mbuzzy2goError").hide();
				if (response.status == "MISSING_MOBILE") {
					$("#mbuzzy2goErrorMobileNumberMissing").show();
				} else if (response.status == "INVALID_MOBILE") {
					$("#mbuzzy2goErrorMobileInvalid").show();
				} else if (response.status == "UNSUPPORTED_CARRIER") {
					$("#mbuzzy2goErrorUnsupportedCarrier").show();
				}
			} else if (response.ui) {
				jQuery.mbox.load(response.ui);
			} else {
				jQuery.mbox.close();
			}
		},

    addMbuzzyBookmark: function(path, page_title){

            var url = "http://"+'www.mbuzzy.com'+"/"+path;

            jQuery.mbox.close();
           // alert("url:"+url+",title:"+page_title);



            var browser=navigator.appName;
            var navindex=navigator.userAgent.indexOf('Safari');
            if (navindex != -1 || browser=='Safari') {
                alert('Press ctrl+D to bookmark (Command+D for macs) after you click Add Bookmark.');
            }
            else if(window.sidebar) // Firefox / Mozilla
            {
               // alert("sidebar");
                window.sidebar.addPanel(page_title, url,'');
            }
            else if(window.opera) // Opera
            {
               // alert("opera");   
                var a = document.createElement('A');alert('Press ctrl+D to bookmark (Command+D for macs) after you click Add Bookmark.');
                a.rel = 'sidebar';
                a.target = '_search';
                a.title = page_title;
                a.href = url;
                a.click();
            } else if(window.chrome)// chrome also has window.external, so move above it.
            {
                alert('Press ctrl+D to bookmark (Command+D for macs) after you click Add Bookmark.');
            }
            else if(window.external) // Inept Exploiter
            {
                  //  alert("external");
                    window.external.AddFavorite(url, page_title);
            }
            else if(document.all) { //MSIE
                window.external.AddFavorite( url, title);

            }
            else
            {
                alert('Your web browser appears to not support adding a bookmark via Javascript. Please manually add one via your browser bookmark menu.');
             }


            return false;
        }



    };
    });

/*!
 * jCarousel - Riding carousels with jQuery
 *   http://sorgalla.com/jcarousel/
 *
 * Copyright (c) 2006 Jan Sorgalla (http://sorgalla.com)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Built on top of the jQuery library
 *   http://jquery.com
 *
 * Inspired by the "Carousel Component" by Bill Scott
 *   http://billwscott.com/carousel/
 */

(function($) {
    /**
     * Creates a carousel for all matched elements.
     *
     * @example $("#mycarousel").jcarousel();
     * @before <ul id="mycarousel" class="jcarousel-skin-name"><li>First item</li><li>Second item</li></ul>
     * @result
     *
     * <div class="jcarousel-skin-name">
     *   <div class="jcarousel-container">
     *     <div class="jcarousel-clip">
     *       <ul class="jcarousel-list">
     *         <li class="jcarousel-item-1">First item</li>
     *         <li class="jcarousel-item-2">Second item</li>
     *       </ul>
     *     </div>
     *     <div disabled="disabled" class="jcarousel-prev jcarousel-prev-disabled"></div>
     *     <div class="jcarousel-next"></div>
     *   </div>
     * </div>
     *
     * @method jcarousel
     * @return jQuery
     * @param o {Hash|String} A set of key/value pairs to set as configuration properties or a method name to call on a formerly created instance.
     */
    $.fn.jcarousel = function(o) {
        if (typeof o == 'string') {
            var instance = $(this).data('jcarousel'), args = Array.prototype.slice.call(arguments, 1);
            return instance[o].apply(instance, args);
        } else
            return this.each(function() {
                $(this).data('jcarousel', new $jc(this, o));
            });
    };

    // Default configuration properties.
    var defaults = {
        vertical: false,
        rtl: false,
        start: 1,
        offset: 1,
        size: null,
        scroll: 3,
        visible: null,
        animation: 'normal',
        easing: 'swing',
        auto: 0,
        wrap: null,
        initCallback: null,
        reloadCallback: null,
        itemLoadCallback: null,
        itemFirstInCallback: null,
        itemFirstOutCallback: null,
        itemLastInCallback: null,
        itemLastOutCallback: null,
        itemVisibleInCallback: null,
        itemVisibleOutCallback: null,
        buttonNextHTML: '<div></div>',
        buttonPrevHTML: '<div></div>',
        buttonNextEvent: 'click',
        buttonPrevEvent: 'click',
        buttonNextCallback: null,
        buttonPrevCallback: null,
        itemFallbackDimension: null
    }, windowLoaded = false;

    $(window).bind('load.jcarousel', function() { windowLoaded = true; })

    /**
     * The jCarousel object.
     *
     * @constructor
     * @class jcarousel
     * @param e {HTMLElement} The element to create the carousel for.
     * @param o {Object} A set of key/value pairs to set as configuration properties.
     * @cat Plugins/jCarousel
     */
    $.jcarousel = function(e, o) {
        this.options    = $.extend({}, defaults, o || {});

        this.locked     = false;

        this.container  = null;
        this.clip       = null;
        this.list       = null;
        this.buttonNext = null;
        this.buttonPrev = null;

        // Only set if not explicitly passed as option
        if (!o || o.rtl === undefined)
            this.options.rtl = ($(e).attr('dir') || $('html').attr('dir') || '').toLowerCase() == 'rtl';

        this.wh = !this.options.vertical ? 'width' : 'height';
        this.lt = !this.options.vertical ? (this.options.rtl ? 'right' : 'left') : 'top';

        // Extract skin class
        var skin = '', split = e.className.split(' ');

        for (var i = 0; i < split.length; i++) {
            if (split[i].indexOf('jcarousel-skin') != -1) {
                $(e).removeClass(split[i]);
                skin = split[i];
                break;
            }
        }

        if (e.nodeName.toUpperCase() == 'UL' || e.nodeName.toUpperCase() == 'OL') {
            this.list = $(e);
            this.container = this.list.parent();

            if (this.container.hasClass('jcarousel-clip')) {
                if (!this.container.parent().hasClass('jcarousel-container'))
                    this.container = this.container.wrap('<div></div>');

                this.container = this.container.parent();
            } else if (!this.container.hasClass('jcarousel-container'))
                this.container = this.list.wrap('<div></div>').parent();
        } else {
            this.container = $(e);
            this.list = this.container.find('ul,ol').eq(0);
        }

        if (skin != '' && this.container.parent()[0].className.indexOf('jcarousel-skin') == -1)
            this.container.wrap('<div class=" '+ skin + '"></div>');

        this.clip = this.list.parent();

        if (!this.clip.length || !this.clip.hasClass('jcarousel-clip'))
            this.clip = this.list.wrap('<div></div>').parent();

        this.buttonNext = $('.jcarousel-next', this.container);

        if (this.buttonNext.size() == 0 && this.options.buttonNextHTML != null)
            this.buttonNext = this.clip.after(this.options.buttonNextHTML).next();

        this.buttonNext.addClass(this.className('jcarousel-next'));

        this.buttonPrev = $('.jcarousel-prev', this.container);

        if (this.buttonPrev.size() == 0 && this.options.buttonPrevHTML != null)
            this.buttonPrev = this.clip.after(this.options.buttonPrevHTML).next();

        this.buttonPrev.addClass(this.className('jcarousel-prev'));

        this.clip.addClass(this.className('jcarousel-clip')).css({
            overflow: 'hidden',
            position: 'relative'
        });
        this.list.addClass(this.className('jcarousel-list')).css({
            overflow: 'hidden',
            position: 'relative',
            top: 0,
            margin: 0,
            padding: 0
        }).css((this.options.rtl ? 'right' : 'left'), 0);
        this.container.addClass(this.className('jcarousel-container')).css({
            position: 'relative'
        });
        if (!this.options.vertical && this.options.rtl)
            this.container.addClass('jcarousel-direction-rtl').attr('dir', 'rtl');

        var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null;
        var li = this.list.children('li');

        var self = this;

        if (li.size() > 0) {
            var wh = 0, i = this.options.offset;
            li.each(function() {
                self.format(this, i++);
                wh += self.dimension(this, di);
            });

            this.list.css(this.wh, (wh + 100) + 'px');

            // Only set if not explicitly passed as option
            if (!o || o.size === undefined)
                this.options.size = li.size();
        }

        // For whatever reason, .show() does not work in Safari...
        this.container.css('display', 'block');
        this.buttonNext.css('display', 'block');
        this.buttonPrev.css('display', 'block');

        this.funcNext   = function() { self.next(); };
        this.funcPrev   = function() { self.prev(); };
        this.funcResize = function() { self.reload(); };

        if (this.options.initCallback != null)
            this.options.initCallback(this, 'init');

        if (!windowLoaded && $.browser.safari) {
            this.buttons(false, false);
            $(window).bind('load.jcarousel', function() { self.setup(); });
        } else
            this.setup();
    };

    // Create shortcut for internal use
    var $jc = $.jcarousel;

    $jc.fn = $jc.prototype = {
        jcarousel: '0.2.5'
    };

    $jc.fn.extend = $jc.extend = $.extend;

    $jc.fn.extend({
        /**
         * Setups the carousel.
         *
         * @method setup
         * @return undefined
         */
        setup: function() {
            this.first     = null;
            this.last      = null;
            this.prevFirst = null;
            this.prevLast  = null;
            this.animating = false;
            this.timer     = null;
            this.tail      = null;
            this.inTail    = false;

            if (this.locked)
                return;

            this.list.css(this.lt, this.pos(this.options.offset) + 'px');
            var p = this.pos(this.options.start);
            this.prevFirst = this.prevLast = null;
            this.animate(p, false);

            $(window).unbind('resize.jcarousel', this.funcResize).bind('resize.jcarousel', this.funcResize);
        },

        /**
         * Clears the list and resets the carousel.
         *
         * @method reset
         * @return undefined
         */
        reset: function() {
            this.list.empty();

            this.list.css(this.lt, '0px');
            this.list.css(this.wh, '10px');

            if (this.options.initCallback != null)
                this.options.initCallback(this, 'reset');

            this.setup();
        },

        /**
         * Reloads the carousel and adjusts positions.
         *
         * @method reload
         * @return undefined
         */
        reload: function() {
            if (this.tail != null && this.inTail)
                this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + this.tail);

            this.tail   = null;
            this.inTail = false;

            if (this.options.reloadCallback != null)
                this.options.reloadCallback(this);

            if (this.options.visible != null) {
                var self = this;
                var di = Math.ceil(this.clipping() / this.options.visible), wh = 0, lt = 0;
                this.list.children('li').each(function(i) {
                    wh += self.dimension(this, di);
                    if (i + 1 < self.first)
                        lt = wh;
                });

                this.list.css(this.wh, wh + 'px');
                this.list.css(this.lt, -lt + 'px');
            }

            this.scroll(this.first, false);
        },

        /**
         * Locks the carousel.
         *
         * @method lock
         * @return undefined
         */
        lock: function() {
            this.locked = true;
            this.buttons();
        },

        /**
         * Unlocks the carousel.
         *
         * @method unlock
         * @return undefined
         */
        unlock: function() {
            this.locked = false;
            this.buttons();
        },

        /**
         * Sets the size of the carousel.
         *
         * @method size
         * @return undefined
         * @param s {Number} The size of the carousel.
         */
        size: function(s) {
            if (s != undefined) {
                this.options.size = s;
                if (!this.locked)
                    this.buttons();
            }

            return this.options.size;
        },

        /**
         * Checks whether a list element exists for the given index (or index range).
         *
         * @method get
         * @return bool
         * @param i {Number} The index of the (first) element.
         * @param i2 {Number} The index of the last element.
         */
        has: function(i, i2) {
            if (i2 == undefined || !i2)
                i2 = i;

            if (this.options.size !== null && i2 > this.options.size)
                i2 = this.options.size;

            for (var j = i; j <= i2; j++) {
                var e = this.get(j);
                if (!e.length || e.hasClass('jcarousel-item-placeholder'))
                    return false;
            }

            return true;
        },

        /**
         * Returns a jQuery object with list element for the given index.
         *
         * @method get
         * @return jQuery
         * @param i {Number} The index of the element.
         */
        get: function(i) {
            return $('.jcarousel-item-' + i, this.list);
        },

        /**
         * Adds an element for the given index to the list.
         * If the element already exists, it updates the inner html.
         * Returns the created element as jQuery object.
         *
         * @method add
         * @return jQuery
         * @param i {Number} The index of the element.
         * @param s {String} The innerHTML of the element.
         */
        add: function(i, s) {
            var e = this.get(i), old = 0, n = $(s);

            if (e.length == 0) {
                var c, e = this.create(i), j = $jc.intval(i);
                while (c = this.get(--j)) {
                    if (j <= 0 || c.length) {
                        j <= 0 ? this.list.prepend(e) : c.after(e);
                        break;
                    }
                }
            } else
                old = this.dimension(e);

            if (n.get(0).nodeName.toUpperCase() == 'LI') {
                e.replaceWith(n);
                e = n;
            } else
                e.empty().append(s);

            this.format(e.removeClass(this.className('jcarousel-item-placeholder')), i);

            var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null;
            var wh = this.dimension(e, di) - old;

            if (i > 0 && i < this.first)
                this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - wh + 'px');

            this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) + wh + 'px');

            return e;
        },

        /**
         * Removes an element for the given index from the list.
         *
         * @method remove
         * @return undefined
         * @param i {Number} The index of the element.
         */
        remove: function(i) {
            var e = this.get(i);

            // Check if item exists and is not currently visible
            if (!e.length || (i >= this.first && i <= this.last))
                return;

            var d = this.dimension(e);

            if (i < this.first)
                this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + d + 'px');

            e.remove();

            this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) - d + 'px');
        },

        /**
         * Moves the carousel forwards.
         *
         * @method next
         * @return undefined
         */
        next: function() {
            this.stopAuto();

            if (this.tail != null && !this.inTail)
                this.scrollTail(false);
            else
                this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'last') && this.options.size != null && this.last == this.options.size) ? 1 : this.first + this.options.scroll);
        },

        /**
         * Moves the carousel backwards.
         *
         * @method prev
         * @return undefined
         */
        prev: function() {
            this.stopAuto();

            if (this.tail != null && this.inTail)
                this.scrollTail(true);
            else
                this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'first') && this.options.size != null && this.first == 1) ? this.options.size : this.first - this.options.scroll);
        },

        /**
         * Scrolls the tail of the carousel.
         *
         * @method scrollTail
         * @return undefined
         * @param b {Boolean} Whether scroll the tail back or forward.
         */
        scrollTail: function(b) {
            if (this.locked || this.animating || !this.tail)
                return;

            var pos  = $jc.intval(this.list.css(this.lt));

            !b ? pos -= this.tail : pos += this.tail;
            this.inTail = !b;

            // Save for callbacks
            this.prevFirst = this.first;
            this.prevLast  = this.last;

            this.animate(pos);
        },

        /**
         * Scrolls the carousel to a certain position.
         *
         * @method scroll
         * @return undefined
         * @param i {Number} The index of the element to scoll to.
         * @param a {Boolean} Flag indicating whether to perform animation.
         */
        scroll: function(i, a) {
            if (this.locked || this.animating)
                return;

            this.animate(this.pos(i), a);
        },

        /**
         * Prepares the carousel and return the position for a certian index.
         *
         * @method pos
         * @return {Number}
         * @param i {Number} The index of the element to scoll to.
         */
        pos: function(i) {
            var pos  = $jc.intval(this.list.css(this.lt));

            if (this.locked || this.animating)
                return pos;

            if (this.options.wrap != 'circular')
                i = i < 1 ? 1 : (this.options.size && i > this.options.size ? this.options.size : i);

            var back = this.first > i;

            // Create placeholders, new list width/height
            // and new list position
            var f = this.options.wrap != 'circular' && this.first <= 1 ? 1 : this.first;
            var c = back ? this.get(f) : this.get(this.last);
            var j = back ? f : f - 1;
            var e = null, l = 0, p = false, d = 0, g;

            while (back ? --j >= i : ++j < i) {
                e = this.get(j);
                p = !e.length;
                if (e.length == 0) {
                    e = this.create(j).addClass(this.className('jcarousel-item-placeholder'));
                    c[back ? 'before' : 'after' ](e);

                    if (this.first != null && this.options.wrap == 'circular' && this.options.size !== null && (j <= 0 || j > this.options.size)) {
                        g = this.get(this.index(j));
                        if (g.length)
                            e = this.add(j, g.clone(true));
                    }
                }

                c = e;
                d = this.dimension(e);

                if (p)
                    l += d;

                if (this.first != null && (this.options.wrap == 'circular' || (j >= 1 && (this.options.size == null || j <= this.options.size))))
                    pos = back ? pos + d : pos - d;
            }

            // Calculate visible items
            var clipping = this.clipping();
            var cache = [];
            var visible = 0, j = i, v = 0;
            var c = this.get(i - 1);

            while (++visible) {
                e = this.get(j);
                p = !e.length;
                if (e.length == 0) {
                    e = this.create(j).addClass(this.className('jcarousel-item-placeholder'));
                    // This should only happen on a next scroll
                    c.length == 0 ? this.list.prepend(e) : c[back ? 'before' : 'after' ](e);

                    if (this.first != null && this.options.wrap == 'circular' && this.options.size !== null && (j <= 0 || j > this.options.size)) {
                        g = this.get(this.index(j));
                        if (g.length)
                            e = this.add(j, g.clone(true));
                    }
                }

                c = e;
                var d = this.dimension(e);
                if (d == 0) {
                    throw new Error('jCarousel: No width/height set for items. This will cause an infinite loop. Aborting...');
                }

                if (this.options.wrap != 'circular' && this.options.size !== null && j > this.options.size)
                    cache.push(e);
                else if (p)
                    l += d;

                v += d;

                if (v >= clipping)
                    break;

                j++;
            }

             // Remove out-of-range placeholders
            for (var x = 0; x < cache.length; x++)
                cache[x].remove();

            // Resize list
            if (l > 0) {
                this.list.css(this.wh, this.dimension(this.list) + l + 'px');

                if (back) {
                    pos -= l;
                    this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - l + 'px');
                }
            }

            // Calculate first and last item
            var last = i + visible - 1;
            if (this.options.wrap != 'circular' && this.options.size && last > this.options.size)
                last = this.options.size;

            if (j > last) {
                visible = 0, j = last, v = 0;
                while (++visible) {
                    var e = this.get(j--);
                    if (!e.length)
                        break;
                    v += this.dimension(e);
                    if (v >= clipping)
                        break;
                }
            }

            var first = last - visible + 1;
            if (this.options.wrap != 'circular' && first < 1)
                first = 1;

            if (this.inTail && back) {
                pos += this.tail;
                this.inTail = false;
            }

            this.tail = null;
            if (this.options.wrap != 'circular' && last == this.options.size && (last - visible + 1) >= 1) {
                var m = $jc.margin(this.get(last), !this.options.vertical ? 'marginRight' : 'marginBottom');
                if ((v - m) > clipping)
                    this.tail = v - clipping - m;
            }

            // Adjust position
            while (i-- > first)
                pos += this.dimension(this.get(i));

            // Save visible item range
            this.prevFirst = this.first;
            this.prevLast  = this.last;
            this.first     = first;
            this.last      = last;

            return pos;
        },

        /**
         * Animates the carousel to a certain position.
         *
         * @method animate
         * @return undefined
         * @param p {Number} Position to scroll to.
         * @param a {Boolean} Flag indicating whether to perform animation.
         */
        animate: function(p, a) {
            if (this.locked || this.animating)
                return;

            this.animating = true;

            var self = this;
            var scrolled = function() {
                self.animating = false;

                if (p == 0)
                    self.list.css(self.lt,  0);

                if (self.options.wrap == 'circular' || self.options.wrap == 'both' || self.options.wrap == 'last' || self.options.size == null || self.last < self.options.size)
                    self.startAuto();

                self.buttons();
                self.notify('onAfterAnimation');

                // This function removes items which are appended automatically for circulation.
                // This prevents the list from growing infinitely.
                if (self.options.wrap == 'circular' && self.options.size !== null)
                    for (var i = self.prevFirst; i <= self.prevLast; i++)
                        if (i !== null && !(i >= self.first && i <= self.last) && (i < 1 || i > self.options.size))
                            self.remove(i);
            };

            this.notify('onBeforeAnimation');

            // Animate
            if (!this.options.animation || a == false) {
                this.list.css(this.lt, p + 'px');
                scrolled();
            } else {
                var o = !this.options.vertical ? (this.options.rtl ? {'right': p} : {'left': p}) : {'top': p};
                this.list.animate(o, this.options.animation, this.options.easing, scrolled);
            }
        },

        /**
         * Starts autoscrolling.
         *
         * @method auto
         * @return undefined
         * @param s {Number} Seconds to periodically autoscroll the content.
         */
        startAuto: function(s) {
            if (s != undefined)
                this.options.auto = s;

            if (this.options.auto == 0)
                return this.stopAuto();

            if (this.timer != null)
                return;

            var self = this;
            this.timer = setTimeout(function() { self.next(); }, this.options.auto * 1000);
        },

        /**
         * Stops autoscrolling.
         *
         * @method stopAuto
         * @return undefined
         */
        stopAuto: function() {
            if (this.timer == null)
                return;

            clearTimeout(this.timer);
            this.timer = null;
        },

        /**
         * Sets the states of the prev/next buttons.
         *
         * @method buttons
         * @return undefined
         */
        buttons: function(n, p) {
            if (n == undefined || n == null) {
                var n = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'first') || this.options.size == null || this.last < this.options.size);
                if (!this.locked && (!this.options.wrap || this.options.wrap == 'first') && this.options.size != null && this.last >= this.options.size)
                    n = this.tail != null && !this.inTail;
            }

            if (p == undefined || p == null) {
                var p = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'last') || this.first > 1);
                if (!this.locked && (!this.options.wrap || this.options.wrap == 'last') && this.options.size != null && this.first == 1)
                    p = this.tail != null && this.inTail;
            }

            var self = this;

            this.buttonNext[n ? 'bind' : 'unbind'](this.options.buttonNextEvent + '.jcarousel', this.funcNext)[n ? 'removeClass' : 'addClass'](this.className('jcarousel-next-disabled')).attr('disabled', n ? false : true);
            this.buttonPrev[p ? 'bind' : 'unbind'](this.options.buttonPrevEvent + '.jcarousel', this.funcPrev)[p ? 'removeClass' : 'addClass'](this.className('jcarousel-prev-disabled')).attr('disabled', p ? false : true);

            if (this.options.buttonNextCallback != null && this.buttonNext.data('jcarouselstate') != n) {
                this.buttonNext.each(function() { self.options.buttonNextCallback(self, this, n); }).data('jcarouselstate', n);
            }

            if (this.options.buttonPrevCallback != null && (this.buttonPrev.data('jcarouselstate') != p)) {
                this.buttonPrev.each(function() { self.options.buttonPrevCallback(self, this, p); }).data('jcarouselstate', p);
            }
        },

        /**
         * Notify callback of a specified event.
         *
         * @method notify
         * @return undefined
         * @param evt {String} The event name
         */
        notify: function(evt) {
            var state = this.prevFirst == null ? 'init' : (this.prevFirst < this.first ? 'next' : 'prev');

            // Load items
            this.callback('itemLoadCallback', evt, state);

            if (this.prevFirst !== this.first) {
                this.callback('itemFirstInCallback', evt, state, this.first);
                this.callback('itemFirstOutCallback', evt, state, this.prevFirst);
            }

            if (this.prevLast !== this.last) {
                this.callback('itemLastInCallback', evt, state, this.last);
                this.callback('itemLastOutCallback', evt, state, this.prevLast);
            }

            this.callback('itemVisibleInCallback', evt, state, this.first, this.last, this.prevFirst, this.prevLast);
            this.callback('itemVisibleOutCallback', evt, state, this.prevFirst, this.prevLast, this.first, this.last);
        },

        callback: function(cb, evt, state, i1, i2, i3, i4) {
            if (this.options[cb] == undefined || (typeof this.options[cb] != 'object' && evt != 'onAfterAnimation'))
                return;

            var callback = typeof this.options[cb] == 'object' ? this.options[cb][evt] : this.options[cb];

            if (!$.isFunction(callback))
                return;

            var self = this;

            if (i1 === undefined)
                callback(self, state, evt);
            else if (i2 === undefined)
                this.get(i1).each(function() { callback(self, this, i1, state, evt); });
            else {
                for (var i = i1; i <= i2; i++)
                    if (i !== null && !(i >= i3 && i <= i4))
                        this.get(i).each(function() { callback(self, this, i, state, evt); });
            }
        },

        create: function(i) {
            return this.format('<li></li>', i);
        },

        format: function(e, i) {
            var e = $(e), split = e.get(0).className.split(' ');
            for (var j = 0; j < split.length; j++) {
                if (split[j].indexOf('jcarousel-') != -1) {
                    e.removeClass(split[j]);
                }
            }
            e.addClass(this.className('jcarousel-item')).addClass(this.className('jcarousel-item-' + i)).css({
                'float': (this.options.rtl ? 'right' : 'left'),
                'list-style': 'none'
            }).attr('jcarouselindex', i);
            return e;
        },

        className: function(c) {
            return c + ' ' + c + (!this.options.vertical ? '-horizontal' : '-vertical');
        },

        dimension: function(e, d) {
            var el = e.jquery != undefined ? e[0] : e;

            var old = !this.options.vertical ?
                (el.offsetWidth || $jc.intval(this.options.itemFallbackDimension)) + $jc.margin(el, 'marginLeft') + $jc.margin(el, 'marginRight') :
                (el.offsetHeight || $jc.intval(this.options.itemFallbackDimension)) + $jc.margin(el, 'marginTop') + $jc.margin(el, 'marginBottom');

            if (d == undefined || old == d)
                return old;

            var w = !this.options.vertical ?
                d - $jc.margin(el, 'marginLeft') - $jc.margin(el, 'marginRight') :
                d - $jc.margin(el, 'marginTop') - $jc.margin(el, 'marginBottom');

            $(el).css(this.wh, w + 'px');

            return this.dimension(el);
        },

        clipping: function() {
            return !this.options.vertical ?
                this.clip[0].offsetWidth - $jc.intval(this.clip.css('borderLeftWidth')) - $jc.intval(this.clip.css('borderRightWidth')) :
                this.clip[0].offsetHeight - $jc.intval(this.clip.css('borderTopWidth')) - $jc.intval(this.clip.css('borderBottomWidth'));
        },

        index: function(i, s) {
            if (s == undefined)
                s = this.options.size;

            return Math.round((((i-1) / s) - Math.floor((i-1) / s)) * s) + 1;
        }
    });

    $jc.extend({
        /**
         * Gets/Sets the global default configuration properties.
         *
         * @method defaults
         * @return {Object}
         * @param d {Object} A set of key/value pairs to set as configuration properties.
         */
        defaults: function(d) {
            return $.extend(defaults, d || {});
        },

        margin: function(e, p) {
            if (!e)
                return 0;

            var el = e.jquery != undefined ? e[0] : e;

            if (p == 'marginRight' && $.browser.safari) {
                var old = {'display': 'block', 'float': 'none', 'width': 'auto'}, oWidth, oWidth2;

                $.swap(el, old, function() { oWidth = el.offsetWidth; });

                old['marginRight'] = 0;
                $.swap(el, old, function() { oWidth2 = el.offsetWidth; });

                return oWidth2 - oWidth;
            }

            return $jc.intval($.css(el, p));
        },

        intval: function(v) {
            v = parseInt(v);
            return isNaN(v) ? 0 : v;
        }
    });

})(jQuery);

function css_browser_selector(u){var ua = u.toLowerCase(),is=function(t){return ua.indexOf(t)>-1;},g='gecko',w='webkit',s='safari',h=document.getElementsByTagName('html')[0],b=[(!(/opera|webtv/i.test(ua))&&/msie\s(\d)/.test(ua))?('ie ie'+RegExp.$1):is('firefox/2')?g+' ff2':is('firefox/3')?g+' ff3':is('gecko/')?g:/opera(\s|\/)(\d+)/.test(ua)?'opera opera'+RegExp.$2:is('konqueror')?'konqueror':is('chrome')?w+' chrome':is('applewebkit/')?w+' '+s+(/version\/(\d+)/.test(ua)?' '+s+RegExp.$1:''):is('mozilla/')?g:'',is('j2me')?'mobile':is('iphone')?'iphone':is('ipod')?'ipod':is('mac')?'mac':is('darwin')?'mac':is('webtv')?'webtv':is('win')?'win':is('freebsd')?'freebsd':(is('x11')||is('linux'))?'linux':'','js']; c = b.join(' '); h.className += ' '+c; return c;}; css_browser_selector(navigator.userAgent);

$(function()
{
    mbuzzy.header =
    {
        loginHandler: function(event)
        {
            $(event.currentTarget).parents(".loginForm").find(".actionHolder").showSpinner(false);
            mbuzzy.common.loginUser("header");
        },

        logoutHandler: function(event)
        {
            var responseHandler = function(response)
            {
                if (response.data && response.data.redir)
                {
                    window.location = response.data.redir;
                }
                else
                {
                    refresh();
                }
            };

            $(event.currentTarget).parents(".userNav").find(".actionHolder").showSpinner(false);
            mjaxAPI.logoutUser(null, responseHandler);
        },

        activateUserNav: function(username)
        {
            // Alas, nothing is dynamic right now...
            // Get all nav data via page refresh!
            //
            refresh();
        },

        showLoginHandler: function(event)
        {
            $("#header .notSignedIn").hide();

            var loginForm = $("#header .loginForm");

			            // Reset username
            //
            // var username = loginForm.find(".username");
            // var init;

            // if (init = username.attr("init"))
            // {
            //     username.val(init);
            //     username.removeAttr("init");
            // }

            // Reset password
            //
            //loginForm.find(".password").val("");

            loginForm.show();
        },

        cancelLoginHandler: function(event)
        {
            $("#header .loginForm").hide();
            $("#header .notSignedIn").show();
            $("#headerLoginUsername").val('')
            $("#headerLoginPassword").val('')
        },

        loginKeyPressHandler: function(event)
        {
            if ((event.keyCode && (event.keyCode == 13)) ||
                (event.which && (event.which == 13)))
            {
                event.preventDefault();
                $("#header .submitLogin").click();
            }
        },

        inputHelperHandler: function(event,userAction)
        {
        	// get the on / off classes
        	var inputHelperEmptyClass = $(event.currentTarget).attr("mb_emptyClass")
        	var inputHelperHasTextClass = $(event.currentTarget).attr("mb_hasTextClass")
        	var inputHelperDefaultValue = $(event.currentTarget).attr("mb_defaultValue")

        	if(!inputHelperEmptyClass) {
        		var inputHelperEmptyClass = "emptyInputHelper"
        	}
        	if(!inputHelperHasTextClass) {
        		var inputHelperHasTextClass = "hasTextInputHelper"
        	}

        	if(inputHelperDefaultValue == $(event.currentTarget).val()) {
        		var hasDefaultText = true;
        	} else {
        		var hasDefaultText = false;
        	}

        	if(hasDefaultText && userAction == "focus") {
    			// clear the field
    			$(event.currentTarget).val('')
    			// add the hasText class
    			$(event.currentTarget).addClass(inputHelperHasTextClass)
    			// remove the empty class
    			$(event.currentTarget).removeClass(inputHelperEmptyClass)
        	} else if(!$(event.currentTarget).val() && userAction == "blur") {
        		// remove the hasText class
        		$(event.currentTarget).removeClass(inputHelperHasTextClass)
        		// add the empty class
        		$(event.currentTarget).addClass(inputHelperEmptyClass)
        		// set field value to default
        		$(event.currentTarget).val(inputHelperDefaultValue)
        	}
        },

		searchFormStayOpen: false,
		searchMenuWaitForMouseOut: false,

		searchMenuClicked: function() {
			mbuzzy.header.searchFormInputFocusRemove();
			mbuzzy.header.closeSubNav();
			mbuzzy.header.searchMenuWaitForMouseOut = true;
		},

		searchFormInputFocus: function() {
			mbuzzy.header.searchFormStayOpen = true;
		},

		searchFormInputFocusRemove: function() {
			mbuzzy.header.searchFormStayOpen = false;
		},

    	showSubNav: function(id){
			if (!mbuzzy.header.searchMenuWaitForMouseOut &&
			    !$('#headerTab'+id).hasClass('onMenu2')) {
					mbuzzy.header.searchFormInputFocusRemove();
					mbuzzy.header.closeSubNav();
					$('#subNav'+id).show();
					$('#headerTab'+id).addClass('onMenu2');
			}
		},

		closeSubNav: function(){
			mbuzzy.header.searchMenuWaitForMouseOut = false;
			if (!mbuzzy.header.searchFormStayOpen) {
				$('.c_subNav').hide();
				$('.onMenu2').removeClass('onMenu2');
			}
		}


    };

    // Add click/hover handlers
    //
    $("body").click(function(event)
    {
        $("#header .menu:visible").not("[menu="+$(event.target).closest(".menuTitle").attr("menu")+"]").hide();
    });

    // Add click/hover handlers
    //
    $("#headerBrowse > a").click(function(event)
    {
        event.preventDefault();
        $("#headerBrowseMenu").toggle();
    });

    $("#headerMobile > a").click(function(event)
    {
        event.preventDefault();
        $("#headerMobileMenu").toggle();
    });

    $("#headerSearch > a").click(function(event)
    {
        event.preventDefault();

        // Reset search box fields
        //
        var searchBox = $("#headerSearchBox");

        searchBox.find(".keywords").val("");
        searchBox.find(".category option[selected]").removeAttr("selected");
        searchBox.find(".category option:first").attr("selected", 1);

        $("#headerSearchBox").toggle();
    });

    $("#header .searchForm .submit").click(function(event)
    {
		event.preventDefault();
		if ($('#headerSearchKeyword').val().length > 0) {
			$("#headerSearchForm").submit();
		}
	});

    $("#headerInbox").click(function(event)
    {
        event.preventDefault();
        $("#headerInboxMenu").toggle();
    });

    $("#header .showLogin").click(function(event)
	{
		event.preventDefault();
		mbuzzy.header.showLoginHandler(event);
	});

    $("#header .cancelLogin").click(function(event)
    {
        event.preventDefault();
        mbuzzy.header.cancelLoginHandler(event);
    });

    $("#header .submitLogin").click(function(event)
	{
	    event.preventDefault();
	    mbuzzy.header.loginHandler(event);
	});

    $("#header .logout").click(function(event)
   {
       event.preventDefault();
       mbuzzy.header.logoutHandler(event);
   });

    //$("#header .loginForm .username").focus(function(event)
    //{
    //    if (!$(event.currentTarget).attr("init"))
    //    {
    //        $(event.currentTarget).attr("init", $(event.currentTarget).val());
    //        $(event.currentTarget).val("");
    //    }
    //});

    $(".inputHelper").focus(function(event)
    {
    	mbuzzy.header.inputHelperHandler(event,"focus")
    });

    $(".inputHelper").blur(function(event)
    {
    	mbuzzy.header.inputHelperHandler(event,"blur")
    });

    $("#header .loginForm .input").keypress(mbuzzy.header.loginKeyPressHandler);
    $("#header .searchForm input").focus(mbuzzy.header.searchFormInputFocus);
    $("#header .searchForm select").focus(mbuzzy.header.searchFormInputFocus);
    $("#header .menuTitle").click(mbuzzy.header.searchMenuClicked);

    jQuery(document).ready(function() {
        jQuery("#headerCarousel").jcarousel({
            visible: 10,
            scroll: 10
        });
        jQuery("#headerCarousel").css({visibility:"visible"});
    });

});


rate = {

openRateUser: function(username) {
	mjaxAPI.open.rateUser(username,null,null);
},

rateUser: function(username) {
	$('#mboxDoBtn').showSpinner();
	mjaxAPI.rateUser(username,$('#rateUserRatingID').val(),null,rate.rateUserResponseHandler); 
	return false;
},

rateUserResponseHandler: function(response) {
		//display error div.
	if ((response.status) && response.ui) {
		$('#mboxDoBtn').hideSpinner();
		jQuery.mbox.load(response.ui);
	} else {
		jQuery.mbox.close();
	}
}

};


profile = {

useProfileStyle: function(colorArray) {
	var bgImage = colorArray['styleName'].toLowerCase();
	var bgImagePath = "url('http://cache.mbuzzy.com/cache/4.1.8.7/images/corners/"+bgImage+".png')";
	var color1 = colorArray['color1'];
	var color2 = colorArray['color2'];
	var color3 = colorArray['color3'];
	
	/* COLOR 1 */
	
	/* main headers */
	$('.catHeader').css("backgroundImage", bgImagePath);
	$('.catHeader > div.catHeader_body').css("backgroundImage", bgImagePath);
	$('.catHeader div.catHeader_body > div.catHeader_body_inner').css("backgroundImage", bgImagePath);
	/* end main headers */
	
	/* side headers */
	$('.catSideHeader').css("backgroundImage", bgImagePath);
	$('.catSideHeader > div.catSideHeader_body').css("backgroundImage", bgImagePath);
	$('.catSideHeader > div.catSideHeader_body > div.catSideHeader_body_inner').css("backgroundImage", bgImagePath);
	/* end side headers */
	
	/* END COLOR 1 */
	
	/* COLOR 2 */
	
	/* profile headers */
	$('.profileHeaders').css("backgroundColor", color2);
	$('.profileHeaders > div > div.hasBackgroundColor').css("backgroundColor", color2);
	$('.profileHeaders > div.topContainer > div > div').css("backgroundColor", color2);
	$('.profileHeaders > div.bottomContainer > div > div').css("backgroundColor", color2);
	/* profile headers */
	
	/* info panel tabs */
	$('.statsCat').css("backgroundColor", color2);
	$('.statsCat > div > div.hasBackgroundColor').css("backgroundColor", color2);
	$('.statsCat > div.topContainer > div > div').css("backgroundColor", color2);
	$('.statsCat > div.bottomContainer > div > div').css("backgroundColor", color2);
	/* end info panel tabs */
	
	$('.profileStatsdivTail').css("backgroundColor", color2);
	$('.profileStatsdivTail').css("borderLeftColor", color2);
	
	/* END COLOR 2 */
	
	/* COLOR 3 */
	
	/* buzzContainerOwner */
	$('.buzzContainerOwner').css("backgroundColor", color3);
	$('.buzzContainerOwner > div > div.hasBackgroundColor').css("backgroundColor", color3);
	$('.buzzContainerOwner > div.topContainer > div > div').css("backgroundColor", color3);
	$('.buzzContainerOwner > div.bottomContainer > div > div').css("backgroundColor", color3);
	/* buzzContainerOwner */
	
	/* body */
	if(color3) {
		$('body').css("backgroundColor", color3);
	}
	else {
		$('body').css("backgroundColor", color2);
	}
	/* end body */
	
	/* END COLOR 3 */
},

openProfileStylePicker: function() {
	$('.settingsTable').fadeIn();
	$('.settingsSectionTray').animate({ height : "77px" }, "slow");
	$('#settings').css("display", "none");
},

closeProfileStylePicker: function(ui) {
	$('.settingsTable').slideUp();
	$('.settingsSectionTray').slideUp();
	$('#settings').css("display", "block");
	if (ui) {
		if (ui.parts) {
			$('#profileStylePicker').html(ui.parts.join(''));
		} else {
			$('#profileStylePicker').html(ui);
		}
	} else {
		profile.previewProfileStyle(profile.currentActiveStyleID);
	}
},

currentActiveStyleID: 0,

previewProfileStyle: function(styleID) {
	if (styleID) {
		$('input[name=gstyle]').val([""+styleID+""]);
	} 
	styleID = mbuzzy.common.getCheckedRadioButtonValue(document.getElementById('profileStylePickerForm').elements['gstyle']);
	var style;
	if (styleID == -1) {
		style = {"color1": $('#profileStyleCustomColor1').val(),"color2":$('#profileStyleCustomColor2').val(),"color3":$('#profileStyleCustomColor3').val()}; 
	} else {
		style = profileStyleColors[styleID]; 
	}
	profile.useProfileStyle(style); 
	return true;
},

setProfileStyle: function() {
	$('#stylePickerSaveButton').showSpinner();
	profile.previewProfileStyle();
	var styleID = mbuzzy.common.getCheckedRadioButtonValue(document.getElementById('profileStylePickerForm').elements['gstyle']);
	if (styleID == -1) {
		mjaxAPI.setProfileCustomStyle($('#profileStyleCustomColor1').val(),$('#profileStyleCustomColor2').val(),$('#profileStyleCustomColor3').val(),null,profile.setProfileStyleResponseHandler); 
	} else {
		mjaxAPI.setProfileStyle(styleID,null,profile.setProfileStyleResponseHandler); 
	}
	return true;
},

setProfileStyleResponseHandler: function(response) {
	if (response.status) {
		$('#stylePickerSaveButton').hideSpinner();
		//display error div.
		if ((response.status == "INVALID_CUSTOM_COLOR1") || 
			(response.status == "INVALID_CUSTOM_COLOR2") ||
			(response.status == "INVALID_CUSTOM_COLOR3")) {
			$("#invalidCustomColor").slideDown();
		} else if (response.status == "INVALID_STYLE_ID") {
			$("#invalidStyleID").slideDown();
		}
	} else {
		profile.closeProfileStylePicker(response.ui);
//		refresh(); 
	}
},

setMood: function(useBubbleLabel) {
	$('.inlineDoButton').showSpinner();
	var opaqueData = {'elementID':'profileMood','useBubbleLabel':useBubbleLabel};
	mjaxAPI.setMood($('#moodID').val(),profile.selectedMoodIconID,opaqueData,mbuzzy.common.editInlineResponseHandler);
},

toggleMoodEmoticonList: function() {
	if ($('#profileMoodEmoticonList').is(':visible')) {
		$('#profileMoodEmoticonList').fadeOut("slow");
		$('#profileMoodEmoteIconEdit').addClass('fauxSelect');
		$('#profileMoodEmoteIconEdit').removeClass('fauxSelectClick');
	} else {        
        // Load emoticons or display menu?
        //
        if ($("#profileMoodEmoticonList .fauxSelectOptionsIcons").length > 0) {
		    $('#profileMoodEmoticonList').fadeIn("slow");
		    $('#profileMoodEmoteIconEdit').addClass('fauxSelectClick');
		    $('#profileMoodEmoteIconEdit').removeClass('fauxSelect');            
        } else {
            var completionHandler = function(response) {
                if (!response.status) {
                    $("#profileMoodEmoticonList").prepend(((response.ui && response.ui.parts) ? 
                                                           response.ui.parts.join("") : 
                                                           response.ui));

            		$('#profileMoodEmoticonList').fadeIn("slow");
            		$('#profileMoodEmoteIconEdit').addClass('fauxSelectClick');
            		$('#profileMoodEmoteIconEdit').removeClass('fauxSelect');                    
                }
            };
            
            mjaxAPI.getEmoticons(null, completionHandler);            
        }
	}
},

selectedMoodIconID: null,

selectMoodIcon: function(iconID) {
	profile.selectedMoodIconID = iconID;
	profile.toggleMoodEmoticonList();
	$('#selectedMoodEmoticon').attr("class", $('#moodEmoticon_'+iconID+'').attr('class')).show();
	$('#profileMoodEmoteIconEdit .selectEmoticon').hide();        
	$('#profileMoodEmoteIconEdit .changeEmoticon').show();
},

setRightNow: function() {
	$('.inlineDoButton').showSpinner();
	var opaqueData = {'elementID':'profileRightNow'};
	mjaxAPI.setRightNow($('#rightNowAction').val(),opaqueData,mbuzzy.common.editInlineResponseHandler);
},

setProfileInfo: function() {
	$('.inlineDoButton').showSpinner();
	var opaqueData = {'elementID':'profileInfo'};
	var gender = mbuzzy.common.getCheckedRadioButtonValue(document.getElementById('profileInfoEditForm').elements['profileInfoGender']);
    var registerBirthdateErrorElement = document.getElementById('registerBirthdateError');
    if(registerBirthdateErrorElement) {
       registerBirthdateErrorElement.style.display = 'none';
    }
	mjaxAPI.setProfileInfo(gender,$('#profileInfoBdayDay').val(),$('#profileInfoBdayMonth').val(), $('#profileInfoBdayYear').val(), $('#profileInfoCity').val(), $('#profileInfoState').val(), $('#profileInfoCountry').val(), $('#profileInfoZipCode').val(), $('#profileInfoAboutMeText').val(), opaqueData,mbuzzy.common.editInlineResponseHandlerUserData);
},

setExtendedProfileInfo: function() {
	$('.inlineDoButton').showSpinner();
	var opaqueData = {'elementID':'extendedProfileInfo'};
	mjaxAPI.setExtendedProfileInfo( $('#extendedProfileInfoJobID').val(), $('#extendedProfileInfoEthnicityID').val(), $('#extendedProfileInfoBodyTypeID').val(), $('#extendedProfileInfoHeightFeet').val(), $('#extendedProfileInfoHeightInches').val(), $('#extendedProfileInfoMaritalStatusID').val(), $('#extendedProfileInfoSexualOrientationID').val(), $('#extendedProfileInfoReligionID').val(), $('#extendedProfileInfoSmokeID').val(), $('#extendedProfileInfoDrinkID').val(), $('#extendedProfileInfoChildrenID').val(), $('#extendedProfileInfoEducationID').val(), $('#extendedProfileInfoHairColor').val(), $('#extendedProfileInfoEyeColor').val(), $('#extendedProfileInfoWeight').val(), opaqueData,mbuzzy.common.editInlineResponseHandler);

},

setProfileFavorites: function() {
	$('.inlineDoButton').showSpinner();
	var opaqueData = {'elementID':'profileFavorites'};
	mjaxAPI.setProfileFavorites( $('#profileFavoriteBands').val(), $('#profileFavoriteBooks').val(), $('#profileFavoriteMovies').val(), opaqueData,mbuzzy.common.editInlineResponseHandler);

},

openChangeRelationship: function(username) {
	friends.openChangeRelationship(username,profile.changeRelationshipsClosed);
},

changeRelationshipsClosed: function() {
	jQuery.mbox.unbindOnClose(profile.changeRelationshipsClosed);
	var opaqueData = {'elementID':'profileRelationships'};
	mjaxAPI.getMyRelationships('profile',opaqueData,mbuzzy.common.editInlineResponseHandler);
},

initEditHover: function() {
    $('.editHoverView').hover(function() {
        $(this).css("backgroundImage", "url('http://cache.mbuzzy.com/cache/4.1.8.7/images/editProfHoverBg.png')");        
        $('.profileEditLink > a > img', this).removeClass('edit_icon').addClass('edit_hover_icon');
        
    }, function() {    
        $(this).css("backgroundImage", "none");
        $('.profileEditLink > a > img', this).removeClass('edit_hover_icon').addClass('edit_icon');
    });
	
	// media slider
	$('.profileManageMedia').hover(function(){
        // only highlight the background color of the corresponding media slider, important if multiple exist on a page
        parentId = $(this).parents(".news_slider").attr("id");        
		$('#'+parentId+' .news_items').css("backgroundColor", "#BEBEBE");
		$('.profileEditMedia', this).attr('src', 'http://cache.mbuzzy.com/cache/4.1.8.7/images/edit_icon_hover.png');
	}, 
	function(){
		$('.news_items').css("backgroundColor", "#EEEEEE");
		$('.profileEditMedia', this).attr('src', 'http://cache.mbuzzy.com/cache/4.1.8.7/images/edit_icon.png');
	});
	
	// top friends
	$('.profileManageFriends').hover(function(){
											  
		var columnCount = 3,
			rowCount = parseInt ( $('.profileFriends_wrapper > div').length / columnCount ), 									
			rowRemainder = parseInt( $('.profileFriends_wrapper > div').length % columnCount ),
			parentMargin = 10,
			topPadding = 8,
			thumbBorder = 3,
			thumbHeight = 105, // 90px + 6px top and bottom border + 9px bottom margin
			bottomPadding = 9;
			
		if(rowRemainder > 0){
			rowCount = rowCount + Number(1);
		}
		
		var hoverHeight = parentMargin + topPadding + ( thumbHeight * rowCount);

		$('.topFriendsBgHover')
		.css({'backgroundColor' : '#BEBEBE', 'height' : hoverHeight+'px'});
		
		$('.profileEditMedia', this).attr('src', 'http://cache.mbuzzy.com/cache/4.1.8.7/images/edit_icon_hover.png');
	}, 
	function(){
		$('.topFriendsBgHover').css("background", "none");
		$('.profileEditMedia', this).attr('src', 'http://cache.mbuzzy.com/cache/4.1.8.7/images/edit_icon.png');
	});
},

rightNowEditClick: function() {
	$('.rightNowHoverView > #profileEditLink > .editLink_rightNow').click(function() {
		$('.rightNowHoverView').css("background", "none");							 
	});
},

vgoodsHover: function(){
	$('.vgoods_single').hover(function() {
		$('.vgoods_tooltip', this).css("display", "block");							   
	}, 
	function(){
		$('.vgoods_tooltip', this).css("display", "none");	
	});
},

editSecretStashDescription: function(){

    $('textarea[maxlength]').bind('keyup mouseup', function(){
        profile.checkLimit(this);
    });

    $('textarea[maxlength]').bind('paste', function(){
        //need to add a delay to allow time for the text to paste into the textarea.
        //used 'setTimeout' because our jquery version is too old to use 'delay'
        var element=this;
        setTimeout(function(){profile.checkLimit(element)}, 300);
    });

},

checkLimit: function(element) {
    //get the limit from maxlength attribute
    var limit = parseInt($(element).attr('maxlength'));
    //get the current text inside the textarea
    var text = $(element).val();
    //count the number of characters in the text
    var chars = text.length;

    //check if there are more characters then allowed
    if(chars > limit){
        //and if there are use substr to get the text before the limit
        var new_text = text.substr(0, limit);
        //and change the current text with the new text
        $(element).val(new_text);
    }
}

};

$(function() {
    // Init edit on hover...
    // 
    profile.initEditHover(); 
	profile.rightNowEditClick();
	profile.vgoodsHover();
    profile.editSecretStashDescription();
});favorites = {

addFavoriteItem: function(type,refID) {
	if ((type.length > 0) && (refID.length > 0)) {
		mjaxAPI.addFavoriteItem(type,refID,null,null);
	}
},

addFavoriteText: function() {
	if ($('#profileDiggingAddText').val().length > 0) {
		var opaqueData = {'elementID':'profileDigging'};
		mjaxAPI.addFavoriteText($('#profileDiggingAddText').val(),opaqueData,mbuzzy.common.editInlineResponseHandler);
	}
},

editFavorite: function(favid) {
	if ($('#profileDiggingText_'+favid).val().length > 0) {
		var opaqueData = {'elementID':'profileDigging'};
		mjaxAPI.editFavoriteText(favid,$('#profileDiggingText_'+favid).val(),opaqueData,mbuzzy.common.editInlineResponseHandler);
	}
},

removeFavorite: function(favid) {
	var opaqueData = {'elementID':'profileDigging'};
	mjaxAPI.removeFavorite(favid,opaqueData,mbuzzy.common.editInlineResponseHandler);

}

};

$(function() {			 
	
		profile.initEditHover();

		$('input[name=gstyle]').click( function() {
			 profile.previewProfileStyle();
			 return true;
			 }
		);		
});

$(function() {
    mbuzzy.buzzStream = {
        containerID: null,

        setContainerID: function(containerID)
        {
            this.containerID = containerID;
        },
        
        getContainerID: function()
        {
            return this.containerID;
        },
        
        getContainer: function()
        {
            return $("#"+this.getContainerID());
        },        
        
        getConfig: function()
        {
            return this.config;            
        },
        
        setConfig: function(config)
        {
            this.config = config;
        },
                
        eventHandler: function(response)
        {
            var opaque = response.opaqueData;

            if (opaque.containerID)
            {
                // FIXME: Argh, ridiculous that we have to do this ourself!
                //
                var events = (response.ui ? 
                              (response.ui.parts ? 
                               response.ui.parts.join("") : 
                               response.ui) : 
                              $("#"+mbuzzy.buzzStream.getContainerID()+" .templates .empty").clone(true).show());
                        
                // Clear event stream when switching type
                //
                if (opaque.lastEventID)
                {                    
                    // Prepend new events
                    //
                    $("#"+opaque.containerID+" .buzzHolder").prepend(events);
                }
                else
                {
                    $("#"+opaque.containerID+" .buzzHolder").empty().html(events);
                }
            
                // FIXME: Need to conditionalize init.
                //        Only new events should be processed.
                //        By re-initializing all events, we reset
                //        up/down pager and viewing window.
                //
                mbuzzy.buzzStream.activate();
            }
        },
    
        getHomeBuzzStreamEvents: function(lastEventID,
                                          limit, 
                                          page,
                                          containerID)
        {
		    var sendData = {afterEventID: lastEventID,
                            limit: limit,
                            page: page};
            var opaque = {containerID: containerID,
                          lastEventID: lastEventID};
                          
            mjaxAPI.getHomeBuzzStreamEvents(sendData,
                                            opaque,
                                            this.eventHandler);
        },
           
        getMyBuzzStreamEvents: function(actionKey,
                                        category,
                                        lastEventID,
                                        limit,
                                        page,
                                        containerID)
        {
		    var sendData = {actionKey: actionKey,
                            category: category,
                            afterEventID: lastEventID,
                            limit: limit,
                            page: page};
            var opaque = {containerID: containerID,
                          lastEventID: lastEventID};

            mjaxAPI.getMyBuzzStreamEvents(sendData,
                                          opaque,
                                          this.eventHandler);
        },
    
        getProfileBuzzStreamEvents: function(profileUsername,
                                             lastEventID,
                                             limit,
                                             page,
                                             containerID)
        {
		    var sendData = {profileUsername: profileUsername, 
                            afterEventID: lastEventID,
                            limit: limit,
                            page: page};
            var opaque = {containerID: targetID,
                          lastEventID: lastEventID};                        
        
            mjaxAPI.getProfileBuzzStreamEvents(sendData,
                                               opaque,
                                               this.eventHandler);
        },
        
        hideCommentsHandler: function(event)
        {
            var buzzEvent = $(event.currentTarget).parents(".event");
            var comments = buzzEvent.find(".commentList");
            var count = comments.find(".comment").length;

            buzzEvent.find(".lessComments").hide();

            comments.find(".comment").each(function(index)
            {
                if ((index >= 2) && 
                    (index < Number(count-1)))
                {
                    $(this).hide();
                }
                
                if (index == 2)
                {
                    var moreComments = buzzEvent.find(".moreComments");

                    if (!moreComments.length)
                    {
                        moreComments = $("#"+mbuzzy.buzzStream.getContainerID()+" .templates .moreComments").clone(true)
                                                                                                            .show();
                        moreComments.find(".count").text(Number(count-3));
                        
                        $(this).before(moreComments)
                    }                                       
                }
            });
            
            buzzEvent.find(".moreComments").show();
        },
        
        showCommentsHandler: function(event)
        {
            var buzzEvent = $(event.currentTarget).parents(".event");
            var lessComments = buzzEvent.find(".lessComments");
            
            if (lessComments.length)
            {
                buzzEvent.find(".moreComments").hide();
                
                buzzEvent.find(".commentList .comment").each(function(index)
                {
                    $(this).show();
                });                
  
                lessComments.show();
            }
            else
            {
                var opaque = {eventID: buzzEvent.attr("eventID")};
            
                var completionHandler = function(response)
                {
                    var container = mbuzzy.buzzStream.getContainer();
                    var opaque = response.opaqueData;
                    var event = container.find(".event[eventID="+opaque.eventID+"]");
                    
                    event.find(".moreComments .actionHolder").hideSpinner();
                                        
                    if (!response.status)
                    {
                        var lessComments = container.find(".templates .lessComments").clone(true).show();
                    
                        event.find(".commentList").html(((response.ui && response.ui.parts) ? 
                                                         response.ui.parts.join("") :
                                                         response.ui))
                                                  .after(lessComments);

                        event.find(".bubbleInfo").each(function(index)
                        {
                            mbuzzy.bubble.initBubble($(this));
                        });
                    }
                };
                
                buzzEvent.find(".moreComments .actionHolder").showSpinner(false);
                mjaxAPI.getBuzzStreamComments(buzzEvent.attr("eventID"),
                                              opaque,
                                              completionHandler);
            }
        },
        
        showVisitorsHandler: function(event)
        {
            var visitors = $(event.currentTarget).parents(".visitors");
            var slider = visitors.find(".slider");

            var limit = slider.attr("limit");
            var start = ((event.data.page*limit)-limit);

            visitors.find(".visitor").hide().slice(start, (Number(start)+Number(limit))).show();
            slider.attr("page", event.data.page);
        },
        
        bindTemplateHandlers: function()
        {
            var container = $("#"+this.getContainerID());
         
            container.find(".templates .commentForm .postComment").click(function(event)
                                                                         {
                                                                             event.preventDefault();
                                                                             mbuzzy.buzzStream.postCommentHandler(event);
                                                                         });
                                                  
             container.find(".templates .commentForm .cancelComment").click(function(event)
                                                                            {
                                                                                event.preventDefault();
                                                                                mbuzzy.buzzStream.cancelCommentHandler(event);
                                                                            });
                                                  
             container.find(".templates .showComments").click(function(event)
                                                              {
                                                                  event.preventDefault();
                                                                  mbuzzy.buzzStream.showCommentsHandler(event);
                                                              });
                                                  
             container.find(".templates .hideComments").click(function(event)
                                                              {
                                                                  event.preventDefault();
                                                                  mbuzzy.buzzStream.hideCommentsHandler(event);
                                                              });
        },
        
        bindActionHandlers: function()
        {
            var container = $("#"+this.getContainerID());
            
            container.find(".event .visitors .slider a").click(function(event)
                                                               {
                                                                   event.preventDefault();
                                                      
                                                                   var page = $(event.currentTarget).parents(".slider").attr("page");
                                                                   
                                                                   if ($(event.currentTarget).hasClass("prevProfile"))
                                                                   {
                                                                       event.data = {page: (page-1)};
                                                                   }
                                                                   else if ($(event.currentTarget).hasClass("nextProfile"))
                                                                   {
                                                                       event.data = {page: (Number(page)+1)};
                                                                   }                                                      
                                                      
                                                                   mbuzzy.buzzStream.showVisitorsHandler(event);
                                                               });
                                                               
            container.find(".addComment").click(function(event)
                                                {
                                                    event.preventDefault();
                                                    mbuzzy.buzzStream.addCommentHandler(event);
                                                });
                                                  
            container.find(".event .showComments").click(function(event)
                                                         {
                                                             event.preventDefault();
                                                             mbuzzy.buzzStream.showCommentsHandler(event);
                                                         });
        },
        
        addCommentHandler: function(event)
        {
            var buzzEvent = $(event.currentTarget).parents(".event");
            
            if (!buzzEvent.find(".commentForm").length)
            {
                var commentForm = $("#"+mbuzzy.buzzStream.getContainerID()+" .templates .commentForm").clone(true).show();
                buzzEvent.append(commentForm);
            }
        },
        
        cancelCommentHandler: function(event)
        {
            $(event.currentTarget).parents(".commentForm").remove();
        },
        
        postCommentHandler: function(event)
        {
            var buzzEvent = $(event.currentTarget).parents(".event");
            var commentForm = buzzEvent.find(".commentForm");
            var opaque = {eventID: buzzEvent.attr("eventID")};
            
            var completionHandler = function(response)
            {
                var container = mbuzzy.buzzStream.getContainer();
                var opaque = response.opaqueData;
                var event = container.find(".event[eventID="+opaque.eventID+"]");
                var commentForm = event.find(".commentForm");
                
                commentForm.find(".actionHolder").hideSpinner();

                if (!response.status)
                {
                    var comments = event.find(".commentList");
                    
                    if (!comments.length)
                    {
                        comments = container.find(".templates .commentList").clone(true).show();
                        commentForm.before(comments);
                        comments = event.find(".commentList");
                    }
                    
                    var comment = container.find(".templates .comment").clone(true).show();
//                    comment.find(".message").text(commentForm.find(".message").val());
                    comment.find(".message").text(response.data.message);
                    
                    commentForm.remove();
                    comments.append(comment);                    
                }
                else
                {
                    commentForm.find(".status").html(container.find(".templates .internalError")
                                                              .clone(true)
                                                              .show())
                                               .show();
                }
            };
            
            commentForm.find(".actionHolder").showSpinner(false);

            mjaxAPI.addBuzzStreamComment(buzzEvent.attr("eventID"),
                                         commentForm.find(".message").val(),
                                         opaque,
                                         completionHandler);
        },
    
        styleEvents: function()
        {
        },
        
        init: function(containerID)
        {
            this.setContainerID(containerID);

            var buzzStream = $("#"+this.getContainerID());
            var config = {loop: (buzzStream.attr("loop") ?
                                 {timeout: buzzStream.attr("timeout"),
                                  mode: buzzStream.attr("mode")} : null), 
                          limit: buzzStream.attr("limit"),
                          animate: buzzStream.attr("animate")};
            this.setConfig(config);
            
            this.bindTemplateHandlers();
            this.activate();
        },
    
        activate: function()
        {
            var config = this.getConfig();
            
            this.styleEvents();
            this.bindActionHandlers();            

            var loop = config.loop;

            // FIXME: Deal with paging options...
            //
            // If no page size defined (limit), 
            // disable paging altogether and display all events.
            // Apologies below for the egregious "return" below, argh!
            // Dont have time to make this code pretty right now.
            //
            if (!config.limit)
            {
                $('.bubbleInfo').each(function()
                {
                    mbuzzy.bubble.initBubble($(this));
                });
                
                return;
            }
            
            var $limitBuzzer = config.limit;

            $currentBuzzIndex = ($limitBuzzer - 1);
            $topBuzzIndex = 0;
            $bottomBuzzIndex = ($limitBuzzer - 1);
            $buzzer = $('ul.buzzHolder');
            $streamCount = $buzzer.find("> li").length;
            $lastBuzzerIndex = $streamCount - 1;
            
            if (loop) 
            {
                $moreBuzzDown = true;
                $moreBuzzUp = true;
            }
            else 
            {
                $moreBuzzDown = false;
                $moreBuzzUp = false;
            }
            
            // Cache items in data array (both markup and height)
            //
            var items = [];
            $buzzer.find('> li').each(function(i)
            {
                items[i] = new Array();
                items[i].push('<li>' + $(this).html() + '</li>', $(this).height());
            });
            
            // Show the first "page"
            //
/*            if ((($streamCount > 0) && ($streamCount >= ($limitBuzzer-3))) || loop)*/ 
            if (($streamCount > 0) && ($streamCount >= ($limitBuzzer-3)))
            {
                $moreBuzzDown = true;
                
                // Clip overflowing items
                //
                $buzzer.find('> li').filter(':gt(' + ($limitBuzzer - 1) + ')').remove();
                
                if (loop)
                {
                    if (loop.mode) 
                    {
                        $("#buzzStreamNav").hide();
                    }
                    else 
                    {
                        $("#buzzUpOn").show();
                        $("#buzzUpOff").hide();
                        
                        $("#buzzDownOn").show();
                        $("#buzzDownOff").hide();
                    }
                }
                else 
                {
                    $("#buzzUpOff").show();
                    $("#buzzUpOn").hide();
                    
                    $("#buzzDownOn").show();
                    $("#buzzDownOff").hide();
                }
                
                // When down button is clicked hide, then remove top item.
                // Expand container down to height of the next item.
                // Attach the next item with an opacity of 0 and fade in the item for a nice visual effect
                //
                var buzzAnimHeight;
                
                $('.buzzDown').click(function(event) {
                    var loop = mbuzzy.buzzStream.getConfig().loop;

                    if ($moreBuzzDown)
                    {
                        if (loop) 
                        {
                            if (!(($currentBuzzIndex + Number(1)) < $streamCount)) 
                            {
                                var nextBuzzIndex = 0;
                            }
                            else 
                            {
                                var nextBuzzIndex = ($currentBuzzIndex + Number(1));
                            }
                        }
                        else 
                        {
                            var nextBuzzIndex = $currentBuzzIndex + Number(1);
                        }
                        
                        if (nextBuzzIndex <= $lastBuzzerIndex)
                        {
                            if (mbuzzy.buzzStream.getConfig().animate)
                            {                            
                                var $insertBuzz = $(items[nextBuzzIndex][0])
                                                      .css({height: 0,
                                                            opacity: 0,
                                                            display: 'none'})
                                                      .appendTo($buzzer);
                                                               
                                if ($.browser.msie)
                                {
//                                    buzzAnimHeight = Number(items[nextBuzzIndex][1] + 8);
                                    buzzAnimHeight = Number(items[nextBuzzIndex][1] + 3);                                    
//                                  buzzAnimHeight = Number(items[nextBuzzIndex][1]);
                                }
                                else 
                                {
                                    buzzAnimHeight = Number(items[nextBuzzIndex][1]);
                                }
                            }
                            else
                            {
                                var $insertBuzz = $(items[nextBuzzIndex][0]).appendTo($buzzer);                            
                            }
                        }
                        else
                        {
                            $insertBuzz = null;
                        }
                        
                        if (mbuzzy.buzzStream.getConfig().animate)
                        {
                            $buzzer.find('> li:first').animate({opacity: 0}, 350)
                                                      .animate({height: 0}, 350, function() 
                            {
                                if ($insertBuzz)
                                {
                                    $insertBuzz.animate({height: buzzAnimHeight}, 350)
                                               .animate({opacity: 1}, 350);
                            
                                    $insertBuzz.find(".bubbleInfo").each(function(index)
                                    {
                                        mbuzzy.bubble.initBubble($(this));
                                    });
                                }

                                $(this).remove();
                            });
                        }
                        else
                        {
                            $buzzer.find('> li:first').remove();                        
                        }
                                                
                        if (loop) 
                        {
                            var top = ($topBuzzIndex + 1);
                            if (top > ($streamCount - 1)) 
                            {
                                $topBuzzIndex = 0;
                            }
                            else 
                            {
                                $topBuzzIndex = top;
                            }
                        }
                        else 
                        {
                            $topBuzzIndex += 1;
                        }
                        
                        $currentBuzzIndex = nextBuzzIndex;
                        $bottomBuzzIndex = $currentBuzzIndex;
                        
                        if (!loop) 
                        {
                        
                            // Enable the up button
                            //
                            $("#buzzUpOn").show();
                            $("#buzzUpOff").hide();
                            $moreBuzzUp = true;                            
                            
                            if ($currentBuzzIndex == Number($lastBuzzerIndex + Number(3)))
                            {
                                // Disable down button
                                //
                                $("#buzzDownOff").show();
                                $("#buzzDownOn").hide();
                                $moreBuzzDown = false;
                            }
                        }
                    }
                    else 
                    {
                        if (!loop) 
                        {
                            $currentBuzzIndex = $lastBuzzerIndex;
                            $bottomBuzzIndex = $lastBuzzerIndex;
                            $moreBuzzDown = false;                            
                        }
                    }
                    
					return false;
                });
                
                // When up button is clicked
                // the container should slide down
                // animating to the height of the next item + 15
                //
                $('.buzzUp').click(function() {
                    var loop = mbuzzy.buzzStream.getConfig().loop;

                    if (($currentBuzzIndex > $limitBuzzer - 1) || loop) 
                    {
                        if (loop) 
                        {
                            var prev = Number($topBuzzIndex - 1);
                            if (prev < 0) 
                            {
                                var prevBuzzIndex = ($streamCount - 1);
                            }
                            else 
                            {
                                var prevBuzzIndex = prev;
                            }
                        }
                        else
                        {
                            var prevBuzzIndex = $topBuzzIndex-1;
                        }
                        
                        $topBuzzIndex = prevBuzzIndex;

                        if (mbuzzy.buzzStream.getConfig().animate)
                        {
                            var $insertBuzz = $(items[prevBuzzIndex][0]).css({height: 0,
                                                                              opacity: 0,
                                                                              display: 'none'})
                                                                        .prependTo($buzzer);
                                                                                                
                            if ($.browser.msie)
                            {
//                                buzzAnimHeight = Number(items[prevBuzzIndex][1] + 8);
                                buzzAnimHeight = Number(items[prevBuzzIndex][1] + 3);
//                              buzzAnimHeight = Number(items[prevBuzzIndex][1]);
                            }
                            else 
                            {
                                buzzAnimHeight = Number(items[prevBuzzIndex][1]);
                            }
                        }
                        else
                        {
                            var $insertBuzz = $(items[prevBuzzIndex][0]).prependTo($buzzer);                            
                        }
                        
                        if ($currentBuzzIndex <= $lastBuzzerIndex)
                        {
                            if (mbuzzy.buzzStream.getConfig().animate)
                            {
                                $buzzer.find('> li:last').animate({opacity: 0}, 350)
                                                         .animate({height: 0}, 350, function()
                                {
                                    $insertBuzz.animate({height: buzzAnimHeight}, 350)
                                               .animate({opacity: 1}, 350);
                            
                                    $insertBuzz.find(".bubbleInfo").each(function(index)
                                    {
                                        mbuzzy.bubble.initBubble($(this));
                                    });
                            
                                    $(this).remove();
                                });                                                                                                                                                             
                            }
                            else
                            {
                                $buzzer.find('> li:last').remove();                                
                            }
                        }
                        else
                        {
                            if (mbuzzy.buzzStream.getConfig().animate)
                            {
                                $insertBuzz.animate({height: buzzAnimHeight}, 350)
                                           .animate({opacity: 1}, 350);
                            }
                        }                                                                      
                        
                        if (loop) 
                        {
                            var bottom = Number($bottomBuzzIndex - 1);
                            if (bottom < 0) 
                            {
                                $currentBuzzIndex = ($streamCount - 1);
                            }
                            else 
                            {
                                $currentBuzzIndex = bottom;
                            }
                        }
                        else 
                        {
                            $currentBuzzIndex -= 1;
                        }
                        
                        $bottomBuzzIndex = $currentBuzzIndex;
                        
                        if (!loop) 
                        {
                            $("#buzzDownOn").show();
                            $("#buzzDownOff").hide();
                            $moreBuzzDown = true;
                            
                            if ($currentBuzzIndex == ($limitBuzzer - 1)) 
                            {
                                // Disable up button
                                //
                                $("#buzzUpOff").show();
                                $("#buzzUpOn").hide();
                                $moreBuzzUp = false;                               
                            }
                        }
                    }
                    else 
                    {
                        if (!loop) 
                        {
                            $moreBuzzUp = false;
                        }
                    }
                    
					return false;
                });
                
                if (loop && !mbuzzy.buzzStream.getTimer())               
                {
                    mbuzzy.buzzStream.setTimer(window.setTimeout("mbuzzy.buzzStream.rotate()", 0));
                }
            }
				            				
            $('.bubbleInfo').each(function()
            {
                mbuzzy.bubble.initBubble($(this));
            });
            
/*            if (loop && !mbuzzy.buzzStream.getTimer())               
            {
                mbuzzy.buzzStream.setTimer(window.setTimeout("mbuzzy.buzzStream.rotate()", 0));
            }*/
        },
        
        rotate: function()
        {
            // Cancel any outstanding timer
            //
            var timer = mbuzzy.buzzStream.getTimer();

            if (timer)
            {
                window.clearTimeout(timer);
                mbuzzy.buzzStream.setTimer(null);
            }

            // Manually trigger up/down click event rotate buzzstream
            //
            var loop = mbuzzy.buzzStream.getConfig().loop;

            if (loop)
            {
                var button = ((loop.mode == 1) ? "buzzUp" : ((loop.mode == 2) ? "buzzDown" : "buzzUp"));
            
                $("."+button).triggerHandler("click");
            
                // Install new timer for next rotate
                //
                mbuzzy.buzzStream.setTimer(window.setTimeout("mbuzzy.buzzStream.rotate()", loop.timeout));
            }
        },
        
        getTimer: function()
        {
            return this.timer;
        },
        
        setTimer: function(timer)
        {
            this.timer = timer;
        },        
        
        timer: null,
        config: null
    };
    
    mbuzzy.buzzStream.init("buzzStream");
});




/*
	- Set a limit
	- Get the total number of comments
	- If commentCount > limit show "view all" button
	- Display new comment at the top of the list

*/

$(function () {
				
	/* comments logic */
	// global comments variables
	var $comments = $('ul.commentHolder');
		//$limitComment $commentCount -- variables are now set in mod_comments.tpl
	
	//If commentCount > limit show "view all" button
	if((typeof($commentCount) != 'undefined')  && (typeof($limitComment) != 'undefined') && ($commentCount > $limitComment)) {
		$('.viewMoreComments').css("display", "block");
	}	
		
	// adding and saving a new comment
	$('.commentButtons').click(
		function() {
			var currentButton = $(this).attr('name').split('_');
			var commentAction = currentButton[0];
			var commentContainer = currentButton[1];
			//var buttonClass = $(this).attr('class').split(' ');
			//var prependResponseTo = buttonClass[1];
			switch(commentAction) {
				case 'save':
					var newMessage = $('textarea[name='+commentContainer+']').val().substring(0,1000);
					$('#addProfileCommentButtons').showSpinner();
					mjaxAPI.addProfileComment(userName,newMessage,null,addCommentResponseHandler);
					$('textarea[name='+commentContainer+']').val("")
					$('.commentTray').fadeOut().css("height", "0");
				break;
				
				case 'cancel' :
				case 'close' :
					$('.commentTray').fadeOut().css("height", "0");
					$('textarea[name='+commentContainer+']').val("")
					$('#saveCommentButtonEnabled').hide();
					$('#saveCommentButtonDisabled').show();
				break;
				
				default:
				break;
			}
			return false;
		}
	);
	
	var commentsItems = [];
	$comments.find('> li').each(function (i) {
			commentsItems[i] = new Array();															
			commentsItems[i].push('<li>' + $(this).html() + '</li>', $('div.comments', this).height());
	});
	
	//show the first items based on the limit provided
	if ((typeof($commentCount) != 'undefined')  && (typeof($limitComment) != 'undefined') && ($commentCount > $limitComment)) 
	{
		// show the "view all" button
	}
	
	function appendNewComment(newCommentDiv) {
		
		$(newCommentDiv).appendTo($('.commentTemp'));
		$('.commentTemp').append(newCommentDiv);
		commentsItems.unshift(new Array());
		commentsItems[0].push('<li>'+$('.commentTemp > li').html()+'</li>', 
		$('.commentTemp > li > div.comments:first').height());
	
		var $insertComment = $(commentsItems[0][0])
		.css({
				opacity : 0,
				display : 'none'
		})
		.prependTo($comments);
		
		$insertComment.css({float : 'left', height: 'auto', display: 'block'}).animate({opacity : 1 });
		
		if($.browser.msie) {
			$insertComment.css("marginBottom", "15px");
		}
		
		$insertComment.find('div.comments')
		.animate({opacity : 1 });
		
		mbuzzy.bubble.initBubble($insertComment);																									
		
		$('.commentTemp').empty();
	}
	
	function addCommentResponseHandler(commentsResponse) {
		var prependMarkup = "";
		var status = commentsResponse.status;
		$('#addProfileCommentButtons').hideSpinner();
	
		if(status) {
			$('#commentResponse').prepend(commentsResponse.ui);
			$('.noComments').css("display", "none");
		} else {
			appendNewComment(commentsResponse.ui);
			$('.noComments').css("display", "none");
		}
	
	}
	
	
});
/*
 * jQuery UI 1.7.1
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI
 */
;jQuery.ui || (function($) {

var _remove = $.fn.remove,
	isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);

//Helper functions and ui object
$.ui = {
	version: "1.7.1",

	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
	plugin: {
		add: function(module, option, set) {
			var proto = $.ui[module].prototype;
			for(var i in set) {
				proto.plugins[i] = proto.plugins[i] || [];
				proto.plugins[i].push([option, set[i]]);
			}
		},
		call: function(instance, name, args) {
			var set = instance.plugins[name];
			if(!set || !instance.element[0].parentNode) { return; }

			for (var i = 0; i < set.length; i++) {
				if (instance.options[set[i][0]]) {
					set[i][1].apply(instance.element, args);
				}
			}
		}
	},

	contains: function(a, b) {
		return document.compareDocumentPosition
			? a.compareDocumentPosition(b) & 16
			: a !== b && a.contains(b);
	},

	hasScroll: function(el, a) {

		//If overflow is hidden, the element might have extra content, but the user wants to hide it
		if ($(el).css('overflow') == 'hidden') { return false; }

		var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
			has = false;

		if (el[scroll] > 0) { return true; }

		// TODO: determine which cases actually cause this to happen
		// if the element doesn't have the scroll set, see if it's possible to
		// set the scroll
		el[scroll] = 1;
		has = (el[scroll] > 0);
		el[scroll] = 0;
		return has;
	},

	isOverAxis: function(x, reference, size) {
		//Determines when x coordinate is over "b" element axis
		return (x > reference) && (x < (reference + size));
	},

	isOver: function(y, x, top, left, height, width) {
		//Determines when x, y coordinates is over "b" element
		return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
	},

	keyCode: {
		BACKSPACE: 8,
		CAPS_LOCK: 20,
		COMMA: 188,
		CONTROL: 17,
		DELETE: 46,
		DOWN: 40,
		END: 35,
		ENTER: 13,
		ESCAPE: 27,
		HOME: 36,
		INSERT: 45,
		LEFT: 37,
		NUMPAD_ADD: 107,
		NUMPAD_DECIMAL: 110,
		NUMPAD_DIVIDE: 111,
		NUMPAD_ENTER: 108,
		NUMPAD_MULTIPLY: 106,
		NUMPAD_SUBTRACT: 109,
		PAGE_DOWN: 34,
		PAGE_UP: 33,
		PERIOD: 190,
		RIGHT: 39,
		SHIFT: 16,
		SPACE: 32,
		TAB: 9,
		UP: 38
	}
};

// WAI-ARIA normalization
if (isFF2) {
	var attr = $.attr,
		removeAttr = $.fn.removeAttr,
		ariaNS = "http://www.w3.org/2005/07/aaa",
		ariaState = /^aria-/,
		ariaRole = /^wairole:/;

	$.attr = function(elem, name, value) {
		var set = value !== undefined;

		return (name == 'role'
			? (set
				? attr.call(this, elem, name, "wairole:" + value)
				: (attr.apply(this, arguments) || "").replace(ariaRole, ""))
			: (ariaState.test(name)
				? (set
					? elem.setAttributeNS(ariaNS,
						name.replace(ariaState, "aaa:"), value)
					: attr.call(this, elem, name.replace(ariaState, "aaa:")))
				: attr.apply(this, arguments)));
	};

	$.fn.removeAttr = function(name) {
		return (ariaState.test(name)
			? this.each(function() {
				this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
			}) : removeAttr.call(this, name));
	};
}

//jQuery plugins
$.fn.extend({
	remove: function() {
		// Safari has a native remove event which actually removes DOM elements,
		// so we have to use triggerHandler instead of trigger (#3037).
		$("*", this).add(this).each(function() {
			$(this).triggerHandler("remove");
		});
		return _remove.apply(this, arguments );
	},

	enableSelection: function() {
		return this
			.attr('unselectable', 'off')
			.css('MozUserSelect', '')
			.unbind('selectstart.ui');
	},

	disableSelection: function() {
		return this
			.attr('unselectable', 'on')
			.css('MozUserSelect', 'none')
			.bind('selectstart.ui', function() { return false; });
	},

	scrollParent: function() {
		var scrollParent;
		if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
			scrollParent = this.parents().filter(function() {
				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
			}).eq(0);
		} else {
			scrollParent = this.parents().filter(function() {
				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
			}).eq(0);
		}

		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
	}
});


//Additional selectors
$.extend($.expr[':'], {
	data: function(elem, i, match) {
		return !!$.data(elem, match[3]);
	},

	focusable: function(element) {
		var nodeName = element.nodeName.toLowerCase(),
			tabIndex = $.attr(element, 'tabindex');
		return (/input|select|textarea|button|object/.test(nodeName)
			? !element.disabled
			: 'a' == nodeName || 'area' == nodeName
				? element.href || !isNaN(tabIndex)
				: !isNaN(tabIndex))
			// the element and all of its ancestors must be visible
			// the browser may report that the area is hidden
			&& !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
	},

	tabbable: function(element) {
		var tabIndex = $.attr(element, 'tabindex');
		return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
	}
});


// $.widget is a factory to create jQuery plugins
// taking some boilerplate code out of the plugin code
function getter(namespace, plugin, method, args) {
	function getMethods(type) {
		var methods = $[namespace][plugin][type] || [];
		return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
	}

	var methods = getMethods('getter');
	if (args.length == 1 && typeof args[0] == 'string') {
		methods = methods.concat(getMethods('getterSetter'));
	}
	return ($.inArray(method, methods) != -1);
}

$.widget = function(name, prototype) {
	var namespace = name.split(".")[0];
	name = name.split(".")[1];

	// create plugin method
	$.fn[name] = function(options) {
		var isMethodCall = (typeof options == 'string'),
			args = Array.prototype.slice.call(arguments, 1);

		// prevent calls to internal methods
		if (isMethodCall && options.substring(0, 1) == '_') {
			return this;
		}

		// handle getter methods
		if (isMethodCall && getter(namespace, name, options, args)) {
			var instance = $.data(this[0], name);
			return (instance ? instance[options].apply(instance, args)
				: undefined);
		}

		// handle initialization and non-getter methods
		return this.each(function() {
			var instance = $.data(this, name);

			// constructor
			(!instance && !isMethodCall &&
				$.data(this, name, new $[namespace][name](this, options))._init());

			// method call
			(instance && isMethodCall && $.isFunction(instance[options]) &&
				instance[options].apply(instance, args));
		});
	};

	// create widget constructor
	$[namespace] = $[namespace] || {};
	$[namespace][name] = function(element, options) {
		var self = this;

		this.namespace = namespace;
		this.widgetName = name;
		this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
		this.widgetBaseClass = namespace + '-' + name;

		this.options = $.extend({},
			$.widget.defaults,
			$[namespace][name].defaults,
			$.metadata && $.metadata.get(element)[name],
			options);

		this.element = $(element)
			.bind('setData.' + name, function(event, key, value) {
				if (event.target == element) {
					return self._setData(key, value);
				}
			})
			.bind('getData.' + name, function(event, key) {
				if (event.target == element) {
					return self._getData(key);
				}
			})
			.bind('remove', function() {
				return self.destroy();
			});
	};

	// add widget prototype
	$[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);

	// TODO: merge getter and getterSetter properties from widget prototype
	// and plugin prototype
	$[namespace][name].getterSetter = 'option';
};

$.widget.prototype = {
	_init: function() {},
	destroy: function() {
		this.element.removeData(this.widgetName)
			.removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
			.removeAttr('aria-disabled');
	},

	option: function(key, value) {
		var options = key,
			self = this;

		if (typeof key == "string") {
			if (value === undefined) {
				return this._getData(key);
			}
			options = {};
			options[key] = value;
		}

		$.each(options, function(key, value) {
			self._setData(key, value);
		});
	},
	_getData: function(key) {
		return this.options[key];
	},
	_setData: function(key, value) {
		this.options[key] = value;

		if (key == 'disabled') {
			this.element
				[value ? 'addClass' : 'removeClass'](
					this.widgetBaseClass + '-disabled' + ' ' +
					this.namespace + '-state-disabled')
				.attr("aria-disabled", value);
		}
	},

	enable: function() {
		this._setData('disabled', false);
	},
	disable: function() {
		this._setData('disabled', true);
	},

	_trigger: function(type, event, data) {
		var callback = this.options[type],
			eventName = (type == this.widgetEventPrefix
				? type : this.widgetEventPrefix + type);

		event = $.Event(event);
		event.type = eventName;

		// copy original event properties over to the new event
		// this would happen if we could call $.event.fix instead of $.Event
		// but we don't have a way to force an event to be fixed multiple times
		if (event.originalEvent) {
			for (var i = $.event.props.length, prop; i;) {
				prop = $.event.props[--i];
				event[prop] = event.originalEvent[prop];
			}
		}

		this.element.trigger(event, data);

		return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
			|| event.isDefaultPrevented());
	}
};

$.widget.defaults = {
	disabled: false
};


/** Mouse Interaction Plugin **/

$.ui.mouse = {
	_mouseInit: function() {
		var self = this;

		this.element
			.bind('mousedown.'+this.widgetName, function(event) {
				return self._mouseDown(event);
			})
			.bind('click.'+this.widgetName, function(event) {
				if(self._preventClickEvent) {
					self._preventClickEvent = false;
					event.stopImmediatePropagation();
					return false;
				}
			});

		// Prevent text selection in IE
		if ($.browser.msie) {
			this._mouseUnselectable = this.element.attr('unselectable');
			this.element.attr('unselectable', 'on');
		}

		this.started = false;
	},

	// TODO: make sure destroying one instance of mouse doesn't mess with
	// other instances of mouse
	_mouseDestroy: function() {
		this.element.unbind('.'+this.widgetName);

		// Restore text selection in IE
		($.browser.msie
			&& this.element.attr('unselectable', this._mouseUnselectable));
	},

	_mouseDown: function(event) {
		// don't let more than one widget handle mouseStart
		// TODO: figure out why we have to use originalEvent
		event.originalEvent = event.originalEvent || {};
		if (event.originalEvent.mouseHandled) { return; }

		// we may have missed mouseup (out of window)
		(this._mouseStarted && this._mouseUp(event));

		this._mouseDownEvent = event;

		var self = this,
			btnIsLeft = (event.which == 1),
			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
			return true;
		}

		this.mouseDelayMet = !this.options.delay;
		if (!this.mouseDelayMet) {
			this._mouseDelayTimer = setTimeout(function() {
				self.mouseDelayMet = true;
			}, this.options.delay);
		}

		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
			this._mouseStarted = (this._mouseStart(event) !== false);
			if (!this._mouseStarted) {
				event.preventDefault();
				return true;
			}
		}

		// these delegates are required to keep context
		this._mouseMoveDelegate = function(event) {
			return self._mouseMove(event);
		};
		this._mouseUpDelegate = function(event) {
			return self._mouseUp(event);
		};
		$(document)
			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);

		// preventDefault() is used to prevent the selection of text here -
		// however, in Safari, this causes select boxes not to be selectable
		// anymore, so this fix is needed
		($.browser.safari || event.preventDefault());

		event.originalEvent.mouseHandled = true;
		return true;
	},

	_mouseMove: function(event) {
		// IE mouseup check - mouseup happened when mouse was out of window
		if ($.browser.msie && !event.button) {
			return this._mouseUp(event);
		}

		if (this._mouseStarted) {
			this._mouseDrag(event);
			return event.preventDefault();
		}

		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
			this._mouseStarted =
				(this._mouseStart(this._mouseDownEvent, event) !== false);
			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
		}

		return !this._mouseStarted;
	},

	_mouseUp: function(event) {
		$(document)
			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);

		if (this._mouseStarted) {
			this._mouseStarted = false;
			this._preventClickEvent = (event.target == this._mouseDownEvent.target);
			this._mouseStop(event);
		}

		return false;
	},

	_mouseDistanceMet: function(event) {
		return (Math.max(
				Math.abs(this._mouseDownEvent.pageX - event.pageX),
				Math.abs(this._mouseDownEvent.pageY - event.pageY)
			) >= this.options.distance
		);
	},

	_mouseDelayMet: function(event) {
		return this.mouseDelayMet;
	},

	// These are placeholder methods, to be overriden by extending plugin
	_mouseStart: function(event) {},
	_mouseDrag: function(event) {},
	_mouseStop: function(event) {},
	_mouseCapture: function(event) { return true; }
};

$.ui.mouse.defaults = {
	cancel: null,
	distance: 1,
	delay: 0
};

})(jQuery);
/*
 * jQuery UI Draggable 1.7.1
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Draggables
 *
 * Depends:
 *	ui.core.js
 */
(function($) {

$.widget("ui.draggable", $.extend({}, $.ui.mouse, {

	_init: function() {

		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
			this.element[0].style.position = 'relative';

		(this.options.addClasses && this.element.addClass("ui-draggable"));
		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));

		this._mouseInit();

	},

	destroy: function() {
		if(!this.element.data('draggable')) return;
		this.element
			.removeData("draggable")
			.unbind(".draggable")
			.removeClass("ui-draggable"
				+ " ui-draggable-dragging"
				+ " ui-draggable-disabled");
		this._mouseDestroy();
	},

	_mouseCapture: function(event) {

		var o = this.options;

		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
			return false;

		//Quit if we're not on a valid handle
		this.handle = this._getHandle(event);
		if (!this.handle)
			return false;

		return true;

	},

	_mouseStart: function(event) {

		var o = this.options;

		//Create and append the visible helper
		this.helper = this._createHelper(event);

		//Cache the helper size
		this._cacheHelperProportions();

		//If ddmanager is used for droppables, set the global draggable
		if($.ui.ddmanager)
			$.ui.ddmanager.current = this;

		/*
		 * - Position generation -
		 * This block generates everything position related - it's the core of draggables.
		 */

		//Cache the margins of the original element
		this._cacheMargins();

		//Store the helper's css position
		this.cssPosition = this.helper.css("position");
		this.scrollParent = this.helper.scrollParent();

		//The element's absolute position on the page minus margins
		this.offset = this.element.offset();
		this.offset = {
			top: this.offset.top - this.margins.top,
			left: this.offset.left - this.margins.left
		};

		$.extend(this.offset, {
			click: { //Where the click happened, relative to the element
				left: event.pageX - this.offset.left,
				top: event.pageY - this.offset.top
			},
			parent: this._getParentOffset(),
			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
		});

		//Generate the original position
		this.originalPosition = this._generatePosition(event);
		this.originalPageX = event.pageX;
		this.originalPageY = event.pageY;

		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
		if(o.cursorAt)
			this._adjustOffsetFromHelper(o.cursorAt);

		//Set a containment if given in the options
		if(o.containment)
			this._setContainment();

		//Call plugins and callbacks
		this._trigger("start", event);

		//Recache the helper size
		this._cacheHelperProportions();

		//Prepare the droppable offsets
		if ($.ui.ddmanager && !o.dropBehaviour)
			$.ui.ddmanager.prepareOffsets(this, event);

		this.helper.addClass("ui-draggable-dragging");
		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
		return true;
	},

	_mouseDrag: function(event, noPropagation) {

		//Compute the helpers position
		this.position = this._generatePosition(event);
		this.positionAbs = this._convertPositionTo("absolute");

		//Call plugins and callbacks and use the resulting position if something is returned
		if (!noPropagation) {
			var ui = this._uiHash();
			this._trigger('drag', event, ui);
			this.position = ui.position;
		}

		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);

		return false;
	},

	_mouseStop: function(event) {

		//If we are using droppables, inform the manager about the drop
		var dropped = false;
		if ($.ui.ddmanager && !this.options.dropBehaviour)
			dropped = $.ui.ddmanager.drop(this, event);

		//if a drop comes from outside (a sortable)
		if(this.dropped) {
			dropped = this.dropped;
			this.dropped = false;
		}

		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
			var self = this;
			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
				self._trigger("stop", event);
				self._clear();
			});
		} else {
			this._trigger("stop", event);
			this._clear();
		}

		return false;
	},

	_getHandle: function(event) {

		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
		$(this.options.handle, this.element)
			.find("*")
			.andSelf()
			.each(function() {
				if(this == event.target) handle = true;
			});

		return handle;

	},

	_createHelper: function(event) {

		var o = this.options;
		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);

		if(!helper.parents('body').length)
			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));

		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
			helper.css("position", "absolute");

		return helper;

	},

	_adjustOffsetFromHelper: function(obj) {
		if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
		if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
		if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
		if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
	},

	_getParentOffset: function() {

		//Get the offsetParent and cache its position
		this.offsetParent = this.helper.offsetParent();
		var po = this.offsetParent.offset();

		// This is a special case where we need to modify a offset calculated on start, since the following happened:
		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
			po.left += this.scrollParent.scrollLeft();
			po.top += this.scrollParent.scrollTop();
		}

		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
			po = { top: 0, left: 0 };

		return {
			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
		};

	},

	_getRelativeOffset: function() {

		if(this.cssPosition == "relative") {
			var p = this.element.position();
			return {
				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
			};
		} else {
			return { top: 0, left: 0 };
		}

	},

	_cacheMargins: function() {
		this.margins = {
			left: (parseInt(this.element.css("marginLeft"),10) || 0),
			top: (parseInt(this.element.css("marginTop"),10) || 0)
		};
	},

	_cacheHelperProportions: function() {
		this.helperProportions = {
			width: this.helper.outerWidth(),
			height: this.helper.outerHeight()
		};
	},

	_setContainment: function() {

		var o = this.options;
		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
		if(o.containment == 'document' || o.containment == 'window') this.containment = [
			0 - this.offset.relative.left - this.offset.parent.left,
			0 - this.offset.relative.top - this.offset.parent.top,
			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
		];

		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
			var ce = $(o.containment)[0]; if(!ce) return;
			var co = $(o.containment).offset();
			var over = ($(ce).css("overflow") != 'hidden');

			this.containment = [
				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
			];
		} else if(o.containment.constructor == Array) {
			this.containment = o.containment;
		}

	},

	_convertPositionTo: function(d, pos) {

		if(!pos) pos = this.position;
		var mod = d == "absolute" ? 1 : -1;
		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);

		return {
			top: (
				pos.top																	// The absolute mouse position
				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
			),
			left: (
				pos.left																// The absolute mouse position
				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
			)
		};

	},

	_generatePosition: function(event) {

		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);

		// This is another very weird special case that only happens for relative elements:
		// 1. If the css position is relative
		// 2. and the scroll parent is the document or similar to the offset parent
		// we have to refresh the relative offset during the scroll so there are no jumps
		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
			this.offset.relative = this._getRelativeOffset();
		}

		var pageX = event.pageX;
		var pageY = event.pageY;

		/*
		 * - Position constraining -
		 * Constrain the position to a mix of grid, containment.
		 */

		if(this.originalPosition) { //If we are not dragging yet, we won't check for options

			if(this.containment) {
				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
			}

			if(o.grid) {
				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;

				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
			}

		}

		return {
			top: (
				pageY																// The absolute mouse position
				- this.offset.click.top													// Click offset (relative to the element)
				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
			),
			left: (
				pageX																// The absolute mouse position
				- this.offset.click.left												// Click offset (relative to the element)
				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
			)
		};

	},

	_clear: function() {
		this.helper.removeClass("ui-draggable-dragging");
		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
		this.helper = null;
		this.cancelHelperRemoval = false;
	},

	// From now on bulk stuff - mainly helpers

	_trigger: function(type, event, ui) {
		ui = ui || this._uiHash();
		$.ui.plugin.call(this, type, [event, ui]);
		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
		return $.widget.prototype._trigger.call(this, type, event, ui);
	},

	plugins: {},

	_uiHash: function(event) {
		return {
			helper: this.helper,
			position: this.position,
			absolutePosition: this.positionAbs, //deprecated
			offset: this.positionAbs
		};
	}

}));

$.extend($.ui.draggable, {
	version: "1.7.1",
	eventPrefix: "drag",
	defaults: {
		addClasses: true,
		appendTo: "parent",
		axis: false,
		cancel: ":input,option",
		connectToSortable: false,
		containment: false,
		cursor: "auto",
		cursorAt: false,
		delay: 0,
		distance: 1,
		grid: false,
		handle: false,
		helper: "original",
		iframeFix: false,
		opacity: false,
		refreshPositions: false,
		revert: false,
		revertDuration: 500,
		scope: "default",
		scroll: true,
		scrollSensitivity: 20,
		scrollSpeed: 20,
		snap: false,
		snapMode: "both",
		snapTolerance: 20,
		stack: false,
		zIndex: false
	}
});

$.ui.plugin.add("draggable", "connectToSortable", {
	start: function(event, ui) {

		var inst = $(this).data("draggable"), o = inst.options,
			uiSortable = $.extend({}, ui, { item: inst.element });
		inst.sortables = [];
		$(o.connectToSortable).each(function() {
			var sortable = $.data(this, 'sortable');
			if (sortable && !sortable.options.disabled) {
				inst.sortables.push({
					instance: sortable,
					shouldRevert: sortable.options.revert
				});
				sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
				sortable._trigger("activate", event, uiSortable);
			}
		});

	},
	stop: function(event, ui) {

		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
		var inst = $(this).data("draggable"),
			uiSortable = $.extend({}, ui, { item: inst.element });

		$.each(inst.sortables, function() {
			if(this.instance.isOver) {

				this.instance.isOver = 0;

				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)

				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
				if(this.shouldRevert) this.instance.options.revert = true;

				//Trigger the stop of the sortable
				this.instance._mouseStop(event);

				this.instance.options.helper = this.instance.options._helper;

				//If the helper has been the original item, restore properties in the sortable
				if(inst.options.helper == 'original')
					this.instance.currentItem.css({ top: 'auto', left: 'auto' });

			} else {
				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
				this.instance._trigger("deactivate", event, uiSortable);
			}

		});

	},
	drag: function(event, ui) {

		var inst = $(this).data("draggable"), self = this;

		var checkPos = function(o) {
			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
			var itemHeight = o.height, itemWidth = o.width;
			var itemTop = o.top, itemLeft = o.left;

			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
		};

		$.each(inst.sortables, function(i) {
			
			//Copy over some variables to allow calling the sortable's native _intersectsWith
			this.instance.positionAbs = inst.positionAbs;
			this.instance.helperProportions = inst.helperProportions;
			this.instance.offset.click = inst.offset.click;
			
			if(this.instance._intersectsWith(this.instance.containerCache)) {

				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
				if(!this.instance.isOver) {

					this.instance.isOver = 1;
					//Now we fake the start of dragging for the sortable instance,
					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
					this.instance.options.helper = function() { return ui.helper[0]; };

					event.target = this.instance.currentItem[0];
					this.instance._mouseCapture(event, true);
					this.instance._mouseStart(event, true, true);

					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
					this.instance.offset.click.top = inst.offset.click.top;
					this.instance.offset.click.left = inst.offset.click.left;
					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;

					inst._trigger("toSortable", event);
					inst.dropped = this.instance.element; //draggable revert needs that
					//hack so receive/update callbacks work (mostly)
					inst.currentItem = inst.element;
					this.instance.fromOutside = inst;

				}

				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
				if(this.instance.currentItem) this.instance._mouseDrag(event);

			} else {

				//If it doesn't intersect with the sortable, and it intersected before,
				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
				if(this.instance.isOver) {

					this.instance.isOver = 0;
					this.instance.cancelHelperRemoval = true;
					
					//Prevent reverting on this forced stop
					this.instance.options.revert = false;
					
					// The out event needs to be triggered independently
					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
					
					this.instance._mouseStop(event, true);
					this.instance.options.helper = this.instance.options._helper;

					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
					this.instance.currentItem.remove();
					if(this.instance.placeholder) this.instance.placeholder.remove();

					inst._trigger("fromSortable", event);
					inst.dropped = false; //draggable revert needs that
				}

			};

		});

	}
});

$.ui.plugin.add("draggable", "cursor", {
	start: function(event, ui) {
		var t = $('body'), o = $(this).data('draggable').options;
		if (t.css("cursor")) o._cursor = t.css("cursor");
		t.css("cursor", o.cursor);
	},
	stop: function(event, ui) {
		var o = $(this).data('draggable').options;
		if (o._cursor) $('body').css("cursor", o._cursor);
	}
});

$.ui.plugin.add("draggable", "iframeFix", {
	start: function(event, ui) {
		var o = $(this).data('draggable').options;
		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
			.css({
				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
				position: "absolute", opacity: "0.001", zIndex: 1000
			})
			.css($(this).offset())
			.appendTo("body");
		});
	},
	stop: function(event, ui) {
		$("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
	}
});

$.ui.plugin.add("draggable", "opacity", {
	start: function(event, ui) {
		var t = $(ui.helper), o = $(this).data('draggable').options;
		if(t.css("opacity")) o._opacity = t.css("opacity");
		t.css('opacity', o.opacity);
	},
	stop: function(event, ui) {
		var o = $(this).data('draggable').options;
		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
	}
});

$.ui.plugin.add("draggable", "scroll", {
	start: function(event, ui) {
		var i = $(this).data("draggable");
		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
	},
	drag: function(event, ui) {

		var i = $(this).data("draggable"), o = i.options, scrolled = false;

		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {

			if(!o.axis || o.axis != 'x') {
				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
			}

			if(!o.axis || o.axis != 'y') {
				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
			}

		} else {

			if(!o.axis || o.axis != 'x') {
				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
			}

			if(!o.axis || o.axis != 'y') {
				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
			}

		}

		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
			$.ui.ddmanager.prepareOffsets(i, event);

	}
});

$.ui.plugin.add("draggable", "snap", {
	start: function(event, ui) {

		var i = $(this).data("draggable"), o = i.options;
		i.snapElements = [];

		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
			var $t = $(this); var $o = $t.offset();
			if(this != i.element[0]) i.snapElements.push({
				item: this,
				width: $t.outerWidth(), height: $t.outerHeight(),
				top: $o.top, left: $o.left
			});
		});

	},
	drag: function(event, ui) {

		var inst = $(this).data("draggable"), o = inst.options;
		var d = o.snapTolerance;

		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;

		for (var i = inst.snapElements.length - 1; i >= 0; i--){

			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;

			//Yes, I know, this is insane ;)
			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
				inst.snapElements[i].snapping = false;
				continue;
			}

			if(o.snapMode != 'inner') {
				var ts = Math.abs(t - y2) <= d;
				var bs = Math.abs(b - y1) <= d;
				var ls = Math.abs(l - x2) <= d;
				var rs = Math.abs(r - x1) <= d;
				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
			}

			var first = (ts || bs || ls || rs);

			if(o.snapMode != 'outer') {
				var ts = Math.abs(t - y1) <= d;
				var bs = Math.abs(b - y2) <= d;
				var ls = Math.abs(l - x1) <= d;
				var rs = Math.abs(r - x2) <= d;
				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
			}

			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);

		};

	}
});

$.ui.plugin.add("draggable", "stack", {
	start: function(event, ui) {

		var o = $(this).data("draggable").options;

		var group = $.makeArray($(o.stack.group)).sort(function(a,b) {
			return (parseInt($(a).css("zIndex"),10) || o.stack.min) - (parseInt($(b).css("zIndex"),10) || o.stack.min);
		});

		$(group).each(function(i) {
			this.style.zIndex = o.stack.min + i;
		});

		this[0].style.zIndex = o.stack.min + group.length;

	}
});

$.ui.plugin.add("draggable", "zIndex", {
	start: function(event, ui) {
		var t = $(ui.helper), o = $(this).data("draggable").options;
		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
		t.css('zIndex', o.zIndex);
	},
	stop: function(event, ui) {
		var o = $(this).data("draggable").options;
		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
	}
});

})(jQuery);
/*
 * jQuery UI Droppable 1.7.1
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Droppables
 *
 * Depends:
 *	ui.core.js
 *	ui.draggable.js
 */
(function($) {

$.widget("ui.droppable", {

	_init: function() {

		var o = this.options, accept = o.accept;
		this.isover = 0; this.isout = 1;

		this.options.accept = this.options.accept && $.isFunction(this.options.accept) ? this.options.accept : function(d) {
			return d.is(accept);
		};

		//Store the droppable's proportions
		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };

		// Add the reference and positions to the manager
		$.ui.ddmanager.droppables[this.options.scope] = $.ui.ddmanager.droppables[this.options.scope] || [];
		$.ui.ddmanager.droppables[this.options.scope].push(this);

		(this.options.addClasses && this.element.addClass("ui-droppable"));

	},

	destroy: function() {
		var drop = $.ui.ddmanager.droppables[this.options.scope];
		for ( var i = 0; i < drop.length; i++ )
			if ( drop[i] == this )
				drop.splice(i, 1);

		this.element
			.removeClass("ui-droppable ui-droppable-disabled")
			.removeData("droppable")
			.unbind(".droppable");
	},

	_setData: function(key, value) {

		if(key == 'accept') {
			this.options.accept = value && $.isFunction(value) ? value : function(d) {
				return d.is(value);
			};
		} else {
			$.widget.prototype._setData.apply(this, arguments);
		}

	},

	_activate: function(event) {
		var draggable = $.ui.ddmanager.current;
		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
		(draggable && this._trigger('activate', event, this.ui(draggable)));
	},

	_deactivate: function(event) {
		var draggable = $.ui.ddmanager.current;
		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
	},

	_over: function(event) {

		var draggable = $.ui.ddmanager.current;
		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element

		if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
			this._trigger('over', event, this.ui(draggable));
		}

	},

	_out: function(event) {

		var draggable = $.ui.ddmanager.current;
		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element

		if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
			this._trigger('out', event, this.ui(draggable));
		}

	},

	_drop: function(event,custom) {

		var draggable = custom || $.ui.ddmanager.current;
		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element

		var childrenIntersection = false;
		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
			var inst = $.data(this, 'droppable');
			if(inst.options.greedy && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)) {
				childrenIntersection = true; return false;
			}
		});
		if(childrenIntersection) return false;

		if(this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
			this._trigger('drop', event, this.ui(draggable));
			return this.element;
		}

		return false;

	},

	ui: function(c) {
		return {
			draggable: (c.currentItem || c.element),
			helper: c.helper,
			position: c.position,
			absolutePosition: c.positionAbs, //deprecated
			offset: c.positionAbs
		};
	}

});

$.extend($.ui.droppable, {
	version: "1.7.1",
	eventPrefix: 'drop',
	defaults: {
		accept: '*',
		activeClass: false,
		addClasses: true,
		greedy: false,
		hoverClass: false,
		scope: 'default',
		tolerance: 'intersect'
	}
});

$.ui.intersect = function(draggable, droppable, toleranceMode) {

	if (!droppable.offset) return false;

	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
	var l = droppable.offset.left, r = l + droppable.proportions.width,
		t = droppable.offset.top, b = t + droppable.proportions.height;

	switch (toleranceMode) {
		case 'fit':
			return (l < x1 && x2 < r
				&& t < y1 && y2 < b);
			break;
		case 'intersect':
			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
			break;
		case 'pointer':
			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
			return isOver;
			break;
		case 'touch':
			return (
					(y1 >= t && y1 <= b) ||	// Top edge touching
					(y2 >= t && y2 <= b) ||	// Bottom edge touching
					(y1 < t && y2 > b)		// Surrounded vertically
				) && (
					(x1 >= l && x1 <= r) ||	// Left edge touching
					(x2 >= l && x2 <= r) ||	// Right edge touching
					(x1 < l && x2 > r)		// Surrounded horizontally
				);
			break;
		default:
			return false;
			break;
		}

};

/*
	This manager tracks offsets of draggables and droppables
*/
$.ui.ddmanager = {
	current: null,
	droppables: { 'default': [] },
	prepareOffsets: function(t, event) {

		var m = $.ui.ddmanager.droppables[t.options.scope];
		var type = event ? event.type : null; // workaround for #2317
		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();

		droppablesLoop: for (var i = 0; i < m.length; i++) {

			if(m[i].options.disabled || (t && !m[i].options.accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue

			m[i].offset = m[i].element.offset();
			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };

			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables

		}

	},
	drop: function(draggable, event) {

		var dropped = false;
		$.each($.ui.ddmanager.droppables[draggable.options.scope], function() {

			if(!this.options) return;
			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
				dropped = this._drop.call(this, event);

			if (!this.options.disabled && this.visible && this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
				this.isout = 1; this.isover = 0;
				this._deactivate.call(this, event);
			}

		});
		return dropped;

	},
	drag: function(draggable, event) {

		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);

		//Run through all droppables and check their positions based on specific tolerance options

		$.each($.ui.ddmanager.droppables[draggable.options.scope], function() {

			if(this.options.disabled || this.greedyChild || !this.visible) return;
			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);

			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
			if(!c) return;

			var parentInstance;
			if (this.options.greedy) {
				var parent = this.element.parents(':data(droppable):eq(0)');
				if (parent.length) {
					parentInstance = $.data(parent[0], 'droppable');
					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
				}
			}

			// we just moved into a greedy child
			if (parentInstance && c == 'isover') {
				parentInstance['isover'] = 0;
				parentInstance['isout'] = 1;
				parentInstance._out.call(parentInstance, event);
			}

			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
			this[c == "isover" ? "_over" : "_out"].call(this, event);

			// we just moved out of a greedy child
			if (parentInstance && c == 'isout') {
				parentInstance['isout'] = 0;
				parentInstance['isover'] = 1;
				parentInstance._over.call(parentInstance, event);
			}
		});

	}
};

})(jQuery);
/*
 * jQuery UI Sortable 1.7.1
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Sortables
 *
 * Depends:
 *	ui.core.js
 */
(function($) {

$.widget("ui.sortable", $.extend({}, $.ui.mouse, {
	_init: function() {

		var o = this.options;
		this.containerCache = {};
		this.element.addClass("ui-sortable");

		//Get the items
		this.refresh();

		//Let's determine if the items are floating
		this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;

		//Let's determine the parent's offset
		this.offset = this.element.offset();

		//Initialize mouse events for interaction
		this._mouseInit();

	},

	destroy: function() {
		this.element
			.removeClass("ui-sortable ui-sortable-disabled")
			.removeData("sortable")
			.unbind(".sortable");
		this._mouseDestroy();

		for ( var i = this.items.length - 1; i >= 0; i-- )
			this.items[i].item.removeData("sortable-item");
	},

	_mouseCapture: function(event, overrideHandle) {

		if (this.reverting) {
			return false;
		}

		if(this.options.disabled || this.options.type == 'static') return false;

		//We have to refresh the items data once first
		this._refreshItems(event);

		//Find out if the clicked node (or one of its parents) is a actual item in this.items
		var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
			if($.data(this, 'sortable-item') == self) {
				currentItem = $(this);
				return false;
			}
		});
		if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);

		if(!currentItem) return false;
		if(this.options.handle && !overrideHandle) {
			var validHandle = false;

			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
			if(!validHandle) return false;
		}

		this.currentItem = currentItem;
		this._removeCurrentsFromItems();
		return true;

	},

	_mouseStart: function(event, overrideHandle, noActivation) {

		var o = this.options, self = this;
		this.currentContainer = this;

		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
		this.refreshPositions();

		//Create and append the visible helper
		this.helper = this._createHelper(event);

		//Cache the helper size
		this._cacheHelperProportions();

		/*
		 * - Position generation -
		 * This block generates everything position related - it's the core of draggables.
		 */

		//Cache the margins of the original element
		this._cacheMargins();

		//Get the next scrolling parent
		this.scrollParent = this.helper.scrollParent();

		//The element's absolute position on the page minus margins
		this.offset = this.currentItem.offset();
		this.offset = {
			top: this.offset.top - this.margins.top,
			left: this.offset.left - this.margins.left
		};

		// Only after we got the offset, we can change the helper's position to absolute
		// TODO: Still need to figure out a way to make relative sorting possible
		this.helper.css("position", "absolute");
		this.cssPosition = this.helper.css("position");

		$.extend(this.offset, {
			click: { //Where the click happened, relative to the element
				left: event.pageX - this.offset.left,
				top: event.pageY - this.offset.top
			},
			parent: this._getParentOffset(),
			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
		});

		//Generate the original position
		this.originalPosition = this._generatePosition(event);
		this.originalPageX = event.pageX;
		this.originalPageY = event.pageY;

		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
		if(o.cursorAt)
			this._adjustOffsetFromHelper(o.cursorAt);

		//Cache the former DOM position
		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };

		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
		if(this.helper[0] != this.currentItem[0]) {
			this.currentItem.hide();
		}

		//Create the placeholder
		this._createPlaceholder();

		//Set a containment if given in the options
		if(o.containment)
			this._setContainment();

		if(o.cursor) { // cursor option
			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
			$('body').css("cursor", o.cursor);
		}

		if(o.opacity) { // opacity option
			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
			this.helper.css("opacity", o.opacity);
		}

		if(o.zIndex) { // zIndex option
			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
			this.helper.css("zIndex", o.zIndex);
		}

		//Prepare scrolling
		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
			this.overflowOffset = this.scrollParent.offset();

		//Call callbacks
		this._trigger("start", event, this._uiHash());

		//Recache the helper size
		if(!this._preserveHelperProportions)
			this._cacheHelperProportions();


		//Post 'activate' events to possible containers
		if(!noActivation) {
			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
		}

		//Prepare possible droppables
		if($.ui.ddmanager)
			$.ui.ddmanager.current = this;

		if ($.ui.ddmanager && !o.dropBehaviour)
			$.ui.ddmanager.prepareOffsets(this, event);

		this.dragging = true;

		this.helper.addClass("ui-sortable-helper");
		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
		return true;

	},

	_mouseDrag: function(event) {

		//Compute the helpers position
		this.position = this._generatePosition(event);
		this.positionAbs = this._convertPositionTo("absolute");

		if (!this.lastPositionAbs) {
			this.lastPositionAbs = this.positionAbs;
		}

		//Do scrolling
		if(this.options.scroll) {
			var o = this.options, scrolled = false;
			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {

				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;

				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;

			} else {

				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);

				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);

			}

			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
				$.ui.ddmanager.prepareOffsets(this, event);
		}

		//Regenerate the absolute position used for position checks
		this.positionAbs = this._convertPositionTo("absolute");

		//Set the helper position
		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';

		//Rearrange
		for (var i = this.items.length - 1; i >= 0; i--) {

			//Cache variables and intersection, continue if no intersection
			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
			if (!intersection) continue;

			if(itemElement != this.currentItem[0] //cannot intersect with itself
				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
				&&	!$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
				&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
			) {

				this.direction = intersection == 1 ? "down" : "up";

				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
					this._rearrange(event, item);
				} else {
					break;
				}

				this._trigger("change", event, this._uiHash());
				break;
			}
		}

		//Post events to containers
		this._contactContainers(event);

		//Interconnect with droppables
		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);

		//Call callbacks
		this._trigger('sort', event, this._uiHash());

		this.lastPositionAbs = this.positionAbs;
		return false;

	},

	_mouseStop: function(event, noPropagation) {

		if(!event) return;

		//If we are using droppables, inform the manager about the drop
		if ($.ui.ddmanager && !this.options.dropBehaviour)
			$.ui.ddmanager.drop(this, event);

		if(this.options.revert) {
			var self = this;
			var cur = self.placeholder.offset();

			self.reverting = true;

			$(this.helper).animate({
				left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
				top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
			}, parseInt(this.options.revert, 10) || 500, function() {
				self._clear(event);
			});
		} else {
			this._clear(event, noPropagation);
		}

		return false;

	},

	cancel: function() {

		var self = this;

		if(this.dragging) {

			this._mouseUp();

			if(this.options.helper == "original")
				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
			else
				this.currentItem.show();

			//Post deactivating events to containers
			for (var i = this.containers.length - 1; i >= 0; i--){
				this.containers[i]._trigger("deactivate", null, self._uiHash(this));
				if(this.containers[i].containerCache.over) {
					this.containers[i]._trigger("out", null, self._uiHash(this));
					this.containers[i].containerCache.over = 0;
				}
			}

		}

		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
		if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
		if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();

		$.extend(this, {
			helper: null,
			dragging: false,
			reverting: false,
			_noFinalSort: null
		});

		if(this.domPosition.prev) {
			$(this.domPosition.prev).after(this.currentItem);
		} else {
			$(this.domPosition.parent).prepend(this.currentItem);
		}

		return true;

	},

	serialize: function(o) {

		var items = this._getItemsAsjQuery(o && o.connected);
		var str = []; o = o || {};

		$(items).each(function() {
			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
		});

		return str.join('&');

	},

	toArray: function(o) {

		var items = this._getItemsAsjQuery(o && o.connected);
		var ret = []; o = o || {};

		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
		return ret;

	},

	/* Be careful with the following core functions */
	_intersectsWith: function(item) {

		var x1 = this.positionAbs.left,
			x2 = x1 + this.helperProportions.width,
			y1 = this.positionAbs.top,
			y2 = y1 + this.helperProportions.height;

		var l = item.left,
			r = l + item.width,
			t = item.top,
			b = t + item.height;

		var dyClick = this.offset.click.top,
			dxClick = this.offset.click.left;

		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;

		if(	   this.options.tolerance == "pointer"
			|| this.options.forcePointerForContainers
			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
		) {
			return isOverElement;
		} else {

			return (l < x1 + (this.helperProportions.width / 2) // Right Half
				&& x2 - (this.helperProportions.width / 2) < r // Left Half
				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half

		}
	},

	_intersectsWithPointer: function(item) {

		var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
			isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
			isOverElement = isOverElementHeight && isOverElementWidth,
			verticalDirection = this._getDragVerticalDirection(),
			horizontalDirection = this._getDragHorizontalDirection();

		if (!isOverElement)
			return false;

		return this.floating ?
			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );

	},

	_intersectsWithSides: function(item) {

		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
			verticalDirection = this._getDragVerticalDirection(),
			horizontalDirection = this._getDragHorizontalDirection();

		if (this.floating && horizontalDirection) {
			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
		} else {
			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
		}

	},

	_getDragVerticalDirection: function() {
		var delta = this.positionAbs.top - this.lastPositionAbs.top;
		return delta != 0 && (delta > 0 ? "down" : "up");
	},

	_getDragHorizontalDirection: function() {
		var delta = this.positionAbs.left - this.lastPositionAbs.left;
		return delta != 0 && (delta > 0 ? "right" : "left");
	},

	refresh: function(event) {
		this._refreshItems(event);
		this.refreshPositions();
	},

	_connectWith: function() {
		var options = this.options;
		return options.connectWith.constructor == String
			? [options.connectWith]
			: options.connectWith;
	},
	
	_getItemsAsjQuery: function(connected) {

		var self = this;
		var items = [];
		var queries = [];
		var connectWith = this._connectWith();

		if(connectWith && connected) {
			for (var i = connectWith.length - 1; i >= 0; i--){
				var cur = $(connectWith[i]);
				for (var j = cur.length - 1; j >= 0; j--){
					var inst = $.data(cur[j], 'sortable');
					if(inst && inst != this && !inst.options.disabled) {
						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper"), inst]);
					}
				};
			};
		}

		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper"), this]);

		for (var i = queries.length - 1; i >= 0; i--){
			queries[i][0].each(function() {
				items.push(this);
			});
		};

		return $(items);

	},

	_removeCurrentsFromItems: function() {

		var list = this.currentItem.find(":data(sortable-item)");

		for (var i=0; i < this.items.length; i++) {

			for (var j=0; j < list.length; j++) {
				if(list[j] == this.items[i].item[0])
					this.items.splice(i,1);
			};

		};

	},

	_refreshItems: function(event) {

		this.items = [];
		this.containers = [this];
		var items = this.items;
		var self = this;
		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
		var connectWith = this._connectWith();

		if(connectWith) {
			for (var i = connectWith.length - 1; i >= 0; i--){
				var cur = $(connectWith[i]);
				for (var j = cur.length - 1; j >= 0; j--){
					var inst = $.data(cur[j], 'sortable');
					if(inst && inst != this && !inst.options.disabled) {
						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
						this.containers.push(inst);
					}
				};
			};
		}

		for (var i = queries.length - 1; i >= 0; i--) {
			var targetData = queries[i][1];
			var _queries = queries[i][0];

			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
				var item = $(_queries[j]);

				item.data('sortable-item', targetData); // Data for target checking (mouse manager)

				items.push({
					item: item,
					instance: targetData,
					width: 0, height: 0,
					left: 0, top: 0
				});
			};
		};

	},

	refreshPositions: function(fast) {

		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
		if(this.offsetParent && this.helper) {
			this.offset.parent = this._getParentOffset();
		}

		for (var i = this.items.length - 1; i >= 0; i--){
			var item = this.items[i];

			//We ignore calculating positions of all connected containers when we're not over them
			if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
				continue;

			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;

			if (!fast) {
				item.width = t.outerWidth();
				item.height = t.outerHeight();
			}

			var p = t.offset();
			item.left = p.left;
			item.top = p.top;
		};

		if(this.options.custom && this.options.custom.refreshContainers) {
			this.options.custom.refreshContainers.call(this);
		} else {
			for (var i = this.containers.length - 1; i >= 0; i--){
				var p = this.containers[i].element.offset();
				this.containers[i].containerCache.left = p.left;
				this.containers[i].containerCache.top = p.top;
				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
			};
		}

	},

	_createPlaceholder: function(that) {

		var self = that || this, o = self.options;

		if(!o.placeholder || o.placeholder.constructor == String) {
			var className = o.placeholder;
			o.placeholder = {
				element: function() {

					var el = $(document.createElement(self.currentItem[0].nodeName))
						.addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
						.removeClass("ui-sortable-helper")[0];

					if(!className)
						el.style.visibility = "hidden";

					return el;
				},
				update: function(container, p) {

					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
					if(className && !o.forcePlaceholderSize) return;

					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
					if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
					if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
				}
			};
		}

		//Create the placeholder
		self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));

		//Append it after the actual current item
		self.currentItem.after(self.placeholder);

		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
		o.placeholder.update(self, self.placeholder);

	},

	_contactContainers: function(event) {
		for (var i = this.containers.length - 1; i >= 0; i--){

			if(this._intersectsWith(this.containers[i].containerCache)) {
				if(!this.containers[i].containerCache.over) {

					if(this.currentContainer != this.containers[i]) {

						//When entering a new container, we will find the item with the least distance and append our item near it
						var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[i].floating ? 'left' : 'top'];
						for (var j = this.items.length - 1; j >= 0; j--) {
							if(!$.ui.contains(this.containers[i].element[0], this.items[j].item[0])) continue;
							var cur = this.items[j][this.containers[i].floating ? 'left' : 'top'];
							if(Math.abs(cur - base) < dist) {
								dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
							}
						}

						if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
							continue;

						this.currentContainer = this.containers[i];
						itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[i].element, true);
						this._trigger("change", event, this._uiHash());
						this.containers[i]._trigger("change", event, this._uiHash(this));

						//Update the placeholder
						this.options.placeholder.update(this.currentContainer, this.placeholder);

					}

					this.containers[i]._trigger("over", event, this._uiHash(this));
					this.containers[i].containerCache.over = 1;
				}
			} else {
				if(this.containers[i].containerCache.over) {
					this.containers[i]._trigger("out", event, this._uiHash(this));
					this.containers[i].containerCache.over = 0;
				}
			}

		};
	},

	_createHelper: function(event) {

		var o = this.options;
		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);

		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);

		if(helper[0] == this.currentItem[0])
			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };

		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());

		return helper;

	},

	_adjustOffsetFromHelper: function(obj) {
		if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
		if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
		if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
		if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
	},

	_getParentOffset: function() {


		//Get the offsetParent and cache its position
		this.offsetParent = this.helper.offsetParent();
		var po = this.offsetParent.offset();

		// This is a special case where we need to modify a offset calculated on start, since the following happened:
		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
			po.left += this.scrollParent.scrollLeft();
			po.top += this.scrollParent.scrollTop();
		}

		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
			po = { top: 0, left: 0 };

		return {
			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
		};

	},

	_getRelativeOffset: function() {

		if(this.cssPosition == "relative") {
			var p = this.currentItem.position();
			return {
				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
			};
		} else {
			return { top: 0, left: 0 };
		}

	},

	_cacheMargins: function() {
		this.margins = {
			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
		};
	},

	_cacheHelperProportions: function() {
		this.helperProportions = {
			width: this.helper.outerWidth(),
			height: this.helper.outerHeight()
		};
	},

	_setContainment: function() {

		var o = this.options;
		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
		if(o.containment == 'document' || o.containment == 'window') this.containment = [
			0 - this.offset.relative.left - this.offset.parent.left,
			0 - this.offset.relative.top - this.offset.parent.top,
			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
		];

		if(!(/^(document|window|parent)$/).test(o.containment)) {
			var ce = $(o.containment)[0];
			var co = $(o.containment).offset();
			var over = ($(ce).css("overflow") != 'hidden');

			this.containment = [
				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
			];
		}

	},

	_convertPositionTo: function(d, pos) {

		if(!pos) pos = this.position;
		var mod = d == "absolute" ? 1 : -1;
		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);

		return {
			top: (
				pos.top																	// The absolute mouse position
				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
			),
			left: (
				pos.left																// The absolute mouse position
				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
				- ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
			)
		};

	},

	_generatePosition: function(event) {

		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);

		// This is another very weird special case that only happens for relative elements:
		// 1. If the css position is relative
		// 2. and the scroll parent is the document or similar to the offset parent
		// we have to refresh the relative offset during the scroll so there are no jumps
		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
			this.offset.relative = this._getRelativeOffset();
		}

		var pageX = event.pageX;
		var pageY = event.pageY;

		/*
		 * - Position constraining -
		 * Constrain the position to a mix of grid, containment.
		 */

		if(this.originalPosition) { //If we are not dragging yet, we won't check for options

			if(this.containment) {
				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
			}

			if(o.grid) {
				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;

				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
			}

		}

		return {
			top: (
				pageY																// The absolute mouse position
				- this.offset.click.top													// Click offset (relative to the element)
				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
			),
			left: (
				pageX																// The absolute mouse position
				- this.offset.click.left												// Click offset (relative to the element)
				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
				+ ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
			)
		};

	},

	_rearrange: function(event, i, a, hardRefresh) {

		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));

		//Various things done here to improve the performance:
		// 1. we create a setTimeout, that calls refreshPositions
		// 2. on the instance, we have a counter variable, that get's higher after every append
		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
		// 4. this lets only the last addition to the timeout stack through
		this.counter = this.counter ? ++this.counter : 1;
		var self = this, counter = this.counter;

		window.setTimeout(function() {
			if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
		},0);

	},

	_clear: function(event, noPropagation) {

		this.reverting = false;
		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
		// everything else normalized again
		var delayedTriggers = [], self = this;

		// We first have to update the dom position of the actual currentItem
		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
		if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
		this._noFinalSort = null;

		if(this.helper[0] == this.currentItem[0]) {
			for(var i in this._storedCSS) {
				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
			}
			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
		} else {
			this.currentItem.show();
		}
		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
		if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
			if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
			for (var i = this.containers.length - 1; i >= 0; i--){
				if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
					delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
					delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
				}
			};
		};

		//Post events to containers
		for (var i = this.containers.length - 1; i >= 0; i--){
			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
			if(this.containers[i].containerCache.over) {
				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
				this.containers[i].containerCache.over = 0;
			}
		}

		//Do what was originally in plugins
		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset cursor
		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index

		this.dragging = false;
		if(this.cancelHelperRemoval) {
			if(!noPropagation) {
				this._trigger("beforeStop", event, this._uiHash());
				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
				this._trigger("stop", event, this._uiHash());
			}
			return false;
		}

		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());

		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);

		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;

		if(!noPropagation) {
			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
			this._trigger("stop", event, this._uiHash());
		}

		this.fromOutside = false;
		return true;

	},

	_trigger: function() {
		if ($.widget.prototype._trigger.apply(this, arguments) === false) {
			this.cancel();
		}
	},

	_uiHash: function(inst) {
		var self = inst || this;
		return {
			helper: self.helper,
			placeholder: self.placeholder || $([]),
			position: self.position,
			absolutePosition: self.positionAbs, //deprecated
			offset: self.positionAbs,
			item: self.currentItem,
			sender: inst ? inst.element : null
		};
	}

}));

$.extend($.ui.sortable, {
	getter: "serialize toArray",
	version: "1.7.1",
	eventPrefix: "sort",
	defaults: {
		appendTo: "parent",
		axis: false,
		cancel: ":input,option",
		connectWith: false,
		containment: false,
		cursor: 'auto',
		cursorAt: false,
		delay: 0,
		distance: 1,
		dropOnEmpty: true,
		forcePlaceholderSize: false,
		forceHelperSize: false,
		grid: false,
		handle: false,
		helper: "original",
		items: '> *',
		opacity: false,
		placeholder: false,
		revert: false,
		scroll: true,
		scrollSensitivity: 20,
		scrollSpeed: 20,
		scope: "default",
		tolerance: "intersect",
		zIndex: 1000
	}
});

})(jQuery);

topFriends = {

	refresh: function() {
		$("#topFriendsList").sortable('refresh');
	},

	saveTopFriends: function() {
		$('.inlineDoButton').showSpinner();
		var newTopFriends = $("#topFriendsList").sortable('toArray');
		for (var iter=0;iter<newTopFriends.length;iter++) {
			newTopFriends[iter] = newTopFriends[iter].replace(/^t_/,'');
		}
		mjaxAPI.setTopFriends(newTopFriends,null,topFriends.saveTopFriendsResponseHandler);
	},

	saveTopFriendsResponseHandler: function(response) {
		refresh();
	},

	sortEndedHandler: function(event,ui) {
		var droppedID = $(ui.item).attr('id');
		if (!droppedID.match(/^t_/)) {
			var newID = "t_"+droppedID;
			$('#'+newID).remove();
			$(ui.item).attr('id',newID);
			$('#'+newID).html($('#newTopFriend').html());
			profilePicture = miniProfileUsers[droppedID]['profilePictureURLs']['sourceURL'];
			$('#'+newID+' img[name=topFriendProfilePicture]').attr('src',profilePicture);
			$('#'+newID+' div[name=topFriendUsername]').html(droppedID);
			topFriends.setDynamicProperties();
			var newTopFriendsList = $('#topFriendsList > li');
			if (newTopFriendsList.length > maxTopFriends) {
				$(newTopFriendsList[newTopFriendsList.length -1]).remove();
			}
			topFriends.setTopFriendCount();
		}
	},

	removeTopFriend: function() {
		$(this).closest('li').remove();
		topFriends.setTopFriendCount();
	},

	setTopFriendCount: function() {
		$('#topFriendCount').html($('#topFriendsList > li').length);
	},

	setDynamicProperties: function() {
		$(".removeTopFriend").click(topFriends.removeTopFriend);
	}

};

secretStash = {

    updateDescription: function(secretStashID, description) {
        var opaqueData = {'elementID':'profileSecretStash'};
        mjaxAPI.updateSecretStashDescription(secretStashID,description,opaqueData,mbuzzy.common.editInlineResponseHandler);
    },

    editPriceOpen: function(secretStashID, newSecretStash, elementID) {
        mjaxAPI.open.editSecretStashPrice(secretStashID,newSecretStash,elementID,null,null);
    },

    editPrice: function(secretStashID, price, elementID) {
        var opaqueData = null;
        if(elementID!=null){
            opaqueData = {'elementID':elementID};            
        }
        mjaxAPI.editSecretStashPrice(secretStashID,price,elementID,opaqueData,mbuzzy.common.editInlineResponseHandler);
    },
    
    rateSecretStash: function(secretStashID, purchaserUserID, secretStashPurchaseID, rating) {
        var opaqueData = {'elementID':'contentRating'};
        mjaxAPI.rateSecretStash(secretStashID,purchaserUserID,secretStashPurchaseID, rating,opaqueData,mbuzzy.common.editInlineResponseHandler);
    },

    openBuyVirtualGood: function(uid,cost,returnURL) {
        var vgRefKey = "SecretStash";
		mjaxAPI.open.buyVirtualGood(uid,vgRefKey,returnURL,cost,null,null);
    },

    openConfirmMoveProfileImage: function(method){
        var opaqueData = null;
        mjaxAPI.open.moveProfileImage(method,opaqueData,mbuzzy.common.editInlineResponseHandler);
    }
};
$(function() {
	mbuzzy.showProfile = {
	 };


});


