//eval(function(p,a,c,k,e,r){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--)r[e(c)]=k[c]||e(c);k=[function(e){return r[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}('9 6x=18;U 4L(){9 P=V;V.4M=\'1.8.1\';V.3d=17;V.4N=17;V.2f=17;9 Q=[];V.1Z=17;V.2I=17;V.3e="";V.4O="6y";V.3f=[];V.4P=2;9 R=[];V.3J=17;V.4Q=14;9 S=3K;9 T=0;V.21=/21/i.2g(6z.6A);V.22=U(c){9 d;7(12 c==\'1w\')d={};W d=c;V.3g=U(){9 o={};9 a=[];15(9 b 1R d){7(12 o[b]==\'1w\')a.1i(b)}Y a};V.2r=U(a,b){d[a]=b};V.1q=U(a){Y d[a]};V.3h=U(a){3L d[a]};V.2s=U(){3L d;d={}}};V.2J=U(){Y"6B"+T++};U 1c(a){Y(12 a!="1w")}V.2K="1d-4R-4S";V.3i="1d-4R-4S";V.4T={"4U":"6C 15 {0} 6D 6E.","4V":"6F 6G.","4W":"3M 2t : U {0} 3N 4X 3O 1r {1}","4Y":"3M 2t :  3j 3N 4X: {0}","4Z":"<1J 13=\'2h:6H\'>3P 6I :</1J> : 50: {0} 6J {1}","1s":"<1J 13=\'2h:3Q\'>3M </1J> : 50: {0} 1t {1}","51":"3P 2t : 6K 3R 15 6L {0}.","52":"3P 2t : 1g 6M 2i 3R 15 {0}.","53":"1K 3k: 1b 3R.","54":"3S.1K 2t: {0}","55":"1K 3k 6N 56: {0}","57":"1K 3k 6O 1z 58 56 1E {0}.","3T":"1K 3k 6P 59 {0}. 6Q 6R 23 6S {1}.","5a":"6T 1E 5b a 1F 6U 6V 3N 6W 6X 5c 3l 59  1o {0}. 6Y 6Z 70 3l 1R 5d 19.","5e":"3m 1E 5f 3l 3U 15 {0}.","5g":"3m 1E 5f 71 3U 15 {0}.","5h":"3m 1E 72 5d 73 58 {0}. 74 75 15 2L 76.","3V":"3V","5i":"<1J>2t 77 {0} : 1o={1}<5j>78: {2} (79: {3}).<5j>7a: {4}</1J>","5k":"3S 3W","2s":"5l","3X":"[X]","5m":"5l 3W","5n":"7b 3W","2L":"[2L]","5o":"3S 7c : {0}","5p":"3m 1E 5c 7d {0}."};V.24=1h V.22();V.2M=1h V.22();V.2N=1h V.22();V.5q=U(a,b){P.24.2r(a,1h P.22(b))};P.5q(P.2K,P.4T);V.1e=U(a,b){9 c=1f;7(P.24.1q(P.3i)&&P.24.1q(P.3i).1q(a)){c=P.24.1q(P.3i).1q(a)}W 7(P.24.1q(P.2K)&&P.24.1q(P.2K).1q(a)){c=P.24.1q(P.2K).1q(a)}7(1c(b)){Y P.5r(c,b)}Y c};V.5r=U(a,b){15(9 i=0;1c(a)&&1c(b)&&i<b.11;i++){9 c=1h 2u("\\\\{"+i+"\\\\}","g");a=a.2v(c,b[i])}Y a};V.2w=1h V.22();U 1a(a){Y S.7e(a)}V.7f=U(a){15(9 b=0;P.1A&&b<P.1A.11;b++){7(P.1A[b].1o==a.1o){P.1A.7g(b,1);1S}}};U 5s(a,b){9 c=0;9 d=a.11;9 e=0;9 f=b.11;9 i=0;9 g=17;26(e+i<f){7(c+i<d){3Y(a.2x(c+i)){1G\'?\':{i++;3Z}1G\'*\':g=14;e+=i;c+=i;5t{++c;7(c==d)Y 14}26(a.2x(c)==\'*\');i=0;3Z}7(b.2x(e+i)!=a.2x(c+i)){7(!g)Y 17;e++;i=0;3Z}i++}W{7(!g)Y 17;e++;i=0}}5t{7(c+i==d)Y 14}26(a.2x(c+i++)==\'*\');Y 17}V.1s=U(a,b,c,d){7(!1c(a)||!1c(b))Y;7(P.3d){P.1x(1d.1e("1s",[a,P.2O(b)]))}7(P.1A){15(9 e=0;e<P.1A.11;e++){9 f=P.1A[e];7((f.1g 2j 2u&&f.1g.2g(a))||f.1g==a||(12 f.1g.2x==\'U\'&&5s(f.1g,a))){b.1g=a;7(P.3d){9 g=a;7(f.5u)g=f.5u;P.1x(1d.1e("4Z",[g,f]))}7(f.2k==\'1H\'&&f.1j){9 h;9 j=\'1w\';7(f.1j.27){h=P.28(f.1j.1r);7(12 h==\'U\'){j=1h h}W 7(h){j=h}W{P.1x(P.1e("4W",[f.1j.27,f.1j.1r]))}7(1c(j)&&12 j[f.1j.27]==\'U\'){j[f.1j.27].1H(18,b)}W{P.1x(P.1e("4Y",[f.1j.27,f.1j.1r]))}}W 7(f.1j.40){f.1j.40.1H(18,b)}}}W 7(P.1A[e].2k==\'7h\'){9 k=P.1A[e].2y;15(9 l=0;l<k.11;l++){7(k[l]!=a){P.1s(k[l],b)}}}}}9 m=14;7(1c(c))m=c;7(m&&18.2P&&18.2P.11>0){9 n=P.2M.3g();15(9 i=0;i<n.11;i++){9 o=P.2M.1q(n[i]);7(o.19&&!o.1T&&18.2P[o.1k+"1L"]&&18.2P[o.1k+"1L"].1d){18.2P[o.1k+"1L"].1d.1s("/5v"+a,b,14,17)}}}7(P.3J){9 p=14;7(1c(d))p=d;7(p&&18.5w.1d){18.5w.1d.1s("/5v"+a,b,17,14)}}};V.2Q=U(c,d,f,g){9 h=U(){7(j.3g().11==0){7(1c(d)){29(U(){d()},0)}3L j;P.3n=17;2l()}Y};9 i;9 j;9 k=14;7(c 2j 2R){i=c;j=f;k=g}W{i=c.2S;d=c.1M;j=c.5x;k=c.3o}7(!1c(j)&&(P.3n||P.3p)){j=1h P.22();7(!1c(P.2m)){P.2m=[]}P.2m.1i({2S:i,1M:d,3o:k});Y}W 7(!1c(j)){P.3n=14;j=1h P.22()}7(i.11<=0){h()}9 l=1h 5y().5z();9 m=i[i.11-1];9 n="7i"+P.2J();9 o=S.2n("2T")[0];9 e=S.1B("1F");e.7j=l;e.1o=n;o.1C(e);9 p=1a(n);j.2r(n,m);9 q=U(a){9 b=1a(a);7(b&&!(1c(k)&&k==17))b.1U.41(b);j.3h(a);7(i.11-1>0){i.42();P.2Q({2S:i,1M:d,5x:j,3o:k})}h()};7(P.21){p.3q=U(){7(V.3r==\'1Z\'){9 a=n;q(a)}};1a(n).1N=m}W{p.2U=U(){9 a=n;q(a)};29(U(){1a(n).1N=m},0)}};V.5A=U(){7(18.5B&&!(P.21&&12(P.1m.5C)=="2V"&&P.1m.5C==14)){Y 1h 5B()}W 7(18.5D){Y 1h 5D("7k.7l")}W Y 1f};U 2z(a,b,c){7(c.1V){c.1V(a,b)}W{P.1x(P.1e("54",[a]))}}U 2l(){7(P.2W&&P.2W.11>0){P.1K(P.2W.42())}W{P.3p=17;7(P.2m&&P.2m.11>0){9 a=P.2m[0];P.2m.5E();P.2Q(a)}}}V.1K=U(a){7(12 a==\'1w\'||!a.1b){P.1x(P.1e("53"));Y}7((P.3n&&a.2o)||(P.3p&&a.2o)){7(!P.7m)P.2W=[];P.2W.1i(a);Y}P.3p=14;9 b=V.5A();9 c="43";9 d=14;9 f;9 g=17;7(a.2a){29(U(){7(g==17){g=14;7(b.5F)b.5F();2z(P.1e("4U",[a.1b]),b,a);2l();Y}},a.2a)}7(1c(a.2o)){d=a.2o}7(a.2A){c=a.2A}7(12 a.1M==\'U\'){f=a.1M}9 h=1f;7(a.1z){h=a.1z}W 7(a.2b){h="";15(9 l 1R a.2b){h=h+l+"="+7n(a.2b[l])+"&"}}7(d==14&&g==17){b.3q=U(){7(b.3r==4&&g==17){g=14;7((b.23==44||b.23==0)&&f){f(b)}W 7(b.23!=44){g=14;2z(P.1e("3T",[a.1b,b.23]),b,a)}2l();Y}}}2X{7(!g)b.7o(c,a.1b,d)}2Y(e){g=14;2z(P.1e("55",[a.1b]),b,a);2l();Y}7(a.2Z&&a.2Z.11>0){15(9 i=0;i<a.2Z.11;i++){b.45(a.2Z[i].30,a.2Z[i].1D)}}7(a.2A){c=a.2A;7(c.7p()==\'7q\'){7(!a.46)b.45("5G-5H","7r/x-7s-7t-7u")}}7(a.46){b.45("5G-5H",a.46)}2X{7(g==17)b.7v(h)}2Y(e){g=14;2z(P.1e("57",[a.1b]),b,a);2l();Y}7(g==17&&d==17){g=14;7(b.23==44||b.23==0){7(f)f(b)}W{g=14;2z(P.1e("3T",[a.1b,b.23]),b,a)}2l();Y}};V.7w=U(a,b){9 c=[];c.1i(a);Y P.2Q({2S:c,1M:b})};V.7x=U(a){Q.1i(a);7(V.1Z){V.47(a)}};V.7y=U(a){P.3f.1i(a)};V.7z=U(a){Y P.2N.1q(a)};V.48=U(){P.1Z=14;15(9 l=0;l<Q.11;l++){P.47(Q[l])}};V.5I=U(){15(9 l=0;l<P.3f.11;l++){P.5J(P.3f[l])}};V.7A=U(a,b){7(P.1Z==14){7(1a(b)){1a(b).1p=P.1e("5a",[b])}}W{S.5b("<1F 1N=\'"+a+"\'></1F>")}};V.5K=U(a){9 b=S.1B("31");b.2c="1O/49";b.5L="5M";7(a[0]==\'/\')a=P.3e+a;b.1P=a;7(S.2n(\'2T\').11==0){9 c=S.1B("2T");S.5N.7B(c,S.5N.7C)}S.2n(\'2T\')[0].1C(b)};V.7D=U(a,b,c){9 d=V.5O(b,a);15(9 i=0;i<d.11;i++){7(d[i].1W.1l(\' \')!=-1){9 e=d[i].1W.2p(\' \');15(9 f 1R e){7(e[f]==b){e[f]=c}}d[i].1W=e.2B(\' \')}W 7(d[i].1W==b){d[i].1W=c}}};V.5O=U(a,b){9 c=[];7(1c(b)){9 d=b;7(12 b==\'1u\'){d=1a(b)}c=V.3s(d,[])}W{c=(S.4a)?S.4a:S.2n("*")}9 e=[];15(9 i=0;i<c.11;i++){7(c[i].1W.1l(\' \')!=-1){9 f=c[i].1W.2p(\' \');15(9 g=0;g<f.11;g++){7(f[g]==a){e.1i(c[i])}}}W 7(c[i].1W==a){e.1i(c[i])}}Y e};V.3s=U(a,b){9 c=a.5P;15(9 l=0;c&&l<c.11;l++){7(c[l].7E==1){b.1i(c[l]);7(c[l].5P.11>0){V.3s(c[l],b)}}}Y b};V.5J=U(a){7(P.2N.1q(a))Y;9 b="1d.2N."+a.30+".7F";9 c=P.28(b);7(12 c!="U"){P.1x(P.1e("5g",[b]))}W{9 d=1h c(a);7(d.3t)d.3t.1H(18);P.2N.2r(a.30,d)}};V.47=U(f){7(P.2w.1q(f.1k)!=1f){Y 1f}9 g="1d.5Q."+f.30+".7G";9 h=P.28(g);7(12 h!="U"){3u(P.1e("5e",[g]),1a(f.1k));Y 1f}9 i;7((12 f.1D==\'1u\')&&f.1D.1l("@{")==0){9 j=/[^@{].*[^}]/.5R(f.1D);f.1D=P.28(1h 32(j))}9 k=f.1k;7(P.21){9 l=1f;7(18.1V){l=18.1V}9 m=U(a,b,c){9 d=k;4b(g,d,b,c,a,1a(d))};18.1V=m;i=1h h(f);18.1V=1f;7(l){18.1V=l}}W 7(12 h==\'U\'){2X{i=1h h(f)}2Y(e){9 n=P.1e("3V");9 o=1f;7(e.5S)n=e.5S;7(e.1t)o=e.1t;7(P.2f){4b(g,f.1k,f.1F,n,o,1a(f.1k));Y 1f}}}7(12 i==\'1r\'){P.2w.2r(f.1k,i);7(i.3t)i.3t.1H(18);7(f.1X&&f.1X.1i){15(9 p=0;p<f.1X.11;p++){9 q=f.1X[p].1g;9 r=f.1X[p].7H;9 s=1f;7(12 r==\'1u\'&&r.1l("@{")==0){9 t=/[^@{].*[^}]/.5R(r);s=P.28(1h 32(t))}W 7(i[r]){s=i[r]}7(s!=1f)P.1X(f.1X[p].1g,s)}}P.1s("/1d/33/3l/1Z",{1o:f.1k});Y i}W{3u(P.1e("5h",[g]),1a(f.1k))}Y 1f};U 4b(a,b,c,d,e,f){9 g=P.1e("5i",[a,b,c,d,e]);3u(g,f)}U 3u(a,b){7(P.4Q){7(!1c(b)||!b)b=S.1B("1n");b.1W="";b.13.2h="3Q";S.1z.1C(b);b.1p=a}W{P.1x(a)}}V.5T=U(a){Y P.2w.1q(a)};V.3v=U(a){7(!1c(a)){9 b=P.2w.3g();15(9 l=0;l<b.11;l++){P.4c(b[l])}P.1Z=17;Q=[]}W{9 c=P.3s(a,[]);15(9 d=0;d<c.11;d++){7(c[d].1o)P.4c(c[d].1o)}}};V.4c=U(a){9 b=P.5T(a);7(b){7(12 b.4d==\'U\'){b.4d()}9 c=1a(a);7(1f!=c)c.1U.41(c)}P.2w.3h(a)};V.2O=U(a,b,c){9 d=P.4P;9 f=0;7(12 b=="3w"){d=b}7(12 c!="1w"){f=c}7(f>=d&&d!=-1){7(12 a=="1u"){Y"\'"+a+"\'"}W Y a}W{f++}9 g=[];7(12 a=="1w")Y\'1w\';7(a 2j 2R){15(9 i=0;i<a.11;i++){g.1i(P.2O(a[i],d,f))}Y"["+g.2B(" , ")+"]"}W 7(12 a=="1u"){Y"\'"+a+"\'"}W 7(12 a=="3w"||12 a=="2V"){Y a}W 7(12 a=="1r"){15(9 h 1R a){2X{7(12 a[h]!="U")g.1i(h+" : "+P.2O(a[h],d,f))}2Y(e){}}7(g.11>0){Y"{"+g.2B(" , ")+"}"}W Y"{}"}W Y a};V.1X=U(l,t){7(!1c(l))Y 1f;9 a;7(12 l==\'1r\'&&!(l 2j 2u)){7(l.1g)l.1g=P.4e(l.1g);7(l.2i)l.1g=1h 2u(l.2i);a=l}W 7(12 t==\'1u\'){a={};7(l.2i)a.1g=1h 2u(l.2i);W a.1g=l;a.1j={};9 b=t.2p(\'.\');a.2k="1H";a.1j.27=b.42();a.1j.1r=b.2B(\'.\')}W 7(12 t==\'U\'){a={};7(l.2i)a.1g=1h 2u(l.2i);W a.1g=l;a.1j={};a.2k="1H";a.1j.40=t}W{P.1x(1d.1e("51",[l]))}7(1c(a)){7(!1c(P.1A))P.1A=[];7(!a.1o)a.1o=P.2J();7(a.1g){a.4f=U(){Y P.2O(V)};P.1A.1i(a)}W{P.1x(1d.1e("52",[l]));Y 1f}Y a}Y 1f};V.4e=U(t){Y t.2v(/^\\s+|\\s+$/g,"")};V.7I=U(a,b){a.2C=1h b();a.2C.3U=a;a.7J=b.2C;15(i 1R a.2C){a[i]=a.2C[i]}};V.5U=U(){9 a=1a("4g");7(a)a.13.5V=\'4h\'};V.5W=U(){9 b=1a("4i");7(b)b.1p=""};V.1x=U(a,c){7(!P.2I){7(!P.2D)P.2D=[];P.2D.1i({1O:a,5X:c});Y}7(!P.2f)Y;9 d=1a("4g");9 b=1a("4i");7(!d){d=S.1B("1n");d.1o=\'4g\';d.13.7K="7L 7M #7N";d.13.7O="5Y";d.13.7P="7Q";d.13.7R="7S";d.13.7T="4j";d.13.4k="#7U";d.13.5Z="4j";d.13.1Y="7V";d.13.1I="7W";9 e="<1n  13=\'1I: 7X; 4k : 7Y; 2h : 4l; 7Z-80 : 81\'>"+"<1n 13=\'4m:3x;1Y:82;1O-60:83\'>"+P.1e("5k")+"</1n><1n 13=\'5Z:4j,1O-60:3x\'><a 1P=\'34:1d.5W()\' 61=\'"+P.1e("5m")+"\' 13=\'2h:4l;1O-4n:2E\'>["+P.1e("2s")+"]</a> <a 1P=\'34:1d.5U()\' 61=\'"+P.1e("5n")+"\' 13=\'2h:4l;1O-4n:2E\'>"+P.1e("3X")+"</a></1n></1n>";9 f=S.1B("1n");f.1p=e;d.1C(f);b=S.1B("1n");b.1o=\'4i\';b.13.1I="84";b.13.3y="85";d.1C(b);7(S.1z){S.1z.1C(d)}}7(d&&P.1Z)d.13.5V=\'86\';9 g=S.1B("1n");g.13.2s="87";7(a&&a.11>88&&P.4N==17){9 h=P.2J();9 i=S.1B("1n");i.1p="<1n 13=\'4m:3x;1Y:89;1I:5Y;35:4h\'>"+a.1v(0,8a)+"</1n><1n 13=\'4m:3x\'>...&62;</1n><a 1o=\'"+h+"4o\' 1P=\\"34:1d.4p(\\\'"+h+"\\\')\\" 13=\'1O-4n: 2E\'><1J 1o=\'"+h+"4q\'>"+P.1e("2L")+"</1J></a>";9 j=S.1B("1n");j.1o=h;j.1p=a;j.13.8b="8c";j.13.4k="#8d";j.13.36="2E";g.1C(i);g.1C(j)}W g.1p=a;7(b)b.1C(g)};V.4p=U(a){9 n=1a(a);7(n&&n.13){n.13.36="8e";9 h=1a(a+"4o");h.1P="34:1d.63(\'"+a+"\')";9 l=1a(a+"4q");l.1p="&62;"+P.1e("3X")}};V.63=U(a){9 n=1a(a);7(n&&n.13){n.13.36="2E";9 h=1a(a+"4o");h.1P="34:1d.4p(\'"+a+"\')";9 l=1a(a+"4q");l.1p=P.1e("2L")}};V.64=U(){7(!P.1m){P.1m={};P.1K({1b:V.3e+V.4O+"/1m.65",2o:17,2a:8f,1V:U(){},1M:U(a){7(a.3z!=\'\'){9 b=4r(\'(\'+a.3z+\')\');7(b.1m){P.1m=b.1m}}}})}66()};V.8g=U(a,b){9 c=a.2p(\'.\');9 d=18[c[0]];7(!1c(d))18[c[0]]=d={};15(9 e=1;e<c.11;e++){7(1c(d[c[e]])){d=d[c[e]]}W{d[c[e]]={};d=d[c[e]]}}7(12 b==\'1r\'){d=b}Y d};P.65=U(){U f(n){Y n<10?\'0\'+n:n}9 m={\'\\b\':\'\\\\b\',\'\\t\':\'\\\\t\',\'\\n\':\'\\\\n\',\'\\f\':\'\\\\f\',\'\\r\':\'\\\\r\',\'"\':\'\\\\"\',\'\\\\\':\'\\\\\\\\\'};U 2d(b,d){9 a,i,k,l,r=/["\\\\\\8h-\\8i\\8j-\\8k]/g,v;3Y(12 b){1G\'1u\':Y r.2g(b)?\'"\'+b.2v(r,U(a){9 c=m[a];7(c){Y c}c=a.8l();Y\'\\\\8m\'+8n.8o(c/16).4f(16)+(c%16).4f(16)})+\'"\':\'"\'+b+\'"\';1G\'3w\':Y 8p(b)?32(b):\'1f\';1G\'2V\':Y 32(b);1G\'1f\':Y 32(b);1G\'8q\':{Y b.8r()+\'-\'+f(b.8s()+1)+\'-\'+f(b.8t())+\'T\'+f(b.8u())+\':\'+f(b.8v())+\':\'+f(b.8w())+\'Z\'}1G\'1r\':7(!b){Y\'1f\'}7(12 b.67===\'U\'){Y 2d(b.67())}a=[];7(12 b.11===\'3w\'&&!(b.8x(\'11\'))){l=b.11;15(i=0;i<l;i+=1){a.1i(2d(b[i],d)||\'1f\')}Y\'[\'+a.2B(\',\')+\']\'}7(d){l=d.11;15(i=0;i<l;i+=1){k=d[i];7(12 k===\'1u\'){v=2d(b[k],d);7(v){a.1i(2d(k)+\':\'+v)}}}}W{15(k 1R b){7(12 k===\'1u\'){v=2d(b[k],d);7(v){a.1i(2d(k)+\':\'+v)}}}}Y\'{\'+a.2B(\',\')+\'}\'}}Y{8y:2d,8z:U(a,b){9 j;a=P.4e(a);U 4s(k,v){9 i,n;7(v&&12 v===\'1r\'){15(i 1R v){7(3j.2C.8A.8B(v,[i])){n=4s(i,v[i]);7(n!==1w){v[i]=n}}}}Y b(k,v)}7(/^[\\],:{}\\s]*$/.2g(a.2v(/\\\\./g,\'@\').2v(/"[^"\\\\\\n\\r]*"|14|17|1f|-?\\d+(?:\\.\\d*)?(:?[8C][+\\-]?\\d+)?/g,\']\').2v(/(?:^|:|,)(?:\\s*\\[)+/g,\'\'))){j=4r(\'(\'+a+\')\');Y 12 b===\'U\'?4s(\'\',j):j}8D 1d.1e(\'4V\');}}}();V.28=U(a){9 b=a.2p(\'.\');9 c=17;9 d=18[b[0]];7(d&&b.11==1)c=14;7(1c(d)){15(9 e=1;e<b.11;e++){9 f=b[e];7(f.1l(\'()\')!=-1){9 g=f.2p(\'()\');7(12 d[g[0]]==\'U\'){9 h=d[g[0]];Y h.1H(18)}}7(1c(d[f])){d=d[f];c=14}W{c=17;1S}}7(c){Y d}}Y 1f};V.4t=U(b,c){9 d=V;V.8E=b;9 e;V.68=U(){15(9 a=0;a<b.2y.11;a++){P.1s(b.2y[a],{1g:b.2y[a],2c:\'69\',1N:d,2a:b.1E})}};V.6a=U(){7(!e){9 a=P.28(b.3O);7(12 a==\'U\'){e=1h a()}W 7(12 a==\'1r\'){e=a}}7((e&&12 e==\'1r\')){7(12 e[b.4u]==\'U\'){e[b.4u]({2c:\'69\',1N:d,2a:b.1E})}}};V.3A=U(){7(c){d.6a()}W{d.68()}18.29(d.3A,b.1E)}};V.8F=U(a){9 b=[];b.1i(a);V.4v(b)};V.4v=U(a){7(1c(a)){15(9 b=0;b<a.11;b++){9 c=a[b];7(c.2k==\'1H\'&&1c(c.1j)&&1c(c.1j.1r)&&1c(c.1j.27)&&1c(c.2a)){9 d={3O:c.1j.1r,4u:c.1j.27,1E:c.2a};9 e=1h P.4t(d,14);R.1i(e);e.3A()}W 7(a[b].2k==\'1s\'){9 f={2y:a[b].2y,1E:c.2a};9 g=1h P.4t(f,17);R.1i(g);g.3A()}}}};U 66(){7(P.2I)Y;W P.2I=14;7(P.1m.6b){3Y(P.1m.6b){1G\'2f\':{P.2f=14;P.1x(P.1e("5o",[P.4M]));1S}1G\'4a\':{P.2f=14;P.3d=14;1S}1G\'8G\':{P.2f=17;1S}}}7(P.1m.37){7(P.1m.37.6c){P.4v(P.1m.37.6c)}7(P.1m.8H){15(9 a=0;a<P.1m.37.6d.11;a++){P.1X(P.1m.37.6d[a])}}}7(P.2D){15(9 i=0;i<P.2D.11;i++){9 b=P.2D[i];P.1x(b.1O,b.5X)}}P.1s("/1d/33/8I",{});P.5I();P.1s("/1d/33/8J",{});P.48();P.1s("/1d/33/8K",{});7(P.1m&&P.1m.6e){9 c=P.1m.6e;7(!/(^4w)/i.2g(c))c=P.3e+c;P.5K(c)}P.1s("/1d/33/8L",{})}V.8M=U(a,b){7(12 b==\'1u\'){9 h=P.28(b);Y h.1H(18,a)}W 7(12 b==\'U\'){Y b.1H(18,a)}Y 1f};V.3B=U(t){9 a;7(t 2j 2R){a=1h 2R();15(9 b=0;b<t.11;b++){a.1i(P.3B(t[b]))}}W 7(t 2j 3j){a=1h 3j();15(9 c 1R t){a[c]=P.3B(t[c])}}W{a=t}Y a};V.8N=U(a){7(a){9 b=a.1g;9 c={6f:a.6f,2c:a.2c,6g:a.6g};7(12 a.1D!="1w")c.1D=a.1D;9 d=a.2k;7(!d)b=b+"/"+a.2c;7(d&&d 2j 2R){15(9 e=0;e<d.11;e++){9 f=P.3B(c);7(d[e].1g)f.1g=d[e].1g;W f.1g=a.1g;7(d[e].1t)f.1t=d[e].1t;1d.1s(f.1g,f)}}W{7(d&&d.1g){b=c.1g=d.1g}7(d&&d.1t)c.1t=d.1t;1d.1s(b,c)}}};V.6h=U(a){9 b=0;9 c=0;7(a.4x){26(14){c+=a.8O;b+=a.8P;7(a.4x==1f){1S}a=a.4x}}W 7(a.y){c+=a.y;b+=a.x}Y{x:b,y:c}};V.6i=U(n,a){7(12 n==\'1w\'||n==1f)Y 1f;9 b=0;7(12 a!=\'1w\')b=a;9 c=n.1U;26(c&&14){7(c.3C>b)1S;7(c.1U&&c.1U.3C)c=c.1U;W 1S}7(!c)Y 1f;Y{h:c.3C,w:c.2F}};V.8Q=U(e){9 f=V;9 g;7(12 e.1j==\'1u\'){V.1k=e.1j;g=1a(V.1k)}W{V.1k=e.1j.1o;g=e.1j}7(!V.1k)V.1k=P.2J();P.2M.2r(f.1k,V);9 h;V.1b=1f;V.1T=17;9 i=17;9 j=17;7(e.8R){i=14;j=14}7(12 e.4y==\'2V\'){4y=e.4y}7(12 e.6j==\'2V\'){j=e.6j}9 k;9 l;U 4z(a){9 b="";9 c=a.2p("://");7(c[1]){7(c[1].1l("/")!=-1){b=c[1].1v(0,c[1].1l("/"))}W{b=c[1]}}Y b}V.2s=U(){7(e.2G){7(f.19){f.3D("")}W{e.1b=""}}W{P.3v(g);g.1p=""}};V.3D=U(b){7(f.19){f.1T=14}7(b.1t)b=b.1t;7(12 b==\'1u\'){f.1b=b}W 7(b.1b){f.1b=b.1b}W 7(b.1D){f.1b=b.1D}U 38(){7(/4w/i.2g(f.1b)&&6k.18.6l.6m!=4z(f.1b)){f.1T=14}W{f.1T=17}7(!f.1T){9 a=f.19.3E?f.19.3E:f.19.18;7(a&&a.1d){a.1d.3J=14}}}7(e.2G){7(!f.19){9 c=3F(U(){7(1a(f.1k+"1L")){3G(c);f.19=1a(f.1k+"1L");7(P.21){f.19.3q=U(){7(V.3r==\'6n\')38()}}W{f.19.2U=38}f.19.1N=f.1b;3H()}},5)}W{7(P.21){f.19.3q=U(){7(V.3r==\'6n\')38()}}W{f.19.2U=38}f.19.1N=f.1b}}W{P.6o.39({1b:f.1b,1Q:g})}};V.8S=U(a){7(a.w){k=a.w;g.13.1Y=k+"1y";7(f.19)f.19.13.1Y=k-2+"1y"}7(a.h){l=a.h;g.13.1I=l+"1y";7(f.19)f.19.13.1I=l-2+"1y"}};V.2H=U(){9 a=P.6i(g);7(i||j){7(!g.1U)Y;9 b=P.6h(g);7(g.1U.8T=="8U"){7(18.6p){7(i)l=18.6p-b.y;7(j)k=18.8V-20}W{7(a==1f){7(j)k=6q}W{7(j)k=a.w-20;7(i)l=a.h-b.y}}}W{7(a==1f){7(j)k=6q}W{7(j)k=a.w;7(i)l=a.h}}7(i){7(l<0)l=4A;g.13.1I=l+"1y"}7(j){g.13.1Y=k+"1y"}}W{g.13.1Y=k+"1y";g.13.1I=l+"1y"}7(l<0){l=4A}7(k<0){k=4B}7(e.2G){7(f.19){f.19.13.1I=l-2+"1y";f.19.13.1Y=k-2+"1y"}}h=S.1z.2F};V.8W=U(a){9 b;7(a.1t)a=a.1t;7(a.1D)b=a.1D;W b=a;7(!f.19)g.1p=b;W{f.2s();g.1p="";4C(a)}};U 3H(){7(18.4D){18.4D(\'6r\',2q)}W 7(18.4E){18.4E(\'2H\',2q,14)}9 a=g;7(f.19){a=f.19}7(e.35)a.13.35=e.35;7(e.4F)a.13.4F=e.4F;7(e.3y)a.13.3y=e.3y;7(e.6s){k=6t(e.6s);g.13.1Y=k+"1y"}W{k=g.2F;j=14}7(e.6u){l=6t(e.6u)}W{l=g.3C;i=14}7(l<=0)l=4A;g.13.1I=l+"1y";7(e.8X&&f.19){f.19.13.1I=l+"1y"}f.2H();7(e.1b&&!e.2G){f.3D(e.1b)}W 7(e.2b&&!f.19){g.1p=e.2b}W 7(e.1b&&!e.1b){f.3D(e.1b)}7(f.19)f.19.13.36="8Y"}9 m=17;9 n=0;U 4C(b){f.19=1a(f.1k+"1L");7(f.19)f.19.1U.41(f.19);9 c="<19 13=\'36:2E\' 1o=\'"+f.1k+"1L\' 30=\'"+f.1k+"1L\' 8Z=0 90="+((e.35==\'4h\')?\'91\':\'92\')+"></19>";g.1p=c;9 d=3F(U(){7(1a(f.1k+"1L")){3G(d);f.19=1a(f.1k+"1L");29(U(){7(/4w/i.2g(f.1b)&&6k.18.6l.6m!=4z(f.1b)){f.1T=14}W{f.1T=17}7(!f.1T&&b){9 a=f.19.3E?f.19.3E:f.19.18;7(a&&a.3K.1z){a.3K.1z.1p=b}}3H()},0)}},5)}U 2q(){7(!P.21){f.2H();Y}7(h!=S.1z.2F&&!m){7(!m){m=14;29(2q,4B)}}W 7(m&&S.1z.2F==n){m=17;f.2H()}W 7(m){n=S.1z.2F;29(2q,4B)}}7(e.2G&&e.2G==14){4C(e.2b)}W 3H()};V.4d=U(){P.2M.3h(93.1k);7(18.4D){18.94(\'6r\',2q)}W 7(18.4E){18.95(\'2H\',2q,14)}};V.6v=U(){9 L=1h 5y().5z();9 M=V;9 N=17;9 O=[];V.39=U(a){7(O.11==0&&!N){39(a)}W{O.1i(a)}};U 39(d){N=14;P.1K({2A:"43",1b:d.1b,2o:17,1M:U(a){4G(a.3z,d);9 b;7(12 d.1Q==\'1u\'){b=1a(d.1Q);7(!1a(d.1Q)){9 c=3F(U(){7(1a(d.1Q)){3G(c);b=1a(d.1Q);29(U(){3I(b,d)},0)}},25)}W{3I(b,d)}}W{3I(d.1Q,d)}},1V:U(){9 a=d.1Q;7(12 d.1Q==\'1u\'){a=1a(d.1Q)}P.3v(a);a.1p=P.1e("5p",[d.1b]);4H()}})}U 3I(a,b){P.3v(a);9 c="96"+L;9 d=b.2b+"<1n 1o=\'"+c+"\'></1n>";a.1p=d;9 f=3F(U(){7(1a(c)){3G(f);2X{M.6w(b,4H)}2Y(e){a.1p="<1J 13=\'2h:3Q\'>"+e.1t+"</1J>"}}},25)}U 4H(){7(O.11>0){9 a=O.5E();39(a)}N=17}V.1q=U(p){9 b;P.1K({2A:"43",1b:p.1b,2o:17,1M:U(a){b=4G(a.3z)}});Y b};U 4G(a,b){b.2e=[];b.3a=[];b.3b=[];b.3c=[];9 c=a;9 d=S.2n("1F");9 e=S.2n("31");26(c.1l("<1F")!=-1){9 f=c.1l("<1F");9 g=c.1l("1N=",(f));9 h=c.1l(">",f);9 k=c.1l("</1F>",(f))+"</1F>".11;7(f!=-1&&g!=-1){9 l;9 m=g+5;9 n=c.1v(g+4,(g+5));9 o=c.1l("\\"",(m+1));o=c.1l(n,(m+1));7(g<h){l=c.1v(m,o);9 p=17;15(9 i=0;i<d.11;i++){7(12 d[i].1N){7(d[i].1N==l){p=14;1S}}}7(!p){b.3b.1i(l)}}}9 q=h+1;9 r=c.1v(q,k-"</1F>".11);7(r.11>0){b.2e.1i(r)}c=c.1v(0,f)+c.1v(k,c.11);o=-1}26(c.1l("<13")!=-1){9 s=c.1l("<13");9 t=c.1l(">",s);9 u=c.1l("</13>",s);9 v=t+1;9 w=c.1v(v,u);7(w.11>0){b.3a.1i(w)}c=c.1v(0,s)+c.1v(u+"</13>".11,c.11)}26(c.1l("<31")!=-1){9 x=c.1l("<31");9 y=c.1l("1P=",x);9 z=c.1l(">",x)+1;7(x!=-1&&y!=-1){9 A;9 B=y+6;9 C=c.1v(y+5,(y+6));9 D=c.1l(C,(B+1));7(y<z){A=c.1v(B,D);9 E=17;15(9 F=0;F<e.11;F++){7(1c(e[F].1P)){7(e[F].1P==A){E=14}}}7(!E){b.3c.1i(A)}}c=c.1v(0,x)+c.1v(z,c.11)}}9 G=S.2n("2T")[0];15(9 H=0;b.3c&&H<b.3c.11;H++){9 I=S.1B("31");I.1P=b.3c[H];I.2c="1O/49";I.5L="5M";G.1C(I)}9 J;7(b.3a.11>0){J=S.1B("13");J.2c="1O/49";9 K;15(9 j=0;j<b.3a.11;j++){K=K+b.3a[j]}7(S.4I[0].4J){S.4I[0].4J=S.4I[0].4J+K}W{J.1C(S.97(K));G.1C(J)}}b.2b=c}V.6w=U(c,d){9 e=U(){15(9 a=0;c.2e&&a<c.2e.11;a++){9 b=c.2e[a];4r(b);7(a==(c.2e.11-1)){7(1c(d))d();Y}}7(c.2e&&c.2e.11==0&&1c(d))d()};7(c.3b&&c.3b.11>0){Y P.2Q({2S:c.3b.98(),1M:e,3o:17})}W{e()}Y 14}};V.6o=1h V.6v()}7(12 1d==\'1w\'){9 1d=1h 4L();1d.5Q={};9 4K=18.2U;18.2U=U(){7(!1d.2I){1d.64()}W{1d.48();Y}7(12 4K==\'U\'){4K()}}}',62,567,'|||||||if||var|||||||||||||||||||||||||||||||||||||||||||||||function|this|else||return|||length|typeof|style|true|for||false|window|iframe|getElement|url|isDefined|jmaki|getMessage|null|topic|new|push|target|uuid|indexOf|config|div|id|innerHTML|get|object|publish|message|string|substring|undefined|log|px|body|subs|createElement|appendChild|value|to|script|case|call|height|span|doAjax|_iframe|callback|src|text|href|injectionPoint|in|break|externalDomain|parentNode|onerror|className|subscribe|width|loaded||MSIE|Map|status|messages||while|functionName|findObject|setTimeout|timeout|content|type|stringify|embeddedScripts|debug|test|color|topicRegExp|instanceof|action|updateAjaxQueue|_scriptQueue|getElementsByTagName|asynchronous|split|layout|put|clear|Error|RegExp|replace|attributes|charAt|topics|handleAjaxError|method|join|prototype|_messages|none|clientWidth|useIframe|resize|initialized|genId|defaultLocale|more|dcontainers|extensions|inspect|frames|addLibraries|Array|libs|head|onload|boolean|ajaxRequestQueue|try|catch|headers|name|link|String|runtime|javascript|overflow|display|glue|enableEvents|inject|embeddedStyles|scriptReferences|styleReferences|debugGlue|webRoot|preextensions|keys|remove|locale|Object|error|widget|Unable|processingScripts|cleanup|processingAjax|onreadystatechange|readyState|getAllChildren|postLoad|logError|clearWidgets|number|left|overflowY|responseText|run|clone|clientHeight|loadURL|contentWindow|setInterval|clearInterval|init|processTask|publishToParent|document|delete|Publish|not|on|Subscribe|red|required|jMaki|ajax_server_error|constructor|unknown|Logger|x_close|switch|continue|functionHandler|removeChild|pop|GET|200|setRequestHeader|contentType|loadWidget|bootstrapWidgets|css|all|logWidgetError|removeWidget|destroy|trim|toString|jmakiLogger|hidden|jmakiLoggerContent|0px|background|white|float|decoration|_href|showLogMessage|_link|eval|walk|Timer|fn|addTimers|http|offsetParent|autosizeH|getHost|320|500|createIframe|attachEvent|addEventListener|overflowX|getContent|processNextTask|styleSheets|cssText|oldLoad|Jmaki|version|verboseDebug|resourcesRoot|inspectDepth|displayErrorsInline|en|us|defaultMessages|request_timeout|invalid_json|publish_function_not_found|found|publish_object_not_found|publish_match|Topic|subscribe_handler_required|subscribe_topic_required|ajax_url_required|ajax_error|ajax_request_open_error|request|ajax_send_body_error|of|with|write_dynamic_script_error|write|load|an|widget_constructor_not_found|find|extension_constructor_not_found|widget_instantiation_error|widget_error|br|jmaki_logger|Clear|clear_logger|hide_logger|jmaki_version|unable_to_load_url|addMessages|messageFormat|matchWildcard|do|topicString|global|parent|inprocess|Date|getMilliseconds|getXHR|XMLHttpRequest|forceActiveXXHR|ActiveXObject|shift|abort|Content|Type|loadExtensions|loadExtension|loadStyle|rel|stylesheet|documentElement|getElementsByStyle|childNodes|widgets|exec|lineNumber|getWidget|hideLogger|visibility|clearLogger|level|12px|right|align|title|nbsp|hideLogMessage|initialize|json|postInitialize|toJSON|processTopic|timer|processCall|logLevel|timers|listeners|theme|widgetId|targetId|getPosition|getDimensions|autosizeW|top|location|host|complete|injector|innerHeight|400|onresize|startWidth|Number|startHeight|Injector|loadScripts|_globalScope|resources|navigator|userAgent|jmk_|Request|timed|out|Invalid|JSON|green|Match|listener|Handler|subscriber|or|making|sending|communicating|Server|returned|code|Attempt|that|can|be|dynamically|Consider|using|the|extension|create|instance|Enable|logging|details|loading|Script|line|Message|Hide|Version|URL|getElementById|unsubscribe|splice|forward|c_script_|start|Microsoft|XMLHTTP|ajaxRequetQueue|encodeURIComponent|open|toLowerCase|post|application|www|form|urlencoded|send|addLibrary|addWidget|addExtension|getExtension|writeScript|insertBefore|firstChild|replaceStyleClass|nodeType|Extension|Widget|handler|extend|superclass|border|1px|solid|000000|fontSize|position|absolute|zIndex|999|bottom|FFFF00|600px|300px|14px|black|font|size|10px|545px|center|286px|auto|visible|both|125|535px|135|margin|5px|FF9900|block|3000|namespace|x00|x1f|x7f|x9f|charCodeAt|u00|Math|floor|isFinite|date|getUTCFullYear|getUTCMonth|getUTCDate|getUTCHours|getUTCMinutes|getUTCSeconds|propertyIsEnumerable|serialize|deserialize|hasOwnProperty|apply|eE|throw|args|addTimer|off|gluelisteners|intialized|extensionsLoaded|widgetsLoaded|loadComplete|filter|processActions|offsetTop|offsetLeft|DContainer|autosize|setSize|nodeName|BODY|innerWidth|setContent|useIFrame|inline|frameborder|scrolling|NO|YES|_self|dettachEvent|removeEventListener|injector_|createTextNode|reverse'.split('|'),0,{}))

