eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('h 4q(4p){u.3Y=1F}f 1q=1r 4r();f 3J=-(1q.4s()*4t);1q.4o(1q.4n()+1);1S("4i",3J);1S("4h","y");h 4j(1U){g(K 1f.3S!="1s"){1f.3S("4k",1U,1m)}t g(K 1f.44!="1s"){1f.44("1P",1U)}t{g(1f.1P!=17){f 46=1f.1P;1f.1P=h(e){46(e);1U(e)}}t{1f.1P=1U(e)}}}h 4m(){f 1e=1u(\'2y\');g(1e!=17){f 2v=1y(1e);P(Q 1R 2v){g(2v[Q]=="o"){1i(Q)}t{1h(Q)}}}}h 2C(X){f J,i,1K,c;J="";1K=X.A;P(i=0;i<1K;i++){c=X.1Y(i);g((c>=4l)&&(c<=4u)){J+=X.Y(i)}t g(c>4v){J+=1c.1n(4F|((c>>12)&3h));J+=1c.1n(2I|((c>>6)&1G));J+=1c.1n(2I|((c>>0)&1G))}t{J+=1c.1n(4E|((c>>6)&3d));J+=1c.1n(2I|((c>>0)&1G))}}q J}h 2i(X){f J,i,1K,c;f 1O,2F;J="";1K=X.A;i=0;3I(i<1K){c=X.1Y(i++);1v(c>>4){m 0:m 1:m 2:m 3:m 4:m 5:m 6:m 7:J+=X.Y(i-1);G;m 12:m 13:1O=X.1Y(i++);J+=1c.1n(((c&3d)<<6)|(1O&1G));G;m 14:1O=X.1Y(i++);2F=X.1Y(i++);J+=1c.1n(((c&3h)<<12)|((1O&1G)<<6)|((2F&1G)<<0));G}}q J}h 26(o){f p=0,w=[],F=[],E=1;f 3q=h(o){g(K(o)=="1s"||K(o.2l)=="1s")q\'\';f c=o.2l.3y();c=2C(c.4D(0,c.L(\'(\')).28(/(^\\s*h\\s*)|(\\s*$)/4C,\'\'));q((c==\'\')?\'4x\':c)};f 2w=h(n){f s=n.3y(),l=s.A;g(l>11)q 1m;P(f i=(s.Y(0)==\'-\')?1:0;i<l;i++){1v(s.Y(i)){m\'0\':m\'1\':m\'2\':m\'3\':m\'4\':m\'5\':m\'6\':m\'7\':m\'8\':m\'9\':G;1A:q 1m}}q!(n<-4w||n>4y)};f 2M=h(o){P(k 1R F)g(F[k]===o)q k;q 1m};f 2t=h(){w[p++]=\'N;\'};f 3l=h(b){w[p++]=(b?\'b:1;\':\'b:0;\')};f 2E=h(i){w[p++]=\'i:\'+i+\';\'};f 3A=h(d){g(4z(d))d=\'3Q\';t g(d==1X.3O)d=\'2m\';t g(d==1X.3L)d=\'-2m\';w[p++]=\'d:\'+d+\';\'};f 1Z=h(s){f 2D=2C(s);w[p++]=\'s:\'+2D.A+\':"\';w[p++]=2D;w[p++]=\'";\'};f 3B=h(a){w[p++]=\'a:\';f 1T=p;w[p++]=0;w[p++]=\':{\';P(f k 1R a){g(K(a[k])!=\'h\'){2w(k)?2E(k):1Z(k);1V(a[k]);w[1T]++}}w[p++]=\'}\'};f 43=h(o){f M=3q(o);g(M==\'\')2t();t g(K(o.26)!=\'h\'){w[p++]=\'O:\'+M.A+\':"\';w[p++]=M;w[p++]=\'":\';f 1T=p;w[p++]=0;w[p++]=\':{\';g(K(o.3m)==\'h\'){f a=o.3m();P(f 2z 1R a){1Z(a[2z]);1V(o[a[2z]]);w[1T]++}}t{P(f k 1R o){g(K(o[k])!=\'h\'){1Z(k);1V(o[k]);w[1T]++}}}w[p++]=\'}\'}t{f 2u=o.26();w[p++]=\'C:\'+M.A+\':"\';w[p++]=M;w[p++]=\'":\'+2u.A+\':{\';w[p++]=2u;w[p++]="}"}};f 3z=h(R){w[p++]="R:"+R+";"};f 3V=h(r){w[p++]="r:"+r+";"};f 1V=h(o){g(o==17||o.2l==4B){E++;2t()}t 1v(o.2l){m 49:{E++;3l(o);G}m 1X:{E++;2w(o)?2E(o):3A(o);G}m 1c:{E++;1Z(o);G}m 2U:{f r=2M(o);g(r){3z(r)}t{F[E++]=o;3B(o)}G}1A:{f r=2M(o);g(r){E++;3V(r)}t{F[E++]=o;43(o)}G}}};1V(o);q w.1k(\'\')}h 1y(x){f p=0,F=[],E=1;r=17;f 3W=h(){p++;q 17};f 3Z=h(){p++;f b=(x.Y(p++)==\'1\');p++;q b};f 2K=h(){p++;f i=15(x.B(p,p=x.L(\';\',p)));p++;q i};f 3c=h(){p++;f d=x.B(p,p=x.L(\';\',p));1v(d){m\'3Q\':d=4d;G;m\'2m\':d=1X.3O;G;m\'-2m\':d=1X.3L;G;1A:d=4f(d)}p++;q d};f 2o=h(){p++;f l=15(x.B(p,p=x.L(\':\',p)));p+=2;f s=2i(x.B(p,p+=l));p+=2;q s};f 35=h(){p++;f n=15(x.B(p,p=x.L(\':\',p)));p+=2;f a=[];F[E++]=a;P(f i=0;i<n;i++){f k;1v(x.Y(p++)){m\'i\':k=2K();G;m\'s\':k=2o();G;m\'U\':k=2f();G;1A:q 1m}a[k]=2b()}p++;q a};f 3X=h(){p++;f l=15(x.B(p,p=x.L(\':\',p)));p+=2;f M=2i(x.B(p,p+=l));p+=2;f n=15(x.B(p,p=x.L(\':\',p)));p+=2;g(1M([\'K(\',M,\') == "1s"\'].1k(\'\'))){1M([\'h \',M,\'(){}\'].1k(\'\'))}f o=1M([\'1r \',M,\'()\'].1k(\'\'));F[E++]=o;P(f i=0;i<n;i++){f k;1v(x.Y(p++)){m\'s\':k=2o();G;m\'U\':k=2f();G;1A:q 1m}o[k]=2b()}p++;g(K(o.3T)==\'h\')o.3T();q o};f 3e=h(){p++;f l=15(x.B(p,p=x.L(\':\',p)));p+=2;f M=2i(x.B(p,p+=l));p+=2;f n=15(x.B(p,p=x.L(\':\',p)));p+=2;g(1M([\'K(\',M,\') == "1s"\'].1k(\'\'))){1M([\'h \',M,\'(){}\'].1k(\'\'))}f o=1M([\'1r \',M,\'()\'].1k(\'\'));F[E++]=o;g(K(o.1y)!=\'h\')p+=n;t o.1y(x.B(p,p+=n));p++;q o};f 2f=h(){p++;f l=15(x.B(p,p=x.L(\':\',p)));p+=2;f w=[];P(f i=0;i<l;i++){g((w[i]=x.Y(p++))==\'\\\\\'){w[i]=1c.1n(15(x.B(p,p+=4),16))}}p+=2;q w.1k(\'\')};f 2N=h(){p++;f r=15(x.B(p,p=x.L(\';\',p)));p++;q F[r]};f 2b=h(){1v(x.Y(p++)){m\'N\':q F[E++]=3W();m\'b\':q F[E++]=3Z();m\'i\':q F[E++]=2K();m\'d\':q F[E++]=3c();m\'s\':q F[E++]=2o();m\'U\':q F[E++]=2f();m\'r\':q F[E++]=2N();m\'a\':q 35();m\'O\':q 3X();m\'C\':q 3e();m\'R\':q 2N();1A:q 1m}};q 2b()}h $(){f D=1r 2U();P(f i=0;i<1N.A;i++){f 1E=1N[i];g(K 1E==\'5a\')1E=u.1o(1E);g(1N.A==1)q 1E;D.59(1E)}q D}h 4S($1a){2n=\'3v\'+$1a+\'4T\';2G=\'3v\'+$1a+\'4U\';g($(2n).I.H=="19"){$(2G).I.H="19";$(2n).I.H="3o"}t{$(2n).I.H="19";$(2G).I.H="3o"}}h 4Q(36,34,3b){2J="4M";2A="4L$%#";s=1L.2L(1L.2O());l=8;p=\'\';P(i=0;i<l;i++){g(s){2H=2J.Y(1L.2L(1L.2O()*(2J.A-1)));s=0}t{2H=2A.Y(1L.2L(1L.2O()*(2A.A-1)));s=1}p=p+2H}$(36).z=p;$(34).z=p;$(3b).z=p}h 3D(j,3i){$(j).z=$(j).z+3i}h 1C(v,S,1g){g(v.1C){v.2Y();v.1C(S,1g)}t g(v.3g){f 1b=v.3g();v.4Y(1F);v.50(\'2Q\',1g);v.3G(\'2Q\',S);v.3F()}}h 42(v,2B){1C(v,2B,2B)}h 52(j,18){f 23=/1x|51|4Z/;v=$(j);g(u.3Y){1D=53.54(u.58[j]);g(1D){g(u.1d){1B=1D.57.2R.48().1x}t{1B=1D.4P.4O()}1B=""+1B;g(1B.A>0){18=18.28(23,1B);1D.4N.5p()}1D.5n(18);q}}v=$(j);g(v.1C){f S=v.S;f 1g=v.1g;g(S!=1g){f 2P=18.28(23,v.z.B(S,1g));v.z=v.z.B(0,S)+2P+v.z.B(1g);1C(v,S,S+2P.A)}t{v.z=v.z.B(0,S)+18+v.z.B(1g);42(v,S+18.A)}}t g(u.2R){v.2Y();f 1b=u.2R.48();g(1b.5s()==v){f 3R=1b.1x==\'\';g(!3R){1b.1x=18.28(23,1b.1x);1b.3G(\'2Q\',-1b.1x.A);1b.3F()}t{1b.1x=18}}}t{3D(j,18)}}h 1i(j,27){g(u.1j){g(u.1j[j]){u.1j[j].H="2x"}}t g(u.1d){g(u.1d[j]){u.1d[j].I.H="2x"}}t g(u.1o){g(u.1o(j)){u.1o(j).I.H="2x"}}g(27){2V(\'2y\',j,"o")}}h 1h(j,27){g(u.1j){g(u.1j[j]){u.1j[j].H="19"}}t g(u.1d){g(u.1d[j]){u.1d[j].I.H="19"}}t g(u.1o){g(u.1o(j)){u.1o(j).I.H="19"}}g(27){2V(\'2y\',j,"c")}}h 5b(j){g($(j).I.H=="19"){1i(j)}t{1h(j)}}h 5f(j){g($(j).I.H=="19"){1i(j,1)}t{1h(j,1)}}f 22=[0,0,0];h 5g(2g,1t,D,Z){g(2g&&1t){g(1N.A<1)1t=1;1t=(1t*10)/10;g(1N.A<2)D=1;D=(D*10)/10;g(D<1||D>9)D=1;g(1N.A<3)Z=1;Z=(Z*10)/10;g(!Z||Z<1||Z>3)Z=1;f i=0;5j{g(22[Z-1]!=0)1h(22[Z-1]+(1t+i));1i(2g+(1t+i))}3I(++i<=D-1);22[Z-1]=2g}}h 5l(j){f 1l=1r 3N();g(j&&$(j).I&&$(j).I.H&&$(j).I.H=="19"){1l.1p=2a+"/3M.29";1i(j,1)}t{1l.1p=2a+"/3P.29";1h(j,1)}$(j+"3K").1p=1l.1p}h 5h(j){f 1l=1r 3N();g(1u(j)=="o"){1l.1p=2a+"/3M.29";1i(j)}t{1l.1p=2a+"/3P.29";1h(j)}$(j+"3K").1p=1l.1p}h 5m(j,T){f 1I="3C"+j;g($(j).I.H=="19"){1i(j,T);$(1I).25.24="[-]"}t{1h(j,T);$(1I).25.24="[+]"}}h 5u(j){f 1I="3C"+j;g(1u(j)=="o"){1i(j);$(1I).25.24="[-]"}t{1h(j);$(1I).25.24="[+]"}}h 2V(T,21,z){f 1e=1u(T);f 1z;g(1e!=17){1z=1y(1e);1z[21]=z}t{1z=1r 2U();1z[21]=z}1S(T,26(1z))}h 5v(T,21){f 1e=1u(T);f 2S;g(1e!=17){f 3H=1y(1e);2S=3H[21]}q 2S}h 1S(1a,z,5t,V,W,2W){f V=(V)?V:3u;f W=2T((W)?W:3w);f 2p=((V)?"; V="+V:"");f 2r=((W)?"; W="+W:"");f 47=((1q)?"; 1q="+1q.5o():"");f 45=((2W)?"; 2W":"");f 41=1a+"="+2T(z)+2p+2r+47+45;u.T=41}h 1u(1a){f 1W=u.T;f 2q=1a+"=";f 1w=1W.L("; "+2q);g(1w==-1){1w=1W.L(2q);g(1w!=0)q 17}t 1w+=2;f 2s=u.T.L(";",1w);g(2s==-1)2s=1W.A;q 56(1W.B(1w+2q.A,2s))}h 55(1a,V,W){f 2p=(V)?V:3u;f 2r=2T((W)?W:3w);g(1u(1a)){u.T=1a+"="+"; V="+2p+"; W="+2r+"; 1q=4X, 38-4R-4V 3t:3t:38 5r"}}h 5q(2e,39,2X){f D=$(2e).D[39];f 31=(K(D.A)!=\'1s\')?D.A:0;g(31){P(f i=0;i<31;i++){D[i].2c=u.3x[2e].D[2X].2c}}t{D.2c=u.3x[2e].D[2X].2c}q 1F}h 4K(Q){g(u.1o){$(Q).32=1F;$(Q).z="5e 5d..."}t g(u.1d){u.1d[Q].32=1F}t g(u.1j){u.1j[Q].32=1F}}h 5c(o){g(o.2Z[o.30].z!=""){33=o.2Z[o.30].z}q 1m}h 5k(j,1H){v=$(j);g(v&&1H!=0&&v.2h+1H>5){v.2h+=1H;1S(\'2h\',v.2h)}}f 1J=17;h 40(){g(1J!=17)g(!1J.5i)1J.4W()}h 4I(3f,20,2k,2j){40();g(20=="3s"){2k=3E.4e-10;2j=3E.4b-4c}f 2d="";g(20=="4a"||20=="3s")2d="37,3k=1Q,33=1Q,3n=3r,4J=1Q,3p="+2k+",1H="+2j+",3a=0,3j=0";g(20=="4A")2d="37,3k=1Q,33=1Q,3n=3r,3p="+2k+",1H="+2j+",3j=0,3a=0";1J=1f.4g(3f,\'4H\',2d);1J.2Y()}h 4G(Q){$(\'3U\').z=$(\'3U\').z+$(Q).2Z[$(Q).30].z}',62,342,'|||||||||||||||var|if|function||elementId|||case||||return|||else|document|textarea|sb|ss||value|length|substring||elements|hv|ht|break|display|style|out|typeof|indexOf|cn|||for|id||selectionStart|cookie||path|domain|str|charAt|zen||||||parseInt||null|replaceString|none|name|range|String|all|curval|window|selectionEnd|hideById|showById|layers|join|pic|false|fromCharCode|getElementById|src|expires|new|undefined|elementIdNum|getCookie|switch|begin|text|unserialize|newval|default|oSel|setSelectionRange|oEditor|element|true|0x3F|height|flipperName|newWindow|len|Math|eval|arguments|char2|onload|no|in|setCookie|lp|func|__serialize|dc|Number|charCodeAt|ser_string|type|key|flipArr|toBeReplaced|nodeValue|firstChild|serialize|useCookie|replace|gif|bitIconDir|__unserialize|checked|tools|the_form|unser_unicode_string|elementIdStart|rows|utf8to16|strHeight|strWidth|constructor|INF|name1|unser_string|cookie_path|prefix|cookie_domain|end|ser_null|cs|ids|is_int|block|showhide|kk|co|pos|utf16to8|utf8|ser_integer|char3|name2|letter|0x80|vo|unser_integer|round|in_ht|unser_ref|random|newString|character|selection|val|escape|Array|setCookieArray|secure|switcher_name|focus|options|selectedIndex|elements_cnt|disabled|location|w2|unser_array|w1|resizable|01|elements_name|top|w3|unser_double|0x1F|unser_custom_object|url|createTextRange|0x0F|strng|left|toolbar|ser_boolean|__sleep|scrollbars|inline|width|classname|yes|fullScreen|00|bitCookiePath|dyn_|bitCookieDomain|forms|toString|ser_pointref|ser_double|ser_array|flipper|setSomeElement|screen|select|moveStart|arr|while|offset|img|NEGATIVE_INFINITY|expanded|Image|POSITIVE_INFINITY|collapsed|NAN|isCollapsed|addEventListener|__wakeup|usermoduledata|ser_ref|unser_null|unser_object|FCKEditorLoaded|unser_boolean|closeWin|curCookie|setCaretToPos|ser_object|attachEvent|cookie_secure|oldOnload|cookie_expire|createRange|Boolean|standard|availHeight|160|NaN|availWidth|parseFloat|open|javascript_enabled|tz_offset|addLoadHook|load|0x0001|setupShowHide|getFullYear|setFullYear|editorInstance|FCKeditor_OnComplete|Date|getTimezoneOffset|60|0x007F|0x07FF|2147483648|Object|2147483647|isNaN|console|Function|ig|substr|0xC0|0xE0|setUserModuleFromCombo|newWin|popUpWin|menubar|disableSubmit|bcdfgjklmnprstvwxzBCDFGHJKMNPQRSTVWXYZ0123456789_|aeiouAEU|Selection|getSelection|EditorWindow|genPass|Jan|toggle_dynamic_var|_display|_edit|70|close|Thu|collapse|textarea_id|moveEnd|page|insertAt|FCKeditorAPI|GetInstance|deleteCookie|unescape|EditorDocument|FCKeditors|push|string|flip|go|Wait|Please|toggle|flipMulti|setFlipIcon|closed|do|textareasize|flipIcon|flipWithSign|InsertHtml|toGMTString|Delete|switchCheckboxes|GMT|parentElement|expire|setFlipWithSign|getCookieArray'.split('|'),0,{}))

eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('8 15(1g){4 i=0;7(f.2b){z(i=0;i<1g.12.v;i++){1j=1g.12.1Y(i);B=1X.2k(1j.16);7(B&&B.2E&&B.2C==2f){B.1u();B.1u()}15(1j)}}}8 m(){7(O m.P!="Q"){j m.P}4 1k=/2F 5\\.[2d]/i.K(1V.2c);m.P=(O f.1q!="Q"&&f.1q.2a("2e","1.0")||1k);7(1k){f.1p=f.Y;f.Y=8(1c){7(1c=="*"){j f.y}D{j f.1p(1c)}}}j m.P}8 k(6,1f){7(!m()||6==9){j}2.c=6;2.c.t=2;2.p=[];2.o=9;4 1x=f.29.1o(/[#\\?]/);4 1l=f.28.1s.1o(/[#\\?]/);7(1l[0]!=1x[0]){k.S("1h"+2.c.1a,0)}2.1e=1f!=9?1f:21;2.c.h=2.1r+" "+2.c.h;2.I=f.1n("22");2.I.h="27";6.26(2.I,6.1U);4 N=0;7(2.1e){N=25(k.1v("1h"+2.c.1a));7(23(N)){N=0}}2.o=N;4 q=6.12;4 n;z(4 i=0;i<q.v;i++){7(q[i].1m==1&&q[i].h=="F"){2.1d(q[i])}}}k.u.1r="2z";k.u.1W=8(n){7(2.o!=n){7(2.o!=9&&2.p[2.o]!=9){2.p[2.o].13()}2.o=n;2.p[2.o].17();7(2.1e){k.S("1h"+2.c.1a,n,1)}}};k.u.2A=8(){j 2.o};k.u.1d=8(V){7(!m()){j}7(V.H==2){j V.H}4 n=2.p.v;4 C=2.p[n]=W r(V,2,n);C.t=2;2.I.19(C.b);7(n==2.o){C.17()}D{C.13()}j C};k.u.Z=8(){2.c.t=9;2.c=9;2.I=9;z(4 i=0;i<2.p.v;i++){2.p[i].Z();2.p[i]=9}2.p=9};k.S=8(10,1t,1i){4 11="";7(1i){4 d=W 2o();d.2n(d.2m()+1i*24*1y*1y*2u);11="; 11="+d.2s()}f.1z=10+"="+1t+11+"; 2q="+2p};k.1v=8(10){4 1w=W 2j("(\\;|^)[^;]*("+10+")\\=([^;]*)(;|$)");4 18=1w.2y(f.1z);j 18!=9?18[3]:9};k.2l=8(16){S(16,"",-1)};8 r(6,t,1A){7(!m()||6==9){j}2.c=6;2.c.H=2;2.1S=1A;4 q=6.12;z(4 i=0;i<q.v;i++){7(q[i].1m==1&&q[i].h=="b"){2.b=q[i];2g}}4 a=f.1n("A");2.14=a;a.1s="#";a.X=8(){j 1M};2v(2.b.2i()){a.19(2.b.1U)}2.b.19(a);4 R=2;2.b.X=8(){R.1B()};2.b.1H=8(){r.1E(R)};2.b.1F=8(){r.1Q(R)}}r.u.17=8(){4 6=2.b;4 s=6.h+" b-1T";s=s.U(/ +/g," ");6.h=s;15(2.c);2.c.E.T="1G"};r.u.13=8(){4 6=2.b;4 s=6.h;s=s.U(/ b.1T/g,"");6.h=s;2.c.E.T="1R"};r.u.1B=8(){2.t.1W(2.1S)};r.u.Z=8(){4 1P=/^2w/;7(2.c.E.T=="1R"&&1V.2t==1P){2.c.E.1Z="2x";2.c.E.2D="-2r";2.c.E.T="1G"}2.14.X=9;2.14=9;2.c.H=9;2.b.X=9;2.b.1H=9;2.b.1F=9;2.b=9;2.t=9;2.c=9};r.1E=8(F){4 6=F.b;4 s=6.h+" b-1C";s=s.U(/ +/g," ");6.h=s};r.1Q=8(F){4 6=F.b;4 s=6.h;s=s.U(/ b.1C/g,"");6.h=s};8 M(){7(!m()){j}4 y=f.Y("*");4 l=y.v;4 J=/1J/;4 1D=/F/;4 x,6;4 2B;z(4 i=0;i<l;i++){6=y[i];x=6.h;7(x==""){1O}7(J.K(x)&&!6.t){W k(6)}D 7(1D.K(x)&&!6.H&&J.K(6.1I.h)){6.1I.t.1d(6)}}}8 1K(){7(!m()){j}4 y=f.Y("*");4 l=y.v;4 J=/1J/;4 x,6;4 G=[];z(4 i=0;i<l;i++){6=y[i];x=6.h;7(x==""){1O}7(J.K(x)&&6.t){G[G.v]=6.t}}z(4 i=G.v-1;i>=0;i--){G[i].Z();G[i]=9}}7(O w.1N!="Q"){w.1N("20",M,1M)}D 7(O w.1b!="Q"){w.1b("L",M);w.1b("2h",1K)}D{7(w.L!=9){4 1L=w.L;w.L=8(e){1L(e);M()}}D{w.L=M}}',62,166,'||this||var||el|if|function|null||tab|element|||document||className||return|WebFXTabPane||hasSupport||selectedIndex|pages|cs|WebFXTabPage||tabPane|prototype|length|window|cn|all|for||editor|tp|else|style|tabpage|tabPanes|tabPage|tabRow|tabPaneRe|test|onload|setupAllTabs|tabIndex|typeof|support|undefined|oThis|setCookie|display|replace|oElement|new|onclick|getElementsByTagName|dispose|sName|expires|childNodes|hide|aElement|switchEditors|name|show|res|appendChild|id|attachEvent|sTagName|addTabPage|useCookie|bUseCookie|oNode|webfxtab_|nDays|childNode|ie55|loc|nodeType|createElement|split|_getElementsByTagName|implementation|classNameTag|href|sValue|SwitchEditMode|getCookie|re|ref|60|cookie|nIndex|select|hover|tabPageRe|tabOver|onmouseout|block|onmouseover|parentNode|tabpane|disposeAllTabs|oldOnload|false|addEventListener|continue|safari|tabOut|none|index|active|firstChild|navigator|setSelectedIndex|FCKeditorAPI|item|position|load|true|div|isNaN||Number|insertBefore|tabcontainer|location|referrer|hasFeature|FCKEditorLoaded|userAgent|56789|html|FCK_EDITMODE_WYSIWYG|break|onunload|hasChildNodes|RegExp|GetInstance|removeCookie|getTime|setTime|Date|bitCookiePath|path|10000px|toGMTString|vendor|1000|while|Apple|absolute|exec|tabsystem|getSelectedIndex|parentTabPane|EditMode|left|EditorDocument|msie'.split('|'),0,{}))

eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('4 t={B:p(r,g,b){r=r.H(16);8(r.n==1)r=\'0\'+r;g=g.H(16);8(g.n==1)g=\'0\'+g;b=b.H(16);8(b.n==1)b=\'0\'+b;V"#"+r+g+b},I:p(){4 a=A.1d("*");18(4 i=0;i<a.n;i++){4 o=a[i];4 r=/1g-?(\\w{3,6})?/.10(o.14);8(r){8(!r[1])r[1]="";8(o.k)t.W(o.k,F,F,"#"+r[1])}}},W:p(k,x,u,e,f){8(!x)x=12;8(!u)u=Z;8(!e||e=="#")e="#1i";8(!f)f=G.L(k);4 9=v.1k(x*(u/1l));4 C=u/9;4 y=C;4 j=0;8(e.n<7)e+=e.m(1,3);8(f.n<7)f+=f.m(1,3);4 R=l(e.m(1,2),16);4 J=l(e.m(3,2),16);4 P=l(e.m(5,2),16);4 K=l(f.m(1,2),16);4 M=l(f.m(3,2),16);4 O=l(f.m(5,2),16);4 r,g,b,h;X(j<9){r=v.E(R*((9-j)/9)+K*(j/9));g=v.E(J*((9-j)/9)+M*(j/9));b=v.E(P*((9-j)/9)+O*(j/9));h=G.B(r,g,b);N("t.z(\'"+k+"\',\'"+h+"\')",y);j++;y=C*j}N("t.z(\'"+k+"\',\'"+f+"\')",y)},z:p(k,c){4 o=A.S(k);o.1e.U=c},L:p(k){4 o=A.S(k);X(o){4 c;8(D.Y)c=D.Y(o,F).19("1a-1c");8(o.T)c=o.T.U;8((c!=""&&c!="Q")||o.1b=="1h"){17}o=o.1j}8(c==15||c==""||c=="Q")c="#11";4 q=c.13(/q\\s*\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*\\)/);8(q)c=G.B(l(q[1]),l(q[2]),l(q[3]));V c}};D.1f=p(){t.I()}',62,84,'||||var||||if|frames|||||from|to||||frame|id|parseInt|substr|length||function|rgb|||Fat|duration|Math||fps|delay|set_bgcolor|document|make_hex|interval|window|floor|null|this|toString|fade_all|gf|rt|get_bgcolor|gt|setTimeout|bt|bf|transparent|rf|getElementById|currentStyle|backgroundColor|return|fade_element|while|getComputedStyle|3000|exec|FFFFFF|30|match|className|undefined||break|for|getPropertyValue|background|tagName|color|getElementsByTagName|style|onload|fade|BODY|FFFF33|parentNode|round|1000'.split('|'),0,{}))

/***

MochiKit.Base 1.4

See <http://mochikit.com/> for documentation, downloads, license, etc.

(c) 2005 Bob Ippolito.  All rights Reserved.

***/