var _globalScope = window;

function Jmaki() {

    var _jmaki = this;
    this.version = '1.8.1';
    this.debugGlue = false;
    this.verboseDebug = false;
    this.debug = false;
    var widgets = [];
    this.loaded = false;
    this.initialized = false;
    this.webRoot = "";
    this.resourcesRoot = "resources";
    this.preextensions = [];
    this.inspectDepth = 2;
    var timers = [];
    this.publishToParent = false;
    this.displayErrorsInline = true;

    var _doc = document;
    var _counter = 0;
    this.MSIE  = /MSIE/i.test(navigator.userAgent);


    /**  Map is a general map object for storing key value pairs
      *
      *  @param mixin - default set of properties
      *
      */
    this.Map = function(mixin) {

        var map;
        if (typeof mixin == 'undefined') map = {};
        else map = mixin;

        /**
         * Get a list of the keys to check
         */
        this.keys = function() {
            var o = {};
            var _keys = [];

            for (var _i in map){
                // make sure we don't return prototype properties.
                if (typeof o[_i] == 'undefined') _keys.push(_i);
            }
            return _keys;
        };
        /**
         * Put stores the value in the table
         * @param key the index in the table where the value will be stored
         * @param value the value to be stored
         */
        this.put = function(key,value) {
            map[key] = value;
        };

        /**
         * Return the value stored in the table
         * @param key the index of the value to retrieve
         */
        this.get = function(key) {
            return map[key];
        };

        /**
         * Remove the value from the table
         * @param key the index of the value to be removed
         */
        this.remove =  function(key) {
            delete map[key];
        };
        /**
         *  Clear the table
         */
        this.clear = function() {
            delete map;
            map = {};
        };
    };

    /**
     *  Generate a unqiue id
     */
    this.genId = function() {
        return "jmk_" + _counter++;
    };

    /**
     * Utility function to see if a variable is defined.
     */
    function isDefined(_target) {
        return (typeof _target != "undefined");
    }

    // default locale - fallback if all fails
    this.defaultLocale = "jmaki-en-us";

    // default locale for messages
    this.locale = "jmaki-en-us";
    // localized messages

    this.defaultMessages = {
        "request_timeout" : "Request for {0} timed out.",
        "invalid_json" : "Invalid JSON.",
        "publish_function_not_found" : "Publish Error : function {0} not found on object {1}",
        "publish_object_not_found" : "Publish Error :  Object not found: {0}",
        "publish_match" : "<span style='color:green'>Subscribe Match :</span> : Topic: {0} listener {1}",
        "publish" : "<span style='color:red'>Publish </span> : Topic: {0} message {1}",
        "subscribe_handler_required" : "Subscribe Error : Handler required for subscriber {0}.",
        "subscribe_topic_required" : "Subscribe Error : topic or topicRegExp required for {0}.",
        "ajax_url_required" : "doAjax error: url required.",
        "ajax_error" : "jMaki.doAjax Error: {0}",
        "ajax_request_open_error" : "doAjax error making request: {0}",
        "ajax_send_body_error" : "doAjax error sending body of request to {0}.",
        "ajax_server_error" : "doAjax error communicating with {0}. Server returned status code {1}.",
        "write_dynamic_script_error" : "Attempt to write a script that can not be dynamically load widget with  id {0}. Consider using the widget in an iframe.",
        "widget_constructor_not_found" : "Unable to find widget constructor for {0}.",
        "extension_constructor_not_found" : "Unable to find extension constructor for {0}.",
        "widget_instantiation_error" : "Unable to create an instance of {0}. Enable logging for more details.",
        "unknown" : "unknown",
        "widget_error" : "<span>Error loading {0} : id={1}<br>Script: {2} (line: {3}).<br>Message: {4}</span>",
        "jmaki_logger" : "jMaki Logger",
        "clear" : "Clear",
        "x_close" : "[X]",
        "clear_logger" : "Clear Logger",
        "hide_logger" : "Hide Logger",
        "more" : "[more]",
        "jmaki_version" : "jMaki Version : {0}",
        "unable_to_load_url" : "Unable to load URL {0}."
    };

    // Localized messages
    // where the first set is a set of languages
    this.messages = new this.Map();

    this.dcontainers =  new this.Map();

    this.extensions = new this.Map();

    /**
     * Add a set of localzied messages
     *
     * @param locale - locale for the messages
     * @param messages - object literal of messsages in key value pairs
     *
     */
    this.addMessages = function(locale, messages) {
        _jmaki.messages.put(locale, new _jmaki.Map(messages));
    };

    // This map is intialized with the default languages and messages
    _jmaki.addMessages(_jmaki.defaultLocale,_jmaki.defaultMessages);

    /**
     * Get a localized message for the given id.
     *
     * @param id - The message id
     * @param args - If provided these will be used to format the message
     *
     * @return null if the message could not be found
     *
     * Messages will be searched for jmaki.locale messages and then
     * the jmaki.defaultLocale messages.
     *
     */
    this.getMessage = function(id,args) {
        var message = null;
        if (_jmaki.messages.get(_jmaki.locale) &&
            _jmaki.messages.get(_jmaki.locale).get(id)) {
            message = _jmaki.messages.get(_jmaki.locale).get(id);
        // fallback
        } else if (_jmaki.messages.get(_jmaki.defaultLocale) &&
            _jmaki.messages.get(_jmaki.defaultLocale).get(id)) {
            message = _jmaki.messages.get(_jmaki.defaultLocale).get(id);
        }
        if (isDefined(args)) {
            return _jmaki.messageFormat(message,args);
        }
        return message;
    };

    this.messageFormat = function(message, args) {
        for (var i=0; isDefined(message) && isDefined(args) && i < args.length; i++) {
            var rex = new RegExp("\\{" + i + "\\}", "g");
            message =  message.replace(rex, args[i]);
        }
        return message;
    };

    this.attributes = new this.Map();

    function getElement(id) {
        return _doc.getElementById(id);
    }

    /**
     *  Unsubscribe a listener
     *  @param _lis
     */
    this.unsubscribe = function(_lis) {
        for (var _l=0; _jmaki.subs && _l < _jmaki.subs.length;_l++ ) {
            if (_jmaki.subs[_l].id  == _lis.id) {
                _jmaki.subs.splice(_l,1);
                break;
            }
        }
    };

	function matchWildcard(pattern,topic) {

		var patpos = 0;
		var patlen = pattern.length;
		var strpos = 0;
		var strlen = topic.length;

		var i=0;
		var star = false;

		while (strpos+i<strlen) {
			if (patpos+i<patlen) {
				switch (pattern.charAt(patpos + i)) {
				case '?': {
					i++;
					continue;
				}
				case '*':
					star = true;
					strpos += i;
					patpos += i;
					do {
						++patpos;
						if (patpos == patlen)
							return true;
					} while (pattern.charAt(patpos) == '*');
					i=0;
					continue;
				}
				if (topic.charAt(strpos + i) != pattern.charAt(patpos + i)) {
					if (!star) return false;
					strpos++;
					i=0;
					continue;
				}
				i++;
			} else {
				if (!star) return false;
				strpos++;
				i=0;
			}
		}
		do {
			if (patpos + i == patlen) return true;
		} while(pattern.charAt(patpos + i++)=='*');
		return false;
	}


    /**
     *  Publish an event to a topic
     *  @param name Name of the topic to be published to
     *  @param args Palyoad of the publish
     *  @param bubbleDown Sends events down to children if set
     *  @param bubbleUp Sends event to parent contexts if they contain jmaki object and current context created by jmaki
     */
    this.publish = function(name, args, bubbleDown, bubbleUp) {
        if (!isDefined(name) || !isDefined(args)) return;
        if (_jmaki.debugGlue) {
            _jmaki.log(jmaki.getMessage("publish",  [name ,_jmaki.inspect(args)]));
        }

        // check the glue for listeners
        if (_jmaki.subs){
            for (var _l=0; _l < _jmaki.subs.length;_l++ ) {
                var _listener = _jmaki.subs[_l];
                     if ((_listener.topic instanceof RegExp &&
_listener.topic.test(name))
                   || _listener.topic == name
                   || (typeof _listener.topic.charAt == 'function' &&
matchWildcard(_listener.topic,name))
                   ) {

                    // set the topic on payload
                    args.topic = name;
                    if (_jmaki.debugGlue) {
                    	var _vname = name;
	                if (_listener.topicString) _vname = _listener.topicString;
                    	_jmaki.log(jmaki.getMessage("publish_match", [_vname, _listener]));
                    }
                    if (_listener.action == 'call' && _listener.target) {
                        // get the top level object
                        var _obj;
                        var myo = 'undefined';
                        if (_listener.target.functionName) {
                            _obj = _jmaki.findObject(_listener.target.object);
                            // create an instance of the object if needed.
                            if (typeof _obj == 'function') {
                                myo = new _obj;
                            } else if (_obj) {
                                myo = _obj;
                            } else {
                              _jmaki.log(_jmaki.getMessage("publish_function_not_found",
                                   [_listener.target.functionName,_listener.target.object]));
                            }
                            if (isDefined(myo) &&
                                typeof myo[_listener.target.functionName] == 'function'){
                                myo[_listener.target.functionName].call(window,args);
                            } else {
                                   _jmaki.log(_jmaki.getMessage("publish_object_not_found",
                                        [_listener.target.functionName,_listener.target.object]));
                            }
                        } else if (_listener.target.functionHandler) {
                            _listener.target.functionHandler.call(window,args);
                        }
                    }
                } else if (_jmaki.subs[_l].action == 'forward') {
                    var _topics = _jmaki.subs[_l].topics;
                    // now multiplex the event
                    for (var ti = 0; ti < _topics.length; ti++){
                        // don't cause a recursive loop if the topic is this one
                        if (_topics[ti] != name) {
                            _jmaki.publish(_topics[ti], args);
                        }
                    }
                }
            }
        }
        // publish to subframes with a global context appended
        var bd = true;
        if (isDefined(bubbleDown)) bd = bubbleDown;
        if (bd && window.frames && window.frames.length > 0) {
            var _frames = _jmaki.dcontainers.keys();
            for (var i=0; i < _frames.length; i++){
              var _dc = _jmaki.dcontainers.get(_frames[i]);
              if (_dc.iframe && !_dc.externalDomain && window.frames[_dc.uuid + "_iframe"] && window.frames[_dc.uuid + "_iframe"].jmaki){
                  window.frames[_dc.uuid + "_iframe"].jmaki.publish("/global" + name, args, true, false);
              }
            }
        }
        //  publish to parent frame if we are a sub-frame. This will prevent duplicate events
        if (_jmaki.publishToParent){
            var bu = true;
            if (isDefined(bubbleUp)) bu = bubbleUp;
              if (bu && window.parent.jmaki){
                  window.parent.jmaki.publish("/global" + name, args, false, true);
            }
        }
    };

    /**
     * Load a set of libraries in order and call the callback function
     */
    this.addLibraries = function(_o, _cb, _inp, _cu) {

        // check to see if anything is still processing and if not
        // call the callback
        var checkQueue = function() {
            if (_inprocess.keys().length == 0) {
                if (isDefined(_cb)){
                    setTimeout(function(){_cb();}, 0);
                }
                delete _inprocess;
                _jmaki.processingScripts = false;
                updateAjaxQueue();
            }
           return;
       };
        var _libs;
        var _inprocess;
        var _cleanup = true;
        // overload the function to allow for object literals
        if (_o instanceof Array) {
             _libs = _o;
             _inprocess = _inp;
             _cleanup = _cu;
        } else {
            _libs = _o.libs;
            _cb = _o.callback;
            _inprocess = _o.inprocess;
            _cleanup = _o.cleanup;
        }
        // queue the request if there are scripts being loaded.
        // this prevents the 2 connections from being sucked up.
        if (!isDefined(_inprocess) && (_jmaki.processingScripts ||
            _jmaki.processingAjax)) {
            _inprocess = new _jmaki.Map();
            if (!isDefined(_jmaki._scriptQueue)) {
                _jmaki._scriptQueue =[];
            }
            _jmaki._scriptQueue.push({libs : _libs, callback : _cb, cleanup : _cleanup});
            return;
        } else if (!isDefined(_inprocess)) {
            _jmaki.processingScripts = true;
            _inprocess = new _jmaki.Map();
        }

        if (_libs.length <= 0) {
            checkQueue();
        }
        var _uuid = new Date().getMilliseconds();
        var _lib = _libs[_libs.length-1];
        var _s_uuid = "c_script_" + _jmaki.genId();
        var head = _doc.getElementsByTagName("head")[0];
        var e = _doc.createElement("script");
        e.start = _uuid;
        e.id =  _s_uuid;
        head.appendChild(e);

        var se = getElement(_s_uuid);
        _inprocess.put(_s_uuid,_lib);
        var loadHandler = function (_id) {
            var _s = getElement(_id);
            // remove the script node
            if (_s  && !(isDefined(_cleanup) && _cleanup == false)) _s.parentNode.removeChild(_s);
            _inprocess.remove(_id);
            if (_libs.length-1 > 0) {
                _libs.pop();
                _jmaki.addLibraries({ libs : _libs, callback : _cb, inprocess : _inprocess, cleanup : _cleanup});
            }
            checkQueue();
        };

        // wait for the script to be laoded
        if (_jmaki.MSIE) {
            se.onreadystatechange = function () {
                if (this.readyState == 'loaded') {
                    var _id = _s_uuid;
                    loadHandler(_id);
                }
            };
            getElement(_s_uuid).src = _lib;
        } else {
            // the onload handler works on opera, ff, safari
            // and the addEventListener will not work on opera
            se.onload = function(){
              	  var _id = _s_uuid;
                  loadHandler(_id);
            };
            setTimeout(function(){
            	getElement(_s_uuid).src = _lib;
            	}, 0);
        }
    };



    /**
     *  Get the XMLHttpRequest object
     *
     *  Allow for config override to allow for older ActiveX XHR for local file
     *  System with IE7
     *
     */
    this.getXHR = function () {
        if (window.XMLHttpRequest &&
             !( _jmaki.MSIE &&
              typeof(_jmaki.config.forceActiveXXHR) == "boolean" &&
             _jmaki.config.forceActiveXXHR == true)) {
            return new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            return new ActiveXObject("Microsoft.XMLHTTP");
        } else return null;
    };

    function handleAjaxError(_m, _r, args){
       if (args.onerror) {
             args.onerror(_m,_r);
           } else {
         _jmaki.log(_jmaki.getMessage("ajax_error", [_m]));
       }
    }

    function updateAjaxQueue() {
		if (_jmaki.ajaxRequestQueue &&
		_jmaki.ajaxRequestQueue.length > 0) {
	        _jmaki.doAjax(_jmaki.ajaxRequestQueue.pop());
		} else {
		    _jmaki.processingAjax = false;
		    if (_jmaki._scriptQueue && _jmaki._scriptQueue.length >0) {
                    var _n = _jmaki._scriptQueue[0];
                   _jmaki._scriptQueue.shift();
                   _jmaki.addLibraries(_n);
                }
		}
    }
    /**
    * Generalized XMLHttpRequest which can be used from evaluated code. Evaluated code is not allowed to make calls.
    * @param args is an object literal containing configuration parameters including method[get| post, get is default], body[bodycontent for a post], asynchronous[true is default]
    */
   this.doAjax= function(args) {
       if (typeof args == 'undefined' || !args.url) {
           _jmaki.log(_jmaki.getMessage("ajax_url_required"));
           return;
       }
       // sync up the processing queues for script and ajax loading
       // synchronous requests should not be stopped
       if ((_jmaki.processingScripts && args.asynchronous) ||
           (_jmaki.processingAjax &&
           args.asynchronous) ) {
           	if (!_jmaki.ajaxRequetQueue) _jmaki.ajaxRequestQueue = [];
           	_jmaki.ajaxRequestQueue.push(args);
           	return;
       }
       _jmaki.processingAjax = true;
       var _req =  this.getXHR();

       var method = "GET";
       var async = true;
       var callback;
       var _c = false;
       if (args.timeout) {
           setTimeout(function(){
             if (_c == false) {
               _c = true;
               if (_req.abort) _req.abort();
               handleAjaxError(_jmaki.getMessage("request_timeout", [args.url]), _req, args);
               updateAjaxQueue();
               return;
              }
           }, args.timeout);
       }

       if  (isDefined(args.asynchronous)) {
            async=args.asynchronous;
       }
       if (args.method) {
            method=args.method;
       }
       if (typeof args.callback == 'function') {
           callback = args.callback;
       }
       var body = null;
       if (args.body) {
           body = args.body;
       } else if (args.content) {
           body = "";
           for (var l in args.content) {
               body = body +  l + "=" + encodeURIComponent(args.content[l]) + "&";
           }
       }
       if (async == true && _c == false) {
       	   _req.onreadystatechange = function() {
           if (_req.readyState ==4 && _c == false) {
               _c = true;
               if ((_req.status == 200 || _req.status ==0) && callback) {
                callback(_req);
               } else if (_req.status != 200){
                   _c = true;
                   handleAjaxError(_jmaki.getMessage("ajax_server_error", [args.url, _req.status]), _req, args);
               }
               updateAjaxQueue();
            return;
           }
       	 }
       }
       try {
          if (!_c)_req.open(method, args.url, async);
       } catch(e) {
         _c = true;
         handleAjaxError(_jmaki.getMessage("ajax_request_open_error", [args.url]),_req, args);
         updateAjaxQueue();
         return;
       }
       // add headers
       if (args.headers && args.headers.length > 0) {
           for (var _h=0;_h < args.headers.length; _h++) {
               _req.setRequestHeader(args.headers[_h].name, args.headers[_h].value);
           }
       }
       // customize the method
       if (args.method) {
            method=args.method;
            if (method.toLowerCase() == 'post') {
               if (!args.contentType) _req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            }
       }
       if (args.contentType) {
           _req.setRequestHeader("Content-Type", args.contentType);
       }
       try {
         if (_c == false) _req.send(body);
       } catch(e) {
         _c = true;
         handleAjaxError(_jmaki.getMessage("ajax_send_body_error", [args.url]), _req, args);
         updateAjaxQueue();
         return;
       }
       if (_c == false && async == false) {
           _c = true;
           if (_req.status ==200 || _req.status ==0) {
                if (callback) callback(_req);
           } else {
               _c = true;
               handleAjaxError(_jmaki.getMessage("ajax_server_error", [args.url,_req.status]), _req, args);
           }
           updateAjaxQueue();
           return;
       }
    };

    /**
     *  Library name is added as a script element which will be loaded when the page is rendered
     *  @param lib library to add
     *  @param cb Callback handler
     */
    this.addLibrary = function(lib, cb) {
      var libs = [];
      libs.push(lib);
      return _jmaki.addLibraries({libs : libs, callback : cb});
    };

    /**
     * Register widget with jMaki
     * @param widget Object respresenting the widget
     */
    this.addWidget = function(widget) {
        widgets.push(widget);
        if (this.loaded){this.loadWidget(widget);}
    };

     /**
     * Register widget with jMaki
     * @param ext Object respresenting the extension params
     */
    this.addExtension = function(ext) {
        _jmaki.preextensions.push(ext);
    };

    /**
     * Register widget with jMaki
     * @param id The id of the extension
     */
    this.getExtension = function(id) {
        return _jmaki.extensions.get(id);
    };

    /**
     * Bootstrap or load all registered widgets
     */
    this.bootstrapWidgets = function() {
        _jmaki.loaded = true;
        for (var l=0; l < widgets.length; l++) {
            _jmaki.loadWidget(widgets[l]);
        }
    };

    /**
     * Bootstrap or load all registered extensions
     */
    this.loadExtensions = function() {
        for (var l=0; l < _jmaki.preextensions.length; l++) {
            _jmaki.loadExtension(_jmaki.preextensions[l]);
        }
    };

   /**
     * Checks wheter a script has been loaded yet
     */
    this.writeScript = function(_s, _id) {
        if (_jmaki.loaded == true) {
            if (getElement(_id)) {
                getElement(_id).innerHTML = _jmaki.getMessage("write_dynamic_script_error", [_id]);
            }
        } else {
            _doc.write("<script src='" + _s + "'></script>");
        }
    };

    /**
     * Loads the style sheet by adding a link element to the DOM
     * @param target name of style sheet to load
     */
    this.loadStyle = function(target) {
        var styleElement = _doc.createElement("link");
        styleElement.type = "text/css";
        styleElement.rel="stylesheet";
        if (target[0] == '/') target = _jmaki.webRoot + target;
        styleElement.href = target;
        if (_doc.getElementsByTagName('head').length == 0) {
            var headN = _doc.createElement("head");
            _doc.documentElement.insertBefore(headN, _doc.documentElement.firstChild);
        }
        _doc.getElementsByTagName('head')[0].appendChild(styleElement);
    };

    /**
     * Replace style class
     * @param root root of the oldStyle classes
     * @param oldStyle name of class or classes to replace
     * @param targetStyle name of new class or classes to use
     */
    this.replaceStyleClass = function (root, oldStyle, targetStyle) {
        var elements = this.getElementsByStyle(oldStyle,root);
        for (var i=0; i < elements.length; i++) {
            // Handle cases where there are multiple classnames
            if (elements[i].className.indexOf(' ') != -1) {
                var classNames = elements[i].className.split(' ');
                for (var ci in classNames) {
                    if (classNames[ci] == oldStyle) {
                        classNames[ci] = targetStyle;
                    }
                }
                // now reset the styles with the replaced values
                elements[i].className = classNames.join(' ');
            } else  if (elements[i].className == oldStyle) {
                elements[i].className = targetStyle;
            }
        }
    };

    /**
    * Find a set of child nodes that contain the className specified
    * @param className is the targetClassName you are looking for
    * @param root  An optional root node to start searching from. The entire document will be searched if not specfied.
    *
    */
    this.getElementsByStyle = function(className, root){
        var elements = [];
        if (isDefined(root)) {
            var rootNode = root;
            if (typeof root == 'string') {
                rootNode = getElement(root);
            }
            elements = this.getAllChildren(rootNode, []);
        } else {
            elements = (_doc.all) ? _doc.all : _doc.getElementsByTagName("*");
        }
	var found = [];
	for (var i=0; i < elements.length; i++) {
	// Handle cases where there are multiple classnames
            if (elements[i].className.indexOf(' ') != -1) {
                var cn = elements[i].className.split(' ');
                for (var ci =0; ci < cn.length; ci++) {
                    if (cn[ci] == className) {
                        found.push(elements[i]);
                    }
                }
            } else  if (elements[i].className == className) {
                found.push(elements[i]);
            }
        }
        return found;
    };

    /**
     * Utility Function to get children
     * @param target Element for which to get the children. All document chilren are loaded if not specified
     * @param children An array used interally to build up a list of children found
     */
    this.getAllChildren = function(target, children) {
        var _nc = target.childNodes;
        for (var l=0; _nc && l <  _nc.length; l++) {
            if (_nc[l].nodeType == 1) {
                children.push(_nc[l]);
                if (_nc[l].childNodes.length > 0) {
                    this.getAllChildren(_nc[l], children);
                }
            }
        }
        return children;
    };

    /**
     * Load extension
     * @param _ext Object representing widget to load
     */
    this.loadExtension = function(_ext) {
        if (_jmaki.extensions.get(_ext)) return;
        var targetName ="jmaki.extensions." + _ext.name + ".Extension";
        var con = _jmaki.findObject(targetName);
        if (typeof con != "function") {
            _jmaki.log(_jmaki.getMessage("extension_constructor_not_found", [targetName]));
        } else {
          var ex = new con(_ext);
          if (ex.postLoad) ex.postLoad.call(window);
          _jmaki.extensions.put(_ext.name, ex);
        }

    };


    /**
     * Load a widget
     * @param _jmw Object representing widget to load
     */
    this.loadWidget = function(_jmw) {
        // see if the widget has been defined.
        if (_jmaki.attributes.get(_jmw.uuid) != null) {
            return null;
        }
        var targetName ="jmaki.widgets." + _jmw.name + ".Widget";
        var con = _jmaki.findObject(targetName);
        if (typeof con != "function") {
            logError(_jmaki.getMessage("widget_constructor_not_found", [targetName]), getElement(_jmw.uuid));
            return null;
        }
        var wimpl;
        // bind the value using a @{foo.obj} notation
        if ((typeof _jmw.value == 'string') && _jmw.value.indexOf("@{") == 0) {
            var _vw = /[^@{].*[^}]/.exec(_jmw.value);
            _jmw.value = _jmaki.findObject(new String(_vw));
        }
        // do not wrap IE with exception handler
        // because we cant' get the right line number
        var _uuid = _jmw.uuid;
        if (_jmaki.MSIE) {
            var oldError = null;
            if (window.onerror) {
                oldError = window.onerror;
            }
            var eh = function(message, url, line) {
                var _puuid = _uuid;
                logWidgetError(targetName, _puuid,url, line, message, getElement(_puuid));
            };
            window.onerror = eh;
            wimpl = new con(_jmw);
            window.onerror = null;
            if (oldError) {
                window.onerror = oldError;
            }
        } else if (typeof con == 'function'){
          try {
                wimpl = new con(_jmw);
           } catch (e){
                var line = _jmaki.getMessage("unknown");
                var description = null;
                if (e.lineNumber) line = e.lineNumber;
                if (e.message) description = e.message;

                if (_jmaki.debug) {
                    logWidgetError(targetName, _jmw.uuid,_jmw.script, line, description , getElement(_jmw.uuid));
                    return null;
                }
            }
        }
        if (typeof wimpl == 'object') {
            _jmaki.attributes.put(_jmw.uuid, wimpl);
            if (wimpl.postLoad) wimpl.postLoad.call(window);
            // map in any subscribe handlers.
            if (_jmw.subscribe && _jmw.subscribe.push) { //string also have length property
                for (var _wi = 0; _wi < _jmw.subscribe.length; _wi++) {
                    var _t = _jmw.subscribe[_wi].topic;
                    var _m = _jmw.subscribe[_wi].handler;
                    var _h = null;
                    if (typeof _m == 'string' && _m.indexOf("@{") == 0) {
                         var _hw = /[^@{].*[^}]/.exec(_m);
                        _h = _jmaki.findObject(new String(_hw));
                    } else if (wimpl[_m]) {
                        _h = wimpl[_m];
                    }
                    if (_h != null) _jmaki.subscribe(_jmw.subscribe[_wi].topic,_h);
                }
            }
            _jmaki.publish("/jmaki/runtime/widget/loaded", { id : _jmw.uuid});
            return wimpl;
        } else {
            logError(_jmaki.getMessage("widget_instantiation_error",[targetName]), getElement(_jmw.uuid ));
        }
        return null;
    };

    function logWidgetError(name,uuid, url, line, _m, div) {
        var message= _jmaki.getMessage("widget_error", [name, uuid, url, line, _m]);
        logError(message, div);
    }

    function logError(message, div) {
        if (_jmaki.displayErrorsInline) {
            if (!isDefined(div) || !div) div = _doc.createElement("div");
            div.className = "";
            div.style.color = "red";
            _doc.body.appendChild(div);
           div.innerHTML = message;
        } else {
            _jmaki.log(message);
        }
    }

    /**
     * An easy way to get a instance of a widget.
     * returns null if their is not a widget with the id.
     */
    this.getWidget = function(id) {
        return _jmaki.attributes.get(id);
    };

    /**
     * destroy all registered widgets under the target node
     * @param _root - The _root to start at. All widgets will be removed if not specified.
     */
    this.clearWidgets = function(_root) {

        if (!isDefined(_root)) {
            var _k = _jmaki.attributes.keys();
            for (var l=0; l < _k.length; l++) {
                _jmaki.removeWidget(_k[l]);
            }
            _jmaki.loaded = false;
            widgets = [];
        } else {
           var _ws = _jmaki.getAllChildren(_root,[]);
           for (var ll=0; ll < _ws.length; ll++) {
                if (_ws[ll].id) _jmaki.removeWidget(_ws[ll].id);
            }
        }
    };

    this.removeWidget = function(_wid) {
        var _w = _jmaki.getWidget(_wid);
        if (_w) {
            if ( typeof _w.destroy == 'function') {
                _w.destroy();
            }
            var _p = getElement(_wid);
            if(null != _p) _p.parentNode.removeChild(_p);
        }
        _jmaki.attributes.remove(_wid);
    };


    this.inspect = function(_o, _inspectDepth, _currentDepth) {
        var _ind = _jmaki.inspectDepth;
        var _cd = 0;

        if (typeof _inspectDepth == "number"){
            _ind =_inspectDepth;
        }
        if (typeof _currentDepth != "undefined"){
            _cd = _currentDepth;
        }
        if (_cd >= _ind && _ind != -1) {
           if (typeof _o == "string") {
               return "'" + _o + "'";
           } else  return _o;
        } else  {
            _cd++;
        }

        var _rs = [];
        if (typeof _o == "undefined")return 'undefined';

        if (_o instanceof Array) {
            for (var i=0; i < _o.length; i++) {
                _rs.push(_jmaki.inspect(_o[i],_ind,_cd));
            }
            return "[" +  _rs.join(" , ") + "]";
        } else if (typeof _o == "string") {
           return "'" + _o + "'";
        } else if (typeof _o == "number" ||
            typeof _o == "boolean") {
           return _o;
        } else if (typeof _o == "object") {
            for (var _oi in _o) {
                try {
                    if (typeof _o[_oi] != "function") _rs.push(_oi  + " : " + _jmaki.inspect(_o[_oi],_ind,_cd));
                } catch(e){}
            }
            if (_rs.length > 0) {
                 return "{" + _rs.join(" , ") + "}";
            }
            else return "{}";
        } else return _o;
    };

    /*
     * Add a glue listener programatcially. following is an example.
     *
     *{topic : "/dojo/fisheye",action: "call", target: { object: "jmaki.dynamicfaces",functionName: "fishEyeValueUpdate"}}
     *   or
     * @param l as topic and
     * @param t as the target object path ending with a function
     */
    this.subscribe = function(l, t) {
        if (!isDefined(l)) return null;
        // handle key word arguments
        var lis;
        if (typeof l == 'object' && !(l instanceof RegExp)) {
            if (l.topic) l.topic = _jmaki.trim(l.topic);
            if (l.topicRegExp) l.topic = new RegExp(l.topicRegExp);
            lis = l;
        // function binding
        } else if (typeof t == 'string'){
          lis = {};
          if (l.topicRegExp) lis.topic = new RegExp(l.topicRegExp);
          else lis.topic = l;
          lis.target = {};
          var _is = t.split('.');
          lis.action = "call";
          lis.target.functionName = _is.pop();
          lis.target.object = _is.join('.');
        // inline function
        } else if (typeof t == 'function') {
          lis = {};
          if (l.topicRegExp) lis.topic =  new RegExp(l.topicRegExp);
          else lis.topic = l;
          lis.target = {};
          lis.action = "call";
          lis.target.functionHandler = t;
        } else {
          _jmaki.log(jmaki.getMessage("subscribe_handler_required", [l]));
        }
        if (isDefined(lis)){
            if (!isDefined(_jmaki.subs))_jmaki.subs = [];
            if (!lis.id) lis.id = _jmaki.genId();
            if (lis.topic){
                lis.toString = function() { return _jmaki.inspect(this)};
                _jmaki.subs.push(lis);
            } else {
                _jmaki.log(jmaki.getMessage("subscribe_topic_required", [l]));
                return null;
            }
            return lis;
        }
        return null;
    };

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

    /*
     * @param _src is the source object
     * @param _par is the class to extend
     */
    this.extend = function(_src, _par) {
        _src.prototype = new _par();
        _src.prototype.constructor = _src;
        _src.superclass = _par.prototype;
        for (i in _src.prototype) {
            _src[i] = _src.prototype[i];
        }
    };

    this.hideLogger = function() {
      var ld = getElement("jmakiLogger");
      if (ld)ld.style.visibility = 'hidden';
    };

    this.clearLogger = function() {
      var b = getElement("jmakiLoggerContent");
      if (b) b.innerHTML = "";
    };

    this.log = function(text, level) {
        // cached messages until after the page has been created
        if (!_jmaki.initialized) {
            if (!_jmaki._messages) _jmaki._messages = [];
            _jmaki._messages.push({ text : text, level : level});
            return;
        }
        if (!_jmaki.debug ) return;
        var ld = getElement("jmakiLogger");
        var b = getElement("jmakiLoggerContent");
        if (!ld){
            ld = _doc.createElement("div");
            ld.id = 'jmakiLogger';
            ld.style.border = "1px solid #000000";
            ld.style.fontSize = "12px";
            ld.style.position  = "absolute";
            ld.style.zIndex  = "999";
            ld.style.bottom = "0px";
            ld.style.background = "#FFFF00";
            ld.style.right ="0px";
            ld.style.width = "600px";
            ld.style.height = "300px";

            var tb = "<div  style='height: 14px; background : black; color : white; font-size : 10px'>" +
                     "<div style='float:left;width:545px;text-align:center'>" +
                     _jmaki.getMessage("jmaki_logger") +
                     "</div><div style='right:0px,text-align:left'><a href='javascript:jmaki.clearLogger()' title='" +
                     _jmaki.getMessage("clear_logger") +
                     "' style='color:white;text-decoration:none'>[" +
                     _jmaki.getMessage("clear") +
                     "]</a> <a href='javascript:jmaki.hideLogger()' title='" +
                     _jmaki.getMessage("hide_logger") +
                      "' style='color:white;text-decoration:none'>" +
                      _jmaki.getMessage("x_close") +
                      "</a></div></div>";
            var tbE = _doc.createElement("div");
            tbE.innerHTML = tb;
            ld.appendChild(tbE);
            b = _doc.createElement("div");
            b.id ='jmakiLoggerContent';
            b.style.height = "286px";
            b.style.overflowY = "auto";
            ld.appendChild(b);
            if (_doc.body) {
               _doc.body.appendChild(ld);
            }

        }
        if (ld && _jmaki.loaded)ld.style.visibility = 'visible' ;
        var lm = _doc.createElement("div");
        lm.style.clear = "both";
        if (text && text.length > 125 && _jmaki.verboseDebug == false) {
            var lid = _jmaki.genId();
            var tn = _doc.createElement("div");
            tn.innerHTML = "<div style='float:left;width:535px;height:12px;overflow:hidden'>" + text.substring(0,135) + "</div><div style='float:left'>...&nbsp;</div><a id='" + lid + "_href' href=\"javascript:jmaki.showLogMessage(\'" + lid +  "\')\" style='text-decoration: none'><span id='" + lid + "_link'>" + _jmaki.getMessage("more") + "</span></a>";
            var mn = _doc.createElement("div");
            mn.id = lid;
            mn.innerHTML = text;
            mn.style.margin = "5px";
            mn.style.background = "#FF9900";
            mn.style.display = "none";
            lm.appendChild(tn);
            lm.appendChild(mn);
        } else lm.innerHTML =  text;
        if (b)b.appendChild(lm);
    };

    this.showLogMessage = function(id) {
        var n = getElement(id);
        if (n && n.style){
            n.style.display = "block";
            var h = getElement(id + "_href");
            h.href = "javascript:jmaki.hideLogMessage('" + id + "')";
            var l = getElement(id + "_link");
            l.innerHTML = "&nbsp;" + _jmaki.getMessage("x_close");
        }
    };

    this.hideLogMessage = function(id) {
        var n = getElement(id);
        if (n && n.style){
            n.style.display = "none";
            var h = getElement(id + "_href");
            h.href = "javascript:jmaki.showLogMessage('" + id + "')";
            var l = getElement(id + "_link");
            l.innerHTML = _jmaki.getMessage("more");
        }
    };

    /**
     * Initialize jMaki by loading the config.json
     *  Write in the glue by loading dependencies and
     *  Register listeners.
     */
    this.initialize = function() {
        if (!_jmaki.config) {
            _jmaki.config = {};
          _jmaki.doAjax({ url : this.webRoot + this.resourcesRoot + "/config.json",
               asynchronous : false,
               timeout : 3000,
               onerror : function() { /* do nothing and continue*/},
               callback :  function(req) {
                  if (req.responseText != '') {
                      var obj = eval('(' + req.responseText + ')');
                      if (obj.config) {
                          _jmaki.config = obj.config;

                      }
                  }
              }
          });
        }
        postInitialize();
    };

    /**
     * Create a namespace with the given string
     */
    this.namespace = function(_path, target) {
        // get the top level object
        var paths = _path.split('.');
        var _obj = window[paths[0]];
        if (!isDefined(_obj)) window[paths[0]] = _obj = {};
        for (var ii = 1; ii < paths.length; ii++) {
            if (isDefined(_obj[paths[ii]])) {
                _obj = _obj[paths[ii]];
            } else {
                _obj[paths[ii]] = {};
                _obj = _obj[paths[ii]];
            }
        }
        // if object provided it becomes the last in the chain
        if (typeof target == 'object') {
            _obj = target;
        }
        return _obj;
    };



    /*

The code was adopt with minor modifications from:
http://www.json.org/json2.js
*/

_jmaki.json = function () {

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

        var m = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        };

        function stringify(value, whitelist) {
            var a,          // The array holding the partial texts.
                i,          // The loop counter.
                k,          // The member key.
                l,          // Length.
                r = /["\\\x00-\x1f\x7f-\x9f]/g,
                v;          // The member value.

            switch (typeof value) {
            case 'string':

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

                return r.test(value) ?
                    '"' + value.replace(r, function (a) {
                        var c = m[a];
                        if (c) {
                            return c;
                        }
                        c = a.charCodeAt();
                        return '\\u00' + Math.floor(c / 16).toString(16) +
                                                   (c % 16).toString(16);
                    }) + '"' :
                    '"' + value + '"';

            case 'number':

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

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

            case 'boolean':
                return String(value);
            case 'null':
                return String(value);
            case 'date': {
              return value.getUTCFullYear() + '-' +
                 f(value.getUTCMonth() + 1) + '-' +
                 f(value.getUTCDate())      + 'T' +
                 f(value.getUTCHours())     + ':' +
                 f(value.getUTCMinutes())   + ':' +
                 f(value.getUTCSeconds())   + 'Z';
            }
            case 'object':

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

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

// If the object has a toJSON method, call it, and stringify the result.

                if (typeof value.toJSON === 'function') {
                    return stringify(value.toJSON());
                }
                a = [];
                if (typeof value.length === 'number' &&
                        !(value.propertyIsEnumerable('length'))) {

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

                    l = value.length;
                    for (i = 0; i < l; i += 1) {
                        a.push(stringify(value[i], whitelist) || 'null');
                    }

// Join all of the elements together and wrap them in brackets.

                    return '[' + a.join(',') + ']';
                }
                if (whitelist) {

// If a whitelist (array of keys) is provided, use it to select the components
// of the object.

                    l = whitelist.length;
                    for (i = 0; i < l; i += 1) {
                        k = whitelist[i];
                        if (typeof k === 'string') {
                            v = stringify(value[k], whitelist);
                            if (v) {
                                a.push(stringify(k) + ':' + v);
                            }
                        }
                    }
                } else {

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

                    for (k in value) {
                        if (typeof k === 'string') {
                            v = stringify(value[k], whitelist);
                            if (v) {
                                a.push(stringify(k) + ':' + v);
                            }
                        }
                    }
                }

// Join all of the member texts together and wrap them in braces.

                return '{' + a.join(',') + '}';
            }
        }

        return {
            serialize: stringify,
            deserialize: function (text, filter) {
                var j;
                text = _jmaki.trim(text);
                function walk(k, v) {
                    var i, n;
                    if (v && typeof v === 'object') {
                        for (i in v) {
                            if (Object.prototype.hasOwnProperty.apply(v, [i])) {
                                n = walk(i, v[i]);
                                if (n !== undefined) {
                                    v[i] = n;
                                }
                            }
                        }
                    }
                    return filter(k, v);
                }

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

// We split the first stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace all backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
                if (/^[\],:{}\s]*$/.test(text.replace(/\\./g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the second stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
                    j = eval('(' + text + ')');

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

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

// If the text is not JSON parseable, then a SyntaxError is thrown.
               throw jmaki.getMessage('invalid_json');
            }
        };

    }();


    this.findObject = function(_path) {
        var paths = _path.split('.');
        var found = false;
        var _obj = window[paths[0]];
		if (_obj && paths.length == 1) found = true;
        if (isDefined(_obj)){
            for (var ii =1; ii < paths.length; ii++) {
                var _lp = paths[ii];
                if (_lp.indexOf('()') != -1){
                  var _ns = _lp.split('()');
                  if (typeof _obj[_ns[0]] == 'function'){
                      var _fn = _obj[_ns[0]];
                      return _fn.call(window);
                  }
                }
                if (isDefined(_obj[_lp])) {
                    _obj = _obj[_lp];
                    found = true;
                } else {
                    found = false;
                    break;
                }
            }
            if (found) {
                return _obj;
            }
        }
        return null;
    };

    this.Timer = function(args, isCall) {
        var _src = this;
        this.args = args;
        var _target;

        this.processTopic = function() {
            for (var ti = 0; ti < args.topics.length; ti++){
                _jmaki.publish(args.topics[ti], {topic: args.topics[ti],
                type:'timer',
                src:_src,
                timeout: args.to});
            }
        };

        this.processCall = function() {
            if (!_target) {
             var  _obj = _jmaki.findObject(args.on);
                if (typeof _obj == 'function'){
                    _target = new _obj();
                } else if (typeof _obj == 'object'){
                    _target = _obj;
                }
            }
            if ((_target && typeof _target == 'object')) {
              if(typeof _target[args.fn] == 'function') {
                _target[args.fn]({type:'timer', src:_src, timeout: args.to});
              }
            }
        };

        this.run = function() {
            if (isCall) {
                _src.processCall();
            } else {
                _src.processTopic();
            }
            window.setTimeout(_src.run,args.to);
        };
    };

    this.addTimer = function(_timer){
        var timers = [];
        timers.push(_timer);
        this.addTimers(timers);
    };

    this.addTimers = function(_timers){
        if (isDefined(_timers)){
            for (var _l=0; _l <_timers.length;_l++ ) {
                // create a wrapper and add the timer
                var _timer = _timers[_l];
                if (_timer.action == 'call' &&
                isDefined(_timer.target) &&
                isDefined(_timer.target.object) &&
                isDefined(_timer.target.functionName) &&
                isDefined(_timer.timeout)) {
                    // create the timer
                    var args = {on: _timer.target.object,
                    fn: _timer.target.functionName,
                    to: _timer.timeout
                    };
                    var t1 = new _jmaki.Timer(args,true);
                    timers.push(t1);
                    t1.run();
                } else if (_timers[_l].action == 'publish') {
                    var args2 = {topics: _timers[_l].topics,
                    to: _timer.timeout
                    };
                    var t2 = new _jmaki.Timer(args2,false);
                    timers.push(t2);
                    t2.run();
                }
            }
        }
    };

    function postInitialize() {
        if (_jmaki.initialized) return;
        else _jmaki.initialized = true;

        if (_jmaki.config.logLevel) {
            switch (_jmaki.config.logLevel) {
                case 'debug' : {
                        _jmaki.debug = true;
                        _jmaki.log(_jmaki.getMessage("jmaki_version",[_jmaki.version]));
                        break;
                    }
                case 'all' : {
                        _jmaki.debug = true;
                        _jmaki.debugGlue = true;
                        break;
                    }
                case  'off' : {
                        _jmaki.debug = false;
                        break;
                    }
            }
        }
        // write out the dependent libraries so we have access
        if (_jmaki.config.glue) {
            if (_jmaki.config.glue.timers) {
                _jmaki.addTimers(_jmaki.config.glue.timers);
            }
            if (_jmaki.config.gluelisteners){
                for (var gl=0; gl < _jmaki.config.glue.listeners.length;gl++) {
                    _jmaki.subscribe (_jmaki.config.glue.listeners[gl]);
                }
            }
        }

        // log any messages that might be queued up during pre-init
        if (_jmaki._messages) {
            for (var i=0; i < _jmaki._messages.length; i++) {
                var _m = _jmaki._messages[i];
                _jmaki.log(_m.text, _m.level);
            }
        }
        _jmaki.publish("/jmaki/runtime/intialized", {});
        _jmaki.loadExtensions();
        _jmaki.publish("/jmaki/runtime/extensionsLoaded", {});
        _jmaki.bootstrapWidgets();

        _jmaki.publish("/jmaki/runtime/widgetsLoaded", {});
        // load the theme
        if ( _jmaki.config && _jmaki.config.theme) {
            var theme = _jmaki.config.theme;
            if (!/(^http)/i.test(theme)) theme = _jmaki.webRoot + theme;
            _jmaki.loadStyle(theme);
        }
        _jmaki.publish("/jmaki/runtime/loadComplete", {});
    }
    /**
     *  All for a filter to be applied to a dataset
     *  @param input - An object you wish to filter
     *  @param filter a string representing the path to the object or
     *    a funciton reference to procress the input
     */
    this.filter = function(input, filter){
        if (typeof filter == 'string') {
            var h = _jmaki.findObject(filter);
            return h.call(window,input);
        } else if (typeof filter == 'function'){
            return filter.call(window, input);
        }
        return null;
    };

     /**
    * A function to cloning an object or array so that different references do not
    * end up with shared references.
    *
    * @param - t A single object or array
    *
    */
    this.clone = function(t) {
       var _obj;
       if (t instanceof Array) {
           _obj = new Array();
           for (var _j=0;_j< t.length;_j++) {
               _obj.push(_jmaki.clone(t[_j]));
           }
       } else if (t instanceof Object) {
           _obj = new Object();
           for (var _jj in t) {
                _obj[_jj] = _jmaki.clone(t[_jj]);
           }
       } else {
           _obj = t;
       }
       return _obj;
    };

    /*  This function takes an object literal and performs actions if present
     *  or it publishes a message to the provided topic.
     *
     *  _t = object literal { topic : 'topic to publish to',
     *                        widgetId : 'source widget id',
     *                        targetId : 'foo',
     *                        action : [
     *                            { topic : '/some topic', message : { payload}}
     *                        ],
     *                        value : 'somevalue'
     *                      }
     * The action, targetId, and value properties are optional.
     * The topic and widgetId are required
     *
     */
    this.processActions = function(_t) {
        if (_t) {
            var _topic = _t.topic;
            var _m = {widgetId : _t.widgetId, type : _t.type, targetId : _t.targetId};
            if (typeof _t.value != "undefined") _m.value = _t.value;
            var action = _t.action;
            if (!action) _topic = _topic + "/" + _t.type;
            if (action && action instanceof Array) {
              for (var _a=0; _a < action.length; _a++) {
                  var payload = _jmaki.clone(_m);
                  if (action[_a].topic) payload.topic = action[_a].topic;
                  else payload.topic = _t.topic;
                  if (action[_a].message) payload.message = action[_a].message;
                  jmaki.publish(payload.topic,payload);
              }
            } else {
              if (action && action.topic) {
                  _topic = _m.topic = action.topic;
              }
              if (action && action.message) _m.message = action.message;
              jmaki.publish(_topic,_m);
            }
        }
    };

    /**
     *  Find the postion of an Element
     *
     */
     this.getPosition = function(_e){
        var pX = 0;
        var pY = 0;
        if(_e.offsetParent) {
            while(true){
                pY += _e.offsetTop;
                pX += _e.offsetLeft;
                if(_e.offsetParent == null){
                    break;
                }
                _e = _e.offsetParent;
            }
        } else if(_e.y) {
                pY += _e.y;
                pX += _e.x;
        }
        return {x: pX, y: pY};
    };

    this.getDimensions = function(n, min) {
        if (typeof n == 'undefined' ||
            n == null) return null;
        var _min = 0;
        if (typeof min != 'undefined') _min = min;
        var rn = n.parentNode;
        while(rn && true) {
            if (rn.clientHeight > _min) break;
            if (rn.parentNode && rn.parentNode.clientHeight)rn = rn.parentNode;
            else break;
        }
        if (!rn) return null;
        return {h : rn.clientHeight,w : rn.clientWidth};
    };

  this.DContainer = function(args){
      var _self = this;
        var _container;

        if (typeof args.target == 'string') {
            this.uuid = args.target;
            _container = getElement(this.uuid);
        } else {
            this.uuid = args.target.id;
            _container = args.target;
        }
        if (!this.uuid) this.uuid = _jmaki.genId();
        // add to a reference of the jmaki containers
        _jmaki.dcontainers.put(_self.uuid, this);

        var oldWidth;
        this.url = null;
        this.externalDomain = false;
        var autoSizeH = false;
        var autoSizeW = false;

        if (args.autosize) {
            autoSizeH = true;
            autoSizeW = true;
        }

        if (typeof args.autosizeH == 'boolean') {
            autosizeH = args.autosizeH;
        }
        if (typeof args.autosizeW == 'boolean') {
            autoSizeW = args.autosizeW;
        }

        // default sizes are all based on the width of the container
        var VIEWPORT_WIDTH;
        var VIEWPORT_HEIGHT;

        function getHost(url) {
            var host = "";
            // get the second 1/2
            var _p = url.split("://");
            if (_p[1]) {
                if (_p[1].indexOf("/") != -1) {
                    host = _p[1].substring(0, _p[1].indexOf("/"));
                } else {
                    host = _p[1];
                }
            }
            return host;
        }

        this.clear = function() {
            if (args.useIframe) {
                if (_self.iframe) {
                    _self.loadURL("");
                } else {
                    args.url = "";
                }
            } else {
                _jmaki.clearWidgets(_container);
                _container.innerHTML = "";
            }
        };

        this.loadURL = function(_url){
            // shut down all events published to iframe
            if (_self.iframe) {
                _self.externalDomain = true;
            }
            if (_url.message) _url = _url.message;
            if (typeof _url == 'string') {
                _self.url = _url;
            } else if (_url.url) {
                _self.url = _url.url;
            } else if (_url.value) {
                _self.url = _url.value;
            }
            // check for jmaki and enable events to flow to parent jmaki instances
            function enableEvents() {
                // check to see if we are in the same domain for pushing messages from the bus
                // check if we are an external link
                if (/http/i.test( _self.url) &&  top.window.location.host != getHost( _self.url)) {
                    _self.externalDomain = true;
                } else {
                    _self.externalDomain = false;
                }
                if (!_self.externalDomain) {
                    var _w = _self.iframe.contentWindow ? _self.iframe.contentWindow  : _self.iframe.window;
                    if (_w && _w.jmaki) {
                        _w.jmaki.publishToParent = true;
                    }
                }
            }
            if (args.useIframe) {
                // wait for the iframe if it hasn't loaded
                if (!_self.iframe) {
                    var _t = setInterval(function() {
                        if (getElement(_self.uuid + "_iframe")) {
                            clearInterval(_t);
                            _self.iframe = getElement(_self.uuid + "_iframe");
                            // wire on event listener to wait for iframe load and then
                                if (_jmaki.MSIE){
                                    _self.iframe.onreadystatechange = function() {
                                        if (this.readyState == 'complete') enableEvents();
                                    }
                                } else {
                                  _self.iframe.onload = enableEvents;
                                }
                            _self.iframe.src =  _self.url;
                            init();
                        }
                    }, 5);
              } else {
                  if (_jmaki.MSIE){
                      _self.iframe.onreadystatechange = function() {
                          if (this.readyState == 'complete') enableEvents();
                      }
                  } else {
                      _self.iframe.onload = enableEvents;
                  }
                  _self.iframe.src = _self.url;
             }
            } else {
                _jmaki.injector.inject({url: _self.url, injectionPoint: _container});
                /*
                if (/http/i.test(_url) &&  top.window.location.host != getHost(_url)) {
                    _self.externalDomain = true;
                } else {
                    _self.externalDomain = false;
                } */
            }
        };

        this.setSize = function(size) {
            if (size.w) {
                VIEWPORT_WIDTH = size.w;
                _container.style.width = VIEWPORT_WIDTH + "px";
                if (_self.iframe)
                    _self.iframe.style.width = VIEWPORT_WIDTH -2 + "px";
            }
            if (size.h) {
                VIEWPORT_HEIGHT = size.h;
                _container.style.height = VIEWPORT_HEIGHT + "px";
                if (_self.iframe)
                    _self.iframe.style.height = VIEWPORT_HEIGHT -2 + "px";
            }
        };

        this.resize = function() {
            var _dim = _jmaki.getDimensions(_container);
            if (autoSizeH || autoSizeW){
                if (!_container.parentNode) return;
                var pos = _jmaki.getPosition(_container);
                if (_container.parentNode.nodeName == "BODY") {
                    if (window.innerHeight){
                        if (autoSizeH)VIEWPORT_HEIGHT = window.innerHeight - pos.y ;
                        if (autoSizeW)VIEWPORT_WIDTH = window.innerWidth - 20;
                    } else {
                        if (_dim == null) {
                            if (autoSizeW)VIEWPORT_WIDTH = 400;
                        } else {
                            if (autoSizeW)VIEWPORT_WIDTH = _dim.w -20;
                            if (autoSizeH)VIEWPORT_HEIGHT = _dim.h - pos.y;
                        }
                    }
                } else {
                    if (_dim == null) {
                        if (autoSizeW)VIEWPORT_WIDTH = 400;
                    } else {
                        if (autoSizeW)VIEWPORT_WIDTH = _dim.w;
                        if (autoSizeH)VIEWPORT_HEIGHT = _dim.h;
                    }
                }
                if (autoSizeH) {
                    if (VIEWPORT_HEIGHT < 0) VIEWPORT_HEIGHT = 320;
                    _container.style.height = VIEWPORT_HEIGHT + "px";
                }
                if (autoSizeW) {
                    _container.style.width = VIEWPORT_WIDTH + "px";
                }
            } else {
                _container.style.width = VIEWPORT_WIDTH + "px";
                _container.style.height = VIEWPORT_HEIGHT + "px";
            }
            if (VIEWPORT_HEIGHT < 0) {
                VIEWPORT_HEIGHT = 320;
            }
            if (VIEWPORT_WIDTH < 0) {
                VIEWPORT_WIDTH = 500;
            }

            if (args.useIframe) {
                if (_self.iframe) {
                    _self.iframe.style.height = VIEWPORT_HEIGHT -2 + "px";
                    _self.iframe.style.width = VIEWPORT_WIDTH -2 + "px";
                }
            }
            // used for tracking with IE
            oldWidth = _doc.body.clientWidth;
        };

        this.setContent = function(_c) {
            var _con;
            if (_c.message)_c = _c.message;
            if (_c.value) _con = _c.value;
            else _con = _c;
            if (!_self.iframe)_container.innerHTML = _con;
            else {
                _self.clear();
                // recreate the ifrfame
                _container.innerHTML = "";
                createIframe(_c);
            }
        };

        function init() {
            if (window.attachEvent) {
                window.attachEvent('onresize', layout);
            } else if (window.addEventListener) {
                window.addEventListener('resize', layout, true);
            }
            var _ot = _container;
            if (_self.iframe) {
                _ot = _self.iframe;
            }
            if (args.overflow) _ot.style.overflow = args.overflow;
            if (args.overflowX)_ot.style.overflowX = args.overflowX;
            if (args.overflowY)_ot.style.overflowY = args.overflowY;

            if (args.startWidth) {
                VIEWPORT_WIDTH = Number(args.startWidth);
                _container.style.width = VIEWPORT_WIDTH + "px";
            } else {
                VIEWPORT_WIDTH = _container.clientWidth;
                autoSizeW = true;
            }

            if (args.startHeight) {
                VIEWPORT_HEIGHT = Number(args.startHeight);
            } else {
                VIEWPORT_HEIGHT = _container.clientHeight;
                autoSizeH = true;
            }
            if (VIEWPORT_HEIGHT <= 0) VIEWPORT_HEIGHT = 320;
            _container.style.height = VIEWPORT_HEIGHT + "px";
            if (args.useIFrame &&  _self.iframe) {
                _self.iframe.style.height = VIEWPORT_HEIGHT + "px";
            }
            _self.resize();
            if (args.url && !args.useIframe) {
                _self.loadURL(args.url);
            } else if (args.content && !_self.iframe) {
                _container.innerHTML = args.content;
            } else if (args.url && !args.url) {
                _self.loadURL(args.url);
            }
            if (_self.iframe) _self.iframe.style.display = "inline";
        }

        var resizing = false;
        var lastSize = 0;

        function createIframe(content) {
            _self.iframe = getElement(_self.uuid + "_iframe");
            if (_self.iframe) _self.iframe.parentNode.removeChild(_self.iframe);
            // use this technique as creating the iframe programmatically does not allow us to turn the border off
            var iframeTemplate = "<iframe style='display:none' id='" + _self.uuid + "_iframe' name='" + _self.uuid +
                "_iframe' frameborder=0 scrolling=" +
                ((args.overflow == 'hidden') ? 'NO' : 'YES') + "></iframe>";
            _container.innerHTML = iframeTemplate;
            // wait for the iframe
            var _t = setInterval(function() {
                if (getElement(_self.uuid + "_iframe")) {
                    clearInterval(_t);
                    _self.iframe = getElement(_self.uuid + "_iframe");
                    setTimeout(function(){
                        if (/http/i.test(_self.url) &&  top.window.location.host != getHost(_self.url)) {
                            _self.externalDomain = true;
                        } else {
                            _self.externalDomain = false;
                        }
                        if (!_self.externalDomain && content) {
                            var _w = _self.iframe.contentWindow ? _self.iframe.contentWindow  : _self.iframe.window;
                            if (_w && _w.document.body) {
                                _w.document.body.innerHTML = content;
                            }
                        }
                        init();},0);
                }
            }, 5);
        }

        function layout() {
            if (!_jmaki.MSIE) {
                _self.resize();
                return;
            }
            // special handling for ie resizing.
            // we wait for no change for a full second before resizing.
            if (oldWidth != _doc.body.clientWidth && !resizing) {
                if (!resizing) {
                    resizing = true;
                    setTimeout(layout,500);
                }
            } else if (resizing && _doc.body.clientWidth == lastSize) {
                resizing = false;
                _self.resize();
            } else if (resizing) {
                lastSize = _doc.body.clientWidth;
                setTimeout(layout, 500);
            }
        }
        if (args.useIframe && args.useIframe == true) {
            createIframe(args.content);
        } else init();
    };

    this.destroy = function() {
        _jmaki.dcontainers.remove(_self.uuid);
        if (window.attachEvent) {
            window.dettachEvent('onresize', layout);
        } else if (window.addEventListener) {
            window.removeEventListener('resize', layout, true);
        }
    };

  this.Injector = function() {

  var _uuid = new Date().getMilliseconds();
  var _injector = this;
  var _processing = false;

  var tasks = [];

  this.inject = function(task) {
   // make sure jmaki creates a list of libraries it can not load
    if (tasks.length == 0 && !_processing) {
        inject(task);
    } else {
        tasks.push(task);
    }
  };

  /**
   *
   * Load template text aloing with an associated script
   *
   * Argument p properties are as follows:
   *
   * url :              Not required but used if you want to get the template from
   *                    something other than the injection serlvet. For example if
   *                    you want to load content directly from a a JSP or HTML file.
   *
   * p.injectionPoint:  Not required. This is the id of an element into. If this is
   *                    not specfied a div will be created under the root node of
   *                    the document and the template will be injected into it.
   *                    Content is injected by setting the innerHTML property
   *                    of an element to the template text.
   */
  function inject(task) {
      _processing = true;
      _jmaki.doAjax({
            method:"GET",
            url: task.url,
            asynchronous: false,
            callback: function(req){
                   getContent(req.responseText, task);
               //if no parent is given append to the document root
               var injectionPoint;
               if (typeof task.injectionPoint == 'string') {
                   injectionPoint = getElement(task.injectionPoint);
                   // wait for the injection point
                   if (!getElement(task.injectionPoint)) {
                       var _t = setInterval(function() {
                           if (getElement(task.injectionPoint)) {
                               clearInterval(_t);
                               injectionPoint = getElement(task.injectionPoint);
                               setTimeout(function(){processTask(injectionPoint,task);},0);
                           }
                       }, 25);
                   } else {
                       processTask(injectionPoint, task);
                   }
                } else {
                    processTask(task.injectionPoint, task);
                }
         },
         onerror : function(){
            var ip = task.injectionPoint;
            if (typeof task.injectionPoint == 'string') {
                ip = getElement(task.injectionPoint);
            }
            _jmaki.clearWidgets(ip);
            ip.innerHTML = _jmaki.getMessage("unable_to_load_url", [task.url]);
            processNextTask();
         }

       });
  }

  function processTask(injectionPoint, task) {
      _jmaki.clearWidgets(injectionPoint);
      var _id = "injector_" + _uuid;
      var data = task.content + "<div id='" + _id + "'></div>";
      injectionPoint.innerHTML = data;
      // wait for the content to be loaded
      var _t = setInterval(function() {
          if (getElement(_id)) {
              clearInterval(_t);
              try {
                  _injector.loadScripts(task,processNextTask);
              } catch (e) {
                  injectionPoint.innerHTML = "<span style='color:red'>" + e.message + "</span>";
              }
          }
      }, 25);
  }

  // pass in a reference to the task
  // start the next task
  function processNextTask() {
      if (tasks.length >0) {
          var _t = tasks.shift();
          inject(_t);
      }
      _processing = false;
  }


  /**
   *
   * Load template text aloing with an associated script
   *
   * Argument p properties are as follows:
   *
   * url :              Not required but used if you want to get the template from
   *                    something other than the injection serlvet. For example if
   *                    you want to load content directly from a a JSP, JSF call, PHP, or HTML file.
   */
  this.get = function (p) {
      var _data;
       _jmaki.doAjax({
            method:"GET",
            url: p.url,
            asynchronous: false,
            callback: function(req){
                _data = getContent(req.responseText);
            }
           }
           );
           return _data;
  };

  /**
   * If were returning an text document remove any script in the
   * the document and add it to the global scope using a time out.
   */
  function getContent(rawContent, _task) {

   _task.embeddedScripts = [];
   _task.embeddedStyles = [];
   _task.scriptReferences = [];
   _task.styleReferences = [];

    var _t = rawContent;

    // recursively go through and weed out the scripts

    var gscripts = _doc.getElementsByTagName("script");
    var gstyles = _doc.getElementsByTagName("link");
    while (_t.indexOf("<script") != -1) {
            var realStart = _t.indexOf("<script");
            var scriptSourceStart = _t.indexOf("src=", (realStart));
            var scriptElementEnd = _t.indexOf(">", realStart);
            var end = _t.indexOf("</script>", (realStart)) + "</script>".length;
            if (realStart != -1 && scriptSourceStart != -1) {
                var scriptSourceName;
                var scriptSourceLinkStart= scriptSourceStart + 5;
                var quoteType =  _t.substring(scriptSourceStart + 4, (scriptSourceStart +5));
                var scriptSourceLinkEnd= _t.indexOf("\"", (scriptSourceLinkStart + 1));
              	scriptSourceLinkEnd= _t.indexOf(quoteType, (scriptSourceLinkStart + 1));
                if (scriptSourceStart < scriptElementEnd) {
                    scriptSourceName = _t.substring(scriptSourceLinkStart, scriptSourceLinkEnd);
                    // prevent multiple inclusions of the same script
                    var exists = false;
                    for (var i = 0; i < gscripts.length; i++) {
                        if (typeof gscripts[i].src) {
                            if (gscripts[i].src == scriptSourceName) {
                                exists = true;
                                break;
                            }
                        }
                    }
                    if (!exists) {
                        _task.scriptReferences.push(scriptSourceName);
                    }
                }
            }
           // now remove the script body
           var scriptBodyStart =  scriptElementEnd + 1;
           var sBody = _t.substring(scriptBodyStart, end - "</script>".length);
           if (sBody.length > 0) {
              	_task.embeddedScripts.push(sBody);
           }
           //remove script
           _t = _t.substring(0, realStart) + _t.substring(end, _t.length);
           scriptSourceLinkEnd = -1;
      }
      while (_t.indexOf("<style") != -1) {
           var rs = _t.indexOf("<style");
           var styleElementEnd = _t.indexOf(">", rs);
           var e2 = _t.indexOf("</style>", rs) ;
           var styleBodyStart =  styleElementEnd + 1;
           var sBody2 = _t.substring(styleBodyStart, e2);
           if (sBody2.length > 0) {
              _task.embeddedStyles.push(sBody2);
           }
           //remove style
           _t = _t.substring(0, rs) + _t.substring(e2 + "</style>".length, _t.length);
        }
        // get the links
        while (_t.indexOf("<link") != -1) {
            var rs2 = _t.indexOf("<link");
            var styleSourceStart = _t.indexOf("href=", rs2);
            var styleElementEnd2 = _t.indexOf(">", rs2) +1;
            if (rs2 != -1 && styleSourceStart != -1) {
                var styleSourceName;
                var styleSourceLinkStart= styleSourceStart + 6;
                var qt =  _t.substring(styleSourceStart + 5, (styleSourceStart + 6));
                var styleSourceLinkEnd= _t.indexOf(qt, (styleSourceLinkStart + 1));
                if (styleSourceStart < styleElementEnd2) {
                    styleSourceName = _t.substring(styleSourceLinkStart, styleSourceLinkEnd);
	              	var exists2 = false;
                        for (var ii = 0; ii < gstyles.length; ii++) {
                            if (isDefined(gstyles[ii].href)) {
                                if (gstyles[ii].href == styleSourceName) {
                                    exists2 = true;
                                }
                            }
                        }
		        if (!exists2) {
		          	_task.styleReferences.push(styleSourceName);
	    	      }
                }
                //remove style
                _t = _t.substring(0, rs2) + _t.substring(styleElementEnd2, _t.length);
            }
        }

        var head = _doc.getElementsByTagName("head")[0];

        // inject the links
        for(var loop = 0; _task.styleReferences && loop < _task.styleReferences.length; loop++) {
            var link = _doc.createElement("link");
            link.href = _task.styleReferences[loop];
            link.type = "text/css";
            link.rel = "stylesheet";
            head.appendChild(link);
        }

        var stylesElement;
        if (_task.embeddedStyles.length > 0) {
            stylesElement = _doc.createElement("style");
            stylesElement.type="text/css";
            var stylesText;
            for(var j = 0; j < _task.embeddedStyles.length; j++) {
                stylesText = stylesText + _task.embeddedStyles[j];
            }
            if (_doc.styleSheets[0].cssText) {
               _doc.styleSheets[0].cssText = _doc.styleSheets[0].cssText + stylesText;
            } else {
                stylesElement.appendChild(_doc.createTextNode(stylesText));
                head.appendChild(stylesElement);
            }
        }
        _task.content = _t;
      }

      this.loadScripts = function(task, initFunction) {
          var _loadEmbeded = function() {
              // evaluate the embedded javascripts in the order they were added
              for(var loop = 0;task.embeddedScripts && loop < task.embeddedScripts.length; loop++) {
                  var script = task.embeddedScripts[loop];
                  // append to the script a method to call the scriptLoaderCallback
                  eval(script);
                  if (loop == (task.embeddedScripts.length -1)) {
                      if (isDefined(initFunction)) initFunction();
                      return;
                  }
              }
              if (task.embeddedScripts && task.embeddedScripts.length == 0 && isDefined(initFunction)) initFunction();
          };
          if (task.scriptReferences && task.scriptReferences.length > 0){
              // load the global scripts before loading the embeded scripts
              return _jmaki.addLibraries({ libs : task.scriptReferences.reverse(), callback : _loadEmbeded, cleanup : false});
          } else {
              _loadEmbeded();
          }
          return true;
     };
  };
  this.injector = new this.Injector();
}

if (typeof jmaki == 'undefined') {
    var jmaki = new Jmaki();
    jmaki.widgets = {};

    var oldLoad  = window.onload;

    /**
     * onload calls bootstrap function to initialize and load all registered widgets
     * override initial onload.
     */
    window.onload = function() {
        if (!jmaki.initialized) {
            jmaki.initialize();
        } else {
            jmaki.bootstrapWidgets();
            return;
        }
        if (typeof oldLoad  == 'function') {
            oldLoad();
        }
    }
}