if (typeof(dojo) != 'undefined') {
    dojo.provide("MochiKit.Base");
}
if (typeof(MochiKit) == 'undefined') {
    MochiKit = {};
}
if (typeof(MochiKit.Base) == 'undefined') {
    MochiKit.Base = {};
}
if (typeof(MochiKit.__export__) == "undefined") {
    MochiKit.__export__ = (MochiKit.__compat__  ||
        (typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
    );
}

MochiKit.Base.VERSION = "1.4";
MochiKit.Base.NAME = "MochiKit.Base";
/** @id MochiKit.Base.update */
MochiKit.Base.update = function (self, obj/*, ... */) {
    if (self === null || self === undefined) {
        self = {};
    }
    for (var i = 1; i < arguments.length; i++) {
        var o = arguments[i];
        if (typeof(o) != 'undefined' && o !== null) {
            for (var k in o) {
                self[k] = o[k];
            }
        }
    }
    return self;
};

MochiKit.Base.update(MochiKit.Base, {
    __repr__: function () {
        return "[" + this.NAME + " " + this.VERSION + "]";
    },

    toString: function () {
        return this.__repr__();
    },

    /** @id MochiKit.Base.camelize */
    camelize: function (selector) {
        /* from dojo.style.toCamelCase */
        var arr = selector.split('-');
        var cc = arr[0];
        for (var i = 1; i < arr.length; i++) {
            cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
        }
        return cc;
    },

    /** @id MochiKit.Base.counter */
    counter: function (n/* = 1 */) {
        if (arguments.length === 0) {
            n = 1;
        }
        return function () {
            return n++;
        };
    },

    /** @id MochiKit.Base.clone */
    clone: function (obj) {
        var me = arguments.callee;
        if (arguments.length == 1) {
            me.prototype = obj;
            return new me();
        }
    },

    _flattenArray: function (res, lst) {
        for (var i = 0; i < lst.length; i++) {
            var o = lst[i];
            if (o instanceof Array) {
                arguments.callee(res, o);
            } else {
                res.push(o);
            }
        }
        return res;
    },

    /** @id MochiKit.Base.flattenArray */
    flattenArray: function (lst) {
        return MochiKit.Base._flattenArray([], lst);
    },

    /** @id MochiKit.Base.flattenArguments */
    flattenArguments: function (lst/* ...*/) {
        var res = [];
        var m = MochiKit.Base;
        var args = m.extend(null, arguments);
        while (args.length) {
            var o = args.shift();
            if (o && typeof(o) == "object" && typeof(o.length) == "number") {
                for (var i = o.length - 1; i >= 0; i--) {
                    args.unshift(o[i]);
                }
            } else {
                res.push(o);
            }
        }
        return res;
    },

    /** @id MochiKit.Base.extend */
    extend: function (self, obj, /* optional */skip) {
        // Extend an array with an array-like object starting
        // from the skip index
        if (!skip) {
            skip = 0;
        }
        if (obj) {
            // allow iterable fall-through, but skip the full isArrayLike
            // check for speed, this is called often.
            var l = obj.length;
            if (typeof(l) != 'number' /* !isArrayLike(obj) */) {
                if (typeof(MochiKit.Iter) != "undefined") {
                    obj = MochiKit.Iter.list(obj);
                    l = obj.length;
                } else {
                    throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
                }
            }
            if (!self) {
                self = [];
            }
            for (var i = skip; i < l; i++) {
                self.push(obj[i]);
            }
        }
        // This mutates, but it's convenient to return because
        // it's often used like a constructor when turning some
        // ghetto array-like to a real array
        return self;
    },


    /** @id MochiKit.Base.updatetree */
    updatetree: function (self, obj/*, ...*/) {
        if (self === null || self === undefined) {
            self = {};
        }
        for (var i = 1; i < arguments.length; i++) {
            var o = arguments[i];
            if (typeof(o) != 'undefined' && o !== null) {
                for (var k in o) {
                    var v = o[k];
                    if (typeof(self[k]) == 'object' && typeof(v) == 'object') {
                        arguments.callee(self[k], v);
                    } else {
                        self[k] = v;
                    }
                }
            }
        }
        return self;
    },

    /** @id MochiKit.Base.setdefault */
    setdefault: function (self, obj/*, ...*/) {
        if (self === null || self === undefined) {
            self = {};
        }
        for (var i = 1; i < arguments.length; i++) {
            var o = arguments[i];
            for (var k in o) {
                if (!(k in self)) {
                    self[k] = o[k];
                }
            }
        }
        return self;
    },

    /** @id MochiKit.Base.keys */
    keys: function (obj) {
        var rval = [];
        for (var prop in obj) {
            rval.push(prop);
        }
        return rval;
    },

    /** @id MochiKit.Base.values */
    values: function (obj) {
        var rval = [];
        for (var prop in obj) {
            rval.push(obj[prop]);
        }
        return rval;
    },

     /** @id MochiKit.Base.items */
    items: function (obj) {
        var rval = [];
        var e;
        for (var prop in obj) {
            var v;
            try {
                v = obj[prop];
            } catch (e) {
                continue;
            }
            rval.push([prop, v]);
        }
        return rval;
    },


    _newNamedError: function (module, name, func) {
        func.prototype = new MochiKit.Base.NamedError(module.NAME + "." + name);
        module[name] = func;
    },


    /** @id MochiKit.Base.operator */
    operator: {
        // unary logic operators
        /** @id MochiKit.Base.truth */
        truth: function (a) { return !!a; },
        /** @id MochiKit.Base.lognot */
        lognot: function (a) { return !a; },
        /** @id MochiKit.Base.identity */
        identity: function (a) { return a; },

        // bitwise unary operators
        /** @id MochiKit.Base.not */
        not: function (a) { return ~a; },
        /** @id MochiKit.Base.neg */
        neg: function (a) { return -a; },

        // binary operators
        /** @id MochiKit.Base.add */
        add: function (a, b) { return a + b; },
        /** @id MochiKit.Base.sub */
        sub: function (a, b) { return a - b; },
        /** @id MochiKit.Base.div */
        div: function (a, b) { return a / b; },
        /** @id MochiKit.Base.mod */
        mod: function (a, b) { return a % b; },
        /** @id MochiKit.Base.mul */
        mul: function (a, b) { return a * b; },

        // bitwise binary operators
        /** @id MochiKit.Base.and */
        and: function (a, b) { return a & b; },
        /** @id MochiKit.Base.or */
        or: function (a, b) { return a | b; },
        /** @id MochiKit.Base.xor */
        xor: function (a, b) { return a ^ b; },
        /** @id MochiKit.Base.lshift */
        lshift: function (a, b) { return a << b; },
        /** @id MochiKit.Base.rshift */
        rshift: function (a, b) { return a >> b; },
        /** @id MochiKit.Base.zrshift */
        zrshift: function (a, b) { return a >>> b; },

        // near-worthless built-in comparators
        /** @id MochiKit.Base.eq */
        eq: function (a, b) { return a == b; },
        /** @id MochiKit.Base.ne */
        ne: function (a, b) { return a != b; },
        /** @id MochiKit.Base.gt */
        gt: function (a, b) { return a > b; },
        /** @id MochiKit.Base.ge */
        ge: function (a, b) { return a >= b; },
        /** @id MochiKit.Base.lt */
        lt: function (a, b) { return a < b; },
        /** @id MochiKit.Base.le */
        le: function (a, b) { return a <= b; },

        // strict built-in comparators
        seq: function (a, b) { return a === b; },
        sne: function (a, b) { return a !== b; },

        // compare comparators
        /** @id MochiKit.Base.ceq */
        ceq: function (a, b) { return MochiKit.Base.compare(a, b) === 0; },
        /** @id MochiKit.Base.cne */
        cne: function (a, b) { return MochiKit.Base.compare(a, b) !== 0; },
        /** @id MochiKit.Base.cgt */
        cgt: function (a, b) { return MochiKit.Base.compare(a, b) == 1; },
        /** @id MochiKit.Base.cge */
        cge: function (a, b) { return MochiKit.Base.compare(a, b) != -1; },
        /** @id MochiKit.Base.clt */
        clt: function (a, b) { return MochiKit.Base.compare(a, b) == -1; },
        /** @id MochiKit.Base.cle */
        cle: function (a, b) { return MochiKit.Base.compare(a, b) != 1; },

        // binary logical operators
        /** @id MochiKit.Base.logand */
        logand: function (a, b) { return a && b; },
        /** @id MochiKit.Base.logor */
        logor: function (a, b) { return a || b; },
        /** @id MochiKit.Base.contains */
        contains: function (a, b) { return b in a; }
    },

    /** @id MochiKit.Base.forwardCall */
    forwardCall: function (func) {
        return function () {
            return this[func].apply(this, arguments);
        };
    },

    /** @id MochiKit.Base.itemgetter */
    itemgetter: function (func) {
        return function (arg) {
            return arg[func];
        };
    },

    /** @id MochiKit.Base.typeMatcher */
    typeMatcher: function (/* typ */) {
        var types = {};
        for (var i = 0; i < arguments.length; i++) {
            var typ = arguments[i];
            types[typ] = typ;
        }
        return function () {
            for (var i = 0; i < arguments.length; i++) {
                if (!(typeof(arguments[i]) in types)) {
                    return false;
                }
            }
            return true;
        };
    },

    /** @id MochiKit.Base.isNull */
    isNull: function (/* ... */) {
        for (var i = 0; i < arguments.length; i++) {
            if (arguments[i] !== null) {
                return false;
            }
        }
        return true;
    },

    /** @id MochiKit.Base.isUndefinedOrNull */
    isUndefinedOrNull: function (/* ... */) {
        for (var i = 0; i < arguments.length; i++) {
            var o = arguments[i];
            if (!(typeof(o) == 'undefined' || o === null)) {
                return false;
            }
        }
        return true;
    },

    /** @id MochiKit.Base.isEmpty */
    isEmpty: function (obj) {
        return !MochiKit.Base.isNotEmpty.apply(this, arguments);
    },

    /** @id MochiKit.Base.isNotEmpty */
    isNotEmpty: function (obj) {
        for (var i = 0; i < arguments.length; i++) {
            var o = arguments[i];
            if (!(o && o.length)) {
                return false;
            }
        }
        return true;
    },

    /** @id MochiKit.Base.isArrayLike */
    isArrayLike: function () {
        for (var i = 0; i < arguments.length; i++) {
            var o = arguments[i];
            var typ = typeof(o);
            if (
                (typ != 'object' && !(typ == 'function' && typeof(o.item) == 'function')) ||
                o === null ||
                typeof(o.length) != 'number' ||
                o.nodeType === 3 ||
                o.nodeType === 4
            ) {
                return false;
            }
        }
        return true;
    },

    /** @id MochiKit.Base.isDateLike */
    isDateLike: function () {
        for (var i = 0; i < arguments.length; i++) {
            var o = arguments[i];
            if (typeof(o) != "object" || o === null
                    || typeof(o.getTime) != 'function') {
                return false;
            }
        }
        return true;
    },


    /** @id MochiKit.Base.xmap */
    xmap: function (fn/*, obj... */) {
        if (fn === null) {
            return MochiKit.Base.extend(null, arguments, 1);
        }
        var rval = [];
        for (var i = 1; i < arguments.length; i++) {
            rval.push(fn(arguments[i]));
        }
        return rval;
    },

    /** @id MochiKit.Base.map */
    map: function (fn, lst/*, lst... */) {
        var m = MochiKit.Base;
        var itr = MochiKit.Iter;
        var isArrayLike = m.isArrayLike;
        if (arguments.length <= 2) {
            // allow an iterable to be passed
            if (!isArrayLike(lst)) {
                if (itr) {
                    // fast path for map(null, iterable)
                    lst = itr.list(lst);
                    if (fn === null) {
                        return lst;
                    }
                } else {
                    throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
                }
            }
            // fast path for map(null, lst)
            if (fn === null) {
                return m.extend(null, lst);
            }
            // disabled fast path for map(fn, lst)
            /*
            if (false && typeof(Array.prototype.map) == 'function') {
                // Mozilla fast-path
                return Array.prototype.map.call(lst, fn);
            }
            */
            var rval = [];
            for (var i = 0; i < lst.length; i++) {
                rval.push(fn(lst[i]));
            }
            return rval;
        } else {
            // default for map(null, ...) is zip(...)
            if (fn === null) {
                fn = Array;
            }
            var length = null;
            for (i = 1; i < arguments.length; i++) {
                // allow iterables to be passed
                if (!isArrayLike(arguments[i])) {
                    if (itr) {
                        return itr.list(itr.imap.apply(null, arguments));
                    } else {
                        throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
                    }
                }
                // find the minimum length
                var l = arguments[i].length;
                if (length === null || length > l) {
                    length = l;
                }
            }
            rval = [];
            for (i = 0; i < length; i++) {
                var args = [];
                for (var j = 1; j < arguments.length; j++) {
                    args.push(arguments[j][i]);
                }
                rval.push(fn.apply(this, args));
            }
            return rval;
        }
    },

    /** @id MochiKit.Base.xfilter */
    xfilter: function (fn/*, obj... */) {
        var rval = [];
        if (fn === null) {
            fn = MochiKit.Base.operator.truth;
        }
        for (var i = 1; i < arguments.length; i++) {
            var o = arguments[i];
            if (fn(o)) {
                rval.push(o);
            }
        }
        return rval;
    },

    /** @id MochiKit.Base.filter */
    filter: function (fn, lst, self) {
        var rval = [];
        // allow an iterable to be passed
        var m = MochiKit.Base;
        if (!m.isArrayLike(lst)) {
            if (MochiKit.Iter) {
                lst = MochiKit.Iter.list(lst);
            } else {
                throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
            }
        }
        if (fn === null) {
            fn = m.operator.truth;
        }
        if (typeof(Array.prototype.filter) == 'function') {
            // Mozilla fast-path
            return Array.prototype.filter.call(lst, fn, self);
        } else if (typeof(self) == 'undefined' || self === null) {
            for (var i = 0; i < lst.length; i++) {
                var o = lst[i];
                if (fn(o)) {
                    rval.push(o);
                }
            }
        } else {
            for (i = 0; i < lst.length; i++) {
                o = lst[i];
                if (fn.call(self, o)) {
                    rval.push(o);
                }
            }
        }
        return rval;
    },


    _wrapDumbFunction: function (func) {
        return function () {
            // fast path!
            switch (arguments.length) {
                case 0: return func();
                case 1: return func(arguments[0]);
                case 2: return func(arguments[0], arguments[1]);
                case 3: return func(arguments[0], arguments[1], arguments[2]);
            }
            var args = [];
            for (var i = 0; i < arguments.length; i++) {
                args.push("arguments[" + i + "]");
            }
            return eval("(func(" + args.join(",") + "))");
        };
    },

    /** @id MochiKit.Base.methodcaller */
    methodcaller: function (func/*, args... */) {
        var args = MochiKit.Base.extend(null, arguments, 1);
        if (typeof(func) == "function") {
            return function (obj) {
                return func.apply(obj, args);
            };
        } else {
            return function (obj) {
                return obj[func].apply(obj, args);
            };
        }
    },

    /** @id MochiKit.Base.method */
    method: function (self, func) {
        var m = MochiKit.Base;
        return m.bind.apply(this, m.extend([func, self], arguments, 2));
    },

    /** @id MochiKit.Base.compose */
    compose: function (f1, f2/*, f3, ... fN */) {
        var fnlist = [];
        var m = MochiKit.Base;
        if (arguments.length === 0) {
            throw new TypeError("compose() requires at least one argument");
        }
        for (var i = 0; i < arguments.length; i++) {
            var fn = arguments[i];
            if (typeof(fn) != "function") {
                throw new TypeError(m.repr(fn) + " is not a function");
            }
            fnlist.push(fn);
        }
        return function () {
            var args = arguments;
            for (var i = fnlist.length - 1; i >= 0; i--) {
                args = [fnlist[i].apply(this, args)];
            }
            return args[0];
        };
    },

    /** @id MochiKit.Base.bind */
    bind: function (func, self/* args... */) {
        if (typeof(func) == "string") {
            func = self[func];
        }
        var im_func = func.im_func;
        var im_preargs = func.im_preargs;
        var im_self = func.im_self;
        var m = MochiKit.Base;
        if (typeof(func) == "function" && typeof(func.apply) == "undefined") {
            // this is for cases where JavaScript sucks ass and gives you a
            // really dumb built-in function like alert() that doesn't have
            // an apply
            func = m._wrapDumbFunction(func);
        }
        if (typeof(im_func) != 'function') {
            im_func = func;
        }
        if (typeof(self) != 'undefined') {
            im_self = self;
        }
        if (typeof(im_preargs) == 'undefined') {
            im_preargs = [];
        } else  {
            im_preargs = im_preargs.slice();
        }
        m.extend(im_preargs, arguments, 2);
        var newfunc = function () {
            var args = arguments;
            var me = arguments.callee;
            if (me.im_preargs.length > 0) {
                args = m.concat(me.im_preargs, args);
            }
            var self = me.im_self;
            if (!self) {
                self = this;
            }
            return me.im_func.apply(self, args);
        };
        newfunc.im_self = im_self;
        newfunc.im_func = im_func;
        newfunc.im_preargs = im_preargs;
        return newfunc;
    },

    /** @id MochiKit.Base.bindMethods */
    bindMethods: function (self) {
        var bind = MochiKit.Base.bind;
        for (var k in self) {
            var func = self[k];
            if (typeof(func) == 'function') {
                self[k] = bind(func, self);
            }
        }
    },

    /** @id MochiKit.Base.registerComparator */
    registerComparator: function (name, check, comparator, /* optional */ override) {
        MochiKit.Base.comparatorRegistry.register(name, check, comparator, override);
    },

    _primitives: {'boolean': true, 'string': true, 'number': true},

    /** @id MochiKit.Base.compare */
    compare: function (a, b) {
        if (a == b) {
            return 0;
        }
        var aIsNull = (typeof(a) == 'undefined' || a === null);
        var bIsNull = (typeof(b) == 'undefined' || b === null);
        if (aIsNull && bIsNull) {
            return 0;
        } else if (aIsNull) {
            return -1;
        } else if (bIsNull) {
            return 1;
        }
        var m = MochiKit.Base;
        // bool, number, string have meaningful comparisons
        var prim = m._primitives;
        if (!(typeof(a) in prim && typeof(b) in prim)) {
            try {
                return m.comparatorRegistry.match(a, b);
            } catch (e) {
                if (e != m.NotFound) {
                    throw e;
                }
            }
        }
        if (a < b) {
            return -1;
        } else if (a > b) {
            return 1;
        }
        // These types can't be compared
        var repr = m.repr;
        throw new TypeError(repr(a) + " and " + repr(b) + " can not be compared");
    },

    /** @id MochiKit.Base.compareDateLike */
    compareDateLike: function (a, b) {
        return MochiKit.Base.compare(a.getTime(), b.getTime());
    },

    /** @id MochiKit.Base.compareArrayLike */
    compareArrayLike: function (a, b) {
        var compare = MochiKit.Base.compare;
        var count = a.length;
        var rval = 0;
        if (count > b.length) {
            rval = 1;
            count = b.length;
        } else if (count < b.length) {
            rval = -1;
        }
        for (var i = 0; i < count; i++) {
            var cmp = compare(a[i], b[i]);
            if (cmp) {
                return cmp;
            }
        }
        return rval;
    },

    /** @id MochiKit.Base.registerRepr */
    registerRepr: function (name, check, wrap, /* optional */override) {
        MochiKit.Base.reprRegistry.register(name, check, wrap, override);
    },

    /** @id MochiKit.Base.repr */
    repr: function (o) {
        if (typeof(o) == "undefined") {
            return "undefined";
        } else if (o === null) {
            return "null";
        }
        try {
            if (typeof(o.__repr__) == 'function') {
                return o.__repr__();
            } else if (typeof(o.repr) == 'function' && o.repr != arguments.callee) {
                return o.repr();
            }
            return MochiKit.Base.reprRegistry.match(o);
        } catch (e) {
            if (typeof(o.NAME) == 'string' && (
                    o.toString == Function.prototype.toString ||
                    o.toString == Object.prototype.toString
                )) {
                return o.NAME;
            }
        }
        try {
            var ostring = (o + "");
        } catch (e) {
            return "[" + typeof(o) + "]";
        }
        if (typeof(o) == "function") {
            ostring = ostring.replace(/^\s+/, "").replace(/\s+/g, " ");
            var idx = ostring.indexOf("{");
            if (idx != -1) {
                ostring = ostring.substr(0, idx) + "{...}";
            }
        }
        return ostring;
    },

    /** @id MochiKit.Base.reprArrayLike */
    reprArrayLike: function (o) {
        var m = MochiKit.Base;
        return "[" + m.map(m.repr, o).join(", ") + "]";
    },

    /** @id MochiKit.Base.reprString */
    reprString: function (o) {
        return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
            ).replace(/[\f]/g, "\\f"
            ).replace(/[\b]/g, "\\b"
            ).replace(/[\n]/g, "\\n"
            ).replace(/[\t]/g, "\\t"
            ).replace(/[\r]/g, "\\r");
    },

    /** @id MochiKit.Base.reprNumber */
    reprNumber: function (o) {
        return o + "";
    },

    /** @id MochiKit.Base.registerJSON */
    registerJSON: function (name, check, wrap, /* optional */override) {
        MochiKit.Base.jsonRegistry.register(name, check, wrap, override);
    },


    /** @id MochiKit.Base.evalJSON */
    evalJSON: function () {
        return eval("(" + MochiKit.Base._filterJSON(arguments[0]) + ")");
    },

    _filterJSON: function (s) {
        var m = s.match(/^\s*\/\*(.*)\*\/\s*$/);
        if (m) {
            return m[1];
        }
        return s;
    },

    /** @id MochiKit.Base.serializeJSON */
    serializeJSON: function (o) {
        var objtype = typeof(o);
        if (objtype == "number" || objtype == "boolean") {
            return o + "";
        } else if (o === null) {
            return "null";
        }
        var m = MochiKit.Base;
        var reprString = m.reprString;
        if (objtype == "string") {
            return reprString(o);
        }
        // recurse
        var me = arguments.callee;
        // short-circuit for objects that support "json" serialization
        // if they return "self" then just pass-through...
        var newObj;
        if (typeof(o.__json__) == "function") {
            newObj = o.__json__();
            if (o !== newObj) {
                return me(newObj);
            }
        }
        if (typeof(o.json) == "function") {
            newObj = o.json();
            if (o !== newObj) {
                return me(newObj);
            }
        }
        // array
        if (objtype != "function" && typeof(o.length) == "number") {
            var res = [];
            for (var i = 0; i < o.length; i++) {
                var val = me(o[i]);
                if (typeof(val) != "string") {
                    val = "undefined";
                }
                res.push(val);
            }
            return "[" + res.join(", ") + "]";
        }
        // look in the registry
        try {
            newObj = m.jsonRegistry.match(o);
            if (o !== newObj) {
                return me(newObj);
            }
        } catch (e) {
            if (e != m.NotFound) {
                // something really bad happened
                throw e;
            }
        }
        // undefined is outside of the spec
        if (objtype == "undefined") {
            throw new TypeError("undefined can not be serialized as JSON");
        }
        // it's a function with no adapter, bad
        if (objtype == "function") {
            return null;
        }
        // generic object code path
        res = [];
        for (var k in o) {
            var useKey;
            if (typeof(k) == "number") {
                useKey = '"' + k + '"';
            } else if (typeof(k) == "string") {
                useKey = reprString(k);
            } else {
                // skip non-string or number keys
                continue;
            }
            val = me(o[k]);
            if (typeof(val) != "string") {
                // skip non-serializable values
                continue;
            }
            res.push(useKey + ":" + val);
        }
        return "{" + res.join(", ") + "}";
    },


    /** @id MochiKit.Base.objEqual */
    objEqual: function (a, b) {
        return (MochiKit.Base.compare(a, b) === 0);
    },

    /** @id MochiKit.Base.arrayEqual */
    arrayEqual: function (self, arr) {
        if (self.length != arr.length) {
            return false;
        }
        return (MochiKit.Base.compare(self, arr) === 0);
    },

    /** @id MochiKit.Base.concat */
    concat: function (/* lst... */) {
        var rval = [];
        var extend = MochiKit.Base.extend;
        for (var i = 0; i < arguments.length; i++) {
            extend(rval, arguments[i]);
        }
        return rval;
    },

    /** @id MochiKit.Base.keyComparator */
    keyComparator: function (key/* ... */) {
        // fast-path for single key comparisons
        var m = MochiKit.Base;
        var compare = m.compare;
        if (arguments.length == 1) {
            return function (a, b) {
                return compare(a[key], b[key]);
            };
        }
        var compareKeys = m.extend(null, arguments);
        return function (a, b) {
            var rval = 0;
            // keep comparing until something is inequal or we run out of
            // keys to compare
            for (var i = 0; (rval === 0) && (i < compareKeys.length); i++) {
                var key = compareKeys[i];
                rval = compare(a[key], b[key]);
            }
            return rval;
        };
    },

    /** @id MochiKit.Base.reverseKeyComparator */
    reverseKeyComparator: function (key) {
        var comparator = MochiKit.Base.keyComparator.apply(this, arguments);
        return function (a, b) {
            return comparator(b, a);
        };
    },

    /** @id MochiKit.Base.partial */
    partial: function (func) {
        var m = MochiKit.Base;
        return m.bind.apply(this, m.extend([func, undefined], arguments, 1));
    },

    /** @id MochiKit.Base.listMinMax */
    listMinMax: function (which, lst) {
        if (lst.length === 0) {
            return null;
        }
        var cur = lst[0];
        var compare = MochiKit.Base.compare;
        for (var i = 1; i < lst.length; i++) {
            var o = lst[i];
            if (compare(o, cur) == which) {
                cur = o;
            }
        }
        return cur;
    },

    /** @id MochiKit.Base.objMax */
    objMax: function (/* obj... */) {
        return MochiKit.Base.listMinMax(1, arguments);
    },

    /** @id MochiKit.Base.objMin */
    objMin: function (/* obj... */) {
        return MochiKit.Base.listMinMax(-1, arguments);
    },

    /** @id MochiKit.Base.findIdentical */
    findIdentical: function (lst, value, start/* = 0 */, /* optional */end) {
        if (typeof(end) == "undefined" || end === null) {
            end = lst.length;
        }
        if (typeof(start) == "undefined" || start === null) {
            start = 0;
        }
        for (var i = start; i < end; i++) {
            if (lst[i] === value) {
                return i;
            }
        }
        return -1;
    },

    /** @id MochiKit.Base.mean */
    mean: function(/* lst... */) {
        /* http://www.nist.gov/dads/HTML/mean.html */
        var sum = 0;

        var m = MochiKit.Base;
        var args = m.extend(null, arguments);
        var count = args.length;

        while (args.length) {
            var o = args.shift();
            if (o && typeof(o) == "object" && typeof(o.length) == "number") {
                count += o.length - 1;
                for (var i = o.length - 1; i >= 0; i--) {
                    sum += o[i];
                }
            } else {
                sum += o;
            }
        }

        if (count <= 0) {
            throw new TypeError('mean() requires at least one argument');
        }

        return sum/count;
    },

    /** @id MochiKit.Base.median */
    median: function(/* lst... */) {
        /* http://www.nist.gov/dads/HTML/median.html */
        var data = MochiKit.Base.flattenArguments(arguments);
        if (data.length === 0) {
            throw new TypeError('median() requires at least one argument');
        }
        data.sort(compare);
        if (data.length % 2 == 0) {
            var upper = data.length / 2;
            return (data[upper] + data[upper - 1]) / 2;
        } else {
            return data[(data.length - 1) / 2];
        }
    },

    /** @id MochiKit.Base.findValue */
    findValue: function (lst, value, start/* = 0 */, /* optional */end) {
        if (typeof(end) == "undefined" || end === null) {
            end = lst.length;
        }
        if (typeof(start) == "undefined" || start === null) {
            start = 0;
        }
        var cmp = MochiKit.Base.compare;
        for (var i = start; i < end; i++) {
            if (cmp(lst[i], value) === 0) {
                return i;
            }
        }
        return -1;
    },

    /** @id MochiKit.Base.nodeWalk */
    nodeWalk: function (node, visitor) {
        var nodes = [node];
        var extend = MochiKit.Base.extend;
        while (nodes.length) {
            var res = visitor(nodes.shift());
            if (res) {
                extend(nodes, res);
            }
        }
    },


    /** @id MochiKit.Base.nameFunctions */
    nameFunctions: function (namespace) {
        var base = namespace.NAME;
        if (typeof(base) == 'undefined') {
            base = '';
        } else {
            base = base + '.';
        }
        for (var name in namespace) {
            var o = namespace[name];
            if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
                try {
                    o.NAME = base + name;
                } catch (e) {
                    // pass
                }
            }
        }
    },


    /** @id MochiKit.Base.queryString */
    queryString: function (names, values) {
        // check to see if names is a string or a DOM element, and if
        // MochiKit.DOM is available.  If so, drop it like it's a form
        // Ugliest conditional in MochiKit?  Probably!
        if (typeof(MochiKit.DOM) != "undefined" && arguments.length == 1
            && (typeof(names) == "string" || (
                typeof(names.nodeType) != "undefined" && names.nodeType > 0
            ))
        ) {
            var kv = MochiKit.DOM.formContents(names);
            names = kv[0];
            values = kv[1];
        } else if (arguments.length == 1) {
            // Allow the return value of formContents to be passed directly
            if (typeof(names.length) == "number" && names.length == 2) {
                return arguments.callee(names[0], names[1]);
            }
            var o = names;
            names = [];
            values = [];
            for (var k in o) {
                var v = o[k];
                if (typeof(v) == "function") {
                    continue;
                } else if (MochiKit.Base.isArrayLike(v)){
                    for (var i = 0; i < v.length; i++) {
                        names.push(k);
                        values.push(v[i]);
                    }
                } else {
                    names.push(k);
                    values.push(v);
                }
            }
        }
        var rval = [];
        var len = Math.min(names.length, values.length);
        var urlEncode = MochiKit.Base.urlEncode;
        for (var i = 0; i < len; i++) {
            v = values[i];
            if (typeof(v) != 'undefined' && v !== null) {
                rval.push(urlEncode(names[i]) + "=" + urlEncode(v));
            }
        }
        return rval.join("&");
    },


    /** @id MochiKit.Base.parseQueryString */
    parseQueryString: function (encodedString, useArrays) {
        // strip a leading '?' from the encoded string
        var qstr = (encodedString.charAt(0) == "?")
            ? encodedString.substring(1)
            : encodedString;
        var pairs = qstr.replace(/\+/g, "%20").split(/(\&amp\;|\&\#38\;|\&#x26;|\&)/);
        var o = {};
        var decode;
        if (typeof(decodeURIComponent) != "undefined") {
            decode = decodeURIComponent;
        } else {
            decode = unescape;
        }
        if (useArrays) {
            for (var i = 0; i < pairs.length; i++) {
                var pair = pairs[i].split("=");
                var name = decode(pair.shift());
                if (!name) {
                    continue;
                }
                var arr = o[name];
                if (!(arr instanceof Array)) {
                    arr = [];
                    o[name] = arr;
                }
                arr.push(decode(pair.join("=")));
            }
        } else {
            for (i = 0; i < pairs.length; i++) {
                pair = pairs[i].split("=");
                var name = pair.shift();
                if (!name) {
                    continue;
                }
                o[decode(name)] = decode(pair.join("="));
            }
        }
        return o;
    }
});

/** @id MochiKit.Base.AdapterRegistry */
MochiKit.Base.AdapterRegistry = function () {
    this.pairs = [];
};

MochiKit.Base.AdapterRegistry.prototype = {
    /** @id MochiKit.Base.AdapterRegistry.prototype.register */
    register: function (name, check, wrap, /* optional */ override) {
        if (override) {
            this.pairs.unshift([name, check, wrap]);
        } else {
            this.pairs.push([name, check, wrap]);
        }
    },

    /** @id MochiKit.Base.AdapterRegistry.prototype.match */
    match: function (/* ... */) {
        for (var i = 0; i < this.pairs.length; i++) {
            var pair = this.pairs[i];
            if (pair[1].apply(this, arguments)) {
                return pair[2].apply(this, arguments);
            }
        }
        throw MochiKit.Base.NotFound;
    },

    /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */
    unregister: function (name) {
        for (var i = 0; i < this.pairs.length; i++) {
            var pair = this.pairs[i];
            if (pair[0] == name) {
                this.pairs.splice(i, 1);
                return true;
            }
        }
        return false;
    }
};


MochiKit.Base.EXPORT = [
    "flattenArray",
    "noop",
    "camelize",
    "counter",
    "clone",
    "extend",
    "update",
    "updatetree",
    "setdefault",
    "keys",
    "values",
    "items",
    "NamedError",
    "operator",
    "forwardCall",
    "itemgetter",
    "typeMatcher",
    "isCallable",
    "isUndefined",
    "isUndefinedOrNull",
    "isNull",
    "isEmpty",
    "isNotEmpty",
    "isArrayLike",
    "isDateLike",
    "xmap",
    "map",
    "xfilter",
    "filter",
    "methodcaller",
    "compose",
    "bind",
    "bindMethods",
    "NotFound",
    "AdapterRegistry",
    "registerComparator",
    "compare",
    "registerRepr",
    "repr",
    "objEqual",
    "arrayEqual",
    "concat",
    "keyComparator",
    "reverseKeyComparator",
    "partial",
    "merge",
    "listMinMax",
    "listMax",
    "listMin",
    "objMax",
    "objMin",
    "nodeWalk",
    "zip",
    "urlEncode",
    "queryString",
    "serializeJSON",
    "registerJSON",
    "evalJSON",
    "parseQueryString",
    "findValue",
    "findIdentical",
    "flattenArguments",
    "method",
    "average",
    "mean",
    "median"
];

MochiKit.Base.EXPORT_OK = [
    "nameFunctions",
    "comparatorRegistry",
    "reprRegistry",
    "jsonRegistry",
    "compareDateLike",
    "compareArrayLike",
    "reprArrayLike",
    "reprString",
    "reprNumber"
];

MochiKit.Base._exportSymbols = function (globals, module) {
    if (!MochiKit.__export__) {
        return;
    }
    var all = module.EXPORT_TAGS[":all"];
    for (var i = 0; i < all.length; i++) {
        globals[all[i]] = module[all[i]];
    }
};

MochiKit.Base.__new__ = function () {
    // A singleton raised when no suitable adapter is found
    var m = this;

    // convenience
    /** @id MochiKit.Base.noop */
    m.noop = m.operator.identity;

    // Backwards compat
    m.forward = m.forwardCall;
    m.find = m.findValue;

    if (typeof(encodeURIComponent) != "undefined") {
        /** @id MochiKit.Base.urlEncode */
        m.urlEncode = function (unencoded) {
            return encodeURIComponent(unencoded).replace(/\'/g, '%27');
        };
    } else {
        m.urlEncode = function (unencoded) {
            return escape(unencoded
                ).replace(/\+/g, '%2B'
                ).replace(/\"/g,'%22'
                ).rval.replace(/\'/g, '%27');
        };
    }

    /** @id MochiKit.Base.NamedError */
    m.NamedError = function (name) {
        this.message = name;
        this.name = name;
    };
    m.NamedError.prototype = new Error();
    m.update(m.NamedError.prototype, {
        repr: function () {
            if (this.message && this.message != this.name) {
                return this.name + "(" + m.repr(this.message) + ")";
            } else {
                return this.name + "()";
            }
        },
        toString: m.forwardCall("repr")
    });

    /** @id MochiKit.Base.NotFound */
    m.NotFound = new m.NamedError("MochiKit.Base.NotFound");


    /** @id MochiKit.Base.listMax */
    m.listMax = m.partial(m.listMinMax, 1);
    /** @id MochiKit.Base.listMin */
    m.listMin = m.partial(m.listMinMax, -1);

    /** @id MochiKit.Base.isCallable */
    m.isCallable = m.typeMatcher('function');
    /** @id MochiKit.Base.isUndefined */
    m.isUndefined = m.typeMatcher('undefined');

    /** @id MochiKit.Base.merge */
    m.merge = m.partial(m.update, null);
    /** @id MochiKit.Base.zip */
    m.zip = m.partial(m.map, null);

    /** @id MochiKit.Base.average */
    m.average = m.mean;

    /** @id MochiKit.Base.comparatorRegistry */
    m.comparatorRegistry = new m.AdapterRegistry();
    m.registerComparator("dateLike", m.isDateLike, m.compareDateLike);
    m.registerComparator("arrayLike", m.isArrayLike, m.compareArrayLike);

    /** @id MochiKit.Base.reprRegistry */
    m.reprRegistry = new m.AdapterRegistry();
    m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike);
    m.registerRepr("string", m.typeMatcher("string"), m.reprString);
    m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber);

    /** @id MochiKit.Base.jsonRegistry */
    m.jsonRegistry = new m.AdapterRegistry();

    var all = m.concat(m.EXPORT, m.EXPORT_OK);
    m.EXPORT_TAGS = {
        ":common": m.concat(m.EXPORT_OK),
        ":all": all
    };

    m.nameFunctions(this);

};

MochiKit.Base.__new__();

//
// XXX: Internet Explorer blows
//
if (MochiKit.__export__) {
    compare = MochiKit.Base.compare;
    compose = MochiKit.Base.compose;
    serializeJSON = MochiKit.Base.serializeJSON;
    mean = MochiKit.Base.mean;
    median = MochiKit.Base.median;
}

MochiKit.Base._exportSymbols(this, MochiKit.Base);

/***

MochiKit.Async 1.4

See <http://mochikit.com/> for documentation, downloads, license, etc.

(c) 2005 Bob Ippolito.  All rights Reserved.

***/

if (typeof(dojo) != 'undefined') {
    dojo.provide("MochiKit.Async");
    dojo.require("MochiKit.Base");
}
if (typeof(JSAN) != 'undefined') {
    JSAN.use("MochiKit.Base", []);
}

try {
    if (typeof(MochiKit.Base) == 'undefined') {
        throw "";
    }
} catch (e) {
    throw "MochiKit.Async depends on MochiKit.Base!";
}

if (typeof(MochiKit.Async) == 'undefined') {
    MochiKit.Async = {};
}

MochiKit.Async.NAME = "MochiKit.Async";
MochiKit.Async.VERSION = "1.4";
MochiKit.Async.__repr__ = function () {
    return "[" + this.NAME + " " + this.VERSION + "]";
};
MochiKit.Async.toString = function () {
    return this.__repr__();
};

/** @id MochiKit.Async.Deferred */
MochiKit.Async.Deferred = function (/* optional */ canceller) {
    this.chain = [];
    this.id = this._nextId();
    this.fired = -1;
    this.paused = 0;
    this.results = [null, null];
    this.canceller = canceller;
    this.silentlyCancelled = false;
    this.chained = false;
};

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

    toString: MochiKit.Base.forwardCall("repr"),

    _nextId: MochiKit.Base.counter(),

    /** @id MochiKit.Async.Deferred.prototype.cancel */
    cancel: function () {
        var self = MochiKit.Async;
        if (this.fired == -1) {
            if (this.canceller) {
                this.canceller(this);
            } else {
                this.silentlyCancelled = true;
            }
            if (this.fired == -1) {
                this.errback(new self.CancelledError(this));
            }
        } else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) {
            this.results[0].cancel();
        }
    },

    _resback: function (res) {
        /***

        The primitive that means either callback or errback

        ***/
        this.fired = ((res instanceof Error) ? 1 : 0);
        this.results[this.fired] = res;
        this._fire();
    },

    _check: function () {
        if (this.fired != -1) {
            if (!this.silentlyCancelled) {
                throw new MochiKit.Async.AlreadyCalledError(this);
            }
            this.silentlyCancelled = false;
            return;
        }
    },

    /** @id MochiKit.Async.Deferred.prototype.callback */
    callback: function (res) {
        this._check();
        if (res instanceof MochiKit.Async.Deferred) {
            throw new Error("Deferred instances can only be chained if they are the result of a callback");
        }
        this._resback(res);
    },

    /** @id MochiKit.Async.Deferred.prototype.errback */
    errback: function (res) {
        this._check();
        var self = MochiKit.Async;
        if (res instanceof self.Deferred) {
            throw new Error("Deferred instances can only be chained if they are the result of a callback");
        }
        if (!(res instanceof Error)) {
            res = new self.GenericError(res);
        }
        this._resback(res);
    },

    /** @id MochiKit.Async.Deferred.prototype.addBoth */
    addBoth: function (fn) {
        if (arguments.length > 1) {
            fn = MochiKit.Base.partial.apply(null, arguments);
        }
        return this.addCallbacks(fn, fn);
    },

    /** @id MochiKit.Async.Deferred.prototype.addCallback */
    addCallback: function (fn) {
        if (arguments.length > 1) {
            fn = MochiKit.Base.partial.apply(null, arguments);
        }
        return this.addCallbacks(fn, null);
    },

    /** @id MochiKit.Async.Deferred.prototype.addErrback */
    addErrback: function (fn) {
        if (arguments.length > 1) {
            fn = MochiKit.Base.partial.apply(null, arguments);
        }
        return this.addCallbacks(null, fn);
    },

    /** @id MochiKit.Async.Deferred.prototype.addCallbacks */
    addCallbacks: function (cb, eb) {
        if (this.chained) {
            throw new Error("Chained Deferreds can not be re-used");
        }
        this.chain.push([cb, eb]);
        if (this.fired >= 0) {
            this._fire();
        }
        return this;
    },

    _fire: function () {
        /***

        Used internally to exhaust the callback sequence when a result
        is available.

        ***/
        var chain = this.chain;
        var fired = this.fired;
        var res = this.results[fired];
        var self = this;
        var cb = null;
        while (chain.length > 0 && this.paused === 0) {
            // Array
            var pair = chain.shift();
            var f = pair[fired];
            if (f === null) {
                continue;
            }
            try {
                res = f(res);
                fired = ((res instanceof Error) ? 1 : 0);
                if (res instanceof MochiKit.Async.Deferred) {
                    cb = function (res) {
                        self._resback(res);
                        self.paused--;
                        if ((self.paused === 0) && (self.fired >= 0)) {
                            self._fire();
                        }
                    };
                    this.paused++;
                }
            } catch (err) {
                fired = 1;
                if (!(err instanceof Error)) {
                    err = new MochiKit.Async.GenericError(err);
                }
                res = err;
            }
        }
        this.fired = fired;
        this.results[fired] = res;
        if (cb && this.paused) {
            // this is for "tail recursion" in case the dependent deferred
            // is already fired
            res.addBoth(cb);
            res.chained = true;
        }
    }
};

MochiKit.Base.update(MochiKit.Async, {
    /** @id MochiKit.Async.evalJSONRequest */
    evalJSONRequest: function (req) {
        return MochiKit.Base.evalJSON(req.responseText);
    },

    /** @id MochiKit.Async.succeed */
    succeed: function (/* optional */result) {
        var d = new MochiKit.Async.Deferred();
        d.callback.apply(d, arguments);
        return d;
    },

    /** @id MochiKit.Async.fail */
    fail: function (/* optional */result) {
        var d = new MochiKit.Async.Deferred();
        d.errback.apply(d, arguments);
        return d;
    },

    /** @id MochiKit.Async.getXMLHttpRequest */
    getXMLHttpRequest: function () {
        var self = arguments.callee;
        if (!self.XMLHttpRequest) {
            var tryThese = [
                function () { return new XMLHttpRequest(); },
                function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
                function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
                function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
                function () {
                    throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest");
                }
            ];
            for (var i = 0; i < tryThese.length; i++) {
                var func = tryThese[i];
                try {
                    self.XMLHttpRequest = func;
                    return func();
                } catch (e) {
                    // pass
                }
            }
        }
        return self.XMLHttpRequest();
    },

    _xhr_onreadystatechange: function (d) {
        // MochiKit.Logging.logDebug('this.readyState', this.readyState);
        var m = MochiKit.Base;
        if (this.readyState == 4) {
            // IE SUCKS
            try {
                this.onreadystatechange = null;
            } catch (e) {
                try {
                    this.onreadystatechange = m.noop;
                } catch (e) {
                }
            }
            var status = null;
            try {
                status = this.status;
                if (!status && m.isNotEmpty(this.responseText)) {
                    // 0 or undefined seems to mean cached or local
                    status = 304;
                }
            } catch (e) {
                // pass
                // MochiKit.Logging.logDebug('error getting status?', repr(items(e)));
            }
            // 200 is OK, 201 is CREATED, 204 is NO CONTENT
            // 304 is NOT MODIFIED, 1223 is apparently a bug in IE
            if (status == 200 || status == 201 || status == 204 ||
                    status == 304 || status == 1223) {
                d.callback(this);
            } else {
                var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed");
                if (err.number) {
                    // XXX: This seems to happen on page change
                    d.errback(err);
                } else {
                    // XXX: this seems to happen when the server is unreachable
                    d.errback(err);
                }
            }
        }
    },

    _xhr_canceller: function (req) {
        // IE SUCKS
        try {
            req.onreadystatechange = null;
        } catch (e) {
            try {
                req.onreadystatechange = MochiKit.Base.noop;
            } catch (e) {
            }
        }
        req.abort();
    },


    /** @id MochiKit.Async.sendXMLHttpRequest */
    sendXMLHttpRequest: function (req, /* optional */ sendContent) {
        if (typeof(sendContent) == "undefined" || sendContent === null) {
            sendContent = "";
        }

        var m = MochiKit.Base;
        var self = MochiKit.Async;
        var d = new self.Deferred(m.partial(self._xhr_canceller, req));

        try {
            req.onreadystatechange = m.bind(self._xhr_onreadystatechange,
                req, d);
            req.send(sendContent);
        } catch (e) {
            try {
                req.onreadystatechange = null;
            } catch (ignore) {
                // pass
            }
            d.errback(e);
        }

        return d;

    },

    /** @id MochiKit.Async.doXHR */
    doXHR: function (url, opts) {
        /*
            Work around a Firefox bug by dealing with XHR during
            the next event loop iteration. Maybe it's this one:
            https://bugzilla.mozilla.org/show_bug.cgi?id=249843
        */
        var self = MochiKit.Async;
        return self.callLater(0, self._doXHR, url, opts);
    },

    _doXHR: function (url, opts) {
        var m = MochiKit.Base;
        opts = m.update({
            method: 'GET',
            sendContent: ''
            /*
            queryString: undefined,
            username: undefined,
            password: undefined,
            headers: undefined,
            mimeType: undefined
            */
        }, opts);
        var self = MochiKit.Async;
        var req = self.getXMLHttpRequest();
        if (opts.queryString) {
            var qs = m.queryString(opts.queryString);
            if (qs) {
                url += "?" + qs;
            }
        }
        // Safari will send undefined:undefined, so we have to check.
        // We can't use apply, since the function is native.
        if ('username' in opts) {
            req.open(opts.method, url, true, opts.username, opts.password);
        } else {
            req.open(opts.method, url, true);
        }
        if (req.overrideMimeType && opts.mimeType) {
            req.overrideMimeType(opts.mimeType);
        }
        req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
        if (opts.headers) {
            var headers = opts.headers;
            if (!m.isArrayLike(headers)) {
                headers = m.items(headers);
            }
            for (var i = 0; i < headers.length; i++) {
                var header = headers[i];
                var name = header[0];
                var value = header[1];
                req.setRequestHeader(name, value);
            }
        }
        return self.sendXMLHttpRequest(req, opts.sendContent);
    },

    _buildURL: function (url/*, ...*/) {
        if (arguments.length > 1) {
            var m = MochiKit.Base;
            var qs = m.queryString.apply(null, m.extend(null, arguments, 1));
            if (qs) {
                return url + "?" + qs;
            }
        }
        return url;
    },

    /** @id MochiKit.Async.doSimpleXMLHttpRequest */
    doSimpleXMLHttpRequest: function (url/*, ...*/) {
        var self = MochiKit.Async;
        url = self._buildURL.apply(self, arguments);
        return self.doXHR(url);
    },

    /** @id MochiKit.Async.loadJSONDoc */
    loadJSONDoc: function (url/*, ...*/) {
        var self = MochiKit.Async;
        url = self._buildURL.apply(self, arguments);
        var d = self.doXHR(url, {
            'mimeType': 'text/plain',
            'headers': [['Accept', 'application/json']]
        });
        d = d.addCallback(self.evalJSONRequest);
        return d;
    },

    /** @id MochiKit.Async.wait */
    wait: function (seconds, /* optional */value) {
        var d = new MochiKit.Async.Deferred();
        var m = MochiKit.Base;
        if (typeof(value) != 'undefined') {
            d.addCallback(function () { return value; });
        }
        var timeout = setTimeout(
            m.bind("callback", d),
            Math.floor(seconds * 1000));
        d.canceller = function () {
            try {
                clearTimeout(timeout);
            } catch (e) {
                // pass
            }
        };
        return d;
    },

    /** @id MochiKit.Async.callLater */
    callLater: function (seconds, func) {
        var m = MochiKit.Base;
        var pfunc = m.partial.apply(m, m.extend(null, arguments, 1));
        return MochiKit.Async.wait(seconds).addCallback(
            function (res) { return pfunc(); }
        );
    }
});


/** @id MochiKit.Async.DeferredLock */
MochiKit.Async.DeferredLock = function () {
    this.waiting = [];
    this.locked = false;
    this.id = this._nextId();
};

MochiKit.Async.DeferredLock.prototype = {
    __class__: MochiKit.Async.DeferredLock,
    /** @id MochiKit.Async.DeferredLock.prototype.acquire */
    acquire: function () {
        var d = new MochiKit.Async.Deferred();
        if (this.locked) {
            this.waiting.push(d);
        } else {
            this.locked = true;
            d.callback(this);
        }
        return d;
    },
    /** @id MochiKit.Async.DeferredLock.prototype.release */
    release: function () {
        if (!this.locked) {
            throw TypeError("Tried to release an unlocked DeferredLock");
        }
        this.locked = false;
        if (this.waiting.length > 0) {
            this.locked = true;
            this.waiting.shift().callback(this);
        }
    },
    _nextId: MochiKit.Base.counter(),
    repr: function () {
        var state;
        if (this.locked) {
            state = 'locked, ' + this.waiting.length + ' waiting';
        } else {
            state = 'unlocked';
        }
        return 'DeferredLock(' + this.id + ', ' + state + ')';
    },
    toString: MochiKit.Base.forwardCall("repr")

};

/** @id MochiKit.Async.DeferredList */
MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) {

    // call parent constructor
    MochiKit.Async.Deferred.apply(this, [canceller]);

    this.list = list;
    var resultList = [];
    this.resultList = resultList;

    this.finishedCount = 0;
    this.fireOnOneCallback = fireOnOneCallback;
    this.fireOnOneErrback = fireOnOneErrback;
    this.consumeErrors = consumeErrors;

    var cb = MochiKit.Base.bind(this._cbDeferred, this);
    for (var i = 0; i < list.length; i++) {
        var d = list[i];
        resultList.push(undefined);
        d.addCallback(cb, i, true);
        d.addErrback(cb, i, false);
    }

    if (list.length === 0 && !fireOnOneCallback) {
        this.callback(this.resultList);
    }

};

MochiKit.Async.DeferredList.prototype = new MochiKit.Async.Deferred();

MochiKit.Async.DeferredList.prototype._cbDeferred = function (index, succeeded, result) {
    this.resultList[index] = [succeeded, result];
    this.finishedCount += 1;
    if (this.fired == -1) {
        if (succeeded && this.fireOnOneCallback) {
            this.callback([index, result]);
        } else if (!succeeded && this.fireOnOneErrback) {
            this.errback(result);
        } else if (this.finishedCount == this.list.length) {
            this.callback(this.resultList);
        }
    }
    if (!succeeded && this.consumeErrors) {
        result = null;
    }
    return result;
};

/** @id MochiKit.Async.gatherResults */
MochiKit.Async.gatherResults = function (deferredList) {
    var d = new MochiKit.Async.DeferredList(deferredList, false, true, false);
    d.addCallback(function (results) {
        var ret = [];
        for (var i = 0; i < results.length; i++) {
            ret.push(results[i][1]);
        }
        return ret;
    });
    return d;
};

/** @id MochiKit.Async.maybeDeferred */
MochiKit.Async.maybeDeferred = function (func) {
    var self = MochiKit.Async;
    var result;
    try {
        var r = func.apply(null, MochiKit.Base.extend([], arguments, 1));
        if (r instanceof self.Deferred) {
            result = r;
        } else if (r instanceof Error) {
            result = self.fail(r);
        } else {
            result = self.succeed(r);
        }
    } catch (e) {
        result = self.fail(e);
    }
    return result;
};


MochiKit.Async.EXPORT = [
    "AlreadyCalledError",
    "CancelledError",
    "BrowserComplianceError",
    "GenericError",
    "XMLHttpRequestError",
    "Deferred",
    "succeed",
    "fail",
    "getXMLHttpRequest",
    "doSimpleXMLHttpRequest",
    "loadJSONDoc",
    "wait",
    "callLater",
    "sendXMLHttpRequest",
    "DeferredLock",
    "DeferredList",
    "gatherResults",
    "maybeDeferred",
    "doXHR"
];

MochiKit.Async.EXPORT_OK = [
    "evalJSONRequest"
];

MochiKit.Async.__new__ = function () {
    var m = MochiKit.Base;
    var ne = m.partial(m._newNamedError, this);

    ne("AlreadyCalledError",
        /** @id MochiKit.Async.AlreadyCalledError */
        function (deferred) {
            /***

            Raised by the Deferred if callback or errback happens
            after it was already fired.

            ***/
            this.deferred = deferred;
        }
    );

    ne("CancelledError",
        /** @id MochiKit.Async.CancelledError */
        function (deferred) {
            /***

            Raised by the Deferred cancellation mechanism.

            ***/
            this.deferred = deferred;
        }
    );

    ne("BrowserComplianceError",
        /** @id MochiKit.Async.BrowserComplianceError */
        function (msg) {
            /***

            Raised when the JavaScript runtime is not capable of performing
            the given function.  Technically, this should really never be
            raised because a non-conforming JavaScript runtime probably
            isn't going to support exceptions in the first place.

            ***/
            this.message = msg;
        }
    );

    ne("GenericError",
        /** @id MochiKit.Async.GenericError */
        function (msg) {
            this.message = msg;
        }
    );

    ne("XMLHttpRequestError",
        /** @id MochiKit.Async.XMLHttpRequestError */
        function (req, msg) {
            /***

            Raised when an XMLHttpRequest does not complete for any reason.

            ***/
            this.req = req;
            this.message = msg;
            try {
                // Strange but true that this can raise in some cases.
                this.number = req.status;
            } catch (e) {
                // pass
            }
        }
    );


    this.EXPORT_TAGS = {
        ":common": this.EXPORT,
        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
    };

    m.nameFunctions(this);

};

MochiKit.Async.__new__();

MochiKit.Base._exportSymbols(this, MochiKit.Async);

/***

MochiKit.Iter 1.4

See <http://mochikit.com/> for documentation, downloads, license, etc.

(c) 2005 Bob Ippolito.  All rights Reserved.

***/

if (typeof(dojo) != 'undefined') {
    dojo.provide('MochiKit.Iter');
    dojo.require('MochiKit.Base');
}

if (typeof(JSAN) != 'undefined') {
    JSAN.use("MochiKit.Base", []);
}

try {
    if (typeof(MochiKit.Base) == 'undefined') {
        throw "";
    }
} catch (e) {
    throw "MochiKit.Iter depends on MochiKit.Base!";
}

if (typeof(MochiKit.Iter) == 'undefined') {
    MochiKit.Iter = {};
}

MochiKit.Iter.NAME = "MochiKit.Iter";
MochiKit.Iter.VERSION = "1.4";
MochiKit.Base.update(MochiKit.Iter, {
    __repr__: function () {
        return "[" + this.NAME + " " + this.VERSION + "]";
    },
    toString: function () {
        return this.__repr__();
    },

    /** @id MochiKit.Iter.registerIteratorFactory  */
    registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) {
        MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override);
    },

    /** @id MochiKit.Iter.iter */
    iter: function (iterable, /* optional */ sentinel) {
        var self = MochiKit.Iter;
        if (arguments.length == 2) {
            return self.takewhile(
                function (a) { return a != sentinel; },
                iterable
            );
        }
        if (typeof(iterable.next) == 'function') {
            return iterable;
        } else if (typeof(iterable.iter) == 'function') {
            return iterable.iter();
        /*
        }  else if (typeof(iterable.__iterator__) == 'function') {
            //
            // XXX: We can't support JavaScript 1.7 __iterator__ directly
            //      because of Object.prototype.__iterator__
            //
            return iterable.__iterator__();
        */
        }

        try {
            return self.iteratorRegistry.match(iterable);
        } catch (e) {
            var m = MochiKit.Base;
            if (e == m.NotFound) {
                e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable");
            }
            throw e;
        }
    },

    /** @id MochiKit.Iter.count */
    count: function (n) {
        if (!n) {
            n = 0;
        }
        var m = MochiKit.Base;
        return {
            repr: function () { return "count(" + n + ")"; },
            toString: m.forwardCall("repr"),
            next: m.counter(n)
        };
    },

    /** @id MochiKit.Iter.cycle */
    cycle: function (p) {
        var self = MochiKit.Iter;
        var m = MochiKit.Base;
        var lst = [];
        var iterator = self.iter(p);
        return {
            repr: function () { return "cycle(...)"; },
            toString: m.forwardCall("repr"),
            next: function () {
                try {
                    var rval = iterator.next();
                    lst.push(rval);
                    return rval;
                } catch (e) {
                    if (e != self.StopIteration) {
                        throw e;
                    }
                    if (lst.length === 0) {
                        this.next = function () {
                            throw self.StopIteration;
                        };
                    } else {
                        var i = -1;
                        this.next = function () {
                            i = (i + 1) % lst.length;
                            return lst[i];
                        };
                    }
                    return this.next();
                }
            }
        };
    },

    /** @id MochiKit.Iter.repeat */
    repeat: function (elem, /* optional */n) {
        var m = MochiKit.Base;
        if (typeof(n) == 'undefined') {
            return {
                repr: function () {
                    return "repeat(" + m.repr(elem) + ")";
                },
                toString: m.forwardCall("repr"),
                next: function () {
                    return elem;
                }
            };
        }
        return {
            repr: function () {
                return "repeat(" + m.repr(elem) + ", " + n + ")";
            },
            toString: m.forwardCall("repr"),
            next: function () {
                if (n <= 0) {
                    throw MochiKit.Iter.StopIteration;
                }
                n -= 1;
                return elem;
            }
        };
    },

    /** @id MochiKit.Iter.next */
    next: function (iterator) {
        return iterator.next();
    },

    /** @id MochiKit.Iter.izip */
    izip: function (p, q/*, ...*/) {
        var m = MochiKit.Base;
        var self = MochiKit.Iter;
        var next = self.next;
        var iterables = m.map(self.iter, arguments);
        return {
            repr: function () { return "izip(...)"; },
            toString: m.forwardCall("repr"),
            next: function () { return m.map(next, iterables); }
        };
    },

    /** @id MochiKit.Iter.ifilter */
    ifilter: function (pred, seq) {
        var m = MochiKit.Base;
        seq = MochiKit.Iter.iter(seq);
        if (pred === null) {
            pred = m.operator.truth;
        }
        return {
            repr: function () { return "ifilter(...)"; },
            toString: m.forwardCall("repr"),
            next: function () {
                while (true) {
                    var rval = seq.next();
                    if (pred(rval)) {
                        return rval;
                    }
                }
                // mozilla warnings aren't too bright
                return undefined;
            }
        };
    },

    /** @id MochiKit.Iter.ifilterfalse */
    ifilterfalse: function (pred, seq) {
        var m = MochiKit.Base;
        seq = MochiKit.Iter.iter(seq);
        if (pred === null) {
            pred = m.operator.truth;
        }
        return {
            repr: function () { return "ifilterfalse(...)"; },
            toString: m.forwardCall("repr"),
            next: function () {
                while (true) {
                    var rval = seq.next();
                    if (!pred(rval)) {
                        return rval;
                    }
                }
                // mozilla warnings aren't too bright
                return undefined;
            }
        };
    },

    /** @id MochiKit.Iter.islice */
    islice: function (seq/*, [start,] stop[, step] */) {
        var self = MochiKit.Iter;
        var m = MochiKit.Base;
        seq = self.iter(seq);
        var start = 0;
        var stop = 0;
        var step = 1;
        var i = -1;
        if (arguments.length == 2) {
            stop = arguments[1];
        } else if (arguments.length == 3) {
            start = arguments[1];
            stop = arguments[2];
        } else {
            start = arguments[1];
            stop = arguments[2];
            step = arguments[3];
        }
        return {
            repr: function () {
                return "islice(" + ["...", start, stop, step].join(", ") + ")";
            },
            toString: m.forwardCall("repr"),
            next: function () {
                var rval;
                while (i < start) {
                    rval = seq.next();
                    i++;
                }
                if (start >= stop) {
                    throw self.StopIteration;
                }
                start += step;
                return rval;
            }
        };
    },

    /** @id MochiKit.Iter.imap */
    imap: function (fun, p, q/*, ...*/) {
        var m = MochiKit.Base;
        var self = MochiKit.Iter;
        var iterables = m.map(self.iter, m.extend(null, arguments, 1));
        var map = m.map;
        var next = self.next;
        return {
            repr: function () { return "imap(...)"; },
            toString: m.forwardCall("repr"),
            next: function () {
                return fun.apply(this, map(next, iterables));
            }
        };
    },

    /** @id MochiKit.Iter.applymap */
    applymap: function (fun, seq, self) {
        seq = MochiKit.Iter.iter(seq);
        var m = MochiKit.Base;
        return {
            repr: function () { return "applymap(...)"; },
            toString: m.forwardCall("repr"),
            next: function () {
                return fun.apply(self, seq.next());
            }
        };
    },

    /** @id MochiKit.Iter.chain */
    chain: function (p, q/*, ...*/) {
        // dumb fast path
        var self = MochiKit.Iter;
        var m = MochiKit.Base;
        if (arguments.length == 1) {
            return self.iter(arguments[0]);
        }
        var argiter = m.map(self.iter, arguments);
        return {
            repr: function () { return "chain(...)"; },
            toString: m.forwardCall("repr"),
            next: function () {
                while (argiter.length > 1) {
                    try {
                        return argiter[0].next();
                    } catch (e) {
                        if (e != self.StopIteration) {
                            throw e;
                        }
                        argiter.shift();
                    }
                }
                if (argiter.length == 1) {
                    // optimize last element
                    var arg = argiter.shift();
                    this.next = m.bind("next", arg);
                    return this.next();
                }
                throw self.StopIteration;
            }
        };
    },

    /** @id MochiKit.Iter.takewhile */
    takewhile: function (pred, seq) {
        var self = MochiKit.Iter;
        seq = self.iter(seq);
        return {
            repr: function () { return "takewhile(...)"; },
            toString: MochiKit.Base.forwardCall("repr"),
            next: function () {
                var rval = seq.next();
                if (!pred(rval)) {
                    this.next = function () {
                        throw self.StopIteration;
                    };
                    this.next();
                }
                return rval;
            }
        };
    },

    /** @id MochiKit.Iter.dropwhile */
    dropwhile: function (pred, seq) {
        seq = MochiKit.Iter.iter(seq);
        var m = MochiKit.Base;
        var bind = m.bind;
        return {
            "repr": function () { return "dropwhile(...)"; },
            "toString": m.forwardCall("repr"),
            "next": function () {
                while (true) {
                    var rval = seq.next();
                    if (!pred(rval)) {
                        break;
                    }
                }
                this.next = bind("next", seq);
                return rval;
            }
        };
    },

    _tee: function (ident, sync, iterable) {
        sync.pos[ident] = -1;
        var m = MochiKit.Base;
        var listMin = m.listMin;
        return {
            repr: function () { return "tee(" + ident + ", ...)"; },
            toString: m.forwardCall("repr"),
            next: function () {
                var rval;
                var i = sync.pos[ident];

                if (i == sync.max) {
                    rval = iterable.next();
                    sync.deque.push(rval);
                    sync.max += 1;
                    sync.pos[ident] += 1;
                } else {
                    rval = sync.deque[i - sync.min];
                    sync.pos[ident] += 1;
                    if (i == sync.min && listMin(sync.pos) != sync.min) {
                        sync.min += 1;
                        sync.deque.shift();
                    }
                }
                return rval;
            }
        };
    },

    /** @id MochiKit.Iter.tee */
    tee: function (iterable, n/* = 2 */) {
        var rval = [];
        var sync = {
            "pos": [],
            "deque": [],
            "max": -1,
            "min": -1
        };
        if (arguments.length == 1 || typeof(n) == "undefined" || n === null) {
            n = 2;
        }
        var self = MochiKit.Iter;
        iterable = self.iter(iterable);
        var _tee = self._tee;
        for (var i = 0; i < n; i++) {
            rval.push(_tee(i, sync, iterable));
        }
        return rval;
    },

    /** @id MochiKit.Iter.list */
    list: function (iterable) {
        // Fast-path for Array and Array-like
        var rval;
        if (iterable instanceof Array) {
            return iterable.slice();
        } 
        // this is necessary to avoid a Safari crash
        if (typeof(iterable) == "function" &&
                !(iterable instanceof Function) &&
                typeof(iterable.length) == 'number') {
            rval = [];
            for (var i = 0; i < iterable.length; i++) {
                rval.push(iterable[i]);
            }
            return rval;
        }

        var self = MochiKit.Iter;
        iterable = self.iter(iterable);
        var rval = [];
        try {
            while (true) {
                rval.push(iterable.next());
            }
        } catch (e) {
            if (e != self.StopIteration) {
                throw e;
            }
            return rval;
        }
        // mozilla warnings aren't too bright
        return undefined;
    },


    /** @id MochiKit.Iter.reduce */
    reduce: function (fn, iterable, /* optional */initial) {
        var i = 0;
        var x = initial;
        var self = MochiKit.Iter;
        iterable = self.iter(iterable);
        if (arguments.length < 3) {
            try {
                x = iterable.next();
            } catch (e) {
                if (e == self.StopIteration) {
                    e = new TypeError("reduce() of empty sequence with no initial value");
                }
                throw e;
            }
            i++;
        }
        try {
            while (true) {
                x = fn(x, iterable.next());
            }
        } catch (e) {
            if (e != self.StopIteration) {
                throw e;
            }
        }
        return x;
    },

    /** @id MochiKit.Iter.range */
    range: function (/* [start,] stop[, step] */) {
        var start = 0;
        var stop = 0;
        var step = 1;
        if (arguments.length == 1) {
            stop = arguments[0];
        } else if (arguments.length == 2) {
            start = arguments[0];
            stop = arguments[1];
        } else if (arguments.length == 3) {
            start = arguments[0];
            stop = arguments[1];
            step = arguments[2];
        } else {
            throw new TypeError("range() takes 1, 2, or 3 arguments!");
        }
        if (step === 0) {
            throw new TypeError("range() step must not be 0");
        }
        return {
            next: function () {
                if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
                    throw MochiKit.Iter.StopIteration;
                }
                var rval = start;
                start += step;
                return rval;
            },
            repr: function () {
                return "range(" + [start, stop, step].join(", ") + ")";
            },
            toString: MochiKit.Base.forwardCall("repr")
        };
    },

    /** @id MochiKit.Iter.sum */
    sum: function (iterable, start/* = 0 */) {
        if (typeof(start) == "undefined" || start === null) {
            start = 0;
        }
        var x = start;
        var self = MochiKit.Iter;
        iterable = self.iter(iterable);
        try {
            while (true) {
                x += iterable.next();
            }
        } catch (e) {
            if (e != self.StopIteration) {
                throw e;
            }
        }
        return x;
    },

    /** @id MochiKit.Iter.exhaust */
    exhaust: function (iterable) {
        var self = MochiKit.Iter;
        iterable = self.iter(iterable);
        try {
            while (true) {
                iterable.next();
            }
        } catch (e) {
            if (e != self.StopIteration) {
                throw e;
            }
        }
    },

    /** @id MochiKit.Iter.forEach */
    forEach: function (iterable, func, /* optional */self) {
        var m = MochiKit.Base;
        if (arguments.length > 2) {
            func = m.bind(func, self);
        }
        // fast path for array
        if (m.isArrayLike(iterable)) {
            try {
                for (var i = 0; i < iterable.length; i++) {
                    func(iterable[i]);
                }
            } catch (e) {
                if (e != MochiKit.Iter.StopIteration) {
                    throw e;
                }
            }
        } else {
            self = MochiKit.Iter;
            self.exhaust(self.imap(func, iterable));
        }
    },

    /** @id MochiKit.Iter.every */
    every: function (iterable, func) {
        var self = MochiKit.Iter;
        try {
            self.ifilterfalse(func, iterable).next();
            return false;
        } catch (e) {
            if (e != self.StopIteration) {
                throw e;
            }
            return true;
        }
    },

    /** @id MochiKit.Iter.sorted */
    sorted: function (iterable, /* optional */cmp) {
        var rval = MochiKit.Iter.list(iterable);
        if (arguments.length == 1) {
            cmp = MochiKit.Base.compare;
        }
        rval.sort(cmp);
        return rval;
    },

    /** @id MochiKit.Iter.reversed */
    reversed: function (iterable) {
        var rval = MochiKit.Iter.list(iterable);
        rval.reverse();
        return rval;
    },

    /** @id MochiKit.Iter.some */
    some: function (iterable, func) {
        var self = MochiKit.Iter;
        try {
            self.ifilter(func, iterable).next();
            return true;
        } catch (e) {
            if (e != self.StopIteration) {
                throw e;
            }
            return false;
        }
    },

    /** @id MochiKit.Iter.iextend */
    iextend: function (lst, iterable) {
        if (MochiKit.Base.isArrayLike(iterable)) {
            // fast-path for array-like
            for (var i = 0; i < iterable.length; i++) {
                lst.push(iterable[i]);
            }
        } else {
            var self = MochiKit.Iter;
            iterable = self.iter(iterable);
            try {
                while (true) {
                    lst.push(iterable.next());
                }
            } catch (e) {
                if (e != self.StopIteration) {
                    throw e;
                }
            }
        }
        return lst;
    },

    /** @id MochiKit.Iter.groupby */
    groupby: function(iterable, /* optional */ keyfunc) {
        var m = MochiKit.Base;
        var self = MochiKit.Iter;
        if (arguments.length < 2) {
            keyfunc = m.operator.identity;
        }
        iterable = self.iter(iterable);

        // shared
        var pk = undefined;
        var k = undefined;
        var v;

        function fetch() {
            v = iterable.next();
            k = keyfunc(v);
        };

        function eat() {
            var ret = v;
            v = undefined;
            return ret;
        };

        var first = true;
        var compare = m.compare;
        return {
            repr: function () { return "groupby(...)"; },
            next: function() {
                // iterator-next

                // iterate until meet next group
                while (compare(k, pk) === 0) {
                    fetch();
                    if (first) {
                        first = false;
                        break;
                    }
                }
                pk = k;
                return [k, {
                    next: function() {
                        // subiterator-next
                        if (v == undefined) { // Is there something to eat?
                            fetch();
                        }
                        if (compare(k, pk) !== 0) {
                            throw self.StopIteration;
                        }
                        return eat();
                    }
                }];
            }
        };
    },

    /** @id MochiKit.Iter.groupby_as_array */
    groupby_as_array: function (iterable, /* optional */ keyfunc) {
        var m = MochiKit.Base;
        var self = MochiKit.Iter;
        if (arguments.length < 2) {
            keyfunc = m.operator.identity;
        }

        iterable = self.iter(iterable);
        var result = [];
        var first = true;
        var prev_key;
        var compare = m.compare;
        while (true) {
            try {
                var value = iterable.next();
                var key = keyfunc(value);
            } catch (e) {
                if (e == self.StopIteration) {
                    break;
                }
                throw e;
            }
            if (first || compare(key, prev_key) !== 0) {
                var values = [];
                result.push([key, values]);
            }
            values.push(value);
            first = false;
            prev_key = key;
        }
        return result;
    },

    /** @id MochiKit.Iter.arrayLikeIter */
    arrayLikeIter: function (iterable) {
        var i = 0;
        return {
            repr: function () { return "arrayLikeIter(...)"; },
            toString: MochiKit.Base.forwardCall("repr"),
            next: function () {
                if (i >= iterable.length) {
                    throw MochiKit.Iter.StopIteration;
                }
                return iterable[i++];
            }
        };
    },

    /** @id MochiKit.Iter.hasIterateNext */
    hasIterateNext: function (iterable) {
        return (iterable && typeof(iterable.iterateNext) == "function");
    },

    /** @id MochiKit.Iter.iterateNextIter */
    iterateNextIter: function (iterable) {
        return {
            repr: function () { return "iterateNextIter(...)"; },
            toString: MochiKit.Base.forwardCall("repr"),
            next: function () {
                var rval = iterable.iterateNext();
                if (rval === null || rval === undefined) {
                    throw MochiKit.Iter.StopIteration;
                }
                return rval;
            }
        };
    }
});


MochiKit.Iter.EXPORT_OK = [
    "iteratorRegistry",
    "arrayLikeIter",
    "hasIterateNext",
    "iterateNextIter"
];

MochiKit.Iter.EXPORT = [
    "StopIteration",
    "registerIteratorFactory",
    "iter",
    "count",
    "cycle",
    "repeat",
    "next",
    "izip",
    "ifilter",
    "ifilterfalse",
    "islice",
    "imap",
    "applymap",
    "chain",
    "takewhile",
    "dropwhile",
    "tee",
    "list",
    "reduce",
    "range",
    "sum",
    "exhaust",
    "forEach",
    "every",
    "sorted",
    "reversed",
    "some",
    "iextend",
    "groupby",
    "groupby_as_array"
];

MochiKit.Iter.__new__ = function () {
    var m = MochiKit.Base;
    // Re-use StopIteration if exists (e.g. SpiderMonkey)
    if (typeof(StopIteration) != "undefined") {
        this.StopIteration = StopIteration;
    } else {
        /** @id MochiKit.Iter.StopIteration */
        this.StopIteration = new m.NamedError("StopIteration");
    }
    this.iteratorRegistry = new m.AdapterRegistry();
    // Register the iterator factory for arrays
    this.registerIteratorFactory(
        "arrayLike",
        m.isArrayLike,
        this.arrayLikeIter
    );

    this.registerIteratorFactory(
        "iterateNext",
        this.hasIterateNext,
        this.iterateNextIter
    );

    this.EXPORT_TAGS = {
        ":common": this.EXPORT,
        ":all": m.concat(this.EXPORT, this.EXPORT_OK)
    };

    m.nameFunctions(this);

};

MochiKit.Iter.__new__();

//
// XXX: Internet Explorer blows
//
if (MochiKit.__export__) {
    reduce = MochiKit.Iter.reduce;
}

MochiKit.Base._exportSymbols(this, MochiKit.Iter);

/***

MochiKit.DOM 1.4

See <http://mochikit.com/> for documentation, downloads, license, etc.

(c) 2005 Bob Ippolito.  All rights Reserved.

***/

if (typeof(dojo) != 'undefined') {
    dojo.provide("MochiKit.DOM");
    dojo.require("MochiKit.Base");
}
if (typeof(JSAN) != 'undefined') {
    JSAN.use("MochiKit.Base", []);
}

try {
    if (typeof(MochiKit.Base) == 'undefined') {
        throw "";
    }
} catch (e) {
    throw "MochiKit.DOM depends on MochiKit.Base!";
}

if (typeof(MochiKit.DOM) == 'undefined') {
    MochiKit.DOM = {};
}

MochiKit.DOM.NAME = "MochiKit.DOM";
MochiKit.DOM.VERSION = "1.4";
MochiKit.DOM.__repr__ = function () {
    return "[" + this.NAME + " " + this.VERSION + "]";
};
MochiKit.DOM.toString = function () {
    return this.__repr__();
};

MochiKit.DOM.EXPORT = [
    "removeEmptyTextNodes",
    "formContents",
    "currentWindow",
    "currentDocument",
    "withWindow",
    "withDocument",
    "registerDOMConverter",
    "coerceToDOM",
    "createDOM",
    "createDOMFunc",
    "isChildNode",
    "getNodeAttribute",
    "removeNodeAttribute",
    "setNodeAttribute",
    "updateNodeAttributes",
    "appendChildNodes",
    "insertSiblingNodesAfter",
    "insertSiblingNodesBefore",
    "replaceChildNodes",
    "removeElement",
    "swapDOM",
    "BUTTON",
    "TT",
    "PRE",
    "H1",
    "H2",
    "H3",
    "BR",
    "CANVAS",
    "HR",
    "LABEL",
    "TEXTAREA",
    "FORM",
    "STRONG",
    "SELECT",
    "OPTION",
    "OPTGROUP",
    "LEGEND",
    "FIELDSET",
    "P",
    "UL",
    "OL",
    "LI",
	"DL",
	"DT",
	"DD",
    "TD",
    "TR",
    "THEAD",
    "TBODY",
    "TFOOT",
    "TABLE",
    "TH",
    "INPUT",
    "SPAN",
    "A",
    "DIV",
    "IMG",
    "getElement",
    "$",
    "getElementsByTagAndClassName",
    "addToCallStack",
    "addLoadEvent",
    "focusOnLoad",
    "setElementClass",
    "toggleElementClass",
    "addElementClass",
    "removeElementClass",
    "swapElementClass",
    "hasElementClass",
    "escapeHTML",
    "toHTML",
    "emitHTML",
    "scrapeText",
    "isParent",
    "getFirstParentByTagAndClassName",
    "makeClipping",
    "undoClipping",
    "makePositioned",
    "undoPositioned",
    "getFirstElementByTagAndClassName"
];

MochiKit.DOM.EXPORT_OK = [
    "domConverters"
];

MochiKit.DOM.DEPRECATED = [
    ['computedStyle', 'MochiKit.Style.getStyle', '1.4'],
    /** @id MochiKit.DOM.elementDimensions  */
    ['elementDimensions', 'MochiKit.Style.getElementDimensions', '1.4'],
    /** @id MochiKit.DOM.elementPosition  */
    ['elementPosition', 'MochiKit.Style.getElementPosition', '1.4'],
    ['hideElement', 'MochiKit.Style.hideElement', '1.4'],
    /** @id MochiKit.DOM.setElementDimensions */
    ['setElementDimensions', 'MochiKit.Style.setElementDimensions', '1.4'],
    /** @id MochiKit.DOM.setElementPosition */
    ['setElementPosition', 'MochiKit.Style.setElementPosition', '1.4'],
    ['setDisplayForElement', 'MochiKit.Style.setDisplayForElement', '1.4'],
    /** @id MochiKit.DOM.setOpacity */
    ['setOpacity', 'MochiKit.Style.setOpacity', '1.4'],
    ['showElement', 'MochiKit.Style.showElement', '1.4'],
    /** @id MochiKit.DOM.Coordinates */
    ['Coordinates', 'MochiKit.Style.Coordinates', '1.4'], // FIXME: broken
    /** @id MochiKit.DOM.Dimensions */
    ['Dimensions', 'MochiKit.Style.Dimensions', '1.4'] // FIXME: broken
];

/** @id MochiKit.DOM.getViewportDimensions */
MochiKit.DOM.getViewportDimensions = new Function('' +
    'if (!MochiKit["Style"]) {' +
    '    throw new Error("This function has been deprecated and depends on MochiKit.Style.");' +
    '}' +
    'return MochiKit.Style.getViewportDimensions.apply(this, arguments);');

MochiKit.Base.update(MochiKit.DOM, {

    /** @id MochiKit.DOM.currentWindow */
    currentWindow: function () {
        return MochiKit.DOM._window;
    },

    /** @id MochiKit.DOM.currentDocument */
    currentDocument: function () {
        return MochiKit.DOM._document;
    },

    /** @id MochiKit.DOM.withWindow */
    withWindow: function (win, func) {
        var self = MochiKit.DOM;
        var oldDoc = self._document;
        var oldWin = self._window;
        var rval;
        try {
            self._window = win;
            self._document = win.document;
            rval = func();
        } catch (e) {
            self._window = oldWin;
            self._document = oldDoc;
            throw e;
        }
        self._window = oldWin;
        self._document = oldDoc;
        return rval;
    },

    /** @id MochiKit.DOM.formContents  */
    formContents: function (elem/* = document.body */) {
        var names = [];
        var values = [];
        var m = MochiKit.Base;
        var self = MochiKit.DOM;
        if (typeof(elem) == "undefined" || elem === null) {
            elem = self._document.body;
        } else {
            elem = self.getElement(elem);
        }
        m.nodeWalk(elem, function (elem) {
            var name = elem.name;
            if (m.isNotEmpty(name)) {
                var tagName = elem.tagName.toUpperCase();
                if (tagName === "INPUT"
                    && (elem.type == "radio" || elem.type == "checkbox")
                    && !elem.checked
                ) {
                    return null;
                }
                if (tagName === "SELECT") {
                    if (elem.type == "select-one") {
                        if (elem.selectedIndex >= 0) {
                            var opt = elem.options[elem.selectedIndex];
                            var v = opt.value;
                            if (!v) {
                                var h = opt.outerHTML;
                                // internet explorer sure does suck.
                                if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
                                    v = opt.text;
                                }
                            }
                            names.push(name);
                            values.push(v);
                            return null;
                        }
                        // no form elements?
                        names.push(name);
                        values.push("");
                        return null;
                    } else {
                        var opts = elem.options;
                        if (!opts.length) {
                            names.push(name);
                            values.push("");
                            return null;
                        }
                        for (var i = 0; i < opts.length; i++) {
                            var opt = opts[i];
                            if (!opt.selected) {
                                continue;
                            }
                            var v = opt.value;
                            if (!v) {
                                var h = opt.outerHTML;
                                // internet explorer sure does suck.
                                if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
                                    v = opt.text;
                                }
                            }
                            names.push(name);
                            values.push(v);
                        }
                        return null;
                    }
                }
                if (tagName === "FORM" || tagName === "P" || tagName === "SPAN"
                    || tagName === "DIV"
                ) {
                    return elem.childNodes;
                }
                names.push(name);
                values.push(elem.value || '');
                return null;
            }
            return elem.childNodes;
        });
        return [names, values];
    },

    /** @id MochiKit.DOM.withDocument */
    withDocument: function (doc, func) {
        var self = MochiKit.DOM;
        var oldDoc = self._document;
        var rval;
        try {
            self._document = doc;
            rval = func();
        } catch (e) {
            self._document = oldDoc;
            throw e;
        }
        self._document = oldDoc;
        return rval;
    },

    /** @id MochiKit.DOM.registerDOMConverter */
    registerDOMConverter: function (name, check, wrap, /* optional */override) {
        MochiKit.DOM.domConverters.register(name, check, wrap, override);
    },

    /** @id MochiKit.DOM.coerceToDOM */
    coerceToDOM: function (node, ctx) {
        var m = MochiKit.Base;
        var im = MochiKit.Iter;
        var self = MochiKit.DOM;
        if (im) {
            var iter = im.iter;
            var repeat = im.repeat;
            var map = m.map;
        }
        var domConverters = self.domConverters;
        var coerceToDOM = arguments.callee;
        var NotFound = m.NotFound;
        while (true) {
            if (typeof(node) == 'undefined' || node === null) {
                return null;
            }
            // this is a safari childNodes object, avoiding crashes w/ attr
            // lookup
            if (typeof(node) == "function" &&
                    typeof(node.length) == "number" &&
                    !(node instanceof Function)) {
                node = im.list(node);
            }
            if (typeof(node.nodeType) != 'undefined' && node.nodeType > 0) {
                return node;
            }
            if (typeof(node) == 'number' || typeof(node) == 'boolean') {
                node = node.toString();
                // FALL THROUGH
            }
            if (typeof(node) == 'string') {
                return self._document.createTextNode(node);
            }
            if (typeof(node.__dom__) == 'function') {
                node = node.__dom__(ctx);
                continue;
            }
            if (typeof(node.dom) == 'function') {
                node = node.dom(ctx);
                continue;
            }
            if (typeof(node) == 'function') {
                node = node.apply(ctx, [ctx]);
                continue;
            }

            if (im) {
                // iterable
                var iterNodes = null;
                try {
                    iterNodes = iter(node);
                } catch (e) {
                    // pass
                }
                if (iterNodes) {
                    return map(coerceToDOM, iterNodes, repeat(ctx));
                }
            }

            // adapter
            try {
                node = domConverters.match(node, ctx);
                continue;
            } catch (e) {
                if (e != NotFound) {
                    throw e;
                }
            }

            // fallback
            return self._document.createTextNode(node.toString());
        }
        // mozilla warnings aren't too bright
        return undefined;
    },

    /** @id MochiKit.DOM.isChildNode */
    isChildNode: function (node, maybeparent) {
        var self = MochiKit.DOM;
        if (typeof(node) == "string") {
            node = self.getElement(node);
        }
        if (typeof(maybeparent) == "string") {
            maybeparent = self.getElement(maybeparent);
        }
        if (typeof(node) == 'undefined' || node === null || node === self._document) {
            return false;
        }
        do {
            if (node === maybeparent) {
                return true;
            }
            var tagName = node.tagName;
            node = node.parentNode;
            if (!tagName) {
                break;
            }
            tagName = tagName.toUpperCase();
        } while (tagName != "BODY" && tagName != "HTML");
        return false;
    },

    /** @id MochiKit.DOM.setNodeAttribute */
    setNodeAttribute: function (node, attr, value) {
        var o = {};
        o[attr] = value;
        try {
            return MochiKit.DOM.updateNodeAttributes(node, o);
        } catch (e) {
            // pass
        }
        return null;
    },

    /** @id MochiKit.DOM.getNodeAttribute */
    getNodeAttribute: function (node, attr) {
        var self = MochiKit.DOM;
        var rename = self.attributeArray.renames[attr];
        node = self.getElement(node);
        try {
            if (rename) {
                return node[rename];
            }
            return node.getAttribute(attr);
        } catch (e) {
            // pass
        }
        return null;
    },

    /** @id MochiKit.DOM.removeNodeAttribute */
    removeNodeAttribute: function (node, attr) {
        var self = MochiKit.DOM;
        var rename = self.attributeArray.renames[attr];
        node = self.getElement(node);
        try {
            if (rename) {
                return node[rename];
            }
            return node.removeAttribute(attr);
        } catch (e) {
            // pass
        }
        return null;
    },

    /** @id MochiKit.DOM.updateNodeAttributes */
    updateNodeAttributes: function (node, attrs) {
        var elem = node;
        var self = MochiKit.DOM;
        if (typeof(node) == 'string') {
            elem = self.getElement(node);
        }
        if (attrs) {
            var updatetree = MochiKit.Base.updatetree;
            if (self.attributeArray.compliant) {
                // not IE, good.
                for (var k in attrs) {
                    var v = attrs[k];
                    if (typeof(v) == 'object' && typeof(elem[k]) == 'object') {
                        if (k == "style" && MochiKit.Style) {
                            MochiKit.Style.setStyle(elem, v);
                        } else {
                            updatetree(elem[k], v);
                        }
                    } else if (k.substring(0, 2) == "on") {
                        if (typeof(v) == "string") {
                            v = new Function(v);
                        }
                        elem[k] = v;
                    } else {
                        elem.setAttribute(k, v);
                    }
                }
            } else {
                // IE is insane in the membrane
                var renames = self.attributeArray.renames;
                for (var k in attrs) {
                    v = attrs[k];
                    var renamed = renames[k];
                    if (k == "style" && typeof(v) == "string") {
                        elem.style.cssText = v;
                    } else if (typeof(renamed) == "string") {
                        elem[renamed] = v;
                    } else if (typeof(elem[k]) == 'object'
                            && typeof(v) == 'object') {
                        if (k == "style" && MochiKit.Style) {
                            MochiKit.Style.setStyle(elem, v);
                        } else {
                            updatetree(elem[k], v);
                        }
                    } else if (k.substring(0, 2) == "on") {
                        if (typeof(v) == "string") {
                            v = new Function(v);
                        }
                        elem[k] = v;
                    } else {
                        elem.setAttribute(k, v);
                    }
                }
            }
        }
        return elem;
    },

    /** @id MochiKit.DOM.appendChildNodes */
    appendChildNodes: function (node/*, nodes...*/) {
        var elem = node;
        var self = MochiKit.DOM;
        if (typeof(node) == 'string') {
            elem = self.getElement(node);
        }
        var nodeStack = [
            self.coerceToDOM(
                MochiKit.Base.extend(null, arguments, 1),
                elem
            )
        ];
        var concat = MochiKit.Base.concat;
        while (nodeStack.length) {
            var n = nodeStack.shift();
            if (typeof(n) == 'undefined' || n === null) {
                // pass
            } else if (typeof(n.nodeType) == 'number') {
                elem.appendChild(n);
            } else {
                nodeStack = concat(n, nodeStack);
            }
        }
        return elem;
    },


    /** @id MochiKit.DOM.insertSiblingNodesBefore */
    insertSiblingNodesBefore: function (node/*, nodes...*/) {
        var elem = node;
        var self = MochiKit.DOM;
        if (typeof(node) == 'string') {
            elem = self.getElement(node);
        }
        var nodeStack = [
            self.coerceToDOM(
                MochiKit.Base.extend(null, arguments, 1),
                elem
            )
        ];
        var parentnode = elem.parentNode;
        var concat = MochiKit.Base.concat;
        while (nodeStack.length) {
            var n = nodeStack.shift();
            if (typeof(n) == 'undefined' || n === null) {
                // pass
            } else if (typeof(n.nodeType) == 'number') {
                parentnode.insertBefore(n, elem);
            } else {
                nodeStack = concat(n, nodeStack);
            }
        }
        return parentnode;
    },

    /** @id MochiKit.DOM.insertSiblingNodesAfter */
    insertSiblingNodesAfter: function (node/*, nodes...*/) {
        var elem = node;
        var self = MochiKit.DOM;

        if (typeof(node) == 'string') {
            elem = self.getElement(node);
        }
        var nodeStack = [
            self.coerceToDOM(
                MochiKit.Base.extend(null, arguments, 1),
                elem
            )
        ];

        if (elem.nextSibling) {
            return self.insertSiblingNodesBefore(elem.nextSibling, nodeStack);
        }
        else {
            return self.appendChildNodes(elem.parentNode, nodeStack);
        }
    },

    /** @id MochiKit.DOM.replaceChildNodes */
    replaceChildNodes: function (node/*, nodes...*/) {
        var elem = node;
        var self = MochiKit.DOM;
        if (typeof(node) == 'string') {
            elem = self.getElement(node);
            arguments[0] = elem;
        }
        var child;
        while ((child = elem.firstChild)) {
            elem.removeChild(child);
        }
        if (arguments.length < 2) {
            return elem;
        } else {
            return self.appendChildNodes.apply(this, arguments);
        }
    },

    /** @id MochiKit.DOM.createDOM */
    createDOM: function (name, attrs/*, nodes... */) {
        var elem;
        var self = MochiKit.DOM;
        var m = MochiKit.Base;
        if (typeof(attrs) == "string" || typeof(attrs) == "number") {
            var args = m.extend([name, null], arguments, 1);
            return arguments.callee.apply(this, args);
        }
        if (typeof(name) == 'string') {
            // Internet Explorer is dumb
            var xhtml = self._xhtml;
            if (attrs && !self.attributeArray.compliant) {
                // http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp
                var contents = "";
                if ('name' in attrs) {
                    contents += ' name="' + self.escapeHTML(attrs.name) + '"';
                }
                if (name == 'input' && 'type' in attrs) {
                    contents += ' type="' + self.escapeHTML(attrs.type) + '"';
                }
                if (contents) {
                    name = "<" + name + contents + ">";
                    xhtml = false;
                }
            }
            var d = self._document;
            if (xhtml && d === document) {
                elem = d.createElementNS("http://www.w3.org/1999/xhtml", name);
            } else {
                elem = d.createElement(name);
            }
        } else {
            elem = name;
        }
        if (attrs) {
            self.updateNodeAttributes(elem, attrs);
        }
        if (arguments.length <= 2) {
            return elem;
        } else {
            var args = m.extend([elem], arguments, 2);
            return self.appendChildNodes.apply(this, args);
        }
    },

    /** @id MochiKit.DOM.createDOMFunc */
    createDOMFunc: function (/* tag, attrs, *nodes */) {
        var m = MochiKit.Base;
        return m.partial.apply(
            this,
            m.extend([MochiKit.DOM.createDOM], arguments)
        );
    },

    /** @id MochiKit.DOM.removeElement */
    removeElement: function (elem) {
        var e = MochiKit.DOM.getElement(elem);
        e.parentNode.removeChild(e);
        return e;
    },

    /** @id MochiKit.DOM.swapDOM */
    swapDOM: function (dest, src) {
        var self = MochiKit.DOM;
        dest = self.getElement(dest);
        var parent = dest.parentNode;
        if (src) {
            src = self.getElement(src);
            parent.replaceChild(src, dest);
        } else {
            parent.removeChild(dest);
        }
        return src;
    },

    /** @id MochiKit.DOM.getElement */
    getElement: function (id) {
        var self = MochiKit.DOM;
        if (arguments.length == 1) {
            return ((typeof(id) == "string") ?
                self._document.getElementById(id) : id);
        } else {
            return MochiKit.Base.map(self.getElement, arguments);
        }
    },

    /** @id MochiKit.DOM.getElementsByTagAndClassName */
    getElementsByTagAndClassName: function (tagName, className,
            /* optional */parent) {
        var self = MochiKit.DOM;
        if (typeof(tagName) == 'undefined' || tagName === null) {
            tagName = '*';
        }
        if (typeof(parent) == 'undefined' || parent === null) {
            parent = self._document;
        }
        parent = self.getElement(parent);
        var children = (parent.getElementsByTagName(tagName)
            || self._document.all);
        if (typeof(className) == 'undefined' || className === null) {
            return MochiKit.Base.extend(null, children);
        }

        var elements = [];
        for (var i = 0; i < children.length; i++) {
            var child = children[i];
            var cls = child.className;
            if (!cls) {
                continue;
            }
            var classNames = cls.split(' ');
            for (var j = 0; j < classNames.length; j++) {
                if (classNames[j] == className) {
                    elements.push(child);
                    break;
                }
            }
        }

        return elements;
    },

    _newCallStack: function (path, once) {
        var rval = function () {
            var callStack = arguments.callee.callStack;
            for (var i = 0; i < callStack.length; i++) {
                if (callStack[i].apply(this, arguments) === false) {
                    break;
                }
            }
            if (once) {
                try {
                    this[path] = null;
                } catch (e) {
                    // pass
                }
            }
        };
        rval.callStack = [];
        return rval;
    },

    /** @id MochiKit.DOM.addToCallStack */
    addToCallStack: function (target, path, func, once) {
        var self = MochiKit.DOM;
        var existing = target[path];
        var regfunc = existing;
        if (!(typeof(existing) == 'function'
                && typeof(existing.callStack) == "object"
                && existing.callStack !== null)) {
            regfunc = self._newCallStack(path, once);
            if (typeof(existing) == 'function') {
                regfunc.callStack.push(existing);
            }
            target[path] = regfunc;
        }
        regfunc.callStack.push(func);
    },

    /** @id MochiKit.DOM.addLoadEvent */
    addLoadEvent: function (func) {
        var self = MochiKit.DOM;
        self.addToCallStack(self._window, "onload", func, true);

    },

    /** @id MochiKit.DOM.focusOnLoad */
    focusOnLoad: function (element) {
        var self = MochiKit.DOM;
        self.addLoadEvent(function () {
            element = self.getElement(element);
            if (element) {
                element.focus();
            }
        });
    },

    /** @id MochiKit.DOM.setElementClass */
    setElementClass: function (element, className) {
        var self = MochiKit.DOM;
        var obj = self.getElement(element);
        if (self.attributeArray.compliant) {
            obj.setAttribute("class", className);
        } else {
            obj.setAttribute("className", className);
        }
    },

    /** @id MochiKit.DOM.toggleElementClass */
    toggleElementClass: function (className/*, element... */) {
        var self = MochiKit.DOM;
        for (var i = 1; i < arguments.length; i++) {
            var obj = self.getElement(arguments[i]);
            if (!self.addElementClass(obj, className)) {
                self.removeElementClass(obj, className);
            }
        }
    },

    /** @id MochiKit.DOM.addElementClass */
    addElementClass: function (element, className) {
        var self = MochiKit.DOM;
        var obj = self.getElement(element);
        var cls = obj.className;
        // trivial case, no className yet
        if (cls == undefined || cls.length === 0) {
            self.setElementClass(obj, className);
            return true;
        }
        // the other trivial case, already set as the only class
        if (cls == className) {
            return false;
        }
        var classes = cls.split(" ");
        for (var i = 0; i < classes.length; i++) {
            // already present
            if (classes[i] == className) {
                return false;
            }
        }
        // append class
        self.setElementClass(obj, cls + " " + className);
        return true;
    },

    /** @id MochiKit.DOM.removeElementClass */
    removeElementClass: function (element, className) {
        var self = MochiKit.DOM;
        var obj = self.getElement(element);
        var cls = obj.className;
        // trivial case, no className yet
        if (cls == undefined || cls.length === 0) {
            return false;
        }
        // other trivial case, set only to className
        if (cls == className) {
            self.setElementClass(obj, "");
            return true;
        }
        var classes = cls.split(" ");
        for (var i = 0; i < classes.length; i++) {
            // already present
            if (classes[i] == className) {
                // only check sane case where the class is used once
                classes.splice(i, 1);
                self.setElementClass(obj, classes.join(" "));
                return true;
            }
        }
        // not found
        return false;
    },

    /** @id MochiKit.DOM.swapElementClass */
    swapElementClass: function (element, fromClass, toClass) {
        var obj = MochiKit.DOM.getElement(element);
        var res = MochiKit.DOM.removeElementClass(obj, fromClass);
        if (res) {
            MochiKit.DOM.addElementClass(obj, toClass);
        }
        return res;
    },

    /** @id MochiKit.DOM.hasElementClass */
    hasElementClass: function (element, className/*...*/) {
        var obj = MochiKit.DOM.getElement(element);
        var cls = obj.className;
        if (!cls) {
            return false;
        }
        var classes = cls.split(" ");
        for (var i = 1; i < arguments.length; i++) {
            var good = false;
            for (var j = 0; j < classes.length; j++) {
                if (classes[j] == arguments[i]) {
                    good = true;
                    break;
                }
            }
            if (!good) {
                return false;
            }
        }
        return true;
    },

    /** @id MochiKit.DOM.escapeHTML */
    escapeHTML: function (s) {
        return s.replace(/&/g, "&amp;"
            ).replace(/"/g, "&quot;"
            ).replace(/</g, "&lt;"
            ).replace(/>/g, "&gt;");
    },

    /** @id MochiKit.DOM.toHTML */
    toHTML: function (dom) {
        return MochiKit.DOM.emitHTML(dom).join("");
    },

    /** @id MochiKit.DOM.emitHTML */
    emitHTML: function (dom, /* optional */lst) {
        if (typeof(lst) == 'undefined' || lst === null) {
            lst = [];
        }
        // queue is the call stack, we're doing this non-recursively
        var queue = [dom];
        var self = MochiKit.DOM;
        var escapeHTML = self.escapeHTML;
        var attributeArray = self.attributeArray;
        while (queue.length) {
            dom = queue.pop();
            if (typeof(dom) == 'string') {
                lst.push(dom);
            } else if (dom.nodeType == 1) {
                // we're not using higher order stuff here
                // because safari has heisenbugs.. argh.
                //
                // I think it might have something to do with
                // garbage collection and function calls.
                lst.push('<' + dom.tagName.toLowerCase());
                var attributes = [];
                var domAttr = attributeArray(dom);
                for (var i = 0; i < domAttr.length; i++) {
                    var a = domAttr[i];
                    attributes.push([
                        " ",
                        a.name,
                        '="',
                        escapeHTML(a.value),
                        '"'
                    ]);
                }
                attributes.sort();
                for (i = 0; i < attributes.length; i++) {
                    var attrs = attributes[i];
                    for (var j = 0; j < attrs.length; j++) {
                        lst.push(attrs[j]);
                    }
                }
                if (dom.hasChildNodes()) {
                    lst.push(">");
                    // queue is the FILO call stack, so we put the close tag
                    // on first
                    queue.push("</" + dom.tagName.toLowerCase() + ">");
                    var cnodes = dom.childNodes;
                    for (i = cnodes.length - 1; i >= 0; i--) {
                        queue.push(cnodes[i]);
                    }
                } else {
                    lst.push('/>');
                }
            } else if (dom.nodeType == 3) {
                lst.push(escapeHTML(dom.nodeValue));
            }
        }
        return lst;
    },

    /** @id MochiKit.DOM.scrapeText */
    scrapeText: function (node, /* optional */asArray) {
        var rval = [];
        (function (node) {
            var cn = node.childNodes;
            if (cn) {
                for (var i = 0; i < cn.length; i++) {
                    arguments.callee.call(this, cn[i]);
                }
            }
            var nodeValue = node.nodeValue;
            if (typeof(nodeValue) == 'string') {
                rval.push(nodeValue);
            }
        })(MochiKit.DOM.getElement(node));
        if (asArray) {
            return rval;
        } else {
            return rval.join("");
        }
    },

    /** @id MochiKit.DOM.removeEmptyTextNodes */
    removeEmptyTextNodes: function (element) {
        element = MochiKit.DOM.getElement(element);
        for (var i = 0; i < element.childNodes.length; i++) {
            var node = element.childNodes[i];
            if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
                node.parentNode.removeChild(node);
            }
        }
    },

    /** @id MochiKit.DOM.makeClipping */
    makeClipping: function (element) {
        element = MochiKit.DOM.getElement(element);
        var oldOverflow = element.style.overflow;
        if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') {
            element.style.overflow = 'hidden';
        }
        return oldOverflow;
    },

    /** @id MochiKit.DOM.undoClipping */
    undoClipping: function (element, overflow) {
        element = MochiKit.DOM.getElement(element);
        if (!overflow) {
            return;
        }
        element.style.overflow = overflow;
    },

    /** @id MochiKit.DOM.makePositioned */
    makePositioned: function (element) {
        element = MochiKit.DOM.getElement(element);
        var pos = MochiKit.Style.getStyle(element, 'position');
        if (pos == 'static' || !pos) {
            element.style.position = 'relative';
            // Opera returns the offset relative to the positioning context,
            // when an element is position relative but top and left have
            // not been defined
            if (/Opera/.test(navigator.userAgent)) {
                element.style.top = 0;
                element.style.left = 0;
            }
        }
    },

    /** @id MochiKit.DOM.undoPositioned */
    undoPositioned: function (element) {
        element = MochiKit.DOM.getElement(element);
        if (element.style.position == 'relative') {
            element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
        }
    },

    /** @id MochiKit.DOM.getFirstElementByTagAndClassName */
    getFirstElementByTagAndClassName: function (tagName, className,
            /* optional */parent) {
        var self = MochiKit.DOM;
        if (typeof(tagName) == 'undefined' || tagName === null) {
            tagName = '*';
        }
        if (typeof(parent) == 'undefined' || parent === null) {
            parent = self._document;
        }
        parent = self.getElement(parent);
        var children = (parent.getElementsByTagName(tagName)
            || self._document.all);
        if (typeof(className) == 'undefined' || className === null) {
            return children[0];
        }

        for (var i = 0; i < children.length; i++) {
            var child = children[i];
            var classNames = child.className.split(' ');
            for (var j = 0; j < classNames.length; j++) {
                if (classNames[j] == className) {
                    return child;
                }
            }
        }
    },

    /** @id MochiKit.DOM.getFirstParentByTagAndClassName */
    getFirstParentByTagAndClassName: function (elem, tagName, className) {
        var self = MochiKit.DOM;
        elem = self.getElement(elem);
        if (typeof(tagName) == 'undefined' || tagName === null) {
            tagName = '*';
        } else {
            tagName = tagName.toUpperCase();
        }
        if (typeof(className) == 'undefined' || className === null) {
            className = null;
        }

        var classList = '';
        var curTagName = '';
        while (elem && elem.tagName) {
            elem = elem.parentNode;
            if (tagName == '*' && className === null) {
                return elem;
            }
            classList = elem.className.split(' ');
            curTagName = elem.tagName.toUpperCase();
            if (className === null && tagName == curTagName) {
                return elem;
            } else if (className !== null) {
                for (var i = 0; i < classList.length; i++) {
                    if (tagName == '*' && classList[i] == className) {
                        return elem;
                    } else if (tagName == curTagName && classList[i] == className) {
                        return elem;
                    }
                }
            }
        }
        return elem;
    },

    /** @id MochiKit.DOM.isParent */
    isParent: function (child, element) {
        if (!child.parentNode || child == element) {
            return false;
        }

        if (child.parentNode == element) {
            return true;
        }

        return MochiKit.DOM.isParent(child.parentNode, element);
    },

    __new__: function (win) {

        var m = MochiKit.Base;
        if (typeof(document) != "undefined") {
            this._document = document;
            var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
            this._xhtml = (document.documentElement &&
                document.createElementNS &&
                document.documentElement.namespaceURI === kXULNSURI);
        } else if (MochiKit.MockDOM) {
            this._document = MochiKit.MockDOM.document;
        }
        this._window = win;

        this.domConverters = new m.AdapterRegistry();

        var __tmpElement = this._document.createElement("span");
        var attributeArray;
        if (__tmpElement && __tmpElement.attributes &&
                __tmpElement.attributes.length > 0) {
            // for braindead browsers (IE) that insert extra junk
            var filter = m.filter;
            attributeArray = function (node) {
                return filter(attributeArray.ignoreAttrFilter, node.attributes);
            };
            attributeArray.ignoreAttr = {};
            var attrs = __tmpElement.attributes;
            var ignoreAttr = attributeArray.ignoreAttr;
            for (var i = 0; i < attrs.length; i++) {
                var a = attrs[i];
                ignoreAttr[a.name] = a.value;
            }
            attributeArray.ignoreAttrFilter = function (a) {
                return (attributeArray.ignoreAttr[a.name] != a.value);
            };
            attributeArray.compliant = false;
            attributeArray.renames = {
                "class": "className",
                "checked": "defaultChecked",
                "usemap": "useMap",
                "for": "htmlFor",
                "readonly": "readOnly",
                "colspan": "colSpan",
                "bgcolor": "bgColor",
                "cellspacing": "cellSpacing",
                "cellpadding": "cellPadding"
            };
        } else {
            attributeArray = function (node) {
                /***

                    Return an array of attributes for a given node,
                    filtering out attributes that don't belong for
                    that are inserted by "Certain Browsers".

                ***/
                return node.attributes;
            };
            attributeArray.compliant = true;
            attributeArray.renames = {};
        }
        this.attributeArray = attributeArray;

        // FIXME: this really belongs in Base, and could probably be cleaner
        var _deprecated = function(fromModule, arr) {
            var modules = arr[1].split('.');
            var str = '';
            var obj = {};

            str += 'if (!MochiKit.' + modules[1] + ') { throw new Error("';
            str += 'This function has been deprecated and depends on MochiKit.';
            str += modules[1] + '.");}';
            str += 'return MochiKit.' + modules[1] + '.' + arr[0];
            str += '.apply(this, arguments);';

            obj[modules[2]] = new Function(str);
            MochiKit.Base.update(MochiKit[fromModule], obj);
        }
        for (var i; i < MochiKit.DOM.DEPRECATED.length; i++) {
            _deprecated('DOM', MochiKit.DOM.DEPRECATED[i]);
        }

        // shorthand for createDOM syntax
        var createDOMFunc = this.createDOMFunc;
        /** @id MochiKit.DOM.UL */
        this.UL = createDOMFunc("ul");
        /** @id MochiKit.DOM.OL */
        this.OL = createDOMFunc("ol");
        /** @id MochiKit.DOM.LI */
        this.LI = createDOMFunc("li");
		/** @id MochiKit.DOM.DL */
        this.DL = createDOMFunc("dl");
		/** @id MochiKit.DOM.DT */
        this.DT = createDOMFunc("dt");
		/** @id MochiKit.DOM.DD */
        this.DD = createDOMFunc("dd");
        /** @id MochiKit.DOM.TD */
        this.TD = createDOMFunc("td");
        /** @id MochiKit.DOM.TR */
        this.TR = createDOMFunc("tr");
        /** @id MochiKit.DOM.TBODY */
        this.TBODY = createDOMFunc("tbody");
        /** @id MochiKit.DOM.THEAD */
        this.THEAD = createDOMFunc("thead");
        /** @id MochiKit.DOM.TFOOT */
        this.TFOOT = createDOMFunc("tfoot");
        /** @id MochiKit.DOM.TABLE */
        this.TABLE = createDOMFunc("table");
        /** @id MochiKit.DOM.TH */
        this.TH = createDOMFunc("th");
        /** @id MochiKit.DOM.INPUT */
        this.INPUT = createDOMFunc("input");
        /** @id MochiKit.DOM.SPAN */
        this.SPAN = createDOMFunc("span");
        /** @id MochiKit.DOM.A */
        this.A = createDOMFunc("a");
        /** @id MochiKit.DOM.DIV */
        this.DIV = createDOMFunc("div");
        /** @id MochiKit.DOM.IMG */
        this.IMG = createDOMFunc("img");
        /** @id MochiKit.DOM.BUTTON */
        this.BUTTON = createDOMFunc("button");
        /** @id MochiKit.DOM.TT */
        this.TT = createDOMFunc("tt");
        /** @id MochiKit.DOM.PRE */
        this.PRE = createDOMFunc("pre");
        /** @id MochiKit.DOM.H1 */
        this.H1 = createDOMFunc("h1");
        /** @id MochiKit.DOM.H2 */
        this.H2 = createDOMFunc("h2");
        /** @id MochiKit.DOM.H3 */
        this.H3 = createDOMFunc("h3");
        /** @id MochiKit.DOM.BR */
        this.BR = createDOMFunc("br");
        /** @id MochiKit.DOM.HR */
        this.HR = createDOMFunc("hr");
        /** @id MochiKit.DOM.LABEL */
        this.LABEL = createDOMFunc("label");
        /** @id MochiKit.DOM.TEXTAREA */
        this.TEXTAREA = createDOMFunc("textarea");
        /** @id MochiKit.DOM.FORM */
        this.FORM = createDOMFunc("form");
        /** @id MochiKit.DOM.P */
        this.P = createDOMFunc("p");
        /** @id MochiKit.DOM.SELECT */
        this.SELECT = createDOMFunc("select");
        /** @id MochiKit.DOM.OPTION */
        this.OPTION = createDOMFunc("option");
        /** @id MochiKit.DOM.OPTGROUP */
        this.OPTGROUP = createDOMFunc("optgroup");
        /** @id MochiKit.DOM.LEGEND */
        this.LEGEND = createDOMFunc("legend");
        /** @id MochiKit.DOM.FIELDSET */
        this.FIELDSET = createDOMFunc("fieldset");
        /** @id MochiKit.DOM.STRONG */
        this.STRONG = createDOMFunc("strong");
        /** @id MochiKit.DOM.CANVAS */
        this.CANVAS = createDOMFunc("canvas");

        /** @id MochiKit.DOM.$ */
        this.$ = this.getElement;

        this.EXPORT_TAGS = {
            ":common": this.EXPORT,
            ":all": m.concat(this.EXPORT, this.EXPORT_OK)
        };

        m.nameFunctions(this);

    }
});


MochiKit.DOM.__new__(((typeof(window) == "undefined") ? this : window));

//
// XXX: Internet Explorer blows
//
if (MochiKit.__export__) {
    withWindow = MochiKit.DOM.withWindow;
    withDocument = MochiKit.DOM.withDocument;
}

MochiKit.Base._exportSymbols(this, MochiKit.DOM);

/***

MochiKit.Style 1.4

See <http://mochikit.com/> for documentation, downloads, license, etc.

(c) 2005-2006 Bob Ippolito, Beau Hartshorne.  All rights Reserved.

***/

if (typeof(dojo) != 'undefined') {
    dojo.provide('MochiKit.Style');
    dojo.require('MochiKit.Base');
    dojo.require('MochiKit.DOM');
}
if (typeof(JSAN) != 'undefined') {
    JSAN.use('MochiKit.Base', []);
    JSAN.use('MochiKit.DOM', []);
}

try {
    if (typeof(MochiKit.Base) == 'undefined') {
        throw '';
    }
} catch (e) {
    throw 'MochiKit.Style depends on MochiKit.Base!';
}

try {
    if (typeof(MochiKit.DOM) == 'undefined') {
        throw '';
    }
} catch (e) {
    throw 'MochiKit.Style depends on MochiKit.DOM!';
}


if (typeof(MochiKit.Style) == 'undefined') {
    MochiKit.Style = {};
}

MochiKit.Style.NAME = 'MochiKit.Style';
MochiKit.Style.VERSION = '1.4';
MochiKit.Style.__repr__ = function () {
    return '[' + this.NAME + ' ' + this.VERSION + ']';
};
MochiKit.Style.toString = function () {
    return this.__repr__();
};

MochiKit.Style.EXPORT_OK = [];

MochiKit.Style.EXPORT = [
    'setStyle',
    'setOpacity',
    'getStyle',
    'getElementDimensions',
    'elementDimensions', // deprecated
    'setElementDimensions',
    'getElementPosition',
    'elementPosition', // deprecated
    'setElementPosition',
    'setDisplayForElement',
    'hideElement',
    'showElement',
    'getViewportDimensions',
    'getViewportPosition',
    'Dimensions',
    'Coordinates'
];


/*

    Dimensions

*/
/** @id MochiKit.Style.Dimensions */
MochiKit.Style.Dimensions = function (w, h) {
    this.w = w;
    this.h = h;
};

MochiKit.Style.Dimensions.prototype.__repr__ = function () {
    var repr = MochiKit.Base.repr;
    return '{w: '  + repr(this.w) + ', h: ' + repr(this.h) + '}';
};

MochiKit.Style.Dimensions.prototype.toString = function () {
    return this.__repr__();
};


/*

    Coordinates

*/
/** @id MochiKit.Style.Coordinates */
MochiKit.Style.Coordinates = function (x, y) {
    this.x = x;
    this.y = y;
};

MochiKit.Style.Coordinates.prototype.__repr__ = function () {
    var repr = MochiKit.Base.repr;
    return '{x: '  + repr(this.x) + ', y: ' + repr(this.y) + '}';
};

MochiKit.Style.Coordinates.prototype.toString = function () {
    return this.__repr__();
};


MochiKit.Base.update(MochiKit.Style, {

    /** @id MochiKit.Style.getStyle */
    getStyle: function (elem, cssProperty) {
        var dom = MochiKit.DOM;
        var d = dom._document;

        elem = dom.getElement(elem);
        cssProperty = MochiKit.Base.camelize(cssProperty);

        if (!elem || elem == d) {
            return undefined;
        }
        if (cssProperty == 'opacity' && elem.filters) {
            var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/);
            if (opacity && opacity[1]) {
                return parseFloat(opacity[1]) / 100;
            }
            return 1.0;
        }
        var value = elem.style ? elem.style[cssProperty] : null;
        if (!value) {
            if (d.defaultView && d.defaultView.getComputedStyle) {
                var css = d.defaultView.getComputedStyle(elem, null);
                cssProperty = cssProperty.replace(/([A-Z])/g, '-$1'
                    ).toLowerCase(); // from dojo.style.toSelectorCase
                value = css ? css.getPropertyValue(cssProperty) : null;
            } else if (elem.currentStyle) {
                value = elem.currentStyle[cssProperty];
            }
        }
        if (cssProperty == 'opacity') {
            value = parseFloat(value);
        }

        if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) {
            if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
                value = 'auto';
            }
        }

        return value == 'auto' ? null : value;
    },

    /** @id MochiKit.Style.setStyle */
    setStyle: function (elem, style) {
        elem = MochiKit.DOM.getElement(elem);
        for (var name in style) {
            if (name == 'opacity') {
                MochiKit.Style.setOpacity(elem, style[name]);
            } else {
                elem.style[MochiKit.Base.camelize(name)] = style[name];
            }
        }
    },

    /** @id MochiKit.Style.setOpacity */
    setOpacity: function (elem, o) {
        elem = MochiKit.DOM.getElement(elem);
        var self = MochiKit.Style;
        if (o == 1) {
            var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
            elem.style["opacity"] = toSet ? 0.999999 : 1.0;
            if (/MSIE/.test(navigator.userAgent)) {
                elem.style['filter'] =
                    self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '');
            }
        } else {
            if (o < 0.00001) {
                o = 0;
            }
            elem.style["opacity"] = o;
            if (/MSIE/.test(navigator.userAgent)) {
                elem.style['filter'] =
                    self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')';
            }
        }
    },

    /*

        getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0.
        Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved.
        License: BSD, http://developer.yahoo.net/yui/license.txt

    */

    /** @id MochiKit.Style.getElementPosition */
    getElementPosition: function (elem, /* optional */relativeTo) {
        var self = MochiKit.Style;
        var dom = MochiKit.DOM;
        elem = dom.getElement(elem);

        if (!elem ||
            (!(elem.x && elem.y) &&
            (!elem.parentNode === null ||
            self.getStyle(elem, 'display') == 'none'))) {
            return undefined;
        }

        var c = new self.Coordinates(0, 0);
        var box = null;
        var parent = null;

        var d = MochiKit.DOM._document;
        var de = d.documentElement;
        var b = d.body;

        if (!elem.parentNode && elem.x && elem.y) {
            /* it's just a MochiKit.Style.Coordinates object */
            c.x += elem.x || 0;
            c.y += elem.y || 0;
        } else if (elem.getBoundingClientRect) { // IE shortcut
            /*

                The IE shortcut can be off by two. We fix it. See:
                http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp

                This is similar to the method used in
                MochiKit.Signal.Event.mouse().

            */
            box = elem.getBoundingClientRect();

            c.x += box.left +
                (de.scrollLeft || b.scrollLeft) -
                (de.clientLeft || 0);

            c.y += box.top +
                (de.scrollTop || b.scrollTop) -
                (de.clientTop || 0);

            // Don't pass through next steps
            return c;
        } else if (elem.offsetParent) {
            c.x += elem.offsetLeft;
            c.y += elem.offsetTop;
            parent = elem.offsetParent;

            if (parent != elem) {
                while (parent) {
                    c.x += parent.offsetLeft;
                    c.y += parent.offsetTop;
                    parent = parent.offsetParent;
                }
            }

            /*

                Opera < 9 and old Safari (absolute) incorrectly account for
                body offsetTop and offsetLeft.

            */
            var ua = navigator.userAgent.toLowerCase();
            if ((typeof(opera) != 'undefined' &&
                parseFloat(opera.version()) < 9) ||
                (ua.indexOf('AppleWebKit') != -1 &&
                self.getStyle(elem, 'position') == 'absolute')) {

                c.x -= b.offsetLeft;
                c.y -= b.offsetTop;

            }
        }

        if (typeof(relativeTo) != 'undefined') {
            relativeTo = arguments.callee(relativeTo);
            if (relativeTo) {
                c.x -= (relativeTo.x || 0);
                c.y -= (relativeTo.y || 0);
            }
        }

        if (elem.parentNode) {
            parent = elem.parentNode;
        } else {
            parent = null;
        }

        while (parent) {
            var tagName = parent.tagName.toUpperCase();
            if (tagName === 'BODY' || tagName === 'HTML') {
                break;
            }
            var disp = self.getStyle(parent, 'display');
            // Handle strange Opera bug for some display
            if (disp.search(/^inline|table-row.*$/i)) {
                c.x -= parent.scrollLeft;
                c.y -= parent.scrollTop;
            }
            if (parent.parentNode) {
                parent = parent.parentNode;
            } else {
                parent = null;
            }
        }

        return c;
    },

    /** @id MochiKit.Style.setElementPosition */
    setElementPosition: function (elem, newPos/* optional */, units) {
        elem = MochiKit.DOM.getElement(elem);
        if (typeof(units) == 'undefined') {
            units = 'px';
        }
        var newStyle = {};
        var isUndefNull = MochiKit.Base.isUndefinedOrNull;
        if (!isUndefNull(newPos.x)) {
            newStyle['left'] = newPos.x + units;
        }
        if (!isUndefNull(newPos.y)) {
            newStyle['top'] = newPos.y + units;
        }
        MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
    },

    /** @id MochiKit.Style.getElementDimensions */
    getElementDimensions: function (elem) {
        var self = MochiKit.Style;
        var dom = MochiKit.DOM;
        if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') {
            return new self.Dimensions(elem.w || 0, elem.h || 0);
        }
        elem = dom.getElement(elem);
        if (!elem) {
            return undefined;
        }
        var disp = self.getStyle(elem, 'display');
        // display can be empty/undefined on WebKit/KHTML
        if (disp != 'none' && disp !== '' && typeof(disp) != 'undefined') {
            return new self.Dimensions(elem.offsetWidth || 0,
                elem.offsetHeight || 0);
        }
        var s = elem.style;
        var originalVisibility = s.visibility;
        var originalPosition = s.position;
        s.visibility = 'hidden';
        s.position = 'absolute';
        s.display = '';
        var originalWidth = elem.offsetWidth;
        var originalHeight = elem.offsetHeight;
        s.display = 'none';
        s.position = originalPosition;
        s.visibility = originalVisibility;
        return new self.Dimensions(originalWidth, originalHeight);
    },

    /** @id MochiKit.Style.setElementDimensions */
    setElementDimensions: function (elem, newSize/* optional */, units) {
        elem = MochiKit.DOM.getElement(elem);
        if (typeof(units) == 'undefined') {
            units = 'px';
        }
        var newStyle = {};
        var isUndefNull = MochiKit.Base.isUndefinedOrNull;
        if (!isUndefNull(newSize.w)) {
            newStyle['width'] = newSize.w + units;
        }
        if (!isUndefNull(newSize.h)) {
            newStyle['height'] = newSize.h + units;
        }
        MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
    },

    /** @id MochiKit.Style.setDisplayForElement */
    setDisplayForElement: function (display, element/*, ...*/) {
        var elements = MochiKit.Base.extend(null, arguments, 1);
        var getElement = MochiKit.DOM.getElement;
        for (var i = 0; i < elements.length; i++) {
            element = getElement(elements[i]);
            if (element) {
                element.style.display = display;
            }
        }
    },

    /** @id MochiKit.Style.getViewportDimensions */
    getViewportDimensions: function () {
        var d = new MochiKit.Style.Dimensions();

        var w = MochiKit.DOM._window;
        var b = MochiKit.DOM._document.body;

        if (w.innerWidth) {
            d.w = w.innerWidth;
            d.h = w.innerHeight;
        } else if (b.parentElement.clientWidth) {
            d.w = b.parentElement.clientWidth;
            d.h = b.parentElement.clientHeight;
        } else if (b && b.clientWidth) {
            d.w = b.clientWidth;
            d.h = b.clientHeight;
        }
        return d;
    },

    /** @id MochiKit.Style.getViewportPosition */
    getViewportPosition: function () {
        var c = new MochiKit.Style.Coordinates(0, 0);
        var d = MochiKit.DOM._document;
        var de = d.documentElement;
        var db = d.body;
        if (de && (de.scrollTop || de.scrollLeft)) {
            c.x = de.scrollLeft;
            c.y = de.scrollTop;
        } else if (db) {
            c.x = db.scrollLeft;
            c.y = db.scrollTop;
        }
        return c;
    },

    __new__: function () {
        var m = MochiKit.Base;

        this.elementPosition = this.getElementPosition;
        this.elementDimensions = this.getElementDimensions;

        this.hideElement = m.partial(this.setDisplayForElement, 'none');
        this.showElement = m.partial(this.setDisplayForElement, 'block');

        this.EXPORT_TAGS = {
            ':common': this.EXPORT,
            ':all': m.concat(this.EXPORT, this.EXPORT_OK)
        };

        m.nameFunctions(this);
    }
});

MochiKit.Style.__new__();
MochiKit.Base._exportSymbols(this, MochiKit.Style);

/* Dependencies: MochiKit Base Async */
BitAjax = {
	"updater": function(target, url, queryString) {
		BitAjax.showSpinner();
		if (queryString != "" && queryString !=null){
			url += "?"+queryString;
		}
		var r = doSimpleXMLHttpRequest(url);
		r.addCallback( BitAjax.updaterCallback, target ); 
		r.addErrback( BitAjax.error );
	},

	"updaterCallback": function(target, rslt){
		BitAjax.hideSpinner();
		var e = document.getElementById(target);
		if (e != null){e.innerHTML = rslt.responseText;}
	},
	
	"error": function( request ) {
		BitAjax.hideSpinner();
		alert( 'Sorry, there was a problem getting the requested data.' );
	},
	
	"getAndCall": function(elm, func, url, force) {
		if (!force && elm.loadedResponse) {
			func(elm.loadedResponse);
		} else {
			BitAjax.showSpinner();
			var r = doSimpleXMLHttpRequest(url);
			r.addCallback( BitAjax.getAndCallCallback, elm ); 
			r.addErrback( BitAjax.error );
		}
	},
	
	"getAndCallCallback": function(elm, rslt){
		BitAjax.hideSpinner();
		elm.loadedResponse = rslt.responseText || "No Response.";
		func(elm.loadedResponse);
	},
	
	"showSpinner": function() {
		var e = document.getElementById('spinner')
		if (e != null){ e.style.display='block' };
	},
	
	"hideSpinner": function() {
		var e = document.getElementById('spinner')
		if (e != null){ e.style.display='none' };
	}
}

eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('6(m(2)==\'e\'){2={}};6(m(2.3)==\'e\'){2.3={}};6(m(2.3.4)==\'e\'){2.3.4={}};2.3.4.i=[];2.3.4.K=5(k){r(7 n L k){2.3.4.i.M(k[n])}};2.3.4.l=0;2.3.4.I=5(n){2.3.4.l=n};2.3.4.b=1;2.3.4.H=5(n){2.3.4.b=n};2.3.4.j;2.3.4.D=5(p){2.3.4.j=p};2.3.4.f;2.3.4.E=5(t){2.3.4.f=t};2.3.4.d=9;2.3.4.F=5(s){2.3.4.d=s};2.3.4.q=5(){7 g=0+2.3.4.l;7 a=2.3.4.i;r(7 n=0;n<a.V;n++){g+=($(a[n])!=\'e\')?v.o.S(a[n]).h:0}W g};2.3.4.A=5(){7 B=2.3.4.q();7 w=v.o.R();7 h=w.h-B;6(h<2.3.4.b){h=2.3.4.b}2.3.4.f.C.z=h+\'x\';6(2.3.4.d!=9){2.3.4.d.C.z=h+\'x\'}};2.3.4.8=9;2.3.4.c=u;2.3.4.Q=5(){T.U=5(){2.3.4.A();2.3.4.c=P;6(2.3.4.8==9){2.3.4.8=O("2.3.4.y()",G)}}};2.3.4.y=5(){6(!2.3.4.c){2.3.4.j.N();J(2.3.4.8);2.3.4.8=9}2.3.4.c=u};',59,59,'||BitMap|Utl|MapResize|function|if|var|resizingInterval|null|reg|minSize|resizingFlag|panelDivRef|undefined|mapDivRef|sum||offsetReg|mapRef|array|offsetBonus|typeof||Style|map|getOffset|for|panelDiv|mapDiv|false|MochiKit||px|checkResizeEnd|height|sizeMapDiv|offset|style|regMap|regMapDiv|regPanelDiv|100|regMinSize|regOffsetBonus|clearInterval|regOffsetObjs|in|push|checkResize|setInterval|true|setResizeListener|getViewportDimensions|getElementDimensions|window|onresize|length|return'.split('|'),0,{}))

eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('5(e(2)==\'c\'){2={}}5(e(2.3)==\'c\'){2.3={}}5(e(2.3.7)==\'c\'){2.3.7=g(a,o,0,9){h(a){6\'i\':o.1=!2.3.7(\'d\',o,0)?o.1.8(9,0):o.1.8(0,9);4;6\'j\':5(!2.3.7(\'d\',o,0)){o.1+=o.1?\' \'+0:0}4;6\'l\':r f=o.1.k(\' \'+0)?\' \'+0:0;o.1=o.1.8(f,\'\');4;6\'d\':q p m(\'\\\\b\'+0+\'\\\\b\').n(o.1);4}}}',28,28,'c1|className|BitMap|Utl|break|if|case|JSCSS|replace|c2|||undefined|check|typeof|rep|function|switch|swap|add|match|remove|RegExp|test||new|return|var'.split('|'),0,{}))

eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('2 H=1e;2 k=17;5 f(){};K(1c(J)==\'1h\'){J={}}J.1m=5(){f.m=B 1k();f.m.Z=5(X){2 h=R.T((H/k*(k-X)));3.C.h=h;3.o.4.h=h+"1n"};f.m.F=5(){2 z=R.T((3.C.h)*(k/H));3.d.F(k-z)};f.m.1j=5(d){2 n=3;3.d=d;2 e=9({\'4\':\'j:s;g:1o;\'});2 i={\'4\':\'1q:1d;1b-g:0;\'};2 N=\'j:19; g:15;\';2 1a={\'4\':\'j:s;g:1i;1g:1f;\'};2 I=\'j:19; g:1p;\';2 G=\'j:s,g:s\';2 L=S.1E.1F();K((L.V("1G")>-1)&&(L.V("1I")<1)){3.M=1B}18{3.M=1r}K(3.M&&S.1v=="1u"){2 Q="r:t.u.q(c=\'8/16.6\', w=\'v\');";2 U="r:t.u.q(c=\'8/12.6\', w=\'v\');";2 W="r:t.u.q(c=\'8/Y.6\', w=\'v\');";2 14="r:t.u.q(c=\'8/10.6\', w=\'v\');";2 l=9({\'y\':Q,\'4\':I});3.o=9({\'y\':U,\'4\':G});2 E=9({\'y\':W,\'4\':i});2 A=9({\'y\':14,\'4\':i})}18{2 l=9(1a,x({\'c\':\'8/16.6\',\'4\':I}));3.o=x({\'c\':\'8/12.6\',\'4\':G});2 E=9(i,x({\'c\':\'8/Y.6\',\'4\':N}));2 A=9(i,x({\'c\':\'8/10.6\',\'4\':N}))}e.p(E);e.p(l);e.p(A);l.p(3.o);3.C=B 1A(3.o,{1y:l});d.1C().p(e);D.11(E,"13",5(){n.d.1z()});D.11(A,"13",5(){n.d.1x()});D.O(d,"1w",5(a,b){n.Z(b)});D.O(3.C,"1s",5(){n.F()});P e};f.m.1t=5(){P B 1D(1H,B 1l(7,7))}};',62,107,'||var|this|style|function|png||images|DIV|||src|map|ctl|YSliderControl|height|top|btnstyle|width|MAXZOOM|slider|prototype|ref|knob|appendChild|AlphaImageLoader|progid|19px|DXImageTransform|Microsoft|scale|sizingMethod|IMG|filter||outbtn|new|slide|GEvent|inbtn|setZoom|knobsize|YSLIDERLENGTH|slidersize|BitSubway|if|agent|ie|btnsize|addListener|return|sloader|Math|navigator|round|kloader|indexOf|iloader|zoom|zoom_ctl_in|setSlider|zoom_ctl_out|addDomListener|yknob|click|oloader||zoom_ctl_bkg||else||sliderstyle|line|typeof|pointer|55|relative|position|undefined|74px|initialize|GControl|GSize|DefineYSliderControl|px|104px|74|cursor|false|dragend|getDefaultPosition|stupid|appVersion|zoomend|zoomOut|container|zoomIn|GDraggableObject|true|getContainer|GControlPosition|userAgent|toLowerCase|msie|G_ANCHOR_TOP_LEFT|opera'.split('|'),0,{}))

if (typeof(BitSubway) == 'undefined') {
    BitSubway = {};
}
if (typeof(BitSubway.MetaData) == 'undefined'){
	BitSubway.MetaData = {};
}

BitSubway.MetaData.Subway = {
	"sys_desc":"NYC Subway",
	"lines_url_names":{'1':'one','2':'two','3':'three','4':'four','5':'five','6':'six','7':'seven'},
	"lines_desc":{'1':'1','2':'2','3':'3','4':'4','5':'5','6':'6','7':'7','a':'A','b':'B','c':'C','d':'D','e':'E','f':'F','g':'G','j':'J','l':'L','m':'M','n':'N','q':'Q','r':'R','s':'S','v':'V','w':'W','z':'Z','jfkairtrain':'JFK Airtrain'},
	"ada_base_url":"http://www.mta.info/mta/ada/stations.htm",
	"station_base_url":"http://www.mta.info/nyct/service/"
}

BitSubway.SubwayDataColumns=["point","name","lines","area","ada","details","page_id"];
BitSubway.SubwayData = [
[[40.7990941845174,-73.96865129470825],"103rd St",["1"],"MN",0,1,176], 
[[40.74986604000175,-73.86271476745605],"103rd St",["7"],"QN",0,1], 
[[40.790273338193565,-73.94765496253967],"103rd St",["6"],"MN",0,1,319], 
[[40.796064688957976,-73.96138787269592],"103rd St",["b","c"],"MN",0,1,174], 
[[40.69519221006348,-73.843435049057],"104-102nd Sts",["j","z"],"QN",0,1], 
[[40.68197235895615,-73.83702993392944],"104th St",["a"],"QN",0,0,343], 
[[40.79477325338044,-73.94437193870544],"110th St",["6"],"MN",0,1,320], 
[[40.79818453817657,-73.95247220993042],"110th St-Central Park N",["2","3"],"MN",0,1], 
[[40.684738575525,-73.8311505317688],"111st St",["a"],"MN",0,1,344], 
[[40.69698177295795,-73.83700847625732],"111st St",["j"],"QN",0,1], 
[[40.75159724033415,-73.85582685470581],"111st St",["7"],"QN",0,1], 
[[40.804381257073445,-73.95528316497803],"116th St",["b","c"],"MN",0,1,111], 
[[40.7985743881347,-73.9415717124939],"116th St",["6"],"MN",0,1,321], 
[[40.80195299186528,-73.94968271255493],"116th St",["2","3"],"MN",0,1,114], 
[[40.807928,-73.963919],"116th St-Columbia Univ",["1"],"MN",0,1,178], 
[[40.70041434542383,-73.82876873016357],"121st St",["j","z"],"QN",0,1], 
[[40.81073168450773,-73.95253658294678],"125th St",["a","c","b","d"],"MN",1,1,99], 
[[40.815636,-73.958296],"125th St",["1"],"MN",0,1,179], 
[[40.804332530217025,-73.93738746643066],"125th St",["4","5","6"],"MN",0,1,112], 
[[40.80775144449727,-73.9454448223114],"125th St",["2","3"],"MN",0,1,113], 
[[40.81706526504568,-73.94795536994934],"135th St",["b","c"],"MN",0,1,98], 
[[40.814077189565865,-73.94083142280579],"135th St",["2","3"],"MN",0,1], 
[[40.821459,-73.954062],"137th St",["1"],"MN",0,1,180], 
[[40.813094667955234,-73.93007040023804],"138th St-Grand Concourse",["4","5"],"BX",0,1,95], 
[[40.820369854830645,-73.93621802330017],"145th St",["3"],"MN",0,1], 
[[40.823999030332224,-73.94470453262329],"145th St",["a","c","b","d"],"MN",0,1,97], 
[[40.82637777811902,-73.95049810409546],"145th St",["1"],"MN",0,1,181], 
[[40.824055861478996,-73.93689393997192],"148th St",["3"],"MN",0,1], 
[[40.81850241645912,-73.92728090286255],"149th St-Grand Concourse",["2","4","5"],"BX",0,1,94], 
[[40.73738055668789,-73.99678230285645],"14th St-6th Aves",["f","v","l","1","2","3"],"MN",0,1,102], 
[[40.738673108048914,-73.9995288848877],"14th St-7th Aves",["1","2","3","f","v","l"],"MN",0,1,103], 
[[40.73972989238724,-74.00247931480408],"14th St-8th Ave",["a","c","e","l"],"MN",1,1,104], 
[[40.8308508918368,-73.94129276275635],"155th St",["c"],"MN",0,1,96], 
[[40.83022581059795,-73.93836379051208],"155th St",["b","d"],"MN",0,1], 
[[40.83400867970049,-73.94487619400024],"157th St",["1"],"MN",0,1,182], 
[[40.660786,-73.980044],"15th St",["f"],"BK",0,0,196], 
[[40.82784720084161,-73.92592906951904],"161st St-Yankee Stadium",["4","b","d"],"BX",1,1,93], 
[[40.836801045460255,-73.9398980140686],"163rd St",["c"],"MN",0,1,192], 
[[40.835704,-73.921244],"167th St",["4"],"BX",0,1,145], 
[[40.83447137634269,-73.9176893234253],"167th St",["b","d"],"BX",0,1,124], 
[[40.84102995684901,-73.93965125083923],"168th St-Broadway",["1","a","c"],"MN",1,1,191], 
[[40.710637808196715,-73.7930417060852],"169th St",["f"],"QN",0,1,309], 
[[40.84017770274874,-73.91771078109741],"170th St",["4"],"BX",0,1,146], 
[[40.83865173469906,-73.91376256942749],"170th St",["b","d"],"BX",0,1,125], 
[[40.84579426123243,-73.91020059585571],"174-175th Sts ",["b","d"],"BX",0,1,126], 
[[40.837336776606065,-73.88772368431091],"174th St-Southern Blvd",["2","5"],"BX",0,1,216], 
[[40.846476007612914,-73.93999457359314],"175th St",["a"],"MN",1,1], 
[[40.84863482488186,-73.91162753105164],"176th St",["4"],"BX",0,1,148],
[[40.71242695613879,-73.78445863723755],"179th St",["f"],"QN",0,1,310],
[[40.85088284179655,-73.93822431564331],"181st St",["a"],"MN",0,1],
[[40.84927596383365,-73.93369674682617],"181st St",["1"],"MN",0,1,183],
[[40.856750050082084,-73.90028715133667],"182-183rd Sts ",["b","d"],"BX",0,1,128],
[[40.858640754769894,-73.90364527702332],"183rd St",["4"],"BX",0,1,150],
[[40.63072779228403,-73.97714853286743],"18th Ave",["f"],"BK",0,0,200],
[[40.620709,-73.990533],"18th Ave",["n"],"BK",0,0], 
[[40.608011,-74.001721],"18th Ave",["m","d"],"BK",0,0,277], 
[[40.741029,-73.997814],"18th St-7th Ave",["1"],"MN",0,1,263], 
[[40.85705840903592,-73.93545627593994],"190th St",["a"],"MN",0,1], 
[[40.85550848503337,-73.92913699150085],"191st St",["1"],"MN",0,1,184], 
[[40.73125075736151,-73.98234128952026],"1st Ave-14th St",["l"],"MN",0,1], 
[[40.87425120632545,-73.87777805328369],"205th St",["d"],"BX",0,1,132], 
[[40.86445047952861,-73.91895532608032],"207th St",["1"],"MN",0,1,186], 
[[40.8676634603888,-73.92119765281677],"207th St-Washington Hts",["a"],"MN",1,1], 
[[40.60453685503522,-73.99817705154419],"20th Ave",["m","d"],"BK",0,0,278], 
[[40.617441,-73.985014],"20th Ave",["n"],"BK",0,0], 
[[40.86956196671498,-73.91520023345947],"215th St",["1"],"MN",0,1,187], 
[[40.88353946334982,-73.86281132698059],"219th St",["2","5"],"BX",0,1,350], 
[[40.7445177279974,-73.9488136768341],"21st St (Van Alst)",["g"],"QN",0,1], 
[[40.753954201190915,-73.94238710403442],"21st St-Queensbridge",["f"],"QN",1,1], 
[[40.8745432587054,-73.90961050987244],"225th St",["1"],"BX",0,1,107], 
[[40.887773502571456,-73.86048316955566],"225th St",["2","5"],"BX",0,1,351], 
[[40.878850881657044,-73.90473961830139],"231st St",["1"],"BX",1,1,188], 
[[40.89335358489396,-73.85738253593445],"233rd St",["2","5"],"BX",1,1,123], 
[[40.898417,-73.854239],"238th St",["2","5"],"BX",0,1,352], 
[[40.885031952534035,-73.90056610107422],"238th St",["1"],"BX",0,1,189], 
[[40.7428513727015,-73.99278044700623],"23rd St-6th Ave",["f","v"],"MN",0,1], 
[[40.74405440412986,-73.99558067321777],"23rd St-7th Ave",["1"],"MN",0,1,264], 
[[40.7452411570555,-73.99845600128174],"23rd St-8th Ave",["c","e"],"MN",0,1,324], 
[[40.74139632588608,-73.98922920227051],"23rd St-Broadway ",["r","w"],"MN",0,1], 
[[40.74623281106757,-73.9454984664917],"45 Road-Court Sq",["7"],"QN",0,1], 
[[40.74769588014885,-73.94517660140991],"LIC-Court Sq",["e","v","g"],"QN",0,1], 
[[40.74670424795305,-73.9433741569519],"LIC-Court Sq",["e","v","g"],"QN",0,1], 
[[40.7401526014217,-73.98633241653442],"23rd St-Park Ave S",["6"],"MN",0,1,313], 
[[40.90340952157061,-73.85031223297119],"241st St",["2"],"BX",0,1,353], 
[[40.88946866455314,-73.89832377433777],"242nd St",["1"],"BX",0,1,190], 
[[40.597869,-73.986911],"25th Ave",["d"],"BK",0,0,280], 
[[40.66052214937429,-73.99808049201965],"25th St",["m","r"],"BK",0,0,286], 
[[40.747181,-73.993321],"28th St-7th Ave",["1"],"MN",0,1,265], 
[[40.74524928542718,-73.98868203163147],"28th St-Broadway",["r","w"],"MN",0,1], 
[[40.743282190511266,-73.9840579032898],"28th St-Park Ave S",["6"],"MN",0,1,314], 
[[40.723664958653345,-73.99116039276123],"2nd Ave-Houston St",["f","v"],"MN",0,1], 
[[40.76690786664717,-73.9214015007019],"30th Ave",["n","w"],"QN",0,0,357], 
[[40.74464778323969,-73.93165826797485],"33rd St",["7"],"QN",0,1], 
[[40.746403504118945,-73.98179411888123],"33rd St-Park Ave",["6"],"MN",0,1,315], 
[[40.749824,-73.98777],"34th St-6th Ave",["b","d","f","v","n","q","r","w"],"MN",1,1,90], 
[[40.75091451882517,-73.99059176445007],"34th St-7th Ave",["1","2","3"],"MN",1,1,91], 
[[40.75214991451662,-73.99343490600586],"34th St-8th Ave",["a","c","e"],"MN",1,1,92], 
[[40.75657926958294,-73.92974853515625],"36th Ave",["n","w"],"QN",0,1,355], 
[[40.75207676672682,-73.927903175354],"36th St",["g","r","v"],"QN",0,1,294], 
[[40.65417364755974,-74.00444269180298],"36th St",["d","m","n","r"],"BK",0,0,282], 
[[40.75270258410526,-73.93290281295776],"39th Ave",["n","w"],"QN",0,1,354], 
[[40.81085348983536,-73.92728090286255],"3rd Ave-138th St",["6"],"BX",0,1,241], 
[[40.81605030884846,-73.91777515411377],"3rd Ave-149th St",["2","5"],"BX",1,1,108], 
[[40.73319381854889,-73.98701906204224],"3rd Ave-14th St",["l"],"MN",0,1], 
[[40.743794291070245,-73.92424464225769],"40th St",["7"],"QN",0,1], 
[[40.75441745608594,-73.98435831069946],"42nd St-5th Ave-6th Ave",["7","b","d","f","v"],"MN",0,1], 
[[40.753604726063955,-73.9818263053894],"42nd St-5th Ave-6th Ave",["7","b","d","f","v"],"MN",0,1], 
[[40.64912697157757,-74.00959253311157],"45th St",["r"],"BK",0,0], 
[[40.756733682142844,-73.91419172286987],"46th St",["g","r","v"],"QN",0,1,296], 
[[40.743176518476595,-73.91871929168701],"46th St",["7"],"QN",0,1], 
[[40.75921236098832,-73.98084998130798],"47-50th Sts-Rockefeller Center",["b","d","f","v"],"MN",0,1,144], 
[[40.760423222951694,-73.98369312286377],"49th St-7th Ave",["n","r","w"],"MN",1,1], 
[[40.63574329257643,-73.99487257003784],"50th St-New Utrecht Ave",["d","m"],"BK",0,0,272], 
[[40.76226791656323,-73.98606419563293],"50th St-8th Ave",["c","e"],"MN",1,1,325], 
[[40.761398397759166,-73.98402571678162],"50th St-Broadway",["1"],"MN",0,1,266], 
[[40.744192588778986,-73.91241073608398],"52nd St",["7"],"QN",0,0], 
[[40.644731168602824,-74.01431322097778],"53rd St",["r"],"BK",0,0], 
[[40.631579,-73.995423],"55th St",["m","d"],"BK",0,0,273], 
[[40.764275080085646,-73.97716999053955],"57th St-6th Ave",["f"],"MN",0,1], 
[[40.76547772392416,-73.9799702167511],"57th St-7th Ave",["n","q","r","w"],"MN",0,1,117], 
[[40.64137713901667,-74.01778936386108],"59th St",["n","r"],"BK",0,0], 
[[40.76804545819932,-73.9818799495697],"59th St-Columbus Circle",["1","a","c","b","d"],"MN",0,1,118], 
[[40.764730137070416,-73.96639823913574],"63rd St-Lexington Ave",["f"],"MN",1,1], 
[[40.76218665360546,-73.96815776824951],"59th St-Lexington Ave",["4","5","6","n","r","w"],"MN",1,1], 
[[40.7603988433982,-73.97580742835999],"5th Ave-53rd St",["e","v"],"MN",0,1], 
[[40.764843900829774,-73.97252440452576],"5th Ave-60th St",["n","r","w"],"MN",0,1], 
[[40.74559880446954,-73.90333414077759],"61st St",["7"],"QN",1,0], 
[[40.73015318726155,-73.86222124099731],"63rd Dr",["g","r","v"],"QN",0,1,302], 
[[40.74927270745124,-73.89764785766602],"65th St",["g","r","v"],"QN",0,0,298], 
[[40.7737818731648,-73.98221254348755],"66th St",["1"],"MN",1,1,267], 
[[40.72697419689535,-73.8536274433136],"67th Ave",["g","r","v"],"QN",0,1,303], 
[[40.76779356460569,-73.96403789520264],"68th St",["6"],"MN",0,1,316], 
[[40.746346606483826,-73.89631748199463],"69th St",["7"],"QN",0,0], 
[[40.72148581266625,-73.84397149085999],"71-Continental Aves",["e","f","v","g","r"],"QN",0,1,120], 
[[40.61890405098613,-73.99894952774048],"71st St",["m","d"],"BK",0,0,275], 
[[40.776186794983424,-73.97585034370422],"72nd St",["b","c"],"MN",0,1,170], 
[[40.778721618334295,-73.98208379745483],"72nd St",["1","2","3"],"MN",1,1], 
[[40.746736760718505,-73.8929808139801],"74th St-Roosevelt Ave",["7","e","f","v","g","r"],"QN",1,1,121], 
[[40.71864793725036,-73.8376522064209],"75th Ave",["e","f"],"QN",0,1,304], 
[[40.773611250404265,-73.9598000049591],"77th St",["6"],"MN",0,1,317], 
[[40.62922958275914,-74.02564287185669],"77th St",["r"],"BK",0,0], 
[[40.612551590215254,-74.00079488754272],"79th St",["m","d"],"BK",0,0,276], 
[[40.783831,-73.980098],"79th St",["1"],"MN",0,1,268], 
[[40.67839237886013,-73.9730715751648],"7th Ave",["q","b"],"BK",0,0,293], 
[[40.666149,-73.980021],"7th Ave",["f"],"BK",0,0,195], 
[[40.762966773898704,-73.9818799495697],"7th Ave-53rd St",["b","d","e"],"MN",0,1,116], 
[[40.67944198385494,-73.85774731636047],"80th St",["a"],"QN",0,0,340], 
[[40.7819956220089,-73.97164463996887],"81st St",["b","c"],"MN",0,1,171], 
[[40.747614599377656,-73.88391494750977],"82nd St-Jackson Hts",["7"],"QN",0,1], 
[[40.78824259068073,-73.9765477180481],"86th St",["1"],"MN",0,1,269], 
[[40.779452799403266,-73.9555299282074],"86th St",["4","5","6"],"MN",0,1,322], 
[[40.62268266420308,-74.02838945388794],"86th St",["r"],"BK",0,0], 
[[40.78525321734988,-73.96926283836365],"86th St",["b","c"],"MN",0,1,172], 
[[40.592795,-73.978246],"86th St",["n"],"BK",0,0], 
[[40.679897621189035,-73.85064482688904],"88th St",["a"],"QN",0,0,341], 
[[40.63483141145488,-74.01015043258667],"8th Ave",["n"],"BK",0,0], 
[[40.7304783951045,-73.9924693107605],"8th St-Broadway",["r","w"],"MN",0,1], 
[[40.645903411039846,-73.99513006210327],"9th Ave",["d","m"],"BK",0,0,270], 
[[40.74841927463572,-73.87649059295654],"90th St-Elmhurst Ave",["7"],"QN",0,1], 
[[40.61574418445948,-74.03113603591919],"95th St",["r"],"BK",0,0], 
[[40.79159735212515,-73.96461725234985],"96th St",["b","c"],"MN",0,1,173], 
[[40.794513338780895,-73.97186994552612],"96th St",["1","2","3"],"MN",0,1], 
[[40.7858218585104,-73.95090579986572],"96th St",["6"],"MN",0,1,318], 
[[40.67032044564304,-73.98886442184448],"9th St-4th Ave",["f","m","r"],"BK",0,0,284], 
[[40.67692778613304,-73.89996528625488],"Alabama Ave",["j"],"QN",0,0], 
[[40.8653916718838,-73.86731743812561],"Allerton Ave",["2","5"],"BX",0,1,348], 
[[40.66742342487791,-73.83192300796509],"Aqueduct-North Conduit Ave",["a"],"QN",0,0], 
[[40.72999058274405,-73.99118185043335],"Astor Place",["6"],"MN",0,1,312], 
[[40.77007682324887,-73.91806483268738],"Astoria Blvd",["n","w"],"QN",0,2,358],
[[40.67588627839574,-73.90387058258057],"Atlantic Ave",["l"],"BK",1,0], 
[[40.68372973337041,-73.97706270217896],"Atlantic Ave-Pacific St",["2","3","4","5","m","n","q","w","r","b","d"],"BK",1,0,115], 
[[40.62991355214697,-73.96157026290894],"Ave H",["q"],"BK",0,0], 
[[40.62590734608393,-73.97629022598267],"Ave I",["f"],"BK",0,0,201], 
[[40.62515819144965,-73.96058320999146],"Ave J",["q"],"BK",0,0], 
[[40.61805709111454,-73.95933866500854],"Ave M",["q"],"BK",0,0], 
[[40.613952441166596,-73.97401571273804],"Ave N",["f"],"BK",0,0,203], 
[[40.608892,-73.973102],"Ave P",["f"],"BK",0,0,204], 
[[40.59883473067795,-73.95569086074829],"Ave U",["q"],"BK",0,0], 
[[40.598150443067965,-73.97925138473511],"Ave U",["n"],"BK",0,0], 
[[40.59691219054059,-73.97324323654175],"Ave U",["f"],"BK",0,0,206], 
[[40.59003621322974,-73.97418737411499],"Ave X",["f"],"BK",0,0,207], 
[[40.588471911136686,-73.98380041122437],"Bay 50th St",["d"],"BK",0,0,281], 
[[40.611826,-73.982077],"Bay Pkwy",["n"],"BK",0,0], 
[[40.60186506304133,-73.99388551712036],"Bay Pkwy",["m","d"],"BK",0,0,279], 
[[40.62082595855659,-73.97534608840942],"Bay Pkwy-22nd Ave",["f"],"BK",0,0,202], 
[[40.63444060144733,-74.02354001998901],"Bay Ridge Ave",["r"],"BK",0,0], 
[[40.879451168440156,-73.83811354637146],"Baychester Ave",["5"],"BX",0,1,235], 
[[40.58358323125094,-73.82642984390259],"Beach 105th St",["a","s"],"QN",0,0], 
[[40.599934,-73.761451],"Beach 25th St",["a"],"QN",0,0], 
[[40.595250289260875,-73.76845121383667],"Beach 36th St",["a"],"QN",0,0], 
[[40.59296918102644,-73.77536058425903],"Beach 44th St",["a"],"QN",0,0], 
[[40.59241518585309,-73.78965139389038],"Beach 60th St",["a"],"QN",0,0], 
[[40.59108720814666,-73.79600286483765],"Beach 67th St",["a"],"QN",0,0], 
[[40.587754927114965,-73.81445646286011],"Beach 90th St",["a","s"],"QN",0,0], 
[[40.585538746085795,-73.82029294967651],"Beach 98th St",["a","s"],"QN",0,0], 
[[40.71776158460436,-73.95785808563232],"Bedford Ave",["l"],"BK",0,0], 
[[40.87368332300964,-73.88999819755554],"Bedford Park Blvd",["4"],"BX",0,1,153], 
[[40.87288827818401,-73.88723015785217],"Bedford Park Blvd",["b","d"],"BX",0,1,131], 
[[40.68975001664651,-73.95148515701294],"Bedford-Nostrand Aves",["g"],"BK",0,0], 
[[40.68093093003134,-73.97568941116333],"Bergen St",["2","3"],"BK",0,0], 
[[40.68675621402294,-73.9904522895813],"Bergen St",["f","g"],"BK",0,0,168], 
[[40.644307853773974,-73.96423101425171],"Beverley Rd",["q"],"BK",0,0], 
[[40.645024231142315,-73.948974609375],"Beverley Rd",["2","5"],"BK",0,0,222], 
[[40.67100399398882,-73.95890951156616],"Botanic Garden",["2","3","4","5","s"],"BK",0,0], 
[[40.720331161623065,-73.99397134780884],"Bowery",["j","m"],"MN",0,1,136], 
[[40.704806478753106,-74.01402354240417],"Bowling Green",["4","5"],"MN",1,1], 
[[40.57768374845163,-73.9606261253357],"Brighton Beach",["q","b"],"BK",0,0,287], 
[[40.60815337894158,-73.81554007530212],"Broad Channel",["a","s"],"QN",0,0], 
[[40.70665271500208,-74.01099801063538],"Broad St",["j","m","z"],"MN",0,1,134], 
[[40.70536767492135,-73.95028352737427],"Broadway",["g"],"BK",0,0,142], 
[[40.761918485139915,-73.9254355430603],"Broadway",["n","w"],"QN",0,1,356], 
[[40.848926990236826,-73.86832594871521],"Bronx Park East",["2","5"],"BX",0,1,346], 
[[40.80757278825516,-73.91929864883423],"Brook Ave",["6"],"BX",0,1,242], 
[[40.846906153506296,-73.832266330719],"Buhre Ave",["6"],"BX",0,1,257], 
[[40.871413,-73.867147],"Burke Ave",["2","5"],"BX",0,1,349], 
[[40.853796223166725,-73.90732526779175],"Burnside Ave",["4"],"BX",0,1,149], 
[[40.6823303463911,-73.90535116195679],"Bushwick Ave",["l"],"BK",0,0], 
[[40.72573833355968,-73.9942717552185],"Uptown Bleecker St-Lafayette St",["6"],"MN",0,1], 
[[40.725039084927516,-73.99530172348022],"Downtown Bleecker St-Lafayette St",["6","b","d","f","v"],"MN",0,1], 
[[40.71937977916394,-74.0018892288208],"Canal Street",["j","m","z","n","q","r","w","6"],"MN",0,1,326], 
[[40.718241354932935,-74.00067687034607],"Canal Street",["j","m","z","n","q","r","w","6"],"MN",1,1,326], 
[[40.71779411151555,-74.00009751319885],"Canal Street",["j","m","z","n","q","r","w","6"],"MN",0,1,326], 
[[40.72179480039333,-74.00521516799927],"Canal-Church Sts",["a","c","e"],"MN",0,1], 
[[40.72254287000301,-74.00628805160522],"Canal-Varick Sts",["1"],"MN",0,1,260], 
[[40.680186,-73.994907],"Carroll St",["f","g"],"BK",0,0,167], 
[[40.83410608978826,-73.85159969329834],"Castle Hill Ave",["6"],"BX",0,1,253], 
[[40.800547968413156,-73.95811557769775],"Cathedral Pkwy",["b","c"],"MN",0,1,175], 
[[40.804109,-73.966742],"Cathedral Pkwy",["1"],"MN",0,1,177], 
[[40.698014816926104,-73.92528533935547],"Central Ave",["m"],"QN",0,0], 
[[40.715452133287066,-74.00918483734131],"Chambers St-W Broadway",["1","2","3"],"MN",0,1], 
[[40.71327271843125,-74.00349855422974],"Chambers-Brooklyn Bridge/City Hall",["4","5","6","j","m","z"],"MN",0,1,135], 
[[40.71258960356785,-74.00465726852417],"Chambers-Brooklyn Bridge/City Hall",["4","5","6","j","m","z"],"MN",1,1,135], 
[[40.71488289002164,-74.00791883468628],"Chambers-St-Park Pl",["2","3","a","c","e"],"MN",0,1], 
[[40.7132483215925,-74.00930285453796],"Chambers-Park Pl-World Trade Ctr",["2","3","a","c","e"],"MN",1,1], 
[[40.71169503779132,-74.0103006362915],"World Trade Ctr-Park Pl",["2","3","a","c","e"],"MN",0,1], 
[[40.68268833190338,-73.91005039215088],"Chauncey St",["j","z"],"BK",0,0], 
[[40.73357592013933,-74.00276899337769],"Christopher St",["1"],"MN",0,1,262], 
[[40.642744821917056,-73.97942304611206],"Church Ave",["f"],"BK",0,0,198], 
[[40.650817,-73.949581],"Church Ave",["2","5"],"BK",1,0,221], 
[[40.64938745451835,-73.96302938461304],"Church Ave",["q","b"],"BK",0,0,291], 
[[40.71328085070884,-74.00695323944092],"City Hall-Broadway",["r","w"],"MN",0,1], 
[[40.69745,-73.992984],"Clark St",["2","3"],"BK",0,0,226], 
[[40.68880633250933,-73.9600682258606],"Classon Ave",["g"],"BK",0,0], 
[[40.67966166652983,-73.88554573059082],"Cleveland St",["j"],"QN",0,0], 
[[40.68812296668819,-73.96581888198853],"Clinton-Washington Aves",["g"],"BK",0,0,240], 
[[40.683241578458706,-73.965904712677],"Clinton-Washington Aves",["c"],"BK",0,0,331], 
[[40.6414422674093,-73.96371603012085],"Cortelyou Rd",["q"],"BK",0,0], 
/* [[40.71132094308453,-74.01216745376587],"Cortlandt St-Greenwich St",["1"],"MN",0,1],  WTC Station - Closed */
/* [[40.7105727473657,-74.01105165481567],"Cortlandt St-Trinity Pl",["r","w"],"MN",0,1],  WTC Station - Closed */
[[40.69365477446245,-73.99049520492554],"Court St-Borough Hall",["2","3","4","5","m","r","w"],"BK",0,0,225], 
[[40.692418292578466,-73.99105310440063],"Court St-Borough Hall",["2","3","4","5","m","r","w"],"BK",1,0,225], 
[[40.68359955907688,-73.87219905853271],"Crescent St",["j","z"],"QN",0,0], 
[[40.80551008589939,-73.91449213027954],"Cypress Ave",["6"],"BX",0,1,243], 
[[40.68932698747902,-73.87400150299072],"Cypress Hills",["j"],"QN",0,0], 
[[40.68985,-73.981266],"DeKalb Ave",["b","m","q","r"],"BK",1,0,119], 
[[40.704261,-73.91932],"DeKalb Ave",["l"],"BK",0,0], 
[[40.71846904133664,-73.98808121681213],"Delancey-Essex Sts",["f","j","m","z"],"MN",0,1,137], 
[[40.77612992283735,-73.91072630882263],"Ditmars Blvd",["n","w"],"QN",0,0,359], 
[[40.63548275638401,-73.97804975509644],"Ditmas Ave",["f"],"BK",0,0,199], 
[[40.86140774031356,-73.92468452453613],"Dyckman St",["1"],"MN",0,1,185], 
[[40.865502,-73.927262],"Dyckman St-200th St",["a"],"MN",0,1], 
[[40.88783027903448,-73.83108615875244],"Dyre Ave-233rd St",["5"],"BX",0,1,236], 
[[40.651210806634026,-73.89902114868164],"E 105th St",["l"],"BK",0,0], 
[[40.808157479622295,-73.90779733657837],"E 143rd St",["6"],"BX",0,1,244], 
[[40.81204717021314,-73.90409588813782],"E 149th St",["6"],"BX",0,1,245], 
[[40.83316445294462,-73.86130928993225],"E 177th St-Parkchester",["6"],"BX",0,1,252], 
[[40.841573770404985,-73.87387275695801],"E 180th St",["2","5"],"BX",0,1,230], 
[[40.677383440651724,-73.90193939208984],"Broadway Junction",["a","c","l","j","z"],"BK",0,0,327], 
[[40.67966166652983,-73.90481472015381],"Broadway Junction",["a","c","l","j","z"],"BK",0,0,327], 
[[40.840080301582425,-73.88022422790527],"E Tremont Ave",["2","5"],"BX",0,1,217], 
[[40.714053412550314,-73.99023771286011],"East Broadway",["f"],"MN",0,1,193], 
[[40.67165498589892,-73.96264314651489],"Eastern Pkwy",["2","3"],"BK",0,0], 
[[40.8285047772599,-73.8791298866272],"Elder Ave",["6"],"BX",0,1,249], 
[[40.69137702687853,-73.86649131774902],"Elderts Lane",["j","z"],"QN",0,0], 
[[40.74176212277341,-73.8810396194458],"Elmhurst Ave",["g","r","v"],"QN",0,0,299], 
[[40.67533297079236,-73.87187719345093],"Euclid Ave",["a","c"],"QN",1,0,330], 
[[40.6053188227324,-73.75531911849976],"Far Rockaway-Mott Ave",["a"],"QN",0,0], 
[[40.63277963339463,-73.94766569137573],"Flatbush Ave",["2","5"],"BK",1,0,224], 
[[40.70071529713514,-73.94197940826416],"Flushing Ave",["j","m"],"QN",1,0,141], 
[[40.69970669685345,-73.95011186599731],"Flushing Ave",["g"],"QN",0,0], 
[[40.862705992809644,-73.90105962753296],"Fordham Rd",["4"],"BX",1,1,151], 
[[40.86241388821674,-73.89708995819092],"Fordham Rd",["b","d"],"BX",0,1,129], 
[[40.70483901199343,-73.9020037651062],"Forest Ave",["m"],"QN",0,0], 
[[40.6924508318694,-73.86013984680176],"Forest Pkwy",["j"],"QN",0,0], 
[[40.68099601981583,-73.95564794540405],"Franklin Ave",["c","s"],"BK",1,0,332], 
[[40.71907891179564,-74.00686740875244],"Franklin St",["1"],"MN",0,1,259], 
[[40.83009592284781,-73.89185428619385],"Freeman St",["2","5"],"BX",0,1,215], 
[[40.70624605943045,-73.89670372009277],"Fresh Pond Rd",["m"],"QN",0,0], 
[[40.640530464129945,-73.9942717552185],"Ft Hamilton Pkwy-New Utrecht Ave",["d","m"],"BK",0,0,271], 
[[40.632519085637355,-74.00633096694946],"Ft Hamilton Pkwy",["n"],"BK",0,0], 
[[40.64955025584002,-73.97551774978638],"Ft Hamilton Pkwy",["f"],"BK",0,0,197], 
[[40.68708163386666,-73.97650480270386],"Fulton St",["g"],"BK",0,0,238], 
[[40.71073539932408,-74.00915265083313],"Fulton St-Broadway-Nassau",["2","3","4","5","a","c","j","m","z"],"MN",0,1,100], 
[[40.71021491165874,-74.00768280029297],"Fulton St-Broadway-Nassau",["2","3","4","5","a","c","j","m","z"],"MN",0,1,100], 
[[40.70949110173649,-74.00649189949036],"Fulton St-Broadway-Nassau",["2","3","4","5","a","c","j","m","z"],"MN",0,1,100], 
[[40.68945715058581,-73.9220666885376],"Gates Ave",["j","z"],"BK",0,0], 
[[40.71437869906487,-73.9443826675415],"Graham Ave",["l"],"BK",0,0], 
[[40.67451927479847,-73.97144079208374],"Grand Army Plaza",["2","3"],"BK",0,0], 
[[40.73680337155386,-73.87766003608704],"Grand Ave",["g","r","v"],"QN",0,1,300], 
[[40.751800429905806,-73.97688031196594],"Grand Central",["4","5","6","7","s"],"MN",1,1,106], 
[[40.718086853001175,-73.99378895759583],"Grand St",["b","d"],"MN",0,1,110], 
[[40.711971,-73.94067],"Grand St",["l"],"BK",0,0], 
[[40.67660231671296,-73.86535406112671],"Grant Ave",["a"],"QN",0,0,339], 
[[40.730120666389844,-73.95425319671631],"Greenpoint Ave",["g"],"BK",0,0], 
[[40.87021912929973,-73.84581685066223],"Gun Hill Rd",["5"],"BX",0,1,234], 
[[40.87734202867769,-73.86648058891296],"Gun Hill Rd",["2","5"],"BX",1,1,133], 
[[40.69606259438467,-73.90507221221924],"Halsey St",["l"],"BK",0,0], 
[[40.68568231726459,-73.91537189483643],"Halsey St",["j"],"BK",0,0], 
[[40.70663644882689,-73.95292282104492],"Hewes St",["j","m"],"QN",0,0,139], 
[[40.69915358698945,-73.98987293243408],"High St",["a","c"],"BK",0,0,227], 
[[40.727836035375304,-74.00540828704834],"Houston St",["1"],"MN",0,1,261], 
[[40.660758171767796,-73.83004546165466],"Howard Beach - Station A",["a","jfkairtrain"],"QN",1,0], 
[[40.69062860710583,-73.98521661758423],"Hoyt St",["2","3"],"BK",0,0,233], 
[[40.68896903762434,-73.98620367050171],"Hoyt-Schermerhorn Sts",["a","c","g"],"BK",0,0,169], 
[[40.74222546260947,-73.94927501678467],"Hunters Pt Ave",["7"],"QN",0,1], 
[[40.82088948050579,-73.89138221740723],"Hunts Pt Ave",["6"],"BX",0,1,247], 
[[40.822074861341726,-73.89684319496155],"Intervale Ave",["2","5"],"BX",0,1,213], 
[[40.81622082257484,-73.90819430351257],"Jackson Ave",["2","5"],"BX",0,1,211], 
[[40.70243964288751,-73.79995107650757],"Jamaica Center",["e","j","z"],"QN",1,1], 
[[40.70243964288749,-73.81683826446533],"Jamaica-Van Wyck",["e"],"QN",0,1], 
[[40.69183258262447,-73.98736238479614],"Jay St",["a","c","f"],"BK",0,0,228], 
[[40.70692923937242,-73.9236330986023],"Jefferson St",["l"],"BK",0,0], 
[[40.749087,-73.869446],"Junction Blvd",["7"],"QN",1,1], 
[[40.66361479037586,-73.90151023864746],"Junius St",["3"],"BK",0,0,162], 
[[40.60903304435483,-73.95740747451782],"Kings Highway",["b","q"],"BK",0,0,289], 
[[40.605188495418204,-73.98075342178345],"Kings Highway",["n"],"BK",0,0], 
[[40.60408070298693,-73.97225618362427],"Kings Highway",["f"],"BK",0,0,205], 
[[40.86604887585585,-73.89430046081543],"Kingsbridge Rd",["b","d"],"BX",0,1,130], 
[[40.86743628504537,-73.89733672142029],"Kingsbridge Rd",["4"],"BX",0,1,152], 
[[40.669321,-73.942045],"Kingston Ave",["3"],"BK",0,0,157], 
[[40.67988948483539,-73.94084215164185],"Kingston-Throop Aves",["c"],"BK",0,0,333], 
[[40.698763153732166,-73.91839742660522],"Knickerbocker Ave",["m"],"BK",0,0], 
[[40.69326430897806,-73.92880439758301],"Kosciusko St",["j"],"BK",0,0], 
[[40.686853840142895,-73.97590398788452],"Lafayette Ave",["c"],"BK",0,0,239], 
[[40.69215797767899,-73.98628950119019],"Lawrence St",["m","r"],"BK",0,0,229], 
[[40.68620299664183,-73.8241982460022],"Lefferts Blvd",["a"],"QN",0,1,345], 
[[40.75782268685437,-73.97131204605103],"Lexington-3rd Aves-51st St",["6","e","v"],"MN",1,1,101], 
[[40.75709126774661,-73.97188067436218],"Lexington-3rd Aves-51st St",["6","e","v"],"MN",1,1,101], 
[[40.67432398628223,-73.8965106010437],"Liberty Ave",["c"],"BK",0,0,336], 
[[40.6637124503877,-73.90086650848389],"Livonia Ave",["l"],"BK",0,0], 
[[40.81627766038624,-73.89615654945374],"Longwood Ave",["6"],"BX",0,1,246], 
[[40.70406634324247,-73.94794464111328],"Lorimer St",["j","m"],"BK",0,0,140], 
[[40.759561806637954,-73.8300883769989],"Main St",["7"],"QN",1,1], 
[[40.70836064128724,-73.95790100097656],"Marcy Ave",["j","m","z"],"BK",1,0,138], 
[[40.71226430831242,-73.88902187347412],"Metropolitan Ave",["m"],"QN",1,0], 
[[40.714037148182875,-73.95164608955383],"Metropolitan Ave-Lorimer St",["g","l"],"BK",0,0,143], 
[[40.714053412550314,-73.94944667816162],"Metropolitan Ave-Lorimer St",["g","l"],"BK",0,0,143], 
[[40.84331881362476,-73.8367509841919],"Middletown Rd",["6"],"BX",0,1,256], 
[[40.70767,-73.939817],"Montrose Ave",["l"],"BK",0,0], 
[[40.70624605943045,-73.93189430236816],"Morgan Ave",["l"],"BK",0,0], 
[[40.854356162011705,-73.86045098304749],"Morris Park",["5"],"BX",0,1,231], 
[[40.82943024413499,-73.87457013130188],"Morrison-Soundview Aves",["6"],"BX",0,1,250], 
[[40.879735085968306,-73.88463377952576],"Mosholu Pkwy",["4"],"BX",0,1,154], 
[[40.844318,-73.914715],"Mt Eden Ave",["4"],"BX",0,1,147], 
[[40.69690856450983,-73.93532752990723],"Myrtle Ave",["j","m","z"],"BK",0,0], 
[[40.69524915144148,-73.94921064376831],"Myrtle-Willoughby Aves",["g"],"BK",0,0], 
[[40.69954401795842,-73.91110181808472],"Myrtle-Wyckoff Aves",["l","m"],"BK",0,0], 
[[40.72364869663408,-73.95077705383301],"Nassau Ave",["g"],"BK",0,0], 
[[40.59489183454932,-73.954918384552],"Neck Rd",["q"],"BK",0,0], 
[[40.579977,-73.974625],"Neptune Ave-Van Sicklen",["f"],"BK",0,0,208], 
[[40.68874125035209,-73.98088216781616],"Nevins St",["2","3","4","5"],"BK",0,0,237], 
[[40.666284112570466,-73.8824987411499],"New Lots Ave",["3"],"BK",0,0,165], 
[[40.62655877806575,-73.99697542190552],"New Utrecht Ave-62nd St",["d","m","n"],"BK",0,0,274], 
[[40.639992,-73.948419],"Newkirk Ave",["2","5"],"BK",0,0,223], 
[[40.63590612718039,-73.96247148513794],"Newkirk Ave",["q","b"],"BK",0,0,290], 
[[40.75323899431278,-73.9067029953003],"Northern Blvd",["g","r","v"],"QN",0,0,297], 
[[40.68161436959853,-73.87910842895508],"Norwood Ave",["j","z"],"BK",0,0], 
[[40.66979964220025,-73.95058393478394],"Nostrand Ave",["3"],"BK",0,0,156], 
[[40.67084124501823,-73.9578366279602],"Franklin Ave",["2","3","4","5","s"],"BK",0,0], 
[[40.680385,-73.949605],"Nostrand Ave",["a","c"],"BK",0,0,328], 
[[40.576184349465805,-73.96856546401978],"Ocean Pkwy",["q"],"BK",0,0], 
[[40.67432398628223,-73.95775079727173],"Park Place ",["s"],"BK",1,0], 
[[40.654857361397404,-73.96191358566284],"Parkside Ave",["q"],"BK",0,0], 
[[40.707644944175705,-73.8027834892273],"Parsons Blvd",["f"],"QN",0,1,308], 
[[40.85275748350158,-73.82726669311523],"Pelham Bay Park",["6"],"BX",1,1,258], 
[[40.857194,-73.867581],"Pelham Pkwy",["2","5"],"BX",0,1,347], 
[[40.858146,-73.856084], "Pelham Pkwy", ["5"],"BX",0,1,232], 
[[40.6647215954703,-73.89406442642212],"Pennsylvania Ave",["3"],"BK",0,0,163], 
[[40.667862,-73.950662],"President St",["2","5"],"BK",0,0,218], 
[[40.72420160305987,-73.99772644042969],"Prince St",["r","w"],"MN",0,1], 
[[40.665567963443664,-73.99272680282593],"Prospect Ave",["m","r"],"BK",0,0,285], 
[[40.81967160141943,-73.90162825584412],"Prospect Ave",["2","5"],"BX",0,1,212], 
[[40.66309393456432,-73.96238565444946],"Prospect Park ",["q","b","s"],"BK",1,0,292], 
[[40.74892320771775,-73.93738746643066],"Queens Plaza",["e","g","r","v"],"QN",1,1], 
[[40.75054064455214,-73.93991947174072],"Queensboro Plaza",["7","n","w"],"QN",0,1], 
[[40.67884802336841,-73.92165899276733],"Ralph Ave",["c"],"BK",0,0,334], 
[[40.70766934306751,-74.01366949081421],"Rector St-Greenwich St",["1"],"MN",0,1], 
[[40.70774253968928,-74.01293992996216],"Rector St-Trinity Pl",["r","w"],"MN",0,1], 
[[40.67819710168893,-73.91080141067505],"Rockaway Ave",["c"],"BK",0,0,335], 
[[40.66257307468539,-73.90880584716797],"Rockaway Ave",["3"],"BK",0,0,161], 
[[40.68047529976021,-73.84363889694214],"Rockaway Blvd",["a"],"QN",0,0,342], 
[[40.58055207026824,-73.83767366409302],"Rockaway Park-Beach 116th St",["a","s"],"QN",1,0], 
[[40.64551266584854,-73.90288352966309],"Rockaway Pkwy",["l"],"BK",1,0], 
[[40.759220487652186,-73.95236492156982],"Roosevelt Island",["f"],"QN",0,1], 
[[40.6615964514495,-73.91550064086914],"Saratoga Ave",["3"],"BK",0,0,160], 
[[40.70273245188341,-73.90764713287354],"Seneca Ave",["m"],"QN",0,0], 
[[40.587103116788455,-73.95333051681519],"Sheepshead Bay",["q","b"],"BK",0,0,288], 
[[40.67406360070414,-73.88084650039673],"Shepherd Ave",["c"],"BK",0,0,338], 
[[40.82408021766984,-73.89294862747192],"Simpson St",["2","5"],"BX",1,1,214], 
[[40.67468201479172,-73.99766206741333],"Smith-9th Sts",["f","g"],"BK",0,0,166], 
[[40.701322,-74.013882],"South Ferry",["1"],"MN",0,1], 
[[40.725470018092764,-74.00394916534424],"Spring St-6th Ave",["c","e"],"MN",0,1,323], 
[[40.72224201693157,-73.997061252594],"Spring St-Lafayette St",["6"],"MN",0,1,311], 
[[40.83157338099184,-73.8671886920929],"St Lawrence Ave",["6"],"BX",0,1,251], 
[[40.75870850588749,-73.91921281814575],"Steinway St",["g","r","v"],"QN",0,1,295], 
[[40.663061380941045,-73.9508843421936],"Sterling St",["2","5"],"BK",0,0,219], 
[[40.577097031111336,-73.98152589797974],"Stillwell Ave",["d","f","n","q"],"BK",1,0,210], 
[[40.705749936270415,-73.80969285964966],"Sutphin Blvd",["f"],"QN",0,1,307], 
[[40.70061769132369,-73.80774021148682],"Sutphin Blvd-Archer Ave",["e","j","z","jfkairtrain"],"QN",1,1,122], 
[[40.66488435937626,-73.92290353775024],"Sutter Ave",["3"],"BK",0,0,159], 
[[40.6683348607101,-73.90202522277832],"Sutter Ave",["l"],"BK",0,0], 
[[40.755912853368315,-73.98664355278015],"Times Square-42nd St",["1","2","3","s","7","n","q","r","w","a","c","e"],"MN",1,1,88], 
[[40.757180663847,-73.98976564407349],"8th Ave-42nd St",["a","c","e","1","2","3","s","7","n","q","r","w"],"MN",0,1], 
[[40.849616819991155,-73.90575885772705],"Tremont Ave",["b","d"],"BX",0,1,127], 
[[40.73463278544994,-73.99036645889282],"Union Square",["4","5","6","l","n","q","r","w"],"MN",1,1,105], 
[[40.677406,-73.983042],"Union St",["m","r"],"BK",0,0,283], 
[[40.714175395179495,-73.83086085319519],"Union Turnpike",["e","f"],"QN",0,1,305], 
[[40.66888822638791,-73.93110036849976],"Utica Ave",["3","4"],"BK",1,0,158], 
[[40.679238573325286,-73.92908334732056],"Utica Ave",["a","c"],"BK",0,0,329], 
[[40.665470306148734,-73.8885498046875],"Van Siclen Ave",["3"],"BK",0,0,164], 
[[40.6725989128794,-73.8902235031128],"Van Siclen Ave",["c"],"BK",0,0,337], 
[[40.67803437027595,-73.89172554016113],"Van Siclen Ave",["j"],"BK",0,0], 
[[40.708986869950174,-73.82052898406982],"Van Wyck Blvd",["e","f"],"QN",0,1,306], 
[[40.74270505658412,-73.95410299301147],"Vernon-Jackson Aves",["7"],"QN",0,1], 
[[40.73166539024325,-74.00090217590332],"W 4th St",["a","c","e","b","d","f","v"],"MN",1,1,109], 
[[40.57651030862564,-73.97646188735962],"W 8th St",["f","q"],"MN",0,1,209], 
[[40.70766934306751,-74.01168465614319],"Wall St-Broadway",["4","5"],"MN",0,1], 
[[40.7063599232408,-74.0095067024231],"Wall St-William St",["2","3"],"MN",0,1], 
[[40.84059165610896,-73.84196519851685],"Westchester Square",["6"],"BX",0,1,255], 
[[40.703277398531995,-74.01302576065063],"Whitehall St",["r","w"],"MN",0,1], 
[[40.828090748423506,-73.88571739196777],"Whitlock Rd",["6"],"BX",0,1,248], 
[[40.7552220490213,-73.8431453704834],"Willets Pt",["7"],"QN",0,1], 
[[40.688578544680915,-73.90444993972778],"Wilson Ave",["l"],"BK",0,0], 
[[40.65707124384342,-73.95028352737427],"Winthrop St",["2","5"],"BK",0,0,220], 
[[40.69368731314954,-73.85215759277344],"Woodhaven Blvd",["j","z"],"QN",0,0], 
[[40.733551530741686,-73.87023568153381],"Woodhaven Blvd",["g","r","v"],"QN",0,1,300], 
[[40.886589296667076,-73.87831449508667],"Woodlawn",["4"],"BX",0,1,155], 
[[40.701528673335076,-73.98671865463257],"York St",["f"],"BK",0,0,194], 
[[40.836727990877655,-73.84664297103882],"Zerega Ave",["6"],"BX",0,1,254],
/* [[40.661043,-73.830056], "Station A Howard Beach", ["jfkairtrain","a"],"QN",0,0],  See Howard Beach */
[[40.66375314201711,-73.82214903831482], "Lefferts Blvd - Station B", ["jfkairtrain"],"QN",1,0], 
[[40.659716411463386,-73.80646347999573], "Federal Circle - Station C", ["jfkairtrain"],"QN",1,0], 
[[40.699519616089894,-73.8072144985199],"Jamaica Station - Station D",["jfkairtrain","e","j","z"],"QN",1,1],  /* see also sutfin */
[[40.6432821182464,-73.78990888595581], "Terminal 1", ["jfkairtrain"],"QN",1,2], 
[[40.641841177427516,-73.78798842430115], "Terminal 2/3", ["jfkairtrain"],"QN",1,2], 
[[40.643843832511685,-73.7822699546814], "Terminal 4", ["jfkairtrain"],"QN",1,2], 
[[40.64637555842709,-73.77889037132263], "Terminal 5/6", ["jfkairtrain"],"QN",1,2], 
[[40.64864670348995,-73.78314971923828], "Terminal 7", ["jfkairtrain"],"QN",1,2], 
[[40.647710577791564,-73.78875017166138], "Terminal 8/9", ["jfkairtrain"],"QN",1,2]
];

if (typeof(BitSubway) == 'undefined') {
    BitSubway = {};
}
if (typeof(BitSubway.MetaData) == 'undefined'){
	BitSubway.MetaData = {};
}

BitSubway.MetaData.Path = {
	"sys_desc":"NJ PATH",
	"lines_desc":{'b':'Blue','by':'Blue-Yellow','y':'Yellow','g':'Green','r':'Red'},
	"ada_base_url":null,
	"station_base_url":"http://www.panynj.gov/CommutingTravel/path/html/advisories.html"
}

// b = blue, by = blue-yellow, y = yellow, g = green, r = red
BitSubway.PathData = [
[[40.74940275339479,-73.98901462554932],"33rd Street",["b","by","y"],"MN",0,0],
[[40.743192775723635,-73.99360656738281],"23rd Street",["b","by","y"],"MN",0,0],
[[40.73711228816394,-73.99802684783936],"14th Street",["b","by","y"],"MN",0,0],
[[40.73451084030937,-73.99961471557617],"9th Street",["b","by","y"],"MN",0,0],
[[40.73288488374377,-74.00695323944092],"Christopher St",["b","by","y"],"MN",0,0],
[[40.73516121180963,-74.02793884277344],"Hoboken",["g","by","b"],"NJ",0,0],
[[40.72686849895493,-74.03433322906494],"Pavona Newport",["g","by","y"],"NJ",0,0],
[[40.71180889228488,-74.01300430297852],"World Trade Center",["g","r"],"MN",0,0],
[[40.71681829726614,-74.03253078460693],"Exchange Place",["g","r"],"NJ",0,0],
[[40.71945296291278,-74.04304504394531],"Grove St",["by","y","r"],"NJ",0,0],
[[40.73190929073142,-74.06201362609863],"Journal Square",["by","y","r"],"NJ",0,0],
[[40.738803174719635,-74.1562557220459],"Harrison",["r"],"NJ",0,0],
[[40.73441328403598,-74.16385173797607],"Newark",["r"],"NJ",0,0]
];


if (typeof(BitSubway) == 'undefined') {
    BitSubway = {};
}
if (typeof(BitSubway.MetaData) == 'undefined'){
	BitSubway.MetaData = {};
}

BitSubway.MetaData.Bergen = {
	"sys_desc":"Hudson-Bergen Light Rail",
	"lines_desc":{"y":"Yellow","g":"Green","b":"Blue"},
	"ada_base_url":"http://www.mylightrail.com/index.php?option=com_content&task=view&id=20&Itemid=66",
	"station_base_url":"http://www.mylightrail.com/index.php?option=com_hblr&task=stations&Itemid=90"
}

BitSubway.BergenData = [
[[40.787787,-74.030922],"Tonnelle Avenue",["y","g"],"NJ",1,0],
[[40.782272,-74.021393],"Bergenline Avenue",["y","g"],"NJ",1,0],
[[40.772471,-74.014378],"Port Imperial",["y","g"],"NJ",1,0],
[[40.76052074107624,-74.02472019195557],"Lincoln Harbor",["y","g"],"NJ",1,0],
[[40.748558,-74.038712],"9th Street/Congress Street",["y","g"],"NJ",1,0],
[[40.740494,-74.043152],"2nd Street",["y","g"],"NJ",1,0],
[[40.73429946820288,-74.0283465385437],"Hoboken Terminal",["g","b"],"NJ",1,0],
[[40.72673840895164,-74.03609275817871],"Pavonia-Newport",["y","b"],"NJ",1,0],
[[40.72306326129451,-74.0372085571289],"Harsimus Cove",["y","b"],"NJ",1,0],
[[40.718733,-74.034124],"Harborside Financial Center",["y","b"],"NJ",1,0],
[[40.716408,-74.034049],"Exchange Place",["y","b"],"NJ",1,0],
[[40.712947,-74.035707],"Essex Street",["y","b"],"NJ",1,0],
[[40.714403,-74.043002],"Marin Boulevard",["y","b"],"NJ",1,0],
[[40.715192,-74.049675],"Jersey Avenue",["y","b"],"NJ",1,0],
[[40.71029623812463,-74.05594110488892],"Liberty State Park",["y","b"],"NJ",1,0],
[[40.7105727473657,-74.07106876373291],"Garfield Avenue",["y"],"NJ",1,0],
[[40.712378,-74.077485],"Martin Luther King Drive",["y"],"NJ",1,0],
[[40.714541,-74.088299],"West Side Avenue",["y"],"NJ",1,0],
[[40.698373,-74.078064],"Richard Street",["b"],"NJ",1,0],
[[40.69235321394892,-74.08733367919922],"Danforth Avenue",["b"],"NJ",1,0],
[[40.678596,-74.101914],"45th Street",["b"],"NJ",1,0],
[[40.671891,-74.107482],"34th Street",["b"],"NJ",1,0],
[[40.661173,-74.116516],"22nd Street",["b"],"NJ",1,0]
];

if (typeof(BitSubway) == 'undefined') {
    BitSubway = {};
}
if (typeof(BitSubway.MetaData) == 'undefined'){
	BitSubway.MetaData = {};
}
BitSubway.MetaData.Watertaxi = {
	"sys_desc":"NY Water Taxi",
	"lines_desc":{"b":"South Brooklyn","o":"Hudson River"},
	"ada_base_url":null,
	"station_base_url":"http://www.nywatertaxi.com/commuters/"
}
//http://www.nywatertaxi.com/map
//http://www.nywatertaxi.com/commuters/hudsonriver/
//http://www.nywatertaxi.com/commuters/brooklyn-army-terminal/
BitSubway.Watertaxi = [
[[41.193285,-73.958652],"Haverstraw",["o"],"RC",0,0],
[[40.934638051100514,-73.90432119369507],"Yonkers",["o"],"YK",0,0],
[[40.71379318219441,-74.01757478713989],"World Finanical Center",["o"],"MN",0,0],
[[40.7033017990239,-74.00630950927734],"Wall Street-Pier 11",["o","b"],"MN",0,0],
[[40.67359164925186,-74.01731729507446],"Van Brunt Street",["b"],"BK",0,0],
[[40.64639183931191,-74.02626514434814],"Brooklyn Army Terminal",["b"],"BK",0,0]
];

BitSubway.MetaData.Waterway = {
	"sys_desc":"NY Waterway",
	"lines_desc":{"m":"Midtown","w":"World Financial Center","11":"Wall Street-Pier 11","s":"Saturday-Sunday"},
	"ada_base_url":null,
	"station_base_url":"http://www.nywaterway.com/ferry/schedules/"
}
//http://www.nywaterway.com/ferry/map/
//http://www.nywaterway.com/ferry/schedules/
//http://www.nywaterway.com/ferry/schedules/ferry-route.asp?ferryid=107
BitSubway.Waterway = [
[[40.433686247571295,-74.07883644104004],"Belford-Harbor Way",["m","w","11"],"NJ",0,0,null,[94,101,120]],
[[40.82806639370559,-73.97167682647705],"Edgewater Landing",["m"],"NJ",0,0,null,[148]],
[[40.771913123811196,-74.01229619979858],"Port Imperial",["m","w","11","s"],"NJ",0,0,null,[100,108,107,100]],
[[40.75900919406845,-74.02276754379272],"Lincoln Harbor",["m"],"NJ",0,0,null,[99]],
[[40.75268632918292,-74.02347564697266],"14th St",["m","w","s"],"MN",0,0,null,[97,103,97]],
[[40.73504739725603,-74.02669429779053],"NJ Transit Terminal",["w","11","s"],"NJ",0,0,null,[105,104,98]],
[[40.72825068953495,-74.03120040893555],"Newport",["m"],"NJ",0,0,null,[147]],
[[40.71517564430887,-74.03317451477051],"Paulus Hook",["m","w","11"],"NJ",0,0,null,[95,102,145]],
[[40.71136973816547,-74.04360294342041],"Liberty Harbor-Maring Blvd",["11"],"NJ",0,0,null,[106]],
[[40.687699927191886,-74.07460927963257],"Port Liberte",["11"],"NJ",0,0,null,[109]],
[[40.76022818627338,-74.00336980819702],"Midtown W 39th St",["m","s"],"MN",0,0,null,[]],
[[40.71283357396645,-74.01665210723877],"World Financial Center",["w"],"MN",0,0,null,[]],
[[40.70390367499479,-74.00635242462158],"Wall Street-Pier 11",["11"],"MN",0,0,null,[]]
];


eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('h={"g":0,"z":r(3,i,t,c){4(h.g){A(t)}m{h.g=1;q.y();2 v=3.5.l;3.5.l=c;2 p=3.5.i;3.5.i=i;3.5.C();3.5.l=v;3.5.i=p}},"D":r(c,e,u){4(h.g){q.x();2 f=8.9(c);4(f.o){2 d=f.o}m 4(f.s){2 d=f.s.8}m{2 d=B.G[c].8}4(d.P.O=="Q:R"){T}2 n="<w>S, E L a M F H.</w>";2 7=8.9(e);6=d.9(\'I\');4(7!=j){7.k=(6!=j)?6.k:n+"a"}e=e+\'K\';7=8.9(e);2 6=d.9(\'J\');4(7!=j){7.k=(6!=j)?6.k:n+"b"}h.g=0;2 3=8.9(u);3.N=\'\'}}}',56,56,'||var|file|if|form|divR|divO|document|getElementById|||frmid||divid|ifrm|uploader_under_way|LibertyAttachment|action|null|innerHTML|target|else|errMsg|contentDocument|old_action|BitAjax|function|contentWindow|waitmsg|fileid|old_target|div|hideSpinner|showSpinner|uploader|alert|window|submit|uploaderComplete|there|retrieving|frames|results|result_tab|result_list|_tab|was|problem|value|href|location|about|blank|Sorry|return'.split('|'),0,{}))

/* NOTE: This script has dependencies on Utl.MapResize.js in Gmap Package */
SUBWAYLINES = {'1':'one','2':'two','3':'three','4':'four','5':'five','6':'six','7':'seven'};
/* STATION = ["ID","STATION_TITLE",[LAT, LNG] ,BOROUGH_CODE,NEIGHBORHOOD_CODE,["1","2","3","4","5","6","7","A","B","C","D","E","F","G","J","K","L","M","N","Q","R","S","V","W","Z"],ACCESS_CODE]
*/

var SUBWAYMAP;

if (typeof(BitSubway) == 'undefined') {
    BitSubway = {};
};
if (typeof(BitSubway.SidePanels) == 'undefined') {
	BitSubway.SidePanels = [];
};
if (typeof(BitSubway.ReqMarkers) == 'undefined') {
	BitSubway.ReqMarkers = [];
};
if (typeof(BitSubway.Markers) == 'undefined') {
	BitSubway.Markers = [];
};
if (typeof(BitSubway.MarkerSets) == 'undefined') {
	BitSubway.MarkerSets = [];
};
if (typeof(BitSubway.ReqCoords) == 'undefined') {
	BitSubway.ReqCoords = [];
};

BitSubway.Init = function() {
	var BS = BitSubway;
	SUBWAYMAP = new BS.Map($('map'),BS.SidePanels,BS.SubwayData,BS.PathData,BS.Language,BS.ReqMarkers,BS.Markers,BS.MarkerSets,BS.BergenData,BS.Waterway,BS.Watertaxi,BS.TextStrings,BS.MetaData,BS.ReqCoords,BS.ReqStation);
};

BitSubway.Unload = function(){
	if (getCookie('map_last_lat')){
		SUBWAYMAP.rememberLastCenterAndZoom();
	}
	GUnload();
};

BitSubway.Map = function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){
	this.station = o;
	this.coords = n;
	this.metadata = m;
	this.strings = l;
	this.watertaxis = k;
	this.waterways = j;
	this.bergenstations = i;
	this.mapdiv = a;
	this.panels = b;
	this.substations = c;
	this.pathstations = d;
	this.oe = e;
	if (e != null){
		this.rememberLanguage(this.oe);
	}
	this.reqmarkers = f;
	this.usermarkers = g;
	this.usermarkersets = h;
	this.bounds;
	this.xmax;
	this.xmin;
	this.ymax;
	this.ymin;
	this.markers = [];
	this.markercounter = 1; //time delay for updating markers
	this.markertimers = []; //list of markers to update
	this.tempmarkers = [];
	this.Geocoder = new GClientGeocoder();
	this.genIcons();
	this.map = new GMap2(this.mapdiv, {draggableCursor: 'default'});
	this.map.enableContinuousZoom();
	this.map.enableScrollWheelZoom();
	
	var map1 = "Subway";
	var map2 = "Ferries";
	switch( this.station.system ){
		case "Waterway":
		case "Watertaxi":
			map1 = "Ferries";
			map2 = "Subway";
			break;
	}
	this.defaultmap = this.addMapType(map1);
	this.activeSystemSearch = "Subway";
	this.addMapType(map2);
	/* create a custom control prototype first then create an instance */
	BitSubway.DefineYSliderControl();
	this.sliderControl = new YSliderControl();
	//this.map.addControl(this.sliderControl, new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(7,7)));

	var e1 = $('subwayfooter');
	BitMap.Utl.JSCSS("remove",e1,"hide"); 
	e2 = $('extra');
	BitMap.Utl.JSCSS("remove",e2,"hide"); 

	/* auto center the map
	 * BitMap.Utl.MapResize comees from Gmap Package
	 */
	this.MR = BitMap.Utl.MapResize;
	//set these variables to customize
	this.MR.regOffsetObjs([$('subwayheader'),$('subwayfooter')]);
	this.MR.regOffsetBonus(4);
	this.MR.regMinSize(400);
	//these are constants dont mess with them
	this.MR.regMap(this.map);
	this.MR.regMapDiv(this.mapdiv);
	this.MR.regPanelDiv($('extra'));
	this.MR.sizeMapDiv();
	this.MR.setResizeListener();
	ref = this;
	var tabs = getElementsByTagAndClassName('h4','tab');
	for (n in tabs){
		this.replaceTabClickHandler( tabs[n] );
	}
	setTimeout("BitMap.Utl.MapResize.sizeMapDiv()", 10);  //fucking safari

	//Center the map
	if (this.station.id != null && this.station.system != null){
		var station = this.getStationData( this.station.id, this.station.system );
	}
	if ( typeof(station) != 'undefined' ){
		var clat = station[0][0]; 
		var clng = station[0][1];
		if ( this.coords.z == null ){ this.coords.z = 15 };
	}else if( this.coords.lat != null ){
		var clat = this.coords.lat;
		var clng = this.coords.lng;
	}else{
		var clat = getCookie('map_center_lat')?getCookie('map_center_lat'):(getCookie('map_last_lat')?getCookie('map_last_lat'):40.72514478577348);
		var clng = getCookie('map_center_lng')?getCookie('map_center_lng'):(getCookie('map_last_lng')?getCookie('map_last_lng'):-73.96751403808594);
	}
	if ( this.coords.z != null ){
		var czoom = this.coords.z;
	}else{
		var czoom = getCookie('map_center_zoom')?getCookie('map_center_zoom'):(getCookie('map_last_zoom')?getCookie('map_last_zoom'):13);
	}
	if (getCookie('map_last_lat')){
		$('pref_center_start_last').style.display = "inline";
		$('pref_center_start_fixed').style.display = "none";
	}
	this.centerlat = (this.reqmarkers.length > 0)?this.reqmarkers[0].lat:clat;
	this.centerlng = (this.reqmarkers.length > 0)?this.reqmarkers[0].lng:clng;
	this.centerzoom = czoom?parseInt(czoom):13;
	this.map.setCenter( new GLatLng(this.centerlat,this.centerlng), this.centerzoom );
	if (this.reqmarkers.length > 0){
		this.mapReqMarkers();
	}	

	this.map.checkResize();
	//something is wack about what the map thinks its size is so we set the center twice - call us crazy
	this.map.setCenter( new GLatLng(this.centerlat,this.centerlng), this.centerzoom );
	
	this.map.setMapType(this.defaultmap);
	
	var maph = MochiKit.Style.getElementDimensions( this.mapdiv );
	var newtop = (maph.h - 100)/ 2;
	this.map.addControl( this.sliderControl, new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(4,newtop)));
	this.sliderControl.setSlider( this.map.getZoom() );
	
	this.checkBounds();
	this.mapSub();
	this.mapPath();
	this.mapBergen();
	this.mapWaterway();
	this.mapWatertaxi();

	if ( typeof(station) != 'undefined' ){		
		this.openMarkerWindow( station.marker.n );
	}
	
	if (this.usermarkers.length > 0){
		this.mapUserMarkers();
	}

	var ref = this;
	GEvent.addListener(this.map, "moveend", function() { ref.updateMarkers(); });
	this.addOverlayListener();
	
	this.sortStationList();
}

BitSubway.Map.prototype = {
	"rememberCenterAndZoom": function(){
		var c = this.map.getCenter();
		setCookie("map_center_lat", c.lat());
		setCookie("map_center_lng", c.lng());
		setCookie("map_center_zoom", this.map.getZoom());
		deleteCookie("map_last_lat");
		deleteCookie("map_last_lng");
		deleteCookie("map_last_zoom");
		$('pref_center_start_last').style.display = "none";
		$('pref_center_start_fixed').style.display = "inline";
	},

	"rememberLastCenterAndZoom":function(){
		var c = this.map.getCenter();
		setCookie("map_last_lat", c.lat());
		setCookie("map_last_lng", c.lng());
		setCookie("map_last_zoom", this.map.getZoom());
		deleteCookie("map_center_lat");
		deleteCookie("map_center_lng");
		deleteCookie("map_center_zoom");
		$('pref_center_start_fixed').style.display = "none";
		$('pref_center_start_last').style.display = "inline";
	},

	"rememberLanguage": function(oe){
		setCookie("map_oe", oe);
	},
	
	"replaceTabClickHandler": function( tab ){
		ref = this;
		var f = tab.onclick;
		tab.onmouseup = f;
		tab.onclick = function(){ ref.MR.sizeMapDiv(); };
	},

	"executeJavascript": function(element) {
		if (element) {
		  var st = element.getElementsByTagName("SCRIPT");
		  var string_to_execute;
		  for (var i=0;i<st.length; i++) {
			string_to_execute = st[i].innerHTML;
			try {
			  eval(string_to_execute.split("<!--").join("").split("-->").join(""));
			} catch(e) {
			  MochiKit.Logging.log(e);
			} // end try
		  } // end for
		} // end if
	},
	
	"handleEvent": function (name, param){
		var func = bind( this[name], this );
		return function(){ func(param) };
	},
	
	"show": function(o){
		o.style.display = 'block';
	},

	"hide": function(o){
		o.style.display = 'none';
	},

	/* a convenience function */
	"getTagVal": function( xml, tag ){
		return xml.getElementsByTagName(tag)[0].firstChild.nodeValue;
	},

	/* stuff we add onto an ajax call */
	"prepForAjax":function( ){
		var q = (this.oe == 'en')?"":"&oe="+this.oe;
		return q;
	},
	
	"addOverlayListener": function(){
		var ref = this;
		GEvent.addListener(this.map, "click", function(overlay) {
			if (overlay){
				var o = overlay;
				if ( o.type == 'marker' ){
					ref.openMarkerWindow(o.n);
				}else if( o.my_html ){
					o.openInfoWindow( o.my_html );
				}
			}
		});
	},

	"openMarkerWindow": function(i){
		var o = this.markers[i];
		if (typeof(o) != 'undefinded' && o != null){
			var m = o.marker;
			if ( typeof(m.my_html) == 'undefined' || m.my_html == null ){
				var id = o.content_id;
				doSimpleXMLHttpRequest("view_marker.php", {content_id:id, pre_window:true}).addCallback( bind(this.loadMarkerCallback, this), i ); 
			}else{
				// if the marker is not attached attach it this plotted may screw up user markers - double check
				if (o.plotted == 0){
					this.map.addOverlay( m ); 
					o.plotted = 1;
				}
				var opt = null;
				if (m.my_maxurl){
					if (m.my_maxdata){
						opt = {maxContent:m.my_maxdata};
					}else{
						var e = DIV(null, "Loading...");
						opt = {maxContent:e};
						var url = m.my_maxurl;
						var mref = m;
						GEvent.addListener(this.map, "infowindowopen", function(){
							var w = ref.map.getInfoWindow();
							GEvent.addListener(w, "maximizeclick", function() {
								GDownloadUrl(url, function(data) {
									mref.my_maxdata = e.innerHTML = data;
									setTimeout("setupAllTabs()", 200); /*thanks safari and ie*/
								});
							});
						});
					}
				}
				m.openInfoWindow( m.my_html, opt);
			}
		}
	},

	"loadMarkerCallback": function(i, rslt){
		var elm = DIV();
		elm.innerHTML = rslt.responseText;
		this.markers[i].marker.my_html = elm;
		this.openMarkerWindow(i);
		setTimeout("setupAllTabs()", 200); /*thanks safari and ie*/
	},
	
	"loopOver": function(arr, fnc){
		var iIterations = arr.length;
		var iLoopCount = Math.ceil(iIterations / 8);
		var iTestValue = iIterations % 8;
		var n = 0;
		do {
			switch (iTestValue) {
				case 0: fnc(n++);
				case 7: fnc(n++);
				case 6: fnc(n++);
				case 5: fnc(n++);
				case 4: fnc(n++);
				case 3: fnc(n++);
				case 2: fnc(n++);
				case 1: fnc(n++);
			}
			iTestValue = 0;
		} while (--iLoopCount > 0);
	},
	
	"checkBounds": function(){
		this.bounds = this.map.getBounds();
		this.xmax = this.bounds.getNorthEast().lat();
		this.xmin = this.bounds.getSouthWest().lat();
		this.ymax = this.bounds.getNorthEast().lng();
		this.ymin = this.bounds.getSouthWest().lng();
	},

	"compareBounds": function(p){
		if (p.lat() < this.xmin || p.lat() > this.xmax ||
			p.lng() < this.ymin || p.lng() > this.ymax) {
			return false;
		}else{
			return true;
		}
	},

	/*---MAPTYPE---*/
	"addMapType": function(type){
		// create copyright
		var c = new GCopyright(1,
								new GLatLngBounds( new GLatLng( -90,-180 ), new GLatLng( 90,180 ) ),
								0,
								type+" imagery &copy;2006 onNYTurf, Map data &copy;2007 Tele Atlas");

		// add to copyright collection
		var cc = new GCopyrightCollection();
		cc.addCopyright(c);

		var typepath = type.toLowerCase();

		// create GTileLayer
		var getUrl=function(a, b){
			var c = 17 - b;
			if (b < 12){
				return "http://mt.google.com/mt?n=404&v=ap.63&x="+a.x+"&y="+a.y+"&zoom="+c;
			}else{
				return "maps/"+typepath+"/onnyturf_only.php?x="+a.x+"&y="+a.y+"&zoom="+c;
			}
		}

		// create tilelayer
		var tl = [];
		tl.push( new GTileLayer( cc, 0, 18 ) );
		tl[0].getTileUrl = getUrl;
		tl[0].isPng = function(){return false;};
		var custommap = new GMapType(tl, G_NORMAL_MAP.getProjection(), type, {errorMessage:"no maps here"});

		// add it to the map
		this.map.addMapType(custommap);
		return custommap;
	},

	/*----ICONS----*/

	"genIcons": function(){
		var i = this.STATION_ICON = new GIcon();
		//i.image = "images/yknob.png";
		i.image = "images/clear.gif";
		//i.shadow = images/clear2.png";
		i.iconSize = new GSize(14, 14);
		//I.shadowSize = new GSize(14, 14);
		i.iconAnchor = new GPoint(10, 10);
		i.infoWindowAnchor = new GPoint(10, 10);
		
		i = this.WHITE_ICON = new GIcon();
		i.image = "/gmap/icons/onnyturf/wht_circle.png";
		i.iconSize = new GSize(14,14);
		i.iconAnchor = new GPoint(10,10);
		i.infoWindowAnchor = new GPoint(10,10);
		
		i = this.ADDRESS_ICON = new GIcon();
		i.image = "images/turf.png";
		i.shadow = "http://www.google.com/mapfiles/shadow50.png";
		i.iconSize = new GSize(20, 34);
		i.shadowSize = new GSize(37, 34);
		i.iconAnchor = new GPoint(9, 34);
		i.infoWindowAnchor = new GPoint(9, 2);			
		i.infoShadowAnchor = new GPoint(18, 25);

		i = this.ORG_ICON = new GIcon();
		i.image = "images/r2fav3.png";
		i.shadow = "http://www.google.com/mapfiles/shadow50.png";
		i.iconSize = new GSize(20, 34);
		i.shadowSize = new GSize(37, 34);
		i.iconAnchor = new GPoint(9, 34);
		i.infoWindowAnchor = new GPoint(9, 2);			
		i.infoShadowAnchor = new GPoint(18, 25);	
	},

	/*----MARKERS---*/
	
	"createMarker": function(point, text, icon, tip) {
		var p = point;
		var i = icon;
		var t = tip;
		var m = new GxMarker(p, i, t);
		m.my_html = text;
		m.type = "marker";
		return m;
	},

	// @mHash a reference to a marker data hash
	"addMarker": function(mHash, hide){
		var n = this.markers.length;
		var m = this.markers[n] = mHash;
		m.n = m.marker.n = n;
		var p = m.marker.getPoint();
		m.plotted = 0;
		if (!hide){
			if ( this.compareBounds(p) ){
				this.map.addOverlay( m.marker );
				m.plotted = 1;
			}
		}else{
			m.hide = 1;
		}
		return n;
	},

	"updateMarkers": function(){
		this.markercounter = 1;
		this.markertimers = [];
		this.checkBounds();
		var ref = this;
		this.loopOver(this.markers, function(i){ref.updateMarker(i);});
		for (n in this.markertimers){ this.markertimers[n](); }
	},

	// @i index of this.markers array
	"updateMarker": function(i){
		var o = this.markers[i];
		if ( o && o.marker ){
			var m = o.marker;
			var p = m.getPoint();
			var ref = this;
			if ( this.compareBounds(p) ){
				if ( !o.plotted && !o.hide ) {
					this.markertimers.push( function() {
								ref.map.addOverlay( m ); 
								o.plotted = 1;
					});
				}
			} else if (o.plotted && !o.force) {
					this.markertimers.push( function() { 
								ref.map.removeOverlay( m ); 
								o.plotted = 0;
					});
			}
		}
	},
			
	"mapReqMarkers": function(){
		var ref = this;
		if (this.reqmarkers.length > 0){
			this.loopOver(this.reqmarkers, function(n){ref.addReqMarker(n);});
			var m = this.reqmarkers[0];
			this.openMarkerWindow(m.n);
		}
	},

	// @i marker hash index
	"addReqMarker": function(i){
		//this.logError("ACTION:addReqMarker<br/>");
		var m = this.reqmarkers[i];
		if (m != null){
			var p = new GLatLng(parseFloat(m.lat), parseFloat(m.lng));
			var tip = "<div class='fav_tip'>"+m.title+"</div>";
			m.marker = this.createMarker(p, null, this.ORG_ICON, tip);
			m.n = this.addMarker(m);
			if ( m.content_id == null && m.marker_id == null){
				m.marker.my_html = this.makeAddressSearchHTML(m.title, i);
				var esctitle = m.title.replace(/\+/g, " ");
				m.address = m.title = esctitle;
				this.tempmarkers[i] = m;
			}
		}
	},	

	"mapSub": function(){
		var ref = this;
		this.loopOver(this.substations, function(n){ref.addStationMarker(n, "Subway");});
	},


	"mapPath": function (){
		var ref = this;
		this.loopOver(this.pathstations, function(n){ ref.addStationMarker(n, "Path"); } );
	},
	
	"mapBergen": function(){
		var ref = this;
		this.loopOver(this.bergenstations, function(n){ ref.addStationMarker(n, "Bergen"); } );
	},

	"mapWatertaxi": function(){
		var ref = this;
		this.loopOver(this.watertaxis, function(n){ ref.addStationMarker(n, "Watertaxi"); } );
	},

	"mapWaterway": function(){
		var ref = this;
		this.loopOver(this.waterways, function(n){ ref.addStationMarker(n, "Waterway"); } );
	},

	"addStationMarker": function( i, pSystem ){
		var linkstyle = "style='text-decoration:underline'";
		// unique data ref
		var meta = this.metadata[pSystem];
		var m = this.getStationData( i, pSystem );
		var p = new GLatLng(parseFloat(m[0][0]), parseFloat(m[0][1]));
		var ada = (m[4])?"<a href='"+meta.ada_base_url+"' title='"+this.strings[4]+"' class='ada'><img src='images/ada.gif' alt='ada'></a>":"";
		var aTip = ["<div class='stationtip'><span class='small'><strong>",meta.sys_desc,"</strong></span><br/><span class='stationname_sm'>",m[1],"</span><br/>"];
		var aText = ["<div id='infowindow' style='white-space: nowrap;'><h4>",meta.sys_desc,"</h4><span class='stationname'>", m[1], "</span>",ada,"<br/>"];
		var zoom = (m[5]==1)?"<a "+linkstyle+" href='javascript:void(0);' onclick='SUBWAYMAP.zoomToStation();'>"+this.strings[2]+"</a>&nbsp;&nbsp;":((m[5]==0 && ( m[3]=="QN" ))?"<a "+linkstyle+" href='/wiki/index.php?page=Help+Map+Subway+Entrances+and+Exits'>"+this.strings[3]+"</a>&nbsp;&nbsp;":"");
		var info = (m[6])?"<a "+linkstyle+" href='javascript:void(0);' onclick='SUBWAYMAP.map.getInfoWindow().maximize();'>"+this.strings[1]+"</a>":"<em>"+this.strings[4]+"</em>";
		var L = meta.lines_desc;
		var lines = m[2];
		var ttl = lines.length;
		for (n=0;n<ttl;n++){
			var l = lines[n];
			var link = this.getLineUrl( n, m, pSystem );
			var alt = L[l]?L[l]:l;
			var img = this.getLineImg( l, pSystem );
			aText.push('<a style="text-decoration:none;" href="', link, '" target="_blank"><img style="border:none; padding-top:2px;" src="',img,'" width="31" height="30" alt="',alt,'"></a>');
			aTip.push('<img style="border:none; padding-top:2px;" src="',img,'" width="16" height="15" alt="',alt,'">');
		}
		aText.push("<p>",zoom,info,"</p>","<p><a "+linkstyle+" href='",bitRootUrl,"subway/?system=",pSystem.toLowerCase(),"&station_id=",i,"'>",this.strings[14],"</a></p>","</div>");
		aTip.push("<br/></div>");
		m.marker = this.createMarker(p, aText.join(""), this.STATION_ICON, aTip.join(""));
		if (m[6]){
			m.marker.my_maxtitle = m[1];
			m.marker.my_maxurl = bitRootUrl + "subway/view_stationdetail.php?page_id=" + m[6];
		}
		this.addMarker(m);
	},

	"getStationData": function(i,s){
		switch ( s ){
			case "Subway":
				m = this.substations[i];
				break;
			case "Path":
				m = this.pathstations[i];
				break;
			case "Bergen":
				m = this.bergenstations[i];
				break;
			case "Watertaxi":
				m = this.watertaxis[i];
				break;
			case "Waterway":
				m = this.waterways[i];
				break;
		}
		return m;
	},

	"getLineImg": function(l,s){
		var i = l;
		switch ( s ){
			case "Subway":
				break;
			case "Path":
				i = l+"path";	
				break;
			case "Bergen":
				i = l+"bergen";	
				break;
			case "Watertaxi":
				i = "wt"+l;	
				break;
			case "Waterway":
				i = "ww"+l;	
				break;
		}
		return 'images/'+i+'.gif';
	},

	// @l line name
	// @s system name
	"getLineUrl": function(n,m,s){
		var l = m[2][n];
		var ret = null;
		var meta = BitSubway.MetaData[s];
		// unique paths
		switch ( s ){
			case "Subway":
				var L = meta.lines_url_names;
				if ( l!='jfkairtrain'){
					var lineinfo = L[l]?L[l]:l;
					lineinfo += l!=3&&l!=7?'line.htm':'lin.htm';
					ret = meta.station_base_url + lineinfo;
				}else{
					ret = 'http://www.panynj.gov/airtrain/';
				}
				break;
			case "Path":
			case "Bergen":
				ret = meta.station_base_url;
				break;
			case "Watertaxi":
				ret = l=="b"?"brooklyn-army-terminal":"hudsonriver";
				break;
			case "Waterway":
				var lids = m[7];
				ret = meta.station_base_url + (lids.length>0?"ferry-route.asp?ferryid="+lids[n]:"");
				break;
		}
		return ret;
	},

    "zoomToStation":function(){
        this.map.setZoom(17);
    },
	
	/*----ADDRESS SEARCH---*/
	
	"getAddress": function(){
	  	var req = $("address").value;
		replaceChildNodes( $('notice'), P(null,this.strings[8]) );
		this.MR.sizeMapDiv();
		this.Geocoder.getLocations( req, bind(this.getAddressCallback, this) );
	},

	"getAddressCallback": function(rslt){
		if (!rslt || rslt.Status.code != 200) {
			replaceChildNodes( $('notice'), P(null, SPAN({"style":"font-weight:bold"},this.strings[9]+" "), SPAN({"style":"font-style:italic"}, this.strings[10]), BR(), this.strings[11] ));
			this.MR.sizeMapDiv();
		} else {
			p = rslt.Placemark[0];
			this.plotAddress(p.Point.coordinates[0],
							 p.Point.coordinates[1], 
							 p.address);
		}
     },
	
	"plotAddress": function(lng, lat, title) {
		var n = this.tempmarkers.length;
		var o = this.tempmarkers[n] = {};
		o.address = title;
		var p = new GLatLng(parseFloat(lat), parseFloat(lng));
		var m = o.marker = new GMarker(p, this.ADDRESS_ICON);
		var esctitle = title.replace(/ /g, "+");
		var linkpath = bitRootUrl+"subway/?address="+esctitle;
		m.my_html = this.makeAddressSearchHTML(title, n);
		this.map.addOverlay(m);
		o.plotted = 1;
		this.map.panTo(p);
		m.openInfoWindowHtml(m.my_html);
		//add it to the list	
		var toggleFunc = this.handleEvent( 'toggleSearchRslt', n );
		var showFunc = this.handleEvent( 'showSearchRslt', n );
		var removeFunc = this.handleEvent( 'removeSearchRslt', n );
		var table = $('search-markers-list');
		var tbody = getFirstElementByTagAndClassName( "tbody", null, table );
		var row = TR({'id':'search_'+n+'_row'}, 
					TD({"style":"width:14px"}, INPUT({'id':'search_'+n+'_input', 'type':'checkbox', 'onclick':toggleFunc, 'checked':true})),
					TD(null, A({'href':'javascript:void(0);', 'onclick':showFunc}, title)),
					TD({"style":"width:12px"}, A({'href':'javascript:void(0);', 'onclick':removeFunc}, IMG({'src':'images/delete.gif', 'alt':this.strings[12] })))
			);
		var sib = getFirstElementByTagAndClassName( "tr", null, table );
		if ( sib != null ){
			insertSiblingNodesBefore( sib, row );
		}else{
			appendChildNodes( table, TBODY(null, row) );
		}
		replaceChildNodes( $('notice'), P(null, this.strings[13]) );
		this.MR.sizeMapDiv();
	},
	
	"toggleSearchCheckbox": function(id){
		var i = $('search_'+id+'_input')
		if ( i.checked == true ){
			i.checked = false;
		}else{
			i.checked = true;
		}
	},
	"toggleSearchRslt": function( n ){
		var o = this.tempmarkers[n];
		if ( o && o.marker ){
			var m = o.marker;
			if ( !o.hide ){
				o.hide = 1;
				if ( o.plotted ){
					this.map.removeOverlay( m );
					o.plotted = 0;
				}
			}else{
				this.map.addOverlay( m );
				o.plotted = 1;
				o.hide = 0;
			}
		}
	},
	"showSearchRslt": function( n ){
		var o = this.tempmarkers[n];
		if ( o && o.marker ){
			var m = o.marker;
			if ( !o.plotted ) {
				this.map.addOverlay( m );
				o.plotted = 1;
				if (o.hide){
					this.toggleSearchCheckbox(n);
				}
				o.hide = 0;
			}
			m.openInfoWindowHtml(m.my_html);
		}
	},
	"removeSearchRslt": function( n ){
		var o = this.tempmarkers[n];
		if ( o && o.marker ){
			if ( o.plotted ) {
				this.map.removeOverlay( o.marker );
				o.plotted = 0;
				o.hide = 1;
			}
			o.marker = null;
//			o = null;
			var e = $('search_'+n+'_row');
			removeElement(e);
		}
	},

	"makeAddressSearchHTML": function(title, n){
		var esctitle = title.replace(/ /g, "+");
		var linkpath = bitRootUrl+"subway/?address="+esctitle;
		var elm = DIV({'class':"display gmarker", 'style':"text-align:center;margin:4px 14px 0 14px;"},
						SPAN({'style':'font-size:16px; font-weight:bold; font-family:arial; white-space:nowrap;'}, title),
						DIV({'class':"opts"},
							A({'href':linkpath}, this.strings[14]),
							A({'href':'mailto:?body='+linkpath }, this.strings[15]),
							A({'href':'javascript:void(0);', 'onclick':'javascript:SUBWAYMAP.addToFav('+n+')'}, this.strings[16])
						)
					);
		return elm;
	},
	
	"getSelectValue":function(e){
		return e[e.selectedIndex].value;
	},

	/*----STATION SEARCH---*/
	"sortStationList": function(){
        // reformat our station data to [{column:value, ...}, ...] style as domains
        var domains = [];
		//limit by dataset
		var s = this.getSelectValue($('sys_opts'));
		var rows;
		switch ( s ){
			case "Subway":
				rows = this.substations;
				break;
			case "Path":
				rows = this.pathstations;
				break;
			case "Bergen":
				rows = this.bergenstations;
				break;
			case "Watertaxi":
				rows = this.watertaxis;
				break;
			case "Waterway":
				rows = this.waterways;
				break;
		}
        var cols = BitSubway.SubwayDataColumns;
        for (var i = 0; i < rows.length; i++) {
            var row = rows[i];
            var domain = {};
            domain.n = row.n;
            for (var j = 0; j < cols.length; j++) {
                domain[cols[j]] = row[j];
            }
            domains.push(domain);
        }
		domains.sort( function(a,b){ return natcompare(a['name'], b['name']) } );

		
		//limit list by area and line
		var aopts = $('area_opts');
		var lopts = $('line_opts');
		if ( s != this.activeSystemSearch ){
			aopts.selectedIndex = 0;
			var lines = this.metadata[s].lines_desc; 
			lopts.options.length = 0;
			lopts.options[0] = new Option("ALL","");
			var i = 1;
			for (l in lines){
				lopts.options[i] = new Option(lines[l],l);
				i++;
			}
		}
		var area = aopts[aopts.selectedIndex].value;
		var line = lopts[lopts.selectedIndex].value;
		
		if (area != ""){
			var areafilter = function(area, data){
					var r= (data.area == area)?1:0;
					return r;
				};
			var matcharea = partial( areafilter, area );
			domains = filter( matcharea, domains );
		}
		if (line != ""){
			var filterfunc = function(line, data){
					var r=( findIdentical(data.lines, line) > -1 )?1:0;
					return r;
				};
			var matchline = partial( filterfunc, line );
			domains = filter( matchline, domains );
		}
		
		replaceChildNodes('faststops', null);
        for (var i = 0; i < domains.length; i++) {
        	var row = domains[i];
			var func = this.handleEvent("openMarkerWindow", row.n);
			appendChildNodes('faststops', DIV({"style":"color:#999"}, " " + row.area + " ", A({"href":"javascript:void(0);", "onclick":func}, row.name), " ("+row.lines.toString().toUpperCase()+")"));
		}

		this.activeSystemSearch = s;
	},
	/*----PANEL CONTROLS---*/
	
	"changeMaptype": function(i){
		var m = this.map.getMapTypes();
		this.map.setMapType(m[i]);
		for (var n=0; n<m.length; n++){
			var e = $('mapbtn_'+n);
			if (n == i){
				BitMap.Utl.JSCSS("add",e,"selected"); 
			}else{
				BitMap.Utl.JSCSS("remove",e,"selected");
			}
		}
	},
	"changePanel": function(ename){
		var panels = this.panels;
		for (n=0;n<panels.length;n++){
			var p = $( panels[n] );
			var e = $( panels[n]+'_panelbtn' );
			if (panels[n] == ename){
				BitMap.Utl.JSCSS("remove",p,"hide");
				BitMap.Utl.JSCSS("add",e,"selected");
				if ( MochiKit.Style.getStyle( $('content'), 'margin-right') != '300px' ){
					MochiKit.Style.setStyle( $('content'), {'margin-right':'300px'} );
					MochiKit.Style.setStyle( this.mapdiv, {'margin-right':'4px'} );
					this.map.checkResize();
				}
			}else{
				BitMap.Utl.JSCSS("add",p,"hide");
				BitMap.Utl.JSCSS("remove",e,"selected");
			}
		}
		this.MR.sizeMapDiv();
		BitMap.Utl.JSCSS("remove",$('extra'),"hide");
	},
	
	"closePanel": function(ename){
		MochiKit.Style.setStyle( $('content'), {'margin-right':'0px'} );
		MochiKit.Style.setStyle( this.mapdiv, {'margin-right':0} );
		BitMap.Utl.JSCSS("add",$('extra'),"hide");
		this.map.checkResize();
		this.updateMarkers();
		var e = $(ename);
		BitMap.Utl.JSCSS("remove",e,"selected");
	}
};


/* Override MapResize functions to handle our custom slider control and update the sidepanel layout*/
BitMap.Utl.MapResize.checkResizeEnd = function(){
	
	if(!BitMap.Utl.MapResize.resizingFlag){
		BitMap.Utl.MapResize.mapRef.checkResize();
		
		//var sliderh = MochiKit.Style.getStyle( SUBWAYMAP.sliderControl, 'height' );
		var maph = MochiKit.Style.getElementDimensions( this.mapDivRef );
		var newtop = (maph.h - 100)/ 2;
		this.mapRef.removeControl( SUBWAYMAP.sliderControl );
		this.mapRef.addControl( SUBWAYMAP.sliderControl, new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(4,newtop)));
//		SUBWAYMAP.sliderControl.setSlider( this.mapRef.getZoom() );

		clearInterval(BitMap.Utl.MapResize.resizingInterval);
		BitMap.Utl.MapResize.resizingInterval = null;
	}
	BitMap.Utl.MapResize.resizingFlag = false;
};

BitMap.Utl.MapResize.orgSizeMapDiv = BitMap.Utl.MapResize.sizeMapDiv;

BitMap.Utl.MapResize.sizeMapDiv = function(){
	BitMap.Utl.MapResize.orgSizeMapDiv();
	
	var offset = BitMap.Utl.MapResize.getOffset();
	var h = getViewportDimensions().h - offset;
	var minh = BitMap.Utl.MapResize.minSize;
	if (h < minh){ h = minh; }
	var post_h = getElementDimensions($('extra20')).h;
	// get each panel
	var panels = BitSubway.SidePanels;
	MochiKit.Iter.forEach(BitSubway.SidePanels, function(id){
		var p = $(id);
		var ph = getElementsByTagAndClassName('div','panel_header',p);
		var ph_h = 0;
		if (isNotEmpty(ph)){
			ph_h = getElementDimensions(ph[0]).h;
			ph[0].style.display='block';
		}
		var tp = getElementsByTagAndClassName('div','tabpage',p);
		if (isNotEmpty(tp)){ 
			MochiKit.Iter.forEach(tp, function(e){
				var tb = getElementsByTagAndClassName('h4','tab',e);
				var th = getElementsByTagAndClassName('div','tab_header',e);
				var sp = getElementsByTagAndClassName('div','scroll_pane',e);
				var tb_h = 0;
				var th_h = 0;
				if (isNotEmpty(tb)){
					tb_h = getElementDimensions(tb[0]).h;
					tb[0].style.display='block';
				}
				if (isNotEmpty(th)){
					th_h = getElementDimensions(th[0]).h;
					th[0].style.display='block';
				}
				if (isNotEmpty(sp)){
					var ht =  ( h - ph_h - tb_h - th_h - post_h - 38);
					ht = (ht > 0)?ht:0;
					sp[0].style.height = ht + 'px';
				}
			});
		}
	});
};

/*
natcompare.js -- Perform 'natural order' comparisons of strings in JavaScript.
Copyright (C) 2005 by SCK-CEN (Belgian Nucleair Research Centre)
Written by Kristof Coomans <kristof[dot]coomans[at]sckcen[dot]be>

Based on the Java version by Pierre-Luc Paour, of which this is more or less a straight conversion.
Copyright (C) 2003 by Pierre-Luc Paour <natorder@paour.com>

The Java version was based on the C version by Martin Pool.
Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au>

This software is provided 'as-is', without any express or implied
warranty.  In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/


function isWhitespaceChar(a)
{
    var charCode;
    charCode = a.charCodeAt(0);

    if ( charCode <= 32 )
    {
        return true;
    }
    else
    {
        return false;
    }
}

function isDigitChar(a)
{
    var charCode;
    charCode = a.charCodeAt(0);

    if ( charCode >= 48  && charCode <= 57 )
    {
        return true;
    }
    else
    {
        return false;
    }
}

function compareRight(a,b)
{
    var bias = 0;
    var ia = 0;
    var ib = 0;

    var ca;
    var cb;

    // The longest run of digits wins.  That aside, the greatest
    // value wins, but we can't know that it will until we've scanned
    // both numbers to know that they have the same magnitude, so we
    // remember it in BIAS.
    for (;; ia++, ib++) {
        ca = a.charAt(ia);
        cb = b.charAt(ib);

        if (!isDigitChar(ca)
                && !isDigitChar(cb)) {
            return bias;
        } else if (!isDigitChar(ca)) {
            return -1;
        } else if (!isDigitChar(cb)) {
            return +1;
        } else if (ca < cb) {
            if (bias == 0) {
                bias = -1;
            }
        } else if (ca > cb) {
            if (bias == 0)
                bias = +1;
        }
    }
}

function natcompare(a,b) {

    var ia = 0, ib = 0;
    var nza = 0, nzb = 0;
    var ca, cb;
    var result;

    while (true)
    {
        // only count the number of zeroes leading the last number compared
        nza = nzb = 0;

        ca = a.charAt(ia);
        cb = b.charAt(ib);

        // skip over leading spaces or zeros
        while ( isWhitespaceChar( ca ) || ca =='0' ) {
            if (ca == '0') {
                nza++;
            } else {
                // only count consecutive zeroes
                nza = 0;
            }

            ca = a.charAt(++ia);
        }

        while ( isWhitespaceChar( cb ) || cb == '0') {
            if (cb == '0') {
                nzb++;
            } else {
                // only count consecutive zeroes
                nzb = 0;
            }

            cb = b.charAt(++ib);
        }

        // process run of digits
        if (isDigitChar(ca) && isDigitChar(cb)) {
            if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) {
                return result;
            }
        }

        if (ca == 0 && cb == 0) {
            // The strings compare the same.  Perhaps the caller
            // will want to call strcmp to break the tie.
            return nza - nzb;
        }

        if (ca < cb) {
            return -1;
        } else if (ca > cb) {
            return +1;
        }

        ++ia; ++ib;
    }
}



MochiKit.Base.update(BitSubway.Map.prototype, {

	/* Some Global Class Variables */
	/*
	this.MARKER_SRC;
	this.MARKER_INDEX;
	this.tempmarkers = new Array();
	this.TEMP_MARKER;
	this.MARKER_ASSISTANT;
	*/

	"mapUserMarkers": function(){
		var ref = this;
		if (this.usermarkers.length > 0){
			this.loopOver(this.usermarkers, function(n){ref.addUserMarker(n);});
		}
	},

	// @i marker hash index
	"addUserMarker": function(i){
		var m = this.usermarkers[i];
		if (m != null){
			var p = new GLatLng(parseFloat(m.lat), parseFloat(m.lng));
			var tip = "<div class='fav_tip'>"+m.title+"</div>";
			m.marker = this.createMarker(p, null, this.ORG_ICON, tip);
			m.marker.type = "marker";
			this.addMarker(m, true);
		}
	},
	
	// @id a usermarker's marker_id
	"showUserMarker": function(id){
		var m = this.getUserMarkerDataById(id);
		if (m != null){
			if ( !m.plotted ) {
				this.map.addOverlay( m.marker );
				m.plotted = 1;
				if (m.hide){
					this.toggleUserMarkerCheckbox(id);
				}
				m.hide = 0;
			}
			this.openMarkerWindow(m.n);
		}
	},

	// @id a usermaker's marker_id
	// returns a reference to the marker hash of data
	"getUserMarkerDataById": function(id){
		var mHash = null;
		for (n in this.usermarkers){
			var m = this.usermarkers[n];
			if (m.marker_id == id ){
				mHash = m;
				break;
			}
		}
		return mHash;
	},

	// @id a usermarker's marker_id
	"toggleUserMarkerDisplay": function(id){
		var m = this.getUserMarkerDataById(id);
		if (m != null){
			if ( !m.hide ){
				m.hide = 1;
				if ( m.plotted ){
					this.map.removeOverlay( m.marker );
					m.plotted = 0;
				}
			}else{
				this.map.addOverlay( m.marker );
				m.plotted = 1;
				m.hide = 0;
			}
		}
	},

	// @id a usermarker's marker_id
	"toggleUserMarkerCheckbox": function(id){
		var i = $('marker_'+id+'_input')
		if ( i.checked == true ){
			i.checked = false;
		}else{
			i.checked = true;
		}
	},

	 "storeMarker": function(f){
		BitAjax.showSpinner( "Saving Marker..." );
//		this.showSpinner("Saving Marker...");
		var str = "edit_marker.php?" + queryString(f) + this.prepForAjax();
		doSimpleXMLHttpRequest(str).addCallback( bind(this.storeMarkerCallback, this) ); 
	 },
	 
	"storeMarkerCallback": function(rslt){
		BitAjax.hideSpinner();
		var xml = rslt.responseXML.documentElement;
		var t = this.markerEditType;
		var n;
		var M;
		var	id = this.getTagVal( xml, 'marker_id' );
		if (t == "user"){
			n = this.markerIndexRef;
			m = this.markers[n] = this.getUserMarkerDataById(id);
		}else{
			n = this.markers.length;
			var i = this.usermarkers.length;
			m = this.markers[n] = this.usermarkers[i] = {};
			m.n = n;
		}
		m.marker_id = id;
		m.content_id = this.getTagVal( xml, 'content_id' );
		m.marker_id = this.getTagVal( xml, 'marker_id' );
		m.title = this.getTagVal( xml, 'title' );
		m.lat = parseFloat( this.getTagVal( xml, 'lat' ));
		m.lng = parseFloat( this.getTagVal( xml, 'lng' ));
		var p = new GLatLng(m.lat, m.lng);
		var tip = "<div class='fav_tip'>"+m.title+"</div>";		
		var oldm = typeof(m.marker)!='undefined'?m.marker:null;
		m.marker = this.createMarker(p, null, this.ORG_ICON, tip);
		this.addMarker(m, true);
		switch (t){
			case "new":
 				this.removeAssistant();
				break;
			case "search":
				var tm = this.tempmarkers[this.markerIndexRef];
				this.map.removeOverlay(tm.marker);
				tm = null;
				break;
			case "user":
			default:
				this.map.removeOverlay(oldm);
				m.hide = 0;
				break;
		}
		//add it to the favorites list in the side panel
		if (t != "user"){
            var elm = TR( {id:"marker_"+m.marker_id+"_row"},
                        TD( {style:"width:14px;"},
							INPUT({ id:"marker_"+m.marker_id+"_input", type:"checkbox", name:"m.marker_id", value:"", onchange:"javascript:SUBWAYMAP.toggleUserMarkerDisplay("+m.marker_id+")" })
                       	),
                        TD( null, 
							A({ href:"javascript:void(0);", onclick:"SUBWAYMAP.showUserMarker("+m.marker_id+");"}, m.title )
                       	),
                        TD( {style:"width:12px;"},
							A({ href:"javascript:void(0);", onclick:"SUBWAYMAP.expungeUserMarker("+m.marker_id+");"}, IMG( {src:"images/delete.gif", alt:"delete"} ) )
                        )
                    );
			var tblid = 'users-markers-list';
			var tbl = $(tblid);
			if (!MochiKit.Base.isUndefinedOrNull( tbl )){
				var li = MochiKit.DOM.getFirstElementByTagAndClassName( 'tr', null, tbl );
				if (!MochiKit.Base.isUndefinedOrNull( li )){
					MochiKit.DOM.insertSiblingNodesBefore(li, elm);
				}else{
					tbl.appendChild(elm);
				}
			}else{
				var tbl = TABLE({id:tblid}, TBODY(null,elm));
				$('user-markers').appendChild(tbl);
			}
		}
		this.showUserMarker(m.marker_id);
		m.force = 0;		
	},	
	 
	"cancelEditMarker": function(id){
		var m;
		var t = this.markerEditType;
		if (t == 'new'){
			this.removeAssistant();
		}else if (t == 'search'){
			m = this.tempmarkers[this.markerIndexRef].marker;
			m.openInfoWindowHtml(m.my_html);
		}else if (t == 'user'){
			m = this.getUserMarkerDataById(id);
			this.openMarkerWindow(m.n);
		}
	},
	 
	"addToFav": function(n){
		if (bLogin == true){
			this.markerEditType = (n!=null)?'search':'new';
			this.markerIndexRef = n;
			doSimpleXMLHttpRequest("edit_marker.php", {oe:this.oe}).addCallback( bind(this.editNewMarkerCallback, this), n );
		}else{
			alert(this.strings[18]);
		}
	},

	"editNewMarkerCallback": function(i, rslt){
		var M = (i != null)?this.tempmarkers[i].marker:this.TEMP_MARKER;
		var elm = SPAN();
		elm.innerHTML = rslt.responseText;
		M.openInfoWindow(elm);
		
		var form = $('edit-marker-form');
		form.edit.value = (i!=null)?"__Address:__ " + this.tempmarkers[i].address:"";
		form['geo[lng]'].value = M.getPoint().lng();
		form['geo[lat]'].value = M.getPoint().lat();
		
		setupAllTabs();
	},


	"editUserMarker": function(id){
		var m = this.getUserMarkerDataById(id);
		this.markerEditType = 'user';
		doSimpleXMLHttpRequest("edit_marker.php", {marker_id:id, oe:this.oe}).addCallback( bind(this.editMarkerCallback, this), m.n );
	},

	"editMarkerCallback": function(i, rslt){
		var m = this.markers[i];
		var elm = SPAN();
		elm.innerHTML = rslt.responseText;
		m.marker.openInfoWindow(elm);
		m.force = 1;
		setupAllTabs();
	},
	
	// attached all favorites to map
	"showAllUserMarkers": function(){
		for (n in this.usermarkers){
			m = this.usermarkers[n];
			if ( !m.plotted ){
				this.map.addOverlay( m.marker );
				m.plotted = 1;
				if ( m.hide ){
					this.toggleUserMarkerCheckbox(m.marker_id);
				}
				m.hide = 0;
			}
		}
	},

	// removes all markers from map
	"hideAllUserMarkers": function(){
		for (n in this.usermarkers){
			m = this.usermarkers[n];
			if ( !m.hide ){
				if ( m.plotted ){
					this.map.removeOverlay( m.marker );
					m.plotted = 0;
				}
				this.toggleUserMarkerCheckbox(m.marker_id);
				m.hide = 1;
			}
		}
	},

	"login": function(f){
//		this.showSpinner("Logging In...");
		loadJSONDoc("validate.php", f).addCallback( bind(this.verifyLogin, this) );
	},

	"register": function(f){
		loadJSONDoc("register.php", f).addCallback( bind(this.verifyLogin, this) ); 
	},

	"verifyLogin": function(rslt){
		if (rslt.Status.code == 200){
			bLogin = true;
			bName = rslt.User.name;
			this.loadFavorites();
		}else if (rslt.Status.code == 401){
			alert(rslt.Status.msg);
		}
	},
	
	"loadFavorites": function(){
		var d = loadJSONDoc( "get_favs.php", {json:'true'} );		
		d.addCallbacks( bind(this.loadFavoritesCallback, this), bind( this.requestFailure, this) ); 
	},

	"requestFailure": function (err) {
		alert(err);
	},
	
	"loadFavoritesCallback": function(rslt){
		if (rslt.Status.code == 200){
			this.usermarkers = rslt.Content;
			this.mapUserMarkers();
			this.loadFavoritesPanel();
		}else if (rslt.Status.code == 204){
			alert(this.strings[19]);
		}
	},
	
	"loadFavoritesPanel": function(){
		doSimpleXMLHttpRequest( "get_favs.php", {oe:this.oe}).addCallback( bind(this.loadFavoritesPanelCallback, this) ); 
	},
	
	"loadFavoritesPanelCallback": function(rslt){
		var elm = DIV();
		elm.innerHTML = rslt.responseText;
		replaceChildNodes( $('subwayfavs'), elm );
		setupAllTabs();
		var tabs = getElementsByTagAndClassName('h4','tab', elm);
		for (n in tabs){
			this.replaceTabClickHandler( tabs[n] );
		}
	},
	 
	"removeMenuRow": function(n){
		var id = this.usermarkers[n].marker_id;	
		var myrow = $('menu_'+n);
		myrow.parentNode.removeChild(myrow);
	},
		
	
	/* ===== AJAX Requests ===== */
	
	"expungeUserMarker": function(id){
		if (confirm(this.strings[20]+" \n\n"+this.strings[21])){
			var str = "edit_marker.php?marker_id=" + id + "&expunge_marker=true";
			doSimpleXMLHttpRequest(str).addCallback( bind(this.clearMarker, this), id ); 
		}
	},
		
	"clearMarker": function(id){
		var row = $('marker_'+id+'_row');
		row.parentNode.removeChild(row);
		var m = this.getUserMarkerDataById(id);
		this.map.closeInfoWindow();
		this.map.removeOverlay( m.marker );
		m.marker = null;
		this.markers[m.n] = null;
		m = null;
	},
	
	
	/******************
	 *  New Marker Location MARKER_ASSISTANT
	 ******************/
	"addAssistant": function(){
		if (this.MARKER_ASSISTANT != null){
			removeAssistant();
		}
		if ( confirm( this.strings[22]+" \n\n"+this.strings[23]+" \n\n"+this.strings[24] ) ){
		var ref = this;
		this.MARKER_ASSISTANT = GEvent.addListener(this.map, "click", function(overlay, point){
			if (point) {
				if (ref.TEMP_MARKER != null) {
					ref.map.closeInfoWindow();
					ref.map.removeOverlay(ref.TEMP_MARKER);
					ref.TEMP_MARKER = null;
				}
				ref.TEMP_MARKER = new GMarker(point);
				ref.map.addOverlay(ref.TEMP_MARKER);
				ref.map.panTo(point);
				ref.addToFav(null);
				//SUBWAYMAP.logError( "[" + point.y + "," + point.x + "]" );
			}
		});
		}
	},
	
		
	"removeAssistant": function(){
		if (this.MARKER_ASSISTANT != null){
			SUBWAYMAP.map.closeInfoWindow();
			SUBWAYMAP.map.removeOverlay(this.TEMP_MARKER);
			GEvent.removeListener(this.MARKER_ASSISTANT);
			this.MARKER_ASSISTANT = null;
		}
	}	
});

MochiKit.Base.update(BitSubway.Map.prototype, {
	"initGSearch": function(){
		var s = this.GSearch = new GlocalSearch();
		this.gsearchmarkers = [];
		this.gsearchnotice = $('gnoticedefault').innerHTML;
		s.setNoHtmlGeneration();
		s.setResultSetSize(GSearch.LARGE_RESULTSET);
		s.setSearchCompleteCallback(this, this.gSearchCallback);
	},

	"gSearchCallback": function(){
		var s = this.GSearch;
		//get results
		if (!s.results) return;
		if (s.results.length == 0) {
			replaceChildNodes( $('gnotice'), P(null, "No results found.") );
			return;
		}else{
			replaceChildNodes( $('gnotice'), P(null, this.gsearchnotice) );
		}

		// clear the map and the old search array
		var e = $("gsearch-pane");
		e.innerHTML = "";
		var aCur = this.gsearchmarkers;
		for (var i = 0; i < aCur.length; i++) {
			var m = aCur[i].marker;
			this.map.removeOverlay(m);
		}
		this.gsearchmarkers = s.results;

		// move the map to the first result
		var first = s.results[0];
		this.map.panTo(new GLatLng(parseFloat(first.lat), parseFloat(first.lng)));

		var rows = [];
		for (var i = 0; i < s.results.length && i<9; i++) {
			var r = s.results[i];
			// create a marker from the data
			var m = this.gsearchmarkers[i].marker = new GMarker(new GLatLng( parseFloat(r.lat),parseFloat(r.lng) ), this.ADDRESS_ICON );
			m.my_html = this.gSearchMakeHTML(r);
			// add marker to map
			this.map.addOverlay(m);
			m.plotted = 1;
			// add text to scrollpane
			var showFunc = this.handleEvent( 'gSearchOpenMarker', i );
			rows.push( TR({'id':'gsearch_'+n+'_row'}, 
							TD({'style':'padding-bottom:6px'}, H3(null, A({'href':'javascript:void(0);', 'onclick':showFunc}, r.titleNoFormatting)),
									SPAN(null, r.streetAddress, ", ", r.city, ", ", r.region)
							)));
		}
		var table = TABLE({'id':'gsearch-markers-list'}, TBODY(null, rows));
		replaceChildNodes( e, table );

		var a = s.getAttribution();
		if (a) {
			e.appendChild(a);
		}else{
			var gb = DIV({'id':'gbranding', 'style':'margin-top:10px'}, "powered by ", IMG({'style':'vertical-align:text-top','src':'http://www.google.com/uds/css/small-logo.png'}) );
			e.appendChild( gb );
		}
	},

	"gSearchSubmit": function() {
		var v = $("gsearch").value;
		if ( !this.GSearch ){
			this.initGSearch();
		}
		this.GSearch.setCenterPoint(this.map.getCenter());
		this.GSearch.execute(v);
		return false;
	},

	"gSearchClear": function() {
		//empty the search list div
	},

	"gSearchMakeHTML": function(o){
		var numbers = [];
		if(o.phoneNumbers) {
			var aN = o.phoneNumbers;
			for (var i=0; i < aN.length; i++){ 
				var sty = null;
				if(aN[i].type == "main") {
					sty = {"style":"bold"};
				}
				numbers.push( BR(), SPAN(sty, aN[i].number) );
			}
		}
		var e = DIV({'class':"display gmarker"},
						H2({'style':'margin-right:14px'}, o.titleNoFormatting),
						P(null, o.streetAddress, BR(), o.city, ", ", o.region, numbers),
						P(null, A({'href':'javascript:void(0);','onclick':'SUBWAYMAP.gSearchZoomIn('+o.lat+','+o.lng+')'}, "Zoom In") )
					);
		return e;
	},
	
	"gSearchOpenMarker": function(n){
		var m = this.gsearchmarkers[n].marker;
		m.openInfoWindowHtml(m.my_html);
	},
	
	"gSearchZoomIn": function(lat,lng){
		this.map.setCenter( new GLatLng( parseFloat(lat), parseFloat(lng) ), 16 );
	}

});

