Add Prototype.js library unit tests. Hopefully the first of many AJAX test suites. Patch by John Resig <jresig@mozilla.com>. r=sayrer
authorsayrer@gmail.com
Mon, 23 Apr 2007 21:01:42 -0700
changeset 748 575391b63de02143dda789d1139f1198d5416d06
parent 747 24d1f8e8258f7684f1edd3bdc2fd1290805ad3d5
child 749 fd60f541b9a8a60ddf6baf5ae0ec1f7a4a37336a
push idunknown
push userunknown
push dateunknown
reviewerssayrer
milestone1.9a4pre
Add Prototype.js library unit tests. Hopefully the first of many AJAX test suites. Patch by John Resig <jresig@mozilla.com>. r=sayrer
dom/tests/mochitest/Makefile.in
dom/tests/mochitest/ajax/Makefile.in
dom/tests/mochitest/ajax/lib/AJAX_setup.js
dom/tests/mochitest/ajax/lib/Makefile.in
dom/tests/mochitest/ajax/lib/MochiKit_packed.js
dom/tests/mochitest/ajax/lib/SimpleTest.js
dom/tests/mochitest/ajax/lib/test.css
dom/tests/mochitest/ajax/prototype/Makefile.in
dom/tests/mochitest/ajax/prototype/dist/prototype.js
dom/tests/mochitest/ajax/prototype/manifest.json
dom/tests/mochitest/ajax/prototype/test/lib/unittest.js
dom/tests/mochitest/ajax/prototype/test/test.css
dom/tests/mochitest/ajax/prototype/test/unit/ajax.html
dom/tests/mochitest/ajax/prototype/test/unit/array.html
dom/tests/mochitest/ajax/prototype/test/unit/base.html
dom/tests/mochitest/ajax/prototype/test/unit/dom.html
dom/tests/mochitest/ajax/prototype/test/unit/element_mixins.html
dom/tests/mochitest/ajax/prototype/test/unit/enumerable.html
dom/tests/mochitest/ajax/prototype/test/unit/fixtures/content.html
dom/tests/mochitest/ajax/prototype/test/unit/fixtures/empty.js
dom/tests/mochitest/ajax/prototype/test/unit/fixtures/hello.js
dom/tests/mochitest/ajax/prototype/test/unit/fixtures/logo.gif
dom/tests/mochitest/ajax/prototype/test/unit/form.html
dom/tests/mochitest/ajax/prototype/test/unit/hash.html
dom/tests/mochitest/ajax/prototype/test/unit/position.html
dom/tests/mochitest/ajax/prototype/test/unit/range.html
dom/tests/mochitest/ajax/prototype/test/unit/selector.html
dom/tests/mochitest/ajax/prototype/test/unit/string.html
dom/tests/mochitest/ajax/prototype/test/unit/unit_tests.html
dom/tests/mochitest/ajax/prototype/test_Prototype.html
--- a/dom/tests/mochitest/Makefile.in
+++ b/dom/tests/mochitest/Makefile.in
@@ -40,13 +40,14 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 
 DIRS		+= dom-level1-core \
 		dom-level2-core \
+		ajax \
 		bugs \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/ajax/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS =	lib \
+	prototype \
+	$(NULL)
+
+include $(topsrcdir)/config/rules.mk
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/ajax/lib/AJAX_setup.js
@@ -0,0 +1,30 @@
+var AJAXtests = [];
+
+function runAJAXTest() {
+  if (AJAXtests.length == 0) {
+    SimpleTest.finish();
+    return;
+  }
+
+  var test = AJAXtests.shift();
+  var testframe = document.getElementById("testframe");
+  testframe.src = test;
+}
+
+function onManifestLoad(manifest) {
+  if (manifest.testcases) {
+    AJAXtests = manifest.testcases;
+    runAJAXTest();    
+  } else {
+    ok(false, "manifest check", "no manifest!?!");
+    SimpleTest.finish();
+  }
+}
+
+function fetchManifest() {
+  var d = loadJSONDoc("manifest.json");
+  d.addBoth(onManifestLoad);
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(fetchManifest);
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/ajax/lib/Makefile.in
@@ -0,0 +1,55 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir	= dom/tests/mochitest/ajax/lib
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES	= \
+		AJAX_setup.js \
+		MochiKit_packed.js \
+		SimpleTest.js \
+		test.css \
+		$(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/ajax/lib/MochiKit_packed.js
@@ -0,0 +1,6113 @@
+/***
+
+    MochiKit.MochiKit 1.4 : PACKED VERSION
+
+    THIS FILE IS AUTOMATICALLY GENERATED.  If creating patches, please
+    diff against the source tree, not this file.
+
+    See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+    (c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Base");
+}
+if(typeof (MochiKit)=="undefined"){
+MochiKit={};
+}
+if(typeof (MochiKit.Base)=="undefined"){
+MochiKit.Base={};
+}
+if(typeof (MochiKit.__export__)=="undefined"){
+MochiKit.__export__=(MochiKit.__compat__||(typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined"));
+}
+MochiKit.Base.VERSION="1.4";
+MochiKit.Base.NAME="MochiKit.Base";
+MochiKit.Base.update=function(_1,_2){
+if(_1===null){
+_1={};
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+if(typeof (o)!="undefined"&&o!==null){
+for(var k in o){
+_1[k]=o[k];
+}
+}
+}
+return _1;
+};
+MochiKit.Base.update(MochiKit.Base,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},camelize:function(_6){
+var _7=_6.split("-");
+var cc=_7[0];
+for(var i=1;i<_7.length;i++){
+cc+=_7[i].charAt(0).toUpperCase()+_7[i].substring(1);
+}
+return cc;
+},counter:function(n){
+if(arguments.length===0){
+n=1;
+}
+return function(){
+return n++;
+};
+},clone:function(obj){
+var me=arguments.callee;
+if(arguments.length==1){
+me.prototype=obj;
+return new me();
+}
+},_flattenArray:function(res,lst){
+for(var i=0;i<lst.length;i++){
+var o=lst[i];
+if(o instanceof Array){
+arguments.callee(res,o);
+}else{
+res.push(o);
+}
+}
+return res;
+},flattenArray:function(lst){
+return MochiKit.Base._flattenArray([],lst);
+},flattenArguments:function(lst){
+var res=[];
+var m=MochiKit.Base;
+var _15=m.extend(null,arguments);
+while(_15.length){
+var o=_15.shift();
+if(o&&typeof (o)=="object"&&typeof (o.length)=="number"){
+for(var i=o.length-1;i>=0;i--){
+_15.unshift(o[i]);
+}
+}else{
+res.push(o);
+}
+}
+return res;
+},extend:function(_16,obj,_17){
+if(!_17){
+_17=0;
+}
+if(obj){
+var l=obj.length;
+if(typeof (l)!="number"){
+if(typeof (MochiKit.Iter)!="undefined"){
+obj=MochiKit.Iter.list(obj);
+l=obj.length;
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+if(!_16){
+_16=[];
+}
+for(var i=_17;i<l;i++){
+_16.push(obj[i]);
+}
+}
+return _16;
+},updatetree:function(_19,obj){
+if(_19===null){
+_19={};
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+if(typeof (o)!="undefined"&&o!==null){
+for(var k in o){
+var v=o[k];
+if(typeof (_19[k])=="object"&&typeof (v)=="object"){
+arguments.callee(_19[k],v);
+}else{
+_19[k]=v;
+}
+}
+}
+}
+return _19;
+},setdefault:function(_21,obj){
+if(_21===null){
+_21={};
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+for(var k in o){
+if(!(k in _21)){
+_21[k]=o[k];
+}
+}
+}
+return _21;
+},keys:function(obj){
+var _22=[];
+for(var _23 in obj){
+_22.push(_23);
+}
+return _22;
+},values:function(obj){
+var _24=[];
+for(var _25 in obj){
+_24.push(obj[_25]);
+}
+return _24;
+},items:function(obj){
+var _26=[];
+var e;
+for(var _28 in obj){
+var v;
+try{
+v=obj[_28];
+}
+catch(e){
+continue;
+}
+_26.push([_28,v]);
+}
+return _26;
+},_newNamedError:function(_29,_30,_31){
+_31.prototype=new MochiKit.Base.NamedError(_29.NAME+"."+_30);
+_29[_30]=_31;
+},operator:{truth:function(a){
+return !!a;
+},lognot:function(a){
+return !a;
+},identity:function(a){
+return a;
+},not:function(a){
+return ~a;
+},neg:function(a){
+return -a;
+},add:function(a,b){
+return a+b;
+},sub:function(a,b){
+return a-b;
+},div:function(a,b){
+return a/b;
+},mod:function(a,b){
+return a%b;
+},mul:function(a,b){
+return a*b;
+},and:function(a,b){
+return a&b;
+},or:function(a,b){
+return a|b;
+},xor:function(a,b){
+return a^b;
+},lshift:function(a,b){
+return a<<b;
+},rshift:function(a,b){
+return a>>b;
+},zrshift:function(a,b){
+return a>>>b;
+},eq:function(a,b){
+return a==b;
+},ne:function(a,b){
+return a!=b;
+},gt:function(a,b){
+return a>b;
+},ge:function(a,b){
+return a>=b;
+},lt:function(a,b){
+return a<b;
+},le:function(a,b){
+return a<=b;
+},seq:function(a,b){
+return a===b;
+},sne:function(a,b){
+return a!==b;
+},ceq:function(a,b){
+return MochiKit.Base.compare(a,b)===0;
+},cne:function(a,b){
+return MochiKit.Base.compare(a,b)!==0;
+},cgt:function(a,b){
+return MochiKit.Base.compare(a,b)==1;
+},cge:function(a,b){
+return MochiKit.Base.compare(a,b)!=-1;
+},clt:function(a,b){
+return MochiKit.Base.compare(a,b)==-1;
+},cle:function(a,b){
+return MochiKit.Base.compare(a,b)!=1;
+},logand:function(a,b){
+return a&&b;
+},logor:function(a,b){
+return a||b;
+},contains:function(a,b){
+return b in a;
+}},forwardCall:function(_34){
+return function(){
+return this[_34].apply(this,arguments);
+};
+},itemgetter:function(_35){
+return function(arg){
+return arg[_35];
+};
+},typeMatcher:function(){
+var _37={};
+for(var i=0;i<arguments.length;i++){
+var typ=arguments[i];
+_37[typ]=typ;
+}
+return function(){
+for(var i=0;i<arguments.length;i++){
+if(!(typeof (arguments[i]) in _37)){
+return false;
+}
+}
+return true;
+};
+},isNull:function(){
+for(var i=0;i<arguments.length;i++){
+if(arguments[i]!==null){
+return false;
+}
+}
+return true;
+},isUndefinedOrNull:function(){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+if(!(typeof (o)=="undefined"||o===null)){
+return false;
+}
+}
+return true;
+},isEmpty:function(obj){
+return !MochiKit.Base.isNotEmpty.apply(this,arguments);
+},isNotEmpty:function(obj){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+if(!(o&&o.length)){
+return false;
+}
+}
+return true;
+},isArrayLike:function(){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+var typ=typeof (o);
+if((typ!="object"&&!(typ=="function"&&typeof (o.item)=="function"))||o===null||typeof (o.length)!="number"||o.nodeType===3){
+return false;
+}
+}
+return true;
+},isDateLike:function(){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+if(typeof (o)!="object"||o===null||typeof (o.getTime)!="function"){
+return false;
+}
+}
+return true;
+},xmap:function(fn){
+if(fn===null){
+return MochiKit.Base.extend(null,arguments,1);
+}
+var _40=[];
+for(var i=1;i<arguments.length;i++){
+_40.push(fn(arguments[i]));
+}
+return _40;
+},map:function(fn,lst){
+var m=MochiKit.Base;
+var itr=MochiKit.Iter;
+var _42=m.isArrayLike;
+if(arguments.length<=2){
+if(!_42(lst)){
+if(itr){
+lst=itr.list(lst);
+if(fn===null){
+return lst;
+}
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+if(fn===null){
+return m.extend(null,lst);
+}
+var _43=[];
+for(var i=0;i<lst.length;i++){
+_43.push(fn(lst[i]));
+}
+return _43;
+}else{
+if(fn===null){
+fn=Array;
+}
+var _44=null;
+for(i=1;i<arguments.length;i++){
+if(!_42(arguments[i])){
+if(itr){
+return itr.list(itr.imap.apply(null,arguments));
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+var l=arguments[i].length;
+if(_44===null||_44>l){
+_44=l;
+}
+}
+_43=[];
+for(i=0;i<_44;i++){
+var _45=[];
+for(var j=1;j<arguments.length;j++){
+_45.push(arguments[j][i]);
+}
+_43.push(fn.apply(this,_45));
+}
+return _43;
+}
+},xfilter:function(fn){
+var _47=[];
+if(fn===null){
+fn=MochiKit.Base.operator.truth;
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+if(fn(o)){
+_47.push(o);
+}
+}
+return _47;
+},filter:function(fn,lst,_48){
+var _49=[];
+var m=MochiKit.Base;
+if(!m.isArrayLike(lst)){
+if(MochiKit.Iter){
+lst=MochiKit.Iter.list(lst);
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+if(fn===null){
+fn=m.operator.truth;
+}
+if(typeof (Array.prototype.filter)=="function"){
+return Array.prototype.filter.call(lst,fn,_48);
+}else{
+if(typeof (_48)=="undefined"||_48===null){
+for(var i=0;i<lst.length;i++){
+var o=lst[i];
+if(fn(o)){
+_49.push(o);
+}
+}
+}else{
+for(i=0;i<lst.length;i++){
+o=lst[i];
+if(fn.call(_48,o)){
+_49.push(o);
+}
+}
+}
+}
+return _49;
+},_wrapDumbFunction:function(_50){
+return function(){
+switch(arguments.length){
+case 0:
+return _50();
+case 1:
+return _50(arguments[0]);
+case 2:
+return _50(arguments[0],arguments[1]);
+case 3:
+return _50(arguments[0],arguments[1],arguments[2]);
+}
+var _51=[];
+for(var i=0;i<arguments.length;i++){
+_51.push("arguments["+i+"]");
+}
+return eval("(func("+_51.join(",")+"))");
+};
+},methodcaller:function(_52){
+var _53=MochiKit.Base.extend(null,arguments,1);
+if(typeof (_52)=="function"){
+return function(obj){
+return _52.apply(obj,_53);
+};
+}else{
+return function(obj){
+return obj[_52].apply(obj,_53);
+};
+}
+},method:function(_54,_55){
+var m=MochiKit.Base;
+return m.bind.apply(this,m.extend([_55,_54],arguments,2));
+},compose:function(f1,f2){
+var _58=[];
+var m=MochiKit.Base;
+if(arguments.length===0){
+throw new TypeError("compose() requires at least one argument");
+}
+for(var i=0;i<arguments.length;i++){
+var fn=arguments[i];
+if(typeof (fn)!="function"){
+throw new TypeError(m.repr(fn)+" is not a function");
+}
+_58.push(fn);
+}
+return function(){
+var _59=arguments;
+for(var i=_58.length-1;i>=0;i--){
+_59=[_58[i].apply(this,_59)];
+}
+return _59[0];
+};
+},bind:function(_60,_61){
+if(typeof (_60)=="string"){
+_60=_61[_60];
+}
+var _62=_60.im_func;
+var _63=_60.im_preargs;
+var _64=_60.im_self;
+var m=MochiKit.Base;
+if(typeof (_60)=="function"&&typeof (_60.apply)=="undefined"){
+_60=m._wrapDumbFunction(_60);
+}
+if(typeof (_62)!="function"){
+_62=_60;
+}
+if(typeof (_61)!="undefined"){
+_64=_61;
+}
+if(typeof (_63)=="undefined"){
+_63=[];
+}else{
+_63=_63.slice();
+}
+m.extend(_63,arguments,2);
+var _65=function(){
+var _66=arguments;
+var me=arguments.callee;
+if(me.im_preargs.length>0){
+_66=m.concat(me.im_preargs,_66);
+}
+var _61=me.im_self;
+if(!_61){
+_61=this;
+}
+return me.im_func.apply(_61,_66);
+};
+_65.im_self=_64;
+_65.im_func=_62;
+_65.im_preargs=_63;
+return _65;
+},bindMethods:function(_67){
+var _68=MochiKit.Base.bind;
+for(var k in _67){
+var _69=_67[k];
+if(typeof (_69)=="function"){
+_67[k]=_68(_69,_67);
+}
+}
+},registerComparator:function(_70,_71,_72,_73){
+MochiKit.Base.comparatorRegistry.register(_70,_71,_72,_73);
+},_primitives:{"boolean":true,"string":true,"number":true},compare:function(a,b){
+if(a==b){
+return 0;
+}
+var _74=(typeof (a)=="undefined"||a===null);
+var _75=(typeof (b)=="undefined"||b===null);
+if(_74&&_75){
+return 0;
+}else{
+if(_74){
+return -1;
+}else{
+if(_75){
+return 1;
+}
+}
+}
+var m=MochiKit.Base;
+var _76=m._primitives;
+if(!(typeof (a) in _76&&typeof (b) in _76)){
+try{
+return m.comparatorRegistry.match(a,b);
+}
+catch(e){
+if(e!=m.NotFound){
+throw e;
+}
+}
+}
+if(a<b){
+return -1;
+}else{
+if(a>b){
+return 1;
+}
+}
+var _77=m.repr;
+throw new TypeError(_77(a)+" and "+_77(b)+" can not be compared");
+},compareDateLike:function(a,b){
+return MochiKit.Base.compare(a.getTime(),b.getTime());
+},compareArrayLike:function(a,b){
+var _78=MochiKit.Base.compare;
+var _79=a.length;
+var _80=0;
+if(_79>b.length){
+_80=1;
+_79=b.length;
+}else{
+if(_79<b.length){
+_80=-1;
+}
+}
+for(var i=0;i<_79;i++){
+var cmp=_78(a[i],b[i]);
+if(cmp){
+return cmp;
+}
+}
+return _80;
+},registerRepr:function(_82,_83,_84,_85){
+MochiKit.Base.reprRegistry.register(_82,_83,_84,_85);
+},repr:function(o){
+if(typeof (o)=="undefined"){
+return "undefined";
+}else{
+if(o===null){
+return "null";
+}
+}
+try{
+if(typeof (o.__repr__)=="function"){
+return o.__repr__();
+}else{
+if(typeof (o.repr)=="function"&&o.repr!=arguments.callee){
+return o.repr();
+}
+}
+return MochiKit.Base.reprRegistry.match(o);
+}
+catch(e){
+if(typeof (o.NAME)=="string"&&(o.toString==Function.prototype.toString||o.toString==Object.prototype.toString)){
+return o.NAME;
+}
+}
+try{
+var _86=(o+"");
+}
+catch(e){
+return "["+typeof (o)+"]";
+}
+if(typeof (o)=="function"){
+o=_86.replace(/^\s+/,"");
+var idx=o.indexOf("{");
+if(idx!=-1){
+o=o.substr(0,idx)+"{...}";
+}
+}
+return _86;
+},reprArrayLike:function(o){
+var m=MochiKit.Base;
+return "["+m.map(m.repr,o).join(", ")+"]";
+},reprString:function(o){
+return ("\""+o.replace(/(["\\])/g,"\\$1")+"\"").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r");
+},reprNumber:function(o){
+return o+"";
+},registerJSON:function(_88,_89,_90,_91){
+MochiKit.Base.jsonRegistry.register(_88,_89,_90,_91);
+},evalJSON:function(){
+return eval("("+arguments[0]+")");
+},serializeJSON:function(o){
+var _92=typeof (o);
+if(_92=="number"||_92=="boolean"){
+return o+"";
+}else{
+if(o===null){
+return "null";
+}
+}
+var m=MochiKit.Base;
+var _93=m.reprString;
+if(_92=="string"){
+return _93(o);
+}
+var me=arguments.callee;
+var _94;
+if(typeof (o.__json__)=="function"){
+_94=o.__json__();
+if(o!==_94){
+return me(_94);
+}
+}
+if(typeof (o.json)=="function"){
+_94=o.json();
+if(o!==_94){
+return me(_94);
+}
+}
+if(_92!="function"&&typeof (o.length)=="number"){
+var res=[];
+for(var i=0;i<o.length;i++){
+var val=me(o[i]);
+if(typeof (val)!="string"){
+val="undefined";
+}
+res.push(val);
+}
+return "["+res.join(", ")+"]";
+}
+try{
+_94=m.jsonRegistry.match(o);
+if(o!==_94){
+return me(_94);
+}
+}
+catch(e){
+if(e!=m.NotFound){
+throw e;
+}
+}
+if(_92=="undefined"){
+throw new TypeError("undefined can not be serialized as JSON");
+}
+if(_92=="function"){
+return null;
+}
+res=[];
+for(var k in o){
+var _96;
+if(typeof (k)=="number"){
+_96="\""+k+"\"";
+}else{
+if(typeof (k)=="string"){
+_96=_93(k);
+}else{
+continue;
+}
+}
+val=me(o[k]);
+if(typeof (val)!="string"){
+continue;
+}
+res.push(_96+":"+val);
+}
+return "{"+res.join(", ")+"}";
+},objEqual:function(a,b){
+return (MochiKit.Base.compare(a,b)===0);
+},arrayEqual:function(_97,arr){
+if(_97.length!=arr.length){
+return false;
+}
+return (MochiKit.Base.compare(_97,arr)===0);
+},concat:function(){
+var _99=[];
+var _100=MochiKit.Base.extend;
+for(var i=0;i<arguments.length;i++){
+_100(_99,arguments[i]);
+}
+return _99;
+},keyComparator:function(key){
+var m=MochiKit.Base;
+var _102=m.compare;
+if(arguments.length==1){
+return function(a,b){
+return _102(a[key],b[key]);
+};
+}
+var _103=m.extend(null,arguments);
+return function(a,b){
+var rval=0;
+for(var i=0;(rval===0)&&(i<_103.length);i++){
+var key=_103[i];
+rval=_102(a[key],b[key]);
+}
+return rval;
+};
+},reverseKeyComparator:function(key){
+var _105=MochiKit.Base.keyComparator.apply(this,arguments);
+return function(a,b){
+return _105(b,a);
+};
+},partial:function(func){
+var m=MochiKit.Base;
+return m.bind.apply(this,m.extend([func,undefined],arguments,1));
+},listMinMax:function(_107,lst){
+if(lst.length===0){
+return null;
+}
+var cur=lst[0];
+var _109=MochiKit.Base.compare;
+for(var i=1;i<lst.length;i++){
+var o=lst[i];
+if(_109(o,cur)==_107){
+cur=o;
+}
+}
+return cur;
+},objMax:function(){
+return MochiKit.Base.listMinMax(1,arguments);
+},objMin:function(){
+return MochiKit.Base.listMinMax(-1,arguments);
+},findIdentical:function(lst,_110,_111,end){
+if(typeof (end)=="undefined"||end===null){
+end=lst.length;
+}
+if(typeof (_111)=="undefined"||_111===null){
+_111=0;
+}
+for(var i=_111;i<end;i++){
+if(lst[i]===_110){
+return i;
+}
+}
+return -1;
+},mean:function(){
+var sum=0;
+var m=MochiKit.Base;
+var args=m.extend(null,arguments);
+var _115=args.length;
+while(args.length){
+var o=args.shift();
+if(o&&typeof (o)=="object"&&typeof (o.length)=="number"){
+_115+=o.length-1;
+for(var i=o.length-1;i>=0;i--){
+sum+=o[i];
+}
+}else{
+sum+=o;
+}
+}
+if(_115<=0){
+throw new TypeError("mean() requires at least one argument");
+}
+return sum/_115;
+},median:function(){
+var data=MochiKit.Base.flattenArguments(arguments);
+if(data.length===0){
+throw new TypeError("median() requires at least one argument");
+}
+data.sort(compare);
+if(data.length%2==0){
+var _117=data.length/2;
+return (data[_117]+data[_117-1])/2;
+}else{
+return data[(data.length-1)/2];
+}
+},findValue:function(lst,_118,_119,end){
+if(typeof (end)=="undefined"||end===null){
+end=lst.length;
+}
+if(typeof (_119)=="undefined"||_119===null){
+_119=0;
+}
+var cmp=MochiKit.Base.compare;
+for(var i=_119;i<end;i++){
+if(cmp(lst[i],_118)===0){
+return i;
+}
+}
+return -1;
+},nodeWalk:function(node,_121){
+var _122=[node];
+var _123=MochiKit.Base.extend;
+while(_122.length){
+var res=_121(_122.shift());
+if(res){
+_123(_122,res);
+}
+}
+},nameFunctions:function(_124){
+var base=_124.NAME;
+if(typeof (base)=="undefined"){
+base="";
+}else{
+base=base+".";
+}
+for(var name in _124){
+var o=_124[name];
+if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){
+try{
+o.NAME=base+name;
+}
+catch(e){
+}
+}
+}
+},queryString:function(_127,_128){
+if(typeof (MochiKit.DOM)!="undefined"&&arguments.length==1&&(typeof (_127)=="string"||(typeof (_127.nodeType)!="undefined"&&_127.nodeType>0))){
+var kv=MochiKit.DOM.formContents(_127);
+_127=kv[0];
+_128=kv[1];
+}else{
+if(arguments.length==1){
+var o=_127;
+_127=[];
+_128=[];
+for(var k in o){
+var v=o[k];
+if(typeof (v)=="function"){
+continue;
+}else{
+if(typeof (v)!="string"&&typeof (v.length)=="number"){
+for(var i=0;i<v.length;i++){
+_127.push(k);
+_128.push(v[i]);
+}
+}else{
+_127.push(k);
+_128.push(v);
+}
+}
+}
+}
+}
+var rval=[];
+var len=Math.min(_127.length,_128.length);
+var _131=MochiKit.Base.urlEncode;
+for(var i=0;i<len;i++){
+v=_128[i];
+if(typeof (v)!="undefined"&&v!==null){
+rval.push(_131(_127[i])+"="+_131(v));
+}
+}
+return rval.join("&");
+},parseQueryString:function(_132,_133){
+var qstr=(_132[0]=="?")?_132.substring(1):_132;
+var _135=qstr.replace(/\+/g,"%20").split(/(\&amp\;|\&\#38\;|\&#x26;|\&)/);
+var o={};
+var _136;
+if(typeof (decodeURIComponent)!="undefined"){
+_136=decodeURIComponent;
+}else{
+_136=unescape;
+}
+if(_133){
+for(var i=0;i<_135.length;i++){
+var pair=_135[i].split("=");
+if(pair.length!==2){
+continue;
+}
+var name=_136(pair[0]);
+var arr=o[name];
+if(!(arr instanceof Array)){
+arr=[];
+o[name]=arr;
+}
+arr.push(_136(pair[1]));
+}
+}else{
+for(i=0;i<_135.length;i++){
+pair=_135[i].split("=");
+if(pair.length!==2){
+continue;
+}
+o[_136(pair[0])]=_136(pair[1]);
+}
+}
+return o;
+}});
+MochiKit.Base.AdapterRegistry=function(){
+this.pairs=[];
+};
+MochiKit.Base.AdapterRegistry.prototype={register:function(name,_138,wrap,_140){
+if(_140){
+this.pairs.unshift([name,_138,wrap]);
+}else{
+this.pairs.push([name,_138,wrap]);
+}
+},match:function(){
+for(var i=0;i<this.pairs.length;i++){
+var pair=this.pairs[i];
+if(pair[1].apply(this,arguments)){
+return pair[2].apply(this,arguments);
+}
+}
+throw MochiKit.Base.NotFound;
+},unregister:function(name){
+for(var i=0;i<this.pairs.length;i++){
+var pair=this.pairs[i];
+if(pair[0]==name){
+this.pairs.splice(i,1);
+return true;
+}
+}
+return false;
+}};
+MochiKit.Base.EXPORT=["flattenArray","noop","camelize","counter","clone","extend","update","updatetree","setdefault","keys","values","items","NamedError","operator","forwardCall","itemgetter","typeMatcher","isCallable","isUndefined","isUndefinedOrNull","isNull","isEmpty","isNotEmpty","isArrayLike","isDateLike","xmap","map","xfilter","filter","methodcaller","compose","bind","bindMethods","NotFound","AdapterRegistry","registerComparator","compare","registerRepr","repr","objEqual","arrayEqual","concat","keyComparator","reverseKeyComparator","partial","merge","listMinMax","listMax","listMin","objMax","objMin","nodeWalk","zip","urlEncode","queryString","serializeJSON","registerJSON","evalJSON","parseQueryString","findValue","findIdentical","flattenArguments","method","average","mean","median"];
+MochiKit.Base.EXPORT_OK=["nameFunctions","comparatorRegistry","reprRegistry","jsonRegistry","compareDateLike","compareArrayLike","reprArrayLike","reprString","reprNumber"];
+MochiKit.Base._exportSymbols=function(_141,_142){
+if(!MochiKit.__export__){
+return;
+}
+var all=_142.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_141[all[i]]=_142[all[i]];
+}
+};
+MochiKit.Base.__new__=function(){
+var m=this;
+m.noop=m.operator.identity;
+m.forward=m.forwardCall;
+m.find=m.findValue;
+if(typeof (encodeURIComponent)!="undefined"){
+m.urlEncode=function(_144){
+return encodeURIComponent(_144).replace(/\'/g,"%27");
+};
+}else{
+m.urlEncode=function(_145){
+return escape(_145).replace(/\+/g,"%2B").replace(/\"/g,"%22").rval.replace(/\'/g,"%27");
+};
+}
+m.NamedError=function(name){
+this.message=name;
+this.name=name;
+};
+m.NamedError.prototype=new Error();
+m.update(m.NamedError.prototype,{repr:function(){
+if(this.message&&this.message!=this.name){
+return this.name+"("+m.repr(this.message)+")";
+}else{
+return this.name+"()";
+}
+},toString:m.forwardCall("repr")});
+m.NotFound=new m.NamedError("MochiKit.Base.NotFound");
+m.listMax=m.partial(m.listMinMax,1);
+m.listMin=m.partial(m.listMinMax,-1);
+m.isCallable=m.typeMatcher("function");
+m.isUndefined=m.typeMatcher("undefined");
+m.merge=m.partial(m.update,null);
+m.zip=m.partial(m.map,null);
+m.average=m.mean;
+m.comparatorRegistry=new m.AdapterRegistry();
+m.registerComparator("dateLike",m.isDateLike,m.compareDateLike);
+m.registerComparator("arrayLike",m.isArrayLike,m.compareArrayLike);
+m.reprRegistry=new m.AdapterRegistry();
+m.registerRepr("arrayLike",m.isArrayLike,m.reprArrayLike);
+m.registerRepr("string",m.typeMatcher("string"),m.reprString);
+m.registerRepr("numbers",m.typeMatcher("number","boolean"),m.reprNumber);
+m.jsonRegistry=new m.AdapterRegistry();
+var all=m.concat(m.EXPORT,m.EXPORT_OK);
+m.EXPORT_TAGS={":common":m.concat(m.EXPORT_OK),":all":all};
+m.nameFunctions(this);
+};
+MochiKit.Base.__new__();
+if(MochiKit.__export__){
+compare=MochiKit.Base.compare;
+compose=MochiKit.Base.compose;
+serializeJSON=MochiKit.Base.serializeJSON;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.Base);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Iter");
+dojo.require("MochiKit.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Iter depends on MochiKit.Base!";
+}
+if(typeof (MochiKit.Iter)=="undefined"){
+MochiKit.Iter={};
+}
+MochiKit.Iter.NAME="MochiKit.Iter";
+MochiKit.Iter.VERSION="1.4";
+MochiKit.Base.update(MochiKit.Iter,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},registerIteratorFactory:function(name,_146,_147,_148){
+MochiKit.Iter.iteratorRegistry.register(name,_146,_147,_148);
+},iter:function(_149,_150){
+var self=MochiKit.Iter;
+if(arguments.length==2){
+return self.takewhile(function(a){
+return a!=_150;
+},_149);
+}
+if(typeof (_149.next)=="function"){
+return _149;
+}else{
+if(typeof (_149.iter)=="function"){
+return _149.iter();
+}
+}
+try{
+return self.iteratorRegistry.match(_149);
+}
+catch(e){
+var m=MochiKit.Base;
+if(e==m.NotFound){
+e=new TypeError(typeof (_149)+": "+m.repr(_149)+" is not iterable");
+}
+throw e;
+}
+},count:function(n){
+if(!n){
+n=0;
+}
+var m=MochiKit.Base;
+return {repr:function(){
+return "count("+n+")";
+},toString:m.forwardCall("repr"),next:m.counter(n)};
+},cycle:function(p){
+var self=MochiKit.Iter;
+var m=MochiKit.Base;
+var lst=[];
+var _153=self.iter(p);
+return {repr:function(){
+return "cycle(...)";
+},toString:m.forwardCall("repr"),next:function(){
+try{
+var rval=_153.next();
+lst.push(rval);
+return rval;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+if(lst.length===0){
+this.next=function(){
+throw self.StopIteration;
+};
+}else{
+var i=-1;
+this.next=function(){
+i=(i+1)%lst.length;
+return lst[i];
+};
+}
+return this.next();
+}
+}};
+},repeat:function(elem,n){
+var m=MochiKit.Base;
+if(typeof (n)=="undefined"){
+return {repr:function(){
+return "repeat("+m.repr(elem)+")";
+},toString:m.forwardCall("repr"),next:function(){
+return elem;
+}};
+}
+return {repr:function(){
+return "repeat("+m.repr(elem)+", "+n+")";
+},toString:m.forwardCall("repr"),next:function(){
+if(n<=0){
+throw MochiKit.Iter.StopIteration;
+}
+n-=1;
+return elem;
+}};
+},next:function(_155){
+return _155.next();
+},izip:function(p,q){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+var next=self.next;
+var _158=m.map(self.iter,arguments);
+return {repr:function(){
+return "izip(...)";
+},toString:m.forwardCall("repr"),next:function(){
+return m.map(next,_158);
+}};
+},ifilter:function(pred,seq){
+var m=MochiKit.Base;
+seq=MochiKit.Iter.iter(seq);
+if(pred===null){
+pred=m.operator.truth;
+}
+return {repr:function(){
+return "ifilter(...)";
+},toString:m.forwardCall("repr"),next:function(){
+while(true){
+var rval=seq.next();
+if(pred(rval)){
+return rval;
+}
+}
+return undefined;
+}};
+},ifilterfalse:function(pred,seq){
+var m=MochiKit.Base;
+seq=MochiKit.Iter.iter(seq);
+if(pred===null){
+pred=m.operator.truth;
+}
+return {repr:function(){
+return "ifilterfalse(...)";
+},toString:m.forwardCall("repr"),next:function(){
+while(true){
+var rval=seq.next();
+if(!pred(rval)){
+return rval;
+}
+}
+return undefined;
+}};
+},islice:function(seq){
+var self=MochiKit.Iter;
+var m=MochiKit.Base;
+seq=self.iter(seq);
+var _161=0;
+var stop=0;
+var step=1;
+var i=-1;
+if(arguments.length==2){
+stop=arguments[1];
+}else{
+if(arguments.length==3){
+_161=arguments[1];
+stop=arguments[2];
+}else{
+_161=arguments[1];
+stop=arguments[2];
+step=arguments[3];
+}
+}
+return {repr:function(){
+return "islice("+["...",_161,stop,step].join(", ")+")";
+},toString:m.forwardCall("repr"),next:function(){
+var rval;
+while(i<_161){
+rval=seq.next();
+i++;
+}
+if(_161>=stop){
+throw self.StopIteration;
+}
+_161+=step;
+return rval;
+}};
+},imap:function(fun,p,q){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+var _165=m.map(self.iter,m.extend(null,arguments,1));
+var map=m.map;
+var next=self.next;
+return {repr:function(){
+return "imap(...)";
+},toString:m.forwardCall("repr"),next:function(){
+return fun.apply(this,map(next,_165));
+}};
+},applymap:function(fun,seq,self){
+seq=MochiKit.Iter.iter(seq);
+var m=MochiKit.Base;
+return {repr:function(){
+return "applymap(...)";
+},toString:m.forwardCall("repr"),next:function(){
+return fun.apply(self,seq.next());
+}};
+},chain:function(p,q){
+var self=MochiKit.Iter;
+var m=MochiKit.Base;
+if(arguments.length==1){
+return self.iter(arguments[0]);
+}
+var _167=m.map(self.iter,arguments);
+return {repr:function(){
+return "chain(...)";
+},toString:m.forwardCall("repr"),next:function(){
+while(_167.length>1){
+try{
+return _167[0].next();
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+_167.shift();
+}
+}
+if(_167.length==1){
+var arg=_167.shift();
+this.next=m.bind("next",arg);
+return this.next();
+}
+throw self.StopIteration;
+}};
+},takewhile:function(pred,seq){
+var self=MochiKit.Iter;
+seq=self.iter(seq);
+return {repr:function(){
+return "takewhile(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+var rval=seq.next();
+if(!pred(rval)){
+this.next=function(){
+throw self.StopIteration;
+};
+this.next();
+}
+return rval;
+}};
+},dropwhile:function(pred,seq){
+seq=MochiKit.Iter.iter(seq);
+var m=MochiKit.Base;
+var bind=m.bind;
+return {"repr":function(){
+return "dropwhile(...)";
+},"toString":m.forwardCall("repr"),"next":function(){
+while(true){
+var rval=seq.next();
+if(!pred(rval)){
+break;
+}
+}
+this.next=bind("next",seq);
+return rval;
+}};
+},_tee:function(_169,sync,_171){
+sync.pos[_169]=-1;
+var m=MochiKit.Base;
+var _172=m.listMin;
+return {repr:function(){
+return "tee("+_169+", ...)";
+},toString:m.forwardCall("repr"),next:function(){
+var rval;
+var i=sync.pos[_169];
+if(i==sync.max){
+rval=_171.next();
+sync.deque.push(rval);
+sync.max+=1;
+sync.pos[_169]+=1;
+}else{
+rval=sync.deque[i-sync.min];
+sync.pos[_169]+=1;
+if(i==sync.min&&_172(sync.pos)!=sync.min){
+sync.min+=1;
+sync.deque.shift();
+}
+}
+return rval;
+}};
+},tee:function(_173,n){
+var rval=[];
+var sync={"pos":[],"deque":[],"max":-1,"min":-1};
+if(arguments.length==1||typeof (n)=="undefined"||n===null){
+n=2;
+}
+var self=MochiKit.Iter;
+_173=self.iter(_173);
+var _tee=self._tee;
+for(var i=0;i<n;i++){
+rval.push(_tee(i,sync,_173));
+}
+return rval;
+},list:function(_175){
+var m=MochiKit.Base;
+if(typeof (_175.slice)=="function"){
+return _175.slice();
+}else{
+if(m.isArrayLike(_175)){
+return m.concat(_175);
+}
+}
+var self=MochiKit.Iter;
+_175=self.iter(_175);
+var rval=[];
+try{
+while(true){
+rval.push(_175.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return rval;
+}
+return undefined;
+},reduce:function(fn,_176,_177){
+var i=0;
+var x=_177;
+var self=MochiKit.Iter;
+_176=self.iter(_176);
+if(arguments.length<3){
+try{
+x=_176.next();
+}
+catch(e){
+if(e==self.StopIteration){
+e=new TypeError("reduce() of empty sequence with no initial value");
+}
+throw e;
+}
+i++;
+}
+try{
+while(true){
+x=fn(x,_176.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+return x;
+},range:function(){
+var _179=0;
+var stop=0;
+var step=1;
+if(arguments.length==1){
+stop=arguments[0];
+}else{
+if(arguments.length==2){
+_179=arguments[0];
+stop=arguments[1];
+}else{
+if(arguments.length==3){
+_179=arguments[0];
+stop=arguments[1];
+step=arguments[2];
+}else{
+throw new TypeError("range() takes 1, 2, or 3 arguments!");
+}
+}
+}
+if(step===0){
+throw new TypeError("range() step must not be 0");
+}
+return {next:function(){
+if((step>0&&_179>=stop)||(step<0&&_179<=stop)){
+throw MochiKit.Iter.StopIteration;
+}
+var rval=_179;
+_179+=step;
+return rval;
+},repr:function(){
+return "range("+[_179,stop,step].join(", ")+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+},sum:function(_180,_181){
+if(typeof (_181)=="undefined"||_181===null){
+_181=0;
+}
+var x=_181;
+var self=MochiKit.Iter;
+_180=self.iter(_180);
+try{
+while(true){
+x+=_180.next();
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+return x;
+},exhaust:function(_182){
+var self=MochiKit.Iter;
+_182=self.iter(_182);
+try{
+while(true){
+_182.next();
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+},forEach:function(_183,func,self){
+var m=MochiKit.Base;
+if(arguments.length>2){
+func=m.bind(func,self);
+}
+if(m.isArrayLike(_183)){
+try{
+for(var i=0;i<_183.length;i++){
+func(_183[i]);
+}
+}
+catch(e){
+if(e!=MochiKit.Iter.StopIteration){
+throw e;
+}
+}
+}else{
+self=MochiKit.Iter;
+self.exhaust(self.imap(func,_183));
+}
+},every:function(_184,func){
+var self=MochiKit.Iter;
+try{
+self.ifilterfalse(func,_184).next();
+return false;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return true;
+}
+},sorted:function(_185,cmp){
+var rval=MochiKit.Iter.list(_185);
+if(arguments.length==1){
+cmp=MochiKit.Base.compare;
+}
+rval.sort(cmp);
+return rval;
+},reversed:function(_186){
+var rval=MochiKit.Iter.list(_186);
+rval.reverse();
+return rval;
+},some:function(_187,func){
+var self=MochiKit.Iter;
+try{
+self.ifilter(func,_187).next();
+return true;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return false;
+}
+},iextend:function(lst,_188){
+if(MochiKit.Base.isArrayLike(_188)){
+for(var i=0;i<_188.length;i++){
+lst.push(_188[i]);
+}
+}else{
+var self=MochiKit.Iter;
+_188=self.iter(_188);
+try{
+while(true){
+lst.push(_188.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+}
+return lst;
+},groupby:function(_189,_190){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(arguments.length<2){
+_190=m.operator.identity;
+}
+_189=self.iter(_189);
+var pk=undefined;
+var k=undefined;
+var v;
+function fetch(){
+v=_189.next();
+k=_190(v);
+}
+function eat(){
+var ret=v;
+v=undefined;
+return ret;
+}
+var _193=true;
+var _194=m.compare;
+return {repr:function(){
+return "groupby(...)";
+},next:function(){
+while(_194(k,pk)===0){
+fetch();
+if(_193){
+_193=false;
+break;
+}
+}
+pk=k;
+return [k,{next:function(){
+if(v==undefined){
+fetch();
+}
+if(_194(k,pk)!==0){
+throw self.StopIteration;
+}
+return eat();
+}}];
+}};
+},groupby_as_array:function(_195,_196){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(arguments.length<2){
+_196=m.operator.identity;
+}
+_195=self.iter(_195);
+var _197=[];
+var _198=true;
+var _199;
+var _200=m.compare;
+while(true){
+try{
+var _201=_195.next();
+var key=_196(_201);
+}
+catch(e){
+if(e==self.StopIteration){
+break;
+}
+throw e;
+}
+if(_198||_200(key,_199)!==0){
+var _202=[];
+_197.push([key,_202]);
+}
+_202.push(_201);
+_198=false;
+_199=key;
+}
+return _197;
+},arrayLikeIter:function(_203){
+var i=0;
+return {repr:function(){
+return "arrayLikeIter(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+if(i>=_203.length){
+throw MochiKit.Iter.StopIteration;
+}
+return _203[i++];
+}};
+},hasIterateNext:function(_204){
+return (_204&&typeof (_204.iterateNext)=="function");
+},iterateNextIter:function(_205){
+return {repr:function(){
+return "iterateNextIter(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+var rval=_205.iterateNext();
+if(rval===null||rval===undefined){
+throw MochiKit.Iter.StopIteration;
+}
+return rval;
+}};
+}});
+MochiKit.Iter.EXPORT_OK=["iteratorRegistry","arrayLikeIter","hasIterateNext","iterateNextIter",];
+MochiKit.Iter.EXPORT=["StopIteration","registerIteratorFactory","iter","count","cycle","repeat","next","izip","ifilter","ifilterfalse","islice","imap","applymap","chain","takewhile","dropwhile","tee","list","reduce","range","sum","exhaust","forEach","every","sorted","reversed","some","iextend","groupby","groupby_as_array"];
+MochiKit.Iter.__new__=function(){
+var m=MochiKit.Base;
+if(typeof (StopIteration)!="undefined"){
+this.StopIteration=StopIteration;
+}else{
+this.StopIteration=new m.NamedError("StopIteration");
+}
+this.iteratorRegistry=new m.AdapterRegistry();
+this.registerIteratorFactory("arrayLike",m.isArrayLike,this.arrayLikeIter);
+this.registerIteratorFactory("iterateNext",this.hasIterateNext,this.iterateNextIter);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Iter.__new__();
+if(MochiKit.__export__){
+reduce=MochiKit.Iter.reduce;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.Iter);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Logging");
+dojo.require("MochiKit.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Logging depends on MochiKit.Base!";
+}
+if(typeof (MochiKit.Logging)=="undefined"){
+MochiKit.Logging={};
+}
+MochiKit.Logging.NAME="MochiKit.Logging";
+MochiKit.Logging.VERSION="1.4";
+MochiKit.Logging.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Logging.toString=function(){
+return this.__repr__();
+};
+MochiKit.Logging.EXPORT=["LogLevel","LogMessage","Logger","alertListener","logger","log","logError","logDebug","logFatal","logWarning"];
+MochiKit.Logging.EXPORT_OK=["logLevelAtLeast","isLogMessage","compareLogMessage"];
+MochiKit.Logging.LogMessage=function(num,_207,info){
+this.num=num;
+this.level=_207;
+this.info=info;
+this.timestamp=new Date();
+};
+MochiKit.Logging.LogMessage.prototype={repr:function(){
+var m=MochiKit.Base;
+return "LogMessage("+m.map(m.repr,[this.num,this.level,this.info]).join(", ")+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+MochiKit.Base.update(MochiKit.Logging,{logLevelAtLeast:function(_209){
+var self=MochiKit.Logging;
+if(typeof (_209)=="string"){
+_209=self.LogLevel[_209];
+}
+return function(msg){
+var _211=msg.level;
+if(typeof (_211)=="string"){
+_211=self.LogLevel[_211];
+}
+return _211>=_209;
+};
+},isLogMessage:function(){
+var _212=MochiKit.Logging.LogMessage;
+for(var i=0;i<arguments.length;i++){
+if(!(arguments[i] instanceof _212)){
+return false;
+}
+}
+return true;
+},compareLogMessage:function(a,b){
+return MochiKit.Base.compare([a.level,a.info],[b.level,b.info]);
+},alertListener:function(msg){
+alert("num: "+msg.num+"\nlevel: "+msg.level+"\ninfo: "+msg.info.join(" "));
+}});
+MochiKit.Logging.Logger=function(_213){
+this.counter=0;
+if(typeof (_213)=="undefined"||_213===null){
+_213=-1;
+}
+this.maxSize=_213;
+this._messages=[];
+this.listeners={};
+this.useNativeConsole=false;
+};
+MochiKit.Logging.Logger.prototype={clear:function(){
+this._messages.splice(0,this._messages.length);
+},logToConsole:function(msg){
+if(typeof (window)!="undefined"&&window.console&&window.console.log){
+window.console.log(msg.replace(/%/g,"\uff05"));
+}else{
+if(typeof (opera)!="undefined"&&opera.postError){
+opera.postError(msg);
+}else{
+if(typeof (printfire)=="function"){
+printfire(msg);
+}else{
+if(typeof (Debug)!="undefined"&&Debug.writeln){
+Debug.writeln(msg);
+}else{
+if(typeof (debug)!="undefined"&&debug.trace){
+debug.trace(msg);
+}
+}
+}
+}
+}
+},dispatchListeners:function(msg){
+for(var k in this.listeners){
+var pair=this.listeners[k];
+if(pair.ident!=k||(pair[0]&&!pair[0](msg))){
+continue;
+}
+pair[1](msg);
+}
+},addListener:function(_214,_215,_216){
+if(typeof (_215)=="string"){
+_215=MochiKit.Logging.logLevelAtLeast(_215);
+}
+var _217=[_215,_216];
+_217.ident=_214;
+this.listeners[_214]=_217;
+},removeListener:function(_218){
+delete this.listeners[_218];
+},baseLog:function(_219,_220){
+var msg=new MochiKit.Logging.LogMessage(this.counter,_219,MochiKit.Base.extend(null,arguments,1));
+this._messages.push(msg);
+this.dispatchListeners(msg);
+if(this.useNativeConsole){
+this.logToConsole(msg.level+": "+msg.info.join(" "));
+}
+this.counter+=1;
+while(this.maxSize>=0&&this._messages.length>this.maxSize){
+this._messages.shift();
+}
+},getMessages:function(_221){
+var _222=0;
+if(!(typeof (_221)=="undefined"||_221===null)){
+_222=Math.max(0,this._messages.length-_221);
+}
+return this._messages.slice(_222);
+},getMessageText:function(_223){
+if(typeof (_223)=="undefined"||_223===null){
+_223=30;
+}
+var _224=this.getMessages(_223);
+if(_224.length){
+var lst=map(function(m){
+return "\n  ["+m.num+"] "+m.level+": "+m.info.join(" ");
+},_224);
+lst.unshift("LAST "+_224.length+" MESSAGES:");
+return lst.join("");
+}
+return "";
+},debuggingBookmarklet:function(_225){
+if(typeof (MochiKit.LoggingPane)=="undefined"){
+alert(this.getMessageText());
+}else{
+MochiKit.LoggingPane.createLoggingPane(_225||false);
+}
+}};
+MochiKit.Logging.__new__=function(){
+this.LogLevel={ERROR:40,FATAL:50,WARNING:30,INFO:20,DEBUG:10};
+var m=MochiKit.Base;
+m.registerComparator("LogMessage",this.isLogMessage,this.compareLogMessage);
+var _226=m.partial;
+var _227=this.Logger;
+var _228=_227.prototype.baseLog;
+m.update(this.Logger.prototype,{debug:_226(_228,"DEBUG"),log:_226(_228,"INFO"),error:_226(_228,"ERROR"),fatal:_226(_228,"FATAL"),warning:_226(_228,"WARNING")});
+var self=this;
+var _229=function(name){
+return function(){
+self.logger[name].apply(self.logger,arguments);
+};
+};
+this.log=_229("log");
+this.logError=_229("error");
+this.logDebug=_229("debug");
+this.logFatal=_229("fatal");
+this.logWarning=_229("warning");
+this.logger=new _227();
+this.logger.useNativeConsole=true;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+if(typeof (printfire)=="undefined"&&typeof (document)!="undefined"&&document.createEvent&&typeof (dispatchEvent)!="undefined"){
+printfire=function(){
+printfire.args=arguments;
+var ev=document.createEvent("Events");
+ev.initEvent("printfire",false,true);
+dispatchEvent(ev);
+};
+}
+MochiKit.Logging.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Logging);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.DateTime");
+}
+if(typeof (MochiKit)=="undefined"){
+MochiKit={};
+}
+if(typeof (MochiKit.DateTime)=="undefined"){
+MochiKit.DateTime={};
+}
+MochiKit.DateTime.NAME="MochiKit.DateTime";
+MochiKit.DateTime.VERSION="1.4";
+MochiKit.DateTime.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.DateTime.toString=function(){
+return this.__repr__();
+};
+MochiKit.DateTime.isoDate=function(str){
+str=str+"";
+if(typeof (str)!="string"||str.length===0){
+return null;
+}
+var iso=str.split("-");
+if(iso.length===0){
+return null;
+}
+return new Date(iso[0],iso[1]-1,iso[2]);
+};
+MochiKit.DateTime._isoRegexp=/(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/;
+MochiKit.DateTime.isoTimestamp=function(str){
+str=str+"";
+if(typeof (str)!="string"||str.length===0){
+return null;
+}
+var res=str.match(MochiKit.DateTime._isoRegexp);
+if(typeof (res)=="undefined"||res===null){
+return null;
+}
+var year,month,day,hour,min,sec,msec;
+year=parseInt(res[1],10);
+if(typeof (res[2])=="undefined"||res[2]===""){
+return new Date(year);
+}
+month=parseInt(res[2],10)-1;
+day=parseInt(res[3],10);
+if(typeof (res[4])=="undefined"||res[4]===""){
+return new Date(year,month,day);
+}
+hour=parseInt(res[4],10);
+min=parseInt(res[5],10);
+sec=(typeof (res[6])!="undefined"&&res[6]!=="")?parseInt(res[6],10):0;
+if(typeof (res[7])!="undefined"&&res[7]!==""){
+msec=Math.round(1000*parseFloat("0."+res[7]));
+}else{
+msec=0;
+}
+if((typeof (res[8])=="undefined"||res[8]==="")&&(typeof (res[9])=="undefined"||res[9]==="")){
+return new Date(year,month,day,hour,min,sec,msec);
+}
+var ofs;
+if(typeof (res[9])!="undefined"&&res[9]!==""){
+ofs=parseInt(res[10],10)*3600000;
+if(typeof (res[11])!="undefined"&&res[11]!==""){
+ofs+=parseInt(res[11],10)*60000;
+}
+if(res[9]=="-"){
+ofs=-ofs;
+}
+}else{
+ofs=0;
+}
+return new Date(Date.UTC(year,month,day,hour,min,sec,msec)-ofs);
+};
+MochiKit.DateTime.toISOTime=function(date,_236){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var hh=date.getHours();
+var mm=date.getMinutes();
+var ss=date.getSeconds();
+var lst=[((_236&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)];
+return lst.join(":");
+};
+MochiKit.DateTime.toISOTimestamp=function(date,_240){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var sep=_240?"T":" ";
+var foot=_240?"Z":"";
+if(_240){
+date=new Date(date.getTime()+(date.getTimezoneOffset()*60000));
+}
+return MochiKit.DateTime.toISODate(date)+sep+MochiKit.DateTime.toISOTime(date,_240)+foot;
+};
+MochiKit.DateTime.toISODate=function(date){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var _243=MochiKit.DateTime._padTwo;
+return [date.getFullYear(),_243(date.getMonth()+1),_243(date.getDate())].join("-");
+};
+MochiKit.DateTime.americanDate=function(d){
+d=d+"";
+if(typeof (d)!="string"||d.length===0){
+return null;
+}
+var a=d.split("/");
+return new Date(a[2],a[0]-1,a[1]);
+};
+MochiKit.DateTime._padTwo=function(n){
+return (n>9)?n:"0"+n;
+};
+MochiKit.DateTime.toPaddedAmericanDate=function(d){
+if(typeof (d)=="undefined"||d===null){
+return null;
+}
+var _245=MochiKit.DateTime._padTwo;
+return [_245(d.getMonth()+1),_245(d.getDate()),d.getFullYear()].join("/");
+};
+MochiKit.DateTime.toAmericanDate=function(d){
+if(typeof (d)=="undefined"||d===null){
+return null;
+}
+return [d.getMonth()+1,d.getDate(),d.getFullYear()].join("/");
+};
+MochiKit.DateTime.EXPORT=["isoDate","isoTimestamp","toISOTime","toISOTimestamp","toISODate","americanDate","toPaddedAmericanDate","toAmericanDate"];
+MochiKit.DateTime.EXPORT_OK=[];
+MochiKit.DateTime.EXPORT_TAGS={":common":MochiKit.DateTime.EXPORT,":all":MochiKit.DateTime.EXPORT};
+MochiKit.DateTime.__new__=function(){
+var base=this.NAME+".";
+for(var k in this){
+var o=this[k];
+if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){
+try{
+o.NAME=base+k;
+}
+catch(e){
+}
+}
+}
+};
+MochiKit.DateTime.__new__();
+if(typeof (MochiKit.Base)!="undefined"){
+MochiKit.Base._exportSymbols(this,MochiKit.DateTime);
+}else{
+(function(_246,_247){
+if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){
+var all=_247.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_246[all[i]]=_247[all[i]];
+}
+}
+})(this,MochiKit.DateTime);
+}
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Format");
+}
+if(typeof (MochiKit)=="undefined"){
+MochiKit={};
+}
+if(typeof (MochiKit.Format)=="undefined"){
+MochiKit.Format={};
+}
+MochiKit.Format.NAME="MochiKit.Format";
+MochiKit.Format.VERSION="1.4";
+MochiKit.Format.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Format.toString=function(){
+return this.__repr__();
+};
+MochiKit.Format._numberFormatter=function(_248,_249,_250,_251,_252,_253,_254,_255,_256){
+return function(num){
+num=parseFloat(num);
+if(typeof (num)=="undefined"||num===null||isNaN(num)){
+return _248;
+}
+var _257=_249;
+var _258=_250;
+if(num<0){
+num=-num;
+}else{
+_257=_257.replace(/-/,"");
+}
+var me=arguments.callee;
+var fmt=MochiKit.Format.formatLocale(_251);
+if(_252){
+num=num*100;
+_258=fmt.percent+_258;
+}
+num=MochiKit.Format.roundToFixed(num,_253);
+var _260=num.split(/\./);
+var _261=_260[0];
+var frac=(_260.length==1)?"":_260[1];
+var res="";
+while(_261.length<_254){
+_261="0"+_261;
+}
+if(_255){
+while(_261.length>_255){
+var i=_261.length-_255;
+res=fmt.separator+_261.substring(i,_261.length)+res;
+_261=_261.substring(0,i);
+}
+}
+res=_261+res;
+if(_253>0){
+while(frac.length<_256){
+frac=frac+"0";
+}
+res=res+fmt.decimal+frac;
+}
+return _257+res+_258;
+};
+};
+MochiKit.Format.numberFormatter=function(_263,_264,_265){
+if(typeof (_264)=="undefined"){
+_264="";
+}
+var _266=_263.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
+if(!_266){
+throw TypeError("Invalid pattern");
+}
+var _267=_263.substr(0,_266.index);
+var _268=_263.substr(_266.index+_266[0].length);
+if(_267.search(/-/)==-1){
+_267=_267+"-";
+}
+var _269=_266[1];
+var frac=(typeof (_266[2])=="string"&&_266[2]!="")?_266[2]:"";
+var _270=(typeof (_266[3])=="string"&&_266[3]!="");
+var tmp=_269.split(/,/);
+var _272;
+if(typeof (_265)=="undefined"){
+_265="default";
+}
+if(tmp.length==1){
+_272=null;
+}else{
+_272=tmp[1].length;
+}
+var _273=_269.length-_269.replace(/0/g,"").length;
+var _274=frac.length-frac.replace(/0/g,"").length;
+var _275=frac.length;
+var rval=MochiKit.Format._numberFormatter(_264,_267,_268,_265,_270,_275,_273,_272,_274);
+var m=MochiKit.Base;
+if(m){
+var fn=arguments.callee;
+var args=m.concat(arguments);
+rval.repr=function(){
+return [self.NAME,"(",map(m.repr,args).join(", "),")"].join("");
+};
+}
+return rval;
+};
+MochiKit.Format.formatLocale=function(_276){
+if(typeof (_276)=="undefined"||_276===null){
+_276="default";
+}
+if(typeof (_276)=="string"){
+var rval=MochiKit.Format.LOCALE[_276];
+if(typeof (rval)=="string"){
+rval=arguments.callee(rval);
+MochiKit.Format.LOCALE[_276]=rval;
+}
+return rval;
+}else{
+return _276;
+}
+};
+MochiKit.Format.twoDigitAverage=function(_277,_278){
+if(_278){
+var res=_277/_278;
+if(!isNaN(res)){
+return MochiKit.Format.twoDigitFloat(_277/_278);
+}
+}
+return "0";
+};
+MochiKit.Format.twoDigitFloat=function(_279){
+var sign=(_279<0?"-":"");
+var s=Math.floor(Math.abs(_279)*100).toString();
+if(s=="0"){
+return s;
+}
+if(s.length<3){
+while(s.charAt(s.length-1)=="0"){
+s=s.substring(0,s.length-1);
+}
+return sign+"0."+s;
+}
+var head=sign+s.substring(0,s.length-2);
+var tail=s.substring(s.length-2,s.length);
+if(tail=="00"){
+return head;
+}else{
+if(tail.charAt(1)=="0"){
+return head+"."+tail.charAt(0);
+}else{
+return head+"."+tail;
+}
+}
+};
+MochiKit.Format.lstrip=function(str,_284){
+str=str+"";
+if(typeof (str)!="string"){
+return null;
+}
+if(!_284){
+return str.replace(/^\s+/,"");
+}else{
+return str.replace(new RegExp("^["+_284+"]+"),"");
+}
+};
+MochiKit.Format.rstrip=function(str,_285){
+str=str+"";
+if(typeof (str)!="string"){
+return null;
+}
+if(!_285){
+return str.replace(/\s+$/,"");
+}else{
+return str.replace(new RegExp("["+_285+"]+$"),"");
+}
+};
+MochiKit.Format.strip=function(str,_286){
+var self=MochiKit.Format;
+return self.rstrip(self.lstrip(str,_286),_286);
+};
+MochiKit.Format.truncToFixed=function(_287,_288){
+_287=Math.floor(_287*Math.pow(10,_288));
+var res=(_287*Math.pow(10,-_288)).toFixed(_288);
+if(res.charAt(0)=="."){
+res="0"+res;
+}
+return res;
+};
+MochiKit.Format.roundToFixed=function(_289,_290){
+return MochiKit.Format.truncToFixed(_289+0.5*Math.pow(10,-_290),_290);
+};
+MochiKit.Format.percentFormat=function(_291){
+return MochiKit.Format.twoDigitFloat(100*_291)+"%";
+};
+MochiKit.Format.EXPORT=["truncToFixed","roundToFixed","numberFormatter","formatLocale","twoDigitAverage","twoDigitFloat","percentFormat","lstrip","rstrip","strip"];
+MochiKit.Format.LOCALE={en_US:{separator:",",decimal:".",percent:"%"},de_DE:{separator:".",decimal:",",percent:"%"},fr_FR:{separator:" ",decimal:",",percent:"%"},"default":"en_US"};
+MochiKit.Format.EXPORT_OK=[];
+MochiKit.Format.EXPORT_TAGS={":all":MochiKit.Format.EXPORT,":common":MochiKit.Format.EXPORT};
+MochiKit.Format.__new__=function(){
+var base=this.NAME+".";
+var k,v,o;
+for(k in this.LOCALE){
+o=this.LOCALE[k];
+if(typeof (o)=="object"){
+o.repr=function(){
+return this.NAME;
+};
+o.NAME=base+"LOCALE."+k;
+}
+}
+for(k in this){
+o=this[k];
+if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){
+try{
+o.NAME=base+k;
+}
+catch(e){
+}
+}
+}
+};
+MochiKit.Format.__new__();
+if(typeof (MochiKit.Base)!="undefined"){
+MochiKit.Base._exportSymbols(this,MochiKit.Format);
+}else{
+(function(_292,_293){
+if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){
+var all=_293.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_292[all[i]]=_293[all[i]];
+}
+}
+})(this,MochiKit.Format);
+}
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Async");
+dojo.require("MochiKit.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Async depends on MochiKit.Base!";
+}
+if(typeof (MochiKit.Async)=="undefined"){
+MochiKit.Async={};
+}
+MochiKit.Async.NAME="MochiKit.Async";
+MochiKit.Async.VERSION="1.4";
+MochiKit.Async.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Async.toString=function(){
+return this.__repr__();
+};
+MochiKit.Async.Deferred=function(_294){
+this.chain=[];
+this.id=this._nextId();
+this.fired=-1;
+this.paused=0;
+this.results=[null,null];
+this.canceller=_294;
+this.silentlyCancelled=false;
+this.chained=false;
+};
+MochiKit.Async.Deferred.prototype={repr:function(){
+var _295;
+if(this.fired==-1){
+_295="unfired";
+}else{
+if(this.fired===0){
+_295="success";
+}else{
+_295="error";
+}
+}
+return "Deferred("+this.id+", "+_295+")";
+},toString:MochiKit.Base.forwardCall("repr"),_nextId:MochiKit.Base.counter(),cancel:function(){
+var self=MochiKit.Async;
+if(this.fired==-1){
+if(this.canceller){
+this.canceller(this);
+}else{
+this.silentlyCancelled=true;
+}
+if(this.fired==-1){
+this.errback(new self.CancelledError(this));
+}
+}else{
+if((this.fired===0)&&(this.results[0] instanceof self.Deferred)){
+this.results[0].cancel();
+}
+}
+},_resback:function(res){
+this.fired=((res instanceof Error)?1:0);
+this.results[this.fired]=res;
+this._fire();
+},_check:function(){
+if(this.fired!=-1){
+if(!this.silentlyCancelled){
+throw new MochiKit.Async.AlreadyCalledError(this);
+}
+this.silentlyCancelled=false;
+return;
+}
+},callback:function(res){
+this._check();
+if(res instanceof MochiKit.Async.Deferred){
+throw new Error("Deferred instances can only be chained if they are the result of a callback");
+}
+this._resback(res);
+},errback:function(res){
+this._check();
+var self=MochiKit.Async;
+if(res instanceof self.Deferred){
+throw new Error("Deferred instances can only be chained if they are the result of a callback");
+}
+if(!(res instanceof Error)){
+res=new self.GenericError(res);
+}
+this._resback(res);
+},addBoth:function(fn){
+if(arguments.length>1){
+fn=MochiKit.Base.partial.apply(null,arguments);
+}
+return this.addCallbacks(fn,fn);
+},addCallback:function(fn){
+if(arguments.length>1){
+fn=MochiKit.Base.partial.apply(null,arguments);
+}
+return this.addCallbacks(fn,null);
+},addErrback:function(fn){
+if(arguments.length>1){
+fn=MochiKit.Base.partial.apply(null,arguments);
+}
+return this.addCallbacks(null,fn);
+},addCallbacks:function(cb,eb){
+if(this.chained){
+throw new Error("Chained Deferreds can not be re-used");
+}
+this.chain.push([cb,eb]);
+if(this.fired>=0){
+this._fire();
+}
+return this;
+},_fire:function(){
+var _298=this.chain;
+var _299=this.fired;
+var res=this.results[_299];
+var self=this;
+var cb=null;
+while(_298.length>0&&this.paused===0){
+var pair=_298.shift();
+var f=pair[_299];
+if(f===null){
+continue;
+}
+try{
+res=f(res);
+_299=((res instanceof Error)?1:0);
+if(res instanceof MochiKit.Async.Deferred){
+cb=function(res){
+self._resback(res);
+self.paused--;
+if((self.paused===0)&&(self.fired>=0)){
+self._fire();
+}
+};
+this.paused++;
+}
+}
+catch(err){
+_299=1;
+if(!(err instanceof Error)){
+err=new MochiKit.Async.GenericError(err);
+}
+res=err;
+}
+}
+this.fired=_299;
+this.results[_299]=res;
+if(cb&&this.paused){
+res.addBoth(cb);
+res.chained=true;
+}
+}};
+MochiKit.Base.update(MochiKit.Async,{evalJSONRequest:function(){
+return eval("("+arguments[0].responseText+")");
+},succeed:function(_301){
+var d=new MochiKit.Async.Deferred();
+d.callback.apply(d,arguments);
+return d;
+},fail:function(_302){
+var d=new MochiKit.Async.Deferred();
+d.errback.apply(d,arguments);
+return d;
+},getXMLHttpRequest:function(){
+var self=arguments.callee;
+if(!self.XMLHttpRequest){
+var _303=[function(){
+return new XMLHttpRequest();
+},function(){
+return new ActiveXObject("Msxml2.XMLHTTP");
+},function(){
+return new ActiveXObject("Microsoft.XMLHTTP");
+},function(){
+return new ActiveXObject("Msxml2.XMLHTTP.4.0");
+},function(){
+throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest");
+}];
+for(var i=0;i<_303.length;i++){
+var func=_303[i];
+try{
+self.XMLHttpRequest=func;
+return func();
+}
+catch(e){
+}
+}
+}
+return self.XMLHttpRequest();
+},_xhr_onreadystatechange:function(d){
+var m=MochiKit.Base;
+if(this.readyState==4){
+try{
+this.onreadystatechange=null;
+}
+catch(e){
+try{
+this.onreadystatechange=m.noop;
+}
+catch(e){
+}
+}
+var _304=null;
+try{
+_304=this.status;
+if(!_304&&m.isNotEmpty(this.responseText)){
+_304=304;
+}
+}
+catch(e){
+}
+if(_304==200||_304==304){
+d.callback(this);
+}else{
+var err=new MochiKit.Async.XMLHttpRequestError(this,"Request failed");
+if(err.number){
+d.errback(err);
+}else{
+d.errback(err);
+}
+}
+}
+},_xhr_canceller:function(req){
+try{
+req.onreadystatechange=null;
+}
+catch(e){
+try{
+req.onreadystatechange=MochiKit.Base.noop;
+}
+catch(e){
+}
+}
+req.abort();
+},sendXMLHttpRequest:function(req,_307){
+if(typeof (_307)=="undefined"||_307===null){
+_307="";
+}
+var m=MochiKit.Base;
+var self=MochiKit.Async;
+var d=new self.Deferred(m.partial(self._xhr_canceller,req));
+try{
+req.onreadystatechange=m.bind(self._xhr_onreadystatechange,req,d);
+req.send(_307);
+}
+catch(e){
+try{
+req.onreadystatechange=null;
+}
+catch(ignore){
+}
+d.errback(e);
+}
+return d;
+},doXHR:function(url,opts){
+var m=MochiKit.Base;
+opts=m.update({method:"GET",sendContent:""},opts);
+var self=MochiKit.Async;
+var req=self.getXMLHttpRequest();
+if(opts.queryString){
+var qs=m.queryString(opts.queryString);
+if(qs){
+url+="?"+qs;
+}
+}
+req.open(opts.method,url,true,opts.username,opts.password);
+if(req.overrideMimeType&&opts.mimeType){
+req.overrideMimeType(opts.mimeType);
+}
+if(opts.headers){
+var _311=opts.headers;
+if(!m.isArrayLike(_311)){
+_311=m.items(_311);
+}
+for(var i=0;i<_311.length;i++){
+var _312=_311[i];
+var name=_312[0];
+var _313=_312[1];
+req.setRequestHeader(name,_313);
+}
+}
+return self.sendXMLHttpRequest(req,opts.sendContent);
+},_buildURL:function(url){
+if(arguments.length>1){
+var m=MochiKit.Base;
+var qs=m.queryString.apply(null,m.extend(null,arguments,1));
+if(qs){
+return url+"?"+qs;
+}
+}
+return url;
+},doSimpleXMLHttpRequest:function(url){
+var self=MochiKit.Async;
+url=self._buildURL.apply(self,arguments);
+return self.doXHR(url);
+},loadJSONDoc:function(url){
+var self=MochiKit.Async;
+url=self._buildURL.apply(self,arguments);
+var d=self.doXHR(url,{"mimeType":"text/plain","headers":[["Accept","application/json"]]});
+d=d.addCallback(self.evalJSONRequest);
+return d;
+},wait:function(_314,_315){
+var d=new MochiKit.Async.Deferred();
+var m=MochiKit.Base;
+if(typeof (_315)!="undefined"){
+d.addCallback(function(){
+return _315;
+});
+}
+var _316=setTimeout(m.bind("callback",d),Math.floor(_314*1000));
+d.canceller=function(){
+try{
+clearTimeout(_316);
+}
+catch(e){
+}
+};
+return d;
+},callLater:function(_317,func){
+var m=MochiKit.Base;
+var _318=m.partial.apply(m,m.extend(null,arguments,1));
+return MochiKit.Async.wait(_317).addCallback(function(res){
+return _318();
+});
+}});
+MochiKit.Async.DeferredLock=function(){
+this.waiting=[];
+this.locked=false;
+this.id=this._nextId();
+};
+MochiKit.Async.DeferredLock.prototype={__class__:MochiKit.Async.DeferredLock,acquire:function(){
+var d=new MochiKit.Async.Deferred();
+if(this.locked){
+this.waiting.push(d);
+}else{
+this.locked=true;
+d.callback(this);
+}
+return d;
+},release:function(){
+if(!this.locked){
+throw TypeError("Tried to release an unlocked DeferredLock");
+}
+this.locked=false;
+if(this.waiting.length>0){
+this.locked=true;
+this.waiting.shift().callback(this);
+}
+},_nextId:MochiKit.Base.counter(),repr:function(){
+var _319;
+if(this.locked){
+_319="locked, "+this.waiting.length+" waiting";
+}else{
+_319="unlocked";
+}
+return "DeferredLock("+this.id+", "+_319+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+MochiKit.Async.DeferredList=function(list,_321,_322,_323,_324){
+MochiKit.Async.Deferred.apply(this,[_324]);
+this.list=list;
+var _325=[];
+this.resultList=_325;
+this.finishedCount=0;
+this.fireOnOneCallback=_321;
+this.fireOnOneErrback=_322;
+this.consumeErrors=_323;
+var cb=MochiKit.Base.bind(this._cbDeferred,this);
+for(var i=0;i<list.length;i++){
+var d=list[i];
+_325.push(undefined);
+d.addCallback(cb,i,true);
+d.addErrback(cb,i,false);
+}
+if(list.length===0&&!_321){
+this.callback(this.resultList);
+}
+};
+MochiKit.Async.DeferredList.prototype=new MochiKit.Async.Deferred();
+MochiKit.Async.DeferredList.prototype._cbDeferred=function(_326,_327,_328){
+this.resultList[_326]=[_327,_328];
+this.finishedCount+=1;
+if(this.fired==-1){
+if(_327&&this.fireOnOneCallback){
+this.callback([_326,_328]);
+}else{
+if(!_327&&this.fireOnOneErrback){
+this.errback(_328);
+}else{
+if(this.finishedCount==this.list.length){
+this.callback(this.resultList);
+}
+}
+}
+}
+if(!_327&&this.consumeErrors){
+_328=null;
+}
+return _328;
+};
+MochiKit.Async.gatherResults=function(_329){
+var d=new MochiKit.Async.DeferredList(_329,false,true,false);
+d.addCallback(function(_330){
+var ret=[];
+for(var i=0;i<_330.length;i++){
+ret.push(_330[i][1]);
+}
+return ret;
+});
+return d;
+};
+MochiKit.Async.maybeDeferred=function(func){
+var self=MochiKit.Async;
+var _331;
+try{
+var r=func.apply(null,MochiKit.Base.extend([],arguments,1));
+if(r instanceof self.Deferred){
+_331=r;
+}else{
+if(r instanceof Error){
+_331=self.fail(r);
+}else{
+_331=self.succeed(r);
+}
+}
+}
+catch(e){
+_331=self.fail(e);
+}
+return _331;
+};
+MochiKit.Async.EXPORT=["AlreadyCalledError","CancelledError","BrowserComplianceError","GenericError","XMLHttpRequestError","Deferred","succeed","fail","getXMLHttpRequest","doSimpleXMLHttpRequest","loadJSONDoc","wait","callLater","sendXMLHttpRequest","DeferredLock","DeferredList","gatherResults","maybeDeferred","doXHR"];
+MochiKit.Async.EXPORT_OK=["evalJSONRequest"];
+MochiKit.Async.__new__=function(){
+var m=MochiKit.Base;
+var ne=m.partial(m._newNamedError,this);
+ne("AlreadyCalledError",function(_334){
+this.deferred=_334;
+});
+ne("CancelledError",function(_335){
+this.deferred=_335;
+});
+ne("BrowserComplianceError",function(msg){
+this.message=msg;
+});
+ne("GenericError",function(msg){
+this.message=msg;
+});
+ne("XMLHttpRequestError",function(req,msg){
+this.req=req;
+this.message=msg;
+try{
+this.number=req.status;
+}
+catch(e){
+}
+});
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Async.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Async);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.DOM");
+dojo.require("MochiKit.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.DOM depends on MochiKit.Base!";
+}
+if(typeof (MochiKit.DOM)=="undefined"){
+MochiKit.DOM={};
+}
+MochiKit.DOM.NAME="MochiKit.DOM";
+MochiKit.DOM.VERSION="1.4";
+MochiKit.DOM.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.DOM.toString=function(){
+return this.__repr__();
+};
+MochiKit.DOM.EXPORT=["removeEmptyTextNodes","formContents","currentWindow","currentDocument","withWindow","withDocument","registerDOMConverter","coerceToDOM","createDOM","createDOMFunc","isChildNode","getNodeAttribute","setNodeAttribute","updateNodeAttributes","appendChildNodes","replaceChildNodes","removeElement","swapDOM","BUTTON","TT","PRE","H1","H2","H3","BR","CANVAS","HR","LABEL","TEXTAREA","FORM","STRONG","SELECT","OPTION","OPTGROUP","LEGEND","FIELDSET","P","UL","OL","LI","TD","TR","THEAD","TBODY","TFOOT","TABLE","TH","INPUT","SPAN","A","DIV","IMG","getElement","$","getElementsByTagAndClassName","addToCallStack","addLoadEvent","focusOnLoad","setElementClass","toggleElementClass","addElementClass","removeElementClass","swapElementClass","hasElementClass","escapeHTML","toHTML","emitHTML","scrapeText"];
+MochiKit.DOM.EXPORT_OK=["domConverters"];
+MochiKit.DOM.DEPRECATED=[["computedStyle","MochiKit.Style.computedStyle","1.4"],["elementDimensions","MochiKit.Style.getElementDimensions","1.4"],["elementPosition","MochiKit.Style.getElementPosition","1.4"],["hideElement","MochiKit.Style.hideElement","1.4"],["setElementDimensions","MochiKit.Style.setElementDimensions","1.4"],["setElementPosition","MochiKit.Style.setElementPosition","1.4"],["setDisplayForElement","MochiKit.Style.setDisplayForElement","1.4"],["setOpacity","MochiKit.Style.setOpacity","1.4"],["showElement","MochiKit.Style.showElement","1.4"],["Coordinates","MochiKit.Style.Coordinates","1.4"],["Dimensions","MochiKit.Style.Dimensions","1.4"]];
+MochiKit.DOM.getViewportDimensions=new Function(""+"if (!MochiKit[\"Style\"]) {"+"    throw new Error(\"This function has been deprecated and depends on MochiKit.Style.\");"+"}"+"return MochiKit.Style.getViewportDimensions.apply(this, arguments);");
+MochiKit.Base.update(MochiKit.DOM,{currentWindow:function(){
+return MochiKit.DOM._window;
+},currentDocument:function(){
+return MochiKit.DOM._document;
+},withWindow:function(win,func){
+var self=MochiKit.DOM;
+var _337=self._document;
+var _338=self._win;
+var rval;
+try{
+self._window=win;
+self._document=win.document;
+rval=func();
+}
+catch(e){
+self._window=_338;
+self._document=_337;
+throw e;
+}
+self._window=_338;
+self._document=_337;
+return rval;
+},formContents:function(elem){
+var _339=[];
+var _340=[];
+var m=MochiKit.Base;
+var self=MochiKit.DOM;
+if(typeof (elem)=="undefined"||elem===null){
+elem=self._document;
+}else{
+elem=self.getElement(elem);
+}
+m.nodeWalk(elem,function(elem){
+var name=elem.name;
+if(m.isNotEmpty(name)){
+var _341=elem.tagName.toUpperCase();
+if(_341==="INPUT"&&(elem.type=="radio"||elem.type=="checkbox")&&!elem.checked){
+return null;
+}
+if(_341==="SELECT"){
+if(elem.type=="select-one"){
+if(elem.selectedIndex>=0){
+var opt=elem.options[elem.selectedIndex];
+_339.push(name);
+_340.push(opt.value);
+return null;
+}
+_339.push(name);
+_340.push("");
+return null;
+}else{
+var opts=elem.options;
+if(!opts.length){
+_339.push(name);
+_340.push("");
+return null;
+}
+for(var i=0;i<opts.length;i++){
+var opt=opts[i];
+if(!opt.selected){
+continue;
+}
+_339.push(name);
+_340.push(opt.value);
+}
+return null;
+}
+}
+if(_341==="FORM"||_341==="P"||_341==="SPAN"||_341==="DIV"){
+return elem.childNodes;
+}
+_339.push(name);
+_340.push(elem.value||"");
+return null;
+}
+return elem.childNodes;
+});
+return [_339,_340];
+},withDocument:function(doc,func){
+var self=MochiKit.DOM;
+var _344=self._document;
+var rval;
+try{
+self._document=doc;
+rval=func();
+}
+catch(e){
+self._document=_344;
+throw e;
+}
+self._document=_344;
+return rval;
+},registerDOMConverter:function(name,_345,wrap,_346){
+MochiKit.DOM.domConverters.register(name,_345,wrap,_346);
+},coerceToDOM:function(node,ctx){
+var m=MochiKit.Base;
+var im=MochiKit.Iter;
+var self=MochiKit.DOM;
+if(im){
+var iter=im.iter;
+var _350=im.repeat;
+var map=m.map;
+}
+var _351=self.domConverters;
+var _352=arguments.callee;
+var _353=m.NotFound;
+while(true){
+if(typeof (node)=="undefined"||node===null){
+return null;
+}
+if(typeof (node.nodeType)!="undefined"&&node.nodeType>0){
+return node;
+}
+if(typeof (node)=="number"||typeof (node)=="boolean"){
+node=node.toString();
+}
+if(typeof (node)=="string"){
+return self._document.createTextNode(node);
+}
+if(typeof (node.__dom__)=="function"){
+node=node.__dom__(ctx);
+continue;
+}
+if(typeof (node.dom)=="function"){
+node=node.dom(ctx);
+continue;
+}
+if(typeof (node)=="function"){
+node=node.apply(ctx,[ctx]);
+continue;
+}
+if(im){
+var _354=null;
+try{
+_354=iter(node);
+}
+catch(e){
+}
+if(_354){
+return map(_352,_354,_350(ctx));
+}
+}
+try{
+node=_351.match(node,ctx);
+continue;
+}
+catch(e){
+if(e!=_353){
+throw e;
+}
+}
+return self._document.createTextNode(node.toString());
+}
+return undefined;
+},isChildNode:function(node,_355){
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+node=self.getElement(node);
+}
+if(typeof (_355)=="string"){
+_355=self.getElement(_355);
+}
+if(node===_355){
+return true;
+}
+while(node&&node.tagName.toUpperCase()!="BODY"){
+node=node.parentNode;
+if(node===_355){
+return true;
+}
+}
+return false;
+},setNodeAttribute:function(node,attr,_357){
+var o={};
+o[attr]=_357;
+try{
+return MochiKit.DOM.updateNodeAttributes(node,o);
+}
+catch(e){
+}
+return null;
+},getNodeAttribute:function(node,attr){
+var self=MochiKit.DOM;
+var _358=self.attributeArray.renames[attr];
+node=self.getElement(node);
+try{
+if(_358){
+return node[_358];
+}
+return node.getAttribute(attr);
+}
+catch(e){
+}
+return null;
+},updateNodeAttributes:function(node,_359){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+if(_359){
+var _360=MochiKit.Base.updatetree;
+if(self.attributeArray.compliant){
+for(var k in _359){
+var v=_359[k];
+if(typeof (v)=="object"&&typeof (elem[k])=="object"){
+_360(elem[k],v);
+}else{
+if(k.substring(0,2)=="on"){
+if(typeof (v)=="string"){
+v=new Function(v);
+}
+elem[k]=v;
+}else{
+elem.setAttribute(k,v);
+}
+}
+}
+}else{
+var _361=self.attributeArray.renames;
+for(k in _359){
+v=_359[k];
+var _362=_361[k];
+if(k=="style"&&typeof (v)=="string"){
+elem.style.cssText=v;
+}else{
+if(typeof (_362)=="string"){
+elem[_362]=v;
+}else{
+if(typeof (elem[k])=="object"&&typeof (v)=="object"){
+_360(elem[k],v);
+}else{
+if(k.substring(0,2)=="on"){
+if(typeof (v)=="string"){
+v=new Function(v);
+}
+elem[k]=v;
+}else{
+elem.setAttribute(k,v);
+}
+}
+}
+}
+}
+}
+}
+return elem;
+},appendChildNodes:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+var _363=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)];
+var _364=MochiKit.Base.concat;
+while(_363.length){
+var n=_363.shift();
+if(typeof (n)=="undefined"||n===null){
+}else{
+if(typeof (n.nodeType)=="number"){
+elem.appendChild(n);
+}else{
+_363=_364(n,_363);
+}
+}
+}
+return elem;
+},replaceChildNodes:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+arguments[0]=elem;
+}
+var _365;
+while((_365=elem.firstChild)){
+elem.removeChild(_365);
+}
+if(arguments.length<2){
+return elem;
+}else{
+return self.appendChildNodes.apply(this,arguments);
+}
+},createDOM:function(name,_366){
+var elem;
+var self=MochiKit.DOM;
+var m=MochiKit.Base;
+if(typeof (_366)=="string"||typeof (_366)=="number"){
+var args=m.extend([name,null],arguments,1);
+return arguments.callee.apply(this,args);
+}
+if(typeof (name)=="string"){
+var _367=self._xhtml;
+if(_366&&!self.attributeArray.compliant){
+var _368="";
+if("name" in _366){
+_368+=" name=\""+self.escapeHTML(_366.name)+"\"";
+}
+if(name=="input"&&"type" in _366){
+_368+=" type=\""+self.escapeHTML(_366.type)+"\"";
+}
+if(_368){
+name="<"+name+_368+">";
+_367=false;
+}
+}
+var d=self._document;
+if(_367&&d===document){
+elem=d.createElementNS("http://www.w3.org/1999/xhtml",name);
+}else{
+elem=d.createElement(name);
+}
+}else{
+elem=name;
+}
+if(_366){
+self.updateNodeAttributes(elem,_366);
+}
+if(arguments.length<=2){
+return elem;
+}else{
+var args=m.extend([elem],arguments,2);
+return self.appendChildNodes.apply(this,args);
+}
+},createDOMFunc:function(){
+var m=MochiKit.Base;
+return m.partial.apply(this,m.extend([MochiKit.DOM.createDOM],arguments));
+},removeElement:function(elem){
+var e=MochiKit.DOM.getElement(elem);
+e.parentNode.removeChild(e);
+return e;
+},swapDOM:function(dest,src){
+var self=MochiKit.DOM;
+dest=self.getElement(dest);
+var _371=dest.parentNode;
+if(src){
+src=self.getElement(src);
+_371.replaceChild(src,dest);
+}else{
+_371.removeChild(dest);
+}
+return src;
+},getElement:function(id){
+var self=MochiKit.DOM;
+if(arguments.length==1){
+return ((typeof (id)=="string")?self._document.getElementById(id):id);
+}else{
+return MochiKit.Base.map(self.getElement,arguments);
+}
+},getElementsByTagAndClassName:function(_373,_374,_375){
+var self=MochiKit.DOM;
+if(typeof (_373)=="undefined"||_373===null){
+_373="*";
+}
+if(typeof (_375)=="undefined"||_375===null){
+_375=self._document;
+}
+_375=self.getElement(_375);
+var _376=(_375.getElementsByTagName(_373)||self._document.all);
+if(typeof (_374)=="undefined"||_374===null){
+return MochiKit.Base.extend(null,_376);
+}
+var _377=[];
+for(var i=0;i<_376.length;i++){
+var _378=_376[i];
+var cls=_378.className;
+if(!cls){
+continue;
+}
+var _380=cls.split(" ");
+for(var j=0;j<_380.length;j++){
+if(_380[j]==_374){
+_377.push(_378);
+break;
+}
+}
+}
+return _377;
+},_newCallStack:function(path,once){
+var rval=function(){
+var _383=arguments.callee.callStack;
+for(var i=0;i<_383.length;i++){
+if(_383[i].apply(this,arguments)===false){
+break;
+}
+}
+if(once){
+try{
+this[path]=null;
+}
+catch(e){
+}
+}
+};
+rval.callStack=[];
+return rval;
+},addToCallStack:function(_384,path,func,once){
+var self=MochiKit.DOM;
+var _385=_384[path];
+var _386=_385;
+if(!(typeof (_385)=="function"&&typeof (_385.callStack)=="object"&&_385.callStack!==null)){
+_386=self._newCallStack(path,once);
+if(typeof (_385)=="function"){
+_386.callStack.push(_385);
+}
+_384[path]=_386;
+}
+_386.callStack.push(func);
+},addLoadEvent:function(func){
+var self=MochiKit.DOM;
+self.addToCallStack(self._window,"onload",func,true);
+},focusOnLoad:function(_387){
+var self=MochiKit.DOM;
+self.addLoadEvent(function(){
+_387=self.getElement(_387);
+if(_387){
+_387.focus();
+}
+});
+},setElementClass:function(_388,_389){
+var self=MochiKit.DOM;
+var obj=self.getElement(_388);
+if(self.attributeArray.compliant){
+obj.setAttribute("class",_389);
+}else{
+obj.setAttribute("className",_389);
+}
+},toggleElementClass:function(_390){
+var self=MochiKit.DOM;
+for(var i=1;i<arguments.length;i++){
+var obj=self.getElement(arguments[i]);
+if(!self.addElementClass(obj,_390)){
+self.removeElementClass(obj,_390);
+}
+}
+},addElementClass:function(_391,_392){
+var self=MochiKit.DOM;
+var obj=self.getElement(_391);
+var cls=obj.className;
+if(cls==undefined||cls.length===0){
+self.setElementClass(obj,_392);
+return true;
+}
+if(cls==_392){
+return false;
+}
+var _393=cls.split(" ");
+for(var i=0;i<_393.length;i++){
+if(_393[i]==_392){
+return false;
+}
+}
+self.setElementClass(obj,cls+" "+_392);
+return true;
+},removeElementClass:function(_394,_395){
+var self=MochiKit.DOM;
+var obj=self.getElement(_394);
+var cls=obj.className;
+if(cls==undefined||cls.length===0){
+return false;
+}
+if(cls==_395){
+self.setElementClass(obj,"");
+return true;
+}
+var _396=cls.split(" ");
+for(var i=0;i<_396.length;i++){
+if(_396[i]==_395){
+_396.splice(i,1);
+self.setElementClass(obj,_396.join(" "));
+return true;
+}
+}
+return false;
+},swapElementClass:function(_397,_398,_399){
+var obj=MochiKit.DOM.getElement(_397);
+var res=MochiKit.DOM.removeElementClass(obj,_398);
+if(res){
+MochiKit.DOM.addElementClass(obj,_399);
+}
+return res;
+},hasElementClass:function(_400,_401){
+var obj=MochiKit.DOM.getElement(_400);
+var cls=obj.className;
+if(!cls){
+return false;
+}
+var _402=cls.split(" ");
+for(var i=1;i<arguments.length;i++){
+var good=false;
+for(var j=0;j<_402.length;j++){
+if(_402[j]==arguments[i]){
+good=true;
+break;
+}
+}
+if(!good){
+return false;
+}
+}
+return true;
+},escapeHTML:function(s){
+return s.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
+},toHTML:function(dom){
+return MochiKit.DOM.emitHTML(dom).join("");
+},emitHTML:function(dom,lst){
+if(typeof (lst)=="undefined"||lst===null){
+lst=[];
+}
+var _405=[dom];
+var self=MochiKit.DOM;
+var _406=self.escapeHTML;
+var _407=self.attributeArray;
+while(_405.length){
+dom=_405.pop();
+if(typeof (dom)=="string"){
+lst.push(dom);
+}else{
+if(dom.nodeType==1){
+lst.push("<"+dom.tagName.toLowerCase());
+var _408=[];
+var _409=_407(dom);
+for(var i=0;i<_409.length;i++){
+var a=_409[i];
+_408.push([" ",a.name,"=\"",_406(a.value),"\""]);
+}
+_408.sort();
+for(i=0;i<_408.length;i++){
+var _410=_408[i];
+for(var j=0;j<_410.length;j++){
+lst.push(_410[j]);
+}
+}
+if(dom.hasChildNodes()){
+lst.push(">");
+_405.push("</"+dom.tagName.toLowerCase()+">");
+var _411=dom.childNodes;
+for(i=_411.length-1;i>=0;i--){
+_405.push(_411[i]);
+}
+}else{
+lst.push("/>");
+}
+}else{
+if(dom.nodeType==3){
+lst.push(_406(dom.nodeValue));
+}
+}
+}
+}
+return lst;
+},scrapeText:function(node,_412){
+var rval=[];
+(function(node){
+var cn=node.childNodes;
+if(cn){
+for(var i=0;i<cn.length;i++){
+arguments.callee.call(this,cn[i]);
+}
+}
+var _414=node.nodeValue;
+if(typeof (_414)=="string"){
+rval.push(_414);
+}
+})(MochiKit.DOM.getElement(node));
+if(_412){
+return rval;
+}else{
+return rval.join("");
+}
+},removeEmptyTextNodes:function(_415){
+_415=MochiKit.DOM.getElement(_415);
+for(var i=0;i<_415.childNodes.length;i++){
+var node=_415.childNodes[i];
+if(node.nodeType==3&&!/\S/.test(node.nodeValue)){
+node.parentNode.removeChild(node);
+}
+}
+},__new__:function(win){
+var m=MochiKit.Base;
+if(typeof (document)!="undefined"){
+this._document=document;
+var _416="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+this._xhtml=(document.documentElement&&document.createElementNS&&document.documentElement.namespaceURI===_416);
+}else{
+if(MochiKit.MockDOM){
+this._document=MochiKit.MockDOM.document;
+}
+}
+this._window=win;
+this.domConverters=new m.AdapterRegistry();
+var _417=this._document.createElement("span");
+var _418;
+if(_417&&_417.attributes&&_417.attributes.length>0){
+var _419=m.filter;
+_418=function(node){
+return _419(_418.ignoreAttrFilter,node.attributes);
+};
+_418.ignoreAttr={};
+var _420=_417.attributes;
+var _421=_418.ignoreAttr;
+for(var i=0;i<_420.length;i++){
+var a=_420[i];
+_421[a.name]=a.value;
+}
+_418.ignoreAttrFilter=function(a){
+return (_418.ignoreAttr[a.name]!=a.value);
+};
+_418.compliant=false;
+_418.renames={"class":"className","checked":"defaultChecked","usemap":"useMap","for":"htmlFor","readonly":"readOnly","colspan":"colSpan","bgcolor":"bgColor"};
+}else{
+_418=function(node){
+return node.attributes;
+};
+_418.compliant=true;
+_418.renames={};
+}
+this.attributeArray=_418;
+var _422=function(_423,arr){
+var _424=arr[1].split(".");
+var str="";
+var obj={};
+str+="if (!MochiKit."+_424[1]+") { throw new Error(\"";
+str+="This function has been deprecated and depends on MochiKit.";
+str+=_424[1]+".\");}";
+str+="return MochiKit."+_424[1]+"."+arr[0];
+str+=".apply(this, arguments);";
+obj[_424[2]]=new Function(str);
+MochiKit.Base.update(MochiKit[_423],obj);
+};
+for(var i;i<MochiKit.DOM.DEPRECATED.length;i++){
+_422("DOM",MochiKit.DOM.DEPRECATED[i]);
+}
+var _425=this.createDOMFunc;
+this.UL=_425("ul");
+this.OL=_425("ol");
+this.LI=_425("li");
+this.TD=_425("td");
+this.TR=_425("tr");
+this.TBODY=_425("tbody");
+this.THEAD=_425("thead");
+this.TFOOT=_425("tfoot");
+this.TABLE=_425("table");
+this.TH=_425("th");
+this.INPUT=_425("input");
+this.SPAN=_425("span");
+this.A=_425("a");
+this.DIV=_425("div");
+this.IMG=_425("img");
+this.BUTTON=_425("button");
+this.TT=_425("tt");
+this.PRE=_425("pre");
+this.H1=_425("h1");
+this.H2=_425("h2");
+this.H3=_425("h3");
+this.BR=_425("br");
+this.HR=_425("hr");
+this.LABEL=_425("label");
+this.TEXTAREA=_425("textarea");
+this.FORM=_425("form");
+this.P=_425("p");
+this.SELECT=_425("select");
+this.OPTION=_425("option");
+this.OPTGROUP=_425("optgroup");
+this.LEGEND=_425("legend");
+this.FIELDSET=_425("fieldset");
+this.STRONG=_425("strong");
+this.CANVAS=_425("canvas");
+this.$=this.getElement;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+}});
+MochiKit.DOM.__new__(((typeof (window)=="undefined")?this:window));
+if(MochiKit.__export__){
+withWindow=MochiKit.DOM.withWindow;
+withDocument=MochiKit.DOM.withDocument;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.DOM);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Style");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Style depends on MochiKit.Base!";
+}
+try{
+if(typeof (MochiKit.DOM)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Style depends on MochiKit.DOM!";
+}
+if(typeof (MochiKit.Style)=="undefined"){
+MochiKit.Style={};
+}
+MochiKit.Style.NAME="MochiKit.Style";
+MochiKit.Style.VERSION="1.4";
+MochiKit.Style.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Style.toString=function(){
+return this.__repr__();
+};
+MochiKit.Style.EXPORT_OK=[];
+MochiKit.Style.EXPORT=["setOpacity","getOpacity","setStyle","getStyle","computedStyle","getElementDimensions","elementDimensions","setElementDimensions","getElementPosition","elementPosition","setElementPosition","setDisplayForElement","hideElement","showElement","getViewportDimensions","getViewportPosition","Dimensions","Coordinates"];
+MochiKit.Style.Dimensions=function(w,h){
+this.w=w;
+this.h=h;
+};
+MochiKit.Style.Dimensions.prototype.__repr__=function(){
+var repr=MochiKit.Base.repr;
+return "{w: "+repr(this.w)+", h: "+repr(this.h)+"}";
+};
+MochiKit.Style.Dimensions.prototype.toString=function(){
+return this.__repr__();
+};
+MochiKit.Style.Coordinates=function(x,y){
+this.x=x;
+this.y=y;
+};
+MochiKit.Style.Coordinates.prototype.__repr__=function(){
+var repr=MochiKit.Base.repr;
+return "{x: "+repr(this.x)+", y: "+repr(this.y)+"}";
+};
+MochiKit.Style.Coordinates.prototype.toString=function(){
+return this.__repr__();
+};
+MochiKit.Base.update(MochiKit.Style,{computedStyle:function(elem,_430){
+var dom=MochiKit.DOM;
+var d=dom._document;
+elem=dom.getElement(elem);
+_430=MochiKit.Base.camelize(_430);
+if(!elem||elem==d){
+return undefined;
+}
+if(_430=="opacity"&&elem.filters){
+try{
+return elem.filters.item("DXImageTransform.Microsoft.Alpha").opacity/100;
+}
+catch(e){
+try{
+return elem.filters.item("alpha").opacity/100;
+}
+catch(e){
+}
+}
+}
+if(elem.currentStyle){
+return elem.currentStyle[_430];
+}
+if(typeof (d.defaultView)=="undefined"){
+return undefined;
+}
+if(d.defaultView===null){
+return undefined;
+}
+var _431=d.defaultView.getComputedStyle(elem,null);
+if(typeof (_431)=="undefined"||_431===null){
+return undefined;
+}
+var _432=_430.replace(/([A-Z])/g,"-$1").toLowerCase();
+return _431.getPropertyValue(_432);
+},getStyle:function(elem,_433){
+elem=MochiKit.DOM.getElement(elem);
+var _434=elem.style[MochiKit.Base.camelize(_433)];
+if(!_434){
+if(document.defaultView&&document.defaultView.getComputedStyle){
+var css=document.defaultView.getComputedStyle(elem,null);
+_434=css?css.getPropertyValue(_433):null;
+}else{
+if(elem.currentStyle){
+_434=elem.currentStyle[MochiKit.Base.camelize(_433)];
+}
+}
+}
+if(/Opera/.test(navigator.userAgent)&&(MochiKit.Base.find(["left","top","right","bottom"],_433)!=-1)){
+if(MochiKit.Style.getStyle(elem,"position")=="static"){
+_434="auto";
+}
+}
+return _434=="auto"?null:_434;
+},setStyle:function(elem,_436){
+elem=MochiKit.DOM.getElement(elem);
+for(name in _436){
+elem.style[MochiKit.Base.camelize(name)]=_436[name];
+}
+},getOpacity:function(elem){
+var _437;
+if(_437=MochiKit.Style.getStyle(elem,"opacity")){
+return parseFloat(_437);
+}
+if(_437=(MochiKit.Style.getStyle(elem,"filter")||"").match(/alpha\(opacity=(.*)\)/)){
+if(_437[1]){
+return parseFloat(_437[1])/100;
+}
+}
+return 1;
+},setOpacity:function(elem,o){
+elem=MochiKit.DOM.getElement(elem);
+var self=MochiKit.Style;
+if(o==1){
+var _438=/Gecko/.test(navigator.userAgent)&&!(/Konqueror|Safari|KHTML/.test(navigator.userAgent));
+self.setStyle(elem,{opacity:_438?0.999999:1});
+if(/MSIE/.test(navigator.userAgent)){
+self.setStyle(elem,{filter:self.getStyle(elem,"filter").replace(/alpha\([^\)]*\)/gi,"")});
+}
+}else{
+if(o<0.00001){
+o=0;
+}
+self.setStyle(elem,{opacity:o});
+if(/MSIE/.test(navigator.userAgent)){
+self.setStyle(elem,{filter:self.getStyle(elem,"filter").replace(/alpha\([^\)]*\)/gi,"")+"alpha(opacity="+o*100+")"});
+}
+}
+},getElementPosition:function(elem,_439){
+var self=MochiKit.Style;
+var dom=MochiKit.DOM;
+elem=dom.getElement(elem);
+if(!elem||(!(elem.x&&elem.y)&&(!elem.parentNode==null||self.computedStyle(elem,"display")=="none"))){
+return undefined;
+}
+var c=new self.Coordinates(0,0);
+var box=null;
+var _442=null;
+var d=MochiKit.DOM._document;
+var de=d.documentElement;
+var b=d.body;
+if(!elem.parentNode&&elem.x&&elem.y){
+c.x+=elem.x||0;
+c.y+=elem.y||0;
+}else{
+if(elem.getBoundingClientRect){
+box=elem.getBoundingClientRect();
+c.x+=box.left+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||0);
+c.y+=box.top+(de.scrollTop||b.scrollTop)-(de.clientTop||0);
+}else{
+if(elem.offsetParent){
+c.x+=elem.offsetLeft;
+c.y+=elem.offsetTop;
+_442=elem.offsetParent;
+if(_442!=elem){
+while(_442){
+c.x+=_442.offsetLeft;
+c.y+=_442.offsetTop;
+_442=_442.offsetParent;
+}
+}
+var ua=navigator.userAgent.toLowerCase();
+if((typeof (opera)!="undefined"&&parseFloat(opera.version())<9)||(ua.indexOf("safari")!=-1&&self.computedStyle(elem,"position")=="absolute")){
+c.x-=b.offsetLeft;
+c.y-=b.offsetTop;
+}
+}
+}
+}
+if(typeof (_439)!="undefined"){
+_439=arguments.callee(_439);
+if(_439){
+c.x-=(_439.x||0);
+c.y-=(_439.y||0);
+}
+}
+if(elem.parentNode){
+_442=elem.parentNode;
+}else{
+_442=null;
+}
+while(_442){
+var _445=_442.tagName.toUpperCase();
+if(_445==="BODY"||_445==="HTML"){
+break;
+}
+c.x-=_442.scrollLeft;
+c.y-=_442.scrollTop;
+if(_442.parentNode){
+_442=_442.parentNode;
+}else{
+_442=null;
+}
+}
+return c;
+},setElementPosition:function(elem,_446,_447){
+elem=MochiKit.DOM.getElement(elem);
+if(typeof (_447)=="undefined"){
+_447="px";
+}
+var _448={};
+var _449=MochiKit.Base.isUndefinedOrNull;
+if(!_449(_446.x)){
+_448["left"]=_446.x+_447;
+}
+if(!_449(_446.y)){
+_448["top"]=_446.y+_447;
+}
+MochiKit.DOM.updateNodeAttributes(elem,{"style":_448});
+},getElementDimensions:function(elem){
+var self=MochiKit.Style;
+var dom=MochiKit.DOM;
+if(typeof (elem.w)=="number"||typeof (elem.h)=="number"){
+return new self.Dimensions(elem.w||0,elem.h||0);
+}
+elem=dom.getElement(elem);
+if(!elem){
+return undefined;
+}
+var disp=self.computedStyle(elem,"display");
+if(disp!="none"&&disp!=""&&typeof (disp)!="undefined"){
+return new self.Dimensions(elem.offsetWidth||0,elem.offsetHeight||0);
+}
+var s=elem.style;
+var _451=s.visibility;
+var _452=s.position;
+s.visibility="hidden";
+s.position="absolute";
+s.display="";
+var _453=elem.offsetWidth;
+var _454=elem.offsetHeight;
+s.display="none";
+s.position=_452;
+s.visibility=_451;
+return new self.Dimensions(_453,_454);
+},setElementDimensions:function(elem,_455,_456){
+elem=MochiKit.DOM.getElement(elem);
+if(typeof (_456)=="undefined"){
+_456="px";
+}
+var _457={};
+var _458=MochiKit.Base.isUndefinedOrNull;
+if(!_458(_455.w)){
+_457["width"]=_455.w+_456;
+}
+if(!_458(_455.h)){
+_457["height"]=_455.h+_456;
+}
+MochiKit.DOM.updateNodeAttributes(elem,{"style":_457});
+},setDisplayForElement:function(_459,_460){
+var _461=MochiKit.Base.extend(null,arguments,1);
+var _462=MochiKit.DOM.getElement;
+for(var i=0;i<_461.length;i++){
+var _460=_462(_461[i]);
+if(_460){
+_460.style.display=_459;
+}
+}
+},getViewportDimensions:function(){
+var d=new MochiKit.Style.Dimensions();
+var w=MochiKit.DOM._window;
+var b=MochiKit.DOM._document.body;
+if(w.innerWidth){
+d.w=w.innerWidth;
+d.h=w.innerHeight;
+}else{
+if(b.parentElement.clientWidth){
+d.w=b.parentElement.clientWidth;
+d.h=b.parentElement.clientHeight;
+}else{
+if(b&&b.clientWidth){
+d.w=b.clientWidth;
+d.h=b.clientHeight;
+}
+}
+}
+return d;
+},getViewportPosition:function(){
+var c=new MochiKit.Style.Coordinates(0,0);
+var d=MochiKit.DOM._document;
+var de=d.documentElement;
+var db=d.body;
+if(de&&(de.scrollTop||de.scrollLeft)){
+c.x=de.scrollLeft;
+c.y=de.scrollTop;
+}else{
+if(db){
+c.x=db.scrollLeft;
+c.y=db.scrollTop;
+}
+}
+return c;
+},__new__:function(){
+var m=MochiKit.Base;
+this.elementPosition=this.getElementPosition;
+this.elementDimensions=this.getElementDimensions;
+this.hideElement=m.partial(this.setDisplayForElement,"none");
+this.showElement=m.partial(this.setDisplayForElement,"block");
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+}});
+MochiKit.Style.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Style);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.LoggingPane");
+dojo.require("MochiKit.Logging");
+dojo.require("MochiKit.Base");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Logging",[]);
+JSAN.use("MochiKit.Base",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.Logging)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.LoggingPane depends on MochiKit.Base and MochiKit.Logging!";
+}
+if(typeof (MochiKit.LoggingPane)=="undefined"){
+MochiKit.LoggingPane={};
+}
+MochiKit.LoggingPane.NAME="MochiKit.LoggingPane";
+MochiKit.LoggingPane.VERSION="1.4";
+MochiKit.LoggingPane.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.LoggingPane.toString=function(){
+return this.__repr__();
+};
+MochiKit.LoggingPane.createLoggingPane=function(_464){
+var m=MochiKit.LoggingPane;
+_464=!(!_464);
+if(m._loggingPane&&m._loggingPane.inline!=_464){
+m._loggingPane.closePane();
+m._loggingPane=null;
+}
+if(!m._loggingPane||m._loggingPane.closed){
+m._loggingPane=new m.LoggingPane(_464,MochiKit.Logging.logger);
+}
+return m._loggingPane;
+};
+MochiKit.LoggingPane.LoggingPane=function(_465,_466){
+if(typeof (_466)=="undefined"||_466===null){
+_466=MochiKit.Logging.logger;
+}
+this.logger=_466;
+var _467=MochiKit.Base.update;
+var _468=MochiKit.Base.updatetree;
+var bind=MochiKit.Base.bind;
+var _469=MochiKit.Base.clone;
+var win=window;
+var uid="_MochiKit_LoggingPane";
+if(typeof (MochiKit.DOM)!="undefined"){
+win=MochiKit.DOM.currentWindow();
+}
+if(!_465){
+var url=win.location.href.split("?")[0].replace(/[#:\/.><&-]/g,"_");
+var name=uid+"_"+url;
+var nwin=win.open("",name,"dependent,resizable,height=200");
+if(!nwin){
+alert("Not able to open debugging window due to pop-up blocking.");
+return undefined;
+}
+nwin.document.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" "+"\"http://www.w3.org/TR/html4/loose.dtd\">"+"<html><head><title>[MochiKit.LoggingPane]</title></head>"+"<body></body></html>");
+nwin.document.close();
+nwin.document.title+=" "+win.document.title;
+win=nwin;
+}
+var doc=win.document;
+this.doc=doc;
+var _472=doc.getElementById(uid);
+var _473=!!_472;
+if(_472&&typeof (_472.loggingPane)!="undefined"){
+_472.loggingPane.logger=this.logger;
+_472.loggingPane.buildAndApplyFilter();
+return _472.loggingPane;
+}
+if(_473){
+var _474;
+while((_474=_472.firstChild)){
+_472.removeChild(_474);
+}
+}else{
+_472=doc.createElement("div");
+_472.id=uid;
+}
+_472.loggingPane=this;
+var _475=doc.createElement("input");
+var _476=doc.createElement("input");
+var _477=doc.createElement("button");
+var _478=doc.createElement("button");
+var _479=doc.createElement("button");
+var _480=doc.createElement("button");
+var _481=doc.createElement("div");
+var _482=doc.createElement("div");
+var _483=uid+"_Listener";
+this.colorTable=_469(this.colorTable);
+var _484=[];
+var _485=null;
+var _486=function(msg){
+var _487=msg.level;
+if(typeof (_487)=="number"){
+_487=MochiKit.Logging.LogLevel[_487];
+}
+return _487;
+};
+var _488=function(msg){
+return msg.info.join(" ");
+};
+var _489=bind(function(msg){
+var _490=_486(msg);
+var text=_488(msg);
+var c=this.colorTable[_490];
+var p=doc.createElement("span");
+p.className="MochiKit-LogMessage MochiKit-LogLevel-"+_490;
+p.style.cssText="margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: "+c;
+p.appendChild(doc.createTextNode(_490+": "+text));
+_482.appendChild(p);
+_482.appendChild(doc.createElement("br"));
+if(_481.offsetHeight>_481.scrollHeight){
+_481.scrollTop=0;
+}else{
+_481.scrollTop=_481.scrollHeight;
+}
+},this);
+var _492=function(msg){
+_484[_484.length]=msg;
+_489(msg);
+};
+var _493=function(){
+var _494,infore;
+try{
+_494=new RegExp(_475.value);
+infore=new RegExp(_476.value);
+}
+catch(e){
+logDebug("Error in filter regex: "+e.message);
+return null;
+}
+return function(msg){
+return (_494.test(_486(msg))&&infore.test(_488(msg)));
+};
+};
+var _495=function(){
+while(_482.firstChild){
+_482.removeChild(_482.firstChild);
+}
+};
+var _496=function(){
+_484=[];
+_495();
+};
+var _497=bind(function(){
+if(this.closed){
+return;
+}
+this.closed=true;
+if(MochiKit.LoggingPane._loggingPane==this){
+MochiKit.LoggingPane._loggingPane=null;
+}
+this.logger.removeListener(_483);
+_472.loggingPane=null;
+if(_465){
+_472.parentNode.removeChild(_472);
+}else{
+this.win.close();
+}
+},this);
+var _498=function(){
+_495();
+for(var i=0;i<_484.length;i++){
+var msg=_484[i];
+if(_485===null||_485(msg)){
+_489(msg);
+}
+}
+};
+this.buildAndApplyFilter=function(){
+_485=_493();
+_498();
+this.logger.removeListener(_483);
+this.logger.addListener(_483,_485,_492);
+};
+var _499=bind(function(){
+_484=this.logger.getMessages();
+_498();
+},this);
+var _500=bind(function(_501){
+_501=_501||window.event;
+key=_501.which||_501.keyCode;
+if(key==13){
+this.buildAndApplyFilter();
+}
+},this);
+var _502="display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: "+this.logFont;
+if(_465){
+_502+="; height: 10em; border-top: 2px solid black";
+}else{
+_502+="; height: 100%;";
+}
+_472.style.cssText=_502;
+if(!_473){
+doc.body.appendChild(_472);
+}
+_502={"cssText":"width: 33%; display: inline; font: "+this.logFont};
+_468(_475,{"value":"FATAL|ERROR|WARNING|INFO|DEBUG","onkeypress":_500,"style":_502});
+_472.appendChild(_475);
+_468(_476,{"value":".*","onkeypress":_500,"style":_502});
+_472.appendChild(_476);
+_502="width: 8%; display:inline; font: "+this.logFont;
+_477.appendChild(doc.createTextNode("Filter"));
+_477.onclick=bind("buildAndApplyFilter",this);
+_477.style.cssText=_502;
+_472.appendChild(_477);
+_478.appendChild(doc.createTextNode("Load"));
+_478.onclick=_499;
+_478.style.cssText=_502;
+_472.appendChild(_478);
+_479.appendChild(doc.createTextNode("Clear"));
+_479.onclick=_496;
+_479.style.cssText=_502;
+_472.appendChild(_479);
+_480.appendChild(doc.createTextNode("Close"));
+_480.onclick=_497;
+_480.style.cssText=_502;
+_472.appendChild(_480);
+_481.style.cssText="overflow: auto; width: 100%";
+_482.style.cssText="width: 100%; height: "+(_465?"8em":"100%");
+_481.appendChild(_482);
+_472.appendChild(_481);
+this.buildAndApplyFilter();
+_499();
+if(_465){
+this.win=undefined;
+}else{
+this.win=win;
+}
+this.inline=_465;
+this.closePane=_497;
+this.closed=false;
+return this;
+};
+MochiKit.LoggingPane.LoggingPane.prototype={"logFont":"8pt Verdana,sans-serif","colorTable":{"ERROR":"red","FATAL":"darkred","WARNING":"blue","INFO":"black","DEBUG":"green"}};
+MochiKit.LoggingPane.EXPORT_OK=["LoggingPane"];
+MochiKit.LoggingPane.EXPORT=["createLoggingPane"];
+MochiKit.LoggingPane.__new__=function(){
+this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)};
+MochiKit.Base.nameFunctions(this);
+MochiKit.LoggingPane._loggingPane=null;
+};
+MochiKit.LoggingPane.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.LoggingPane);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Color");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Style");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Style",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Color depends on MochiKit.Base";
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Color depends on MochiKit.DOM";
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Color depends on MochiKit.Style";
+}
+if(typeof (MochiKit.Color)=="undefined"){
+MochiKit.Color={};
+}
+MochiKit.Color.NAME="MochiKit.Color";
+MochiKit.Color.VERSION="1.4";
+MochiKit.Color.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Color.toString=function(){
+return this.__repr__();
+};
+MochiKit.Color.Color=function(red,_504,blue,_506){
+if(typeof (_506)=="undefined"||_506===null){
+_506=1;
+}
+this.rgb={r:red,g:_504,b:blue,a:_506};
+};
+MochiKit.Color.Color.prototype={__class__:MochiKit.Color.Color,colorWithAlpha:function(_507){
+var rgb=this.rgb;
+var m=MochiKit.Color;
+return m.Color.fromRGB(rgb.r,rgb.g,rgb.b,_507);
+},colorWithHue:function(hue){
+var hsl=this.asHSL();
+hsl.h=hue;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},colorWithSaturation:function(_511){
+var hsl=this.asHSL();
+hsl.s=_511;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},colorWithLightness:function(_512){
+var hsl=this.asHSL();
+hsl.l=_512;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},darkerColorWithLevel:function(_513){
+var hsl=this.asHSL();
+hsl.l=Math.max(hsl.l-_513,0);
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},lighterColorWithLevel:function(_514){
+var hsl=this.asHSL();
+hsl.l=Math.min(hsl.l+_514,1);
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},blendedColor:function(_515,_516){
+if(typeof (_516)=="undefined"||_516===null){
+_516=0.5;
+}
+var sf=1-_516;
+var s=this.rgb;
+var d=_515.rgb;
+var df=_516;
+return MochiKit.Color.Color.fromRGB((s.r*sf)+(d.r*df),(s.g*sf)+(d.g*df),(s.b*sf)+(d.b*df),(s.a*sf)+(d.a*df));
+},compareRGB:function(_519){
+var a=this.asRGB();
+var b=_519.asRGB();
+return MochiKit.Base.compare([a.r,a.g,a.b,a.a],[b.r,b.g,b.b,b.a]);
+},isLight:function(){
+return this.asHSL().b>0.5;
+},isDark:function(){
+return (!this.isLight());
+},toHSLString:function(){
+var c=this.asHSL();
+var ccc=MochiKit.Color.clampColorComponent;
+var rval=this._hslString;
+if(!rval){
+var mid=(ccc(c.h,360).toFixed(0)+","+ccc(c.s,100).toPrecision(4)+"%"+","+ccc(c.l,100).toPrecision(4)+"%");
+var a=c.a;
+if(a>=1){
+a=1;
+rval="hsl("+mid+")";
+}else{
+if(a<=0){
+a=0;
+}
+rval="hsla("+mid+","+a+")";
+}
+this._hslString=rval;
+}
+return rval;
+},toRGBString:function(){
+var c=this.rgb;
+var ccc=MochiKit.Color.clampColorComponent;
+var rval=this._rgbString;
+if(!rval){
+var mid=(ccc(c.r,255).toFixed(0)+","+ccc(c.g,255).toFixed(0)+","+ccc(c.b,255).toFixed(0));
+if(c.a!=1){
+rval="rgba("+mid+","+c.a+")";
+}else{
+rval="rgb("+mid+")";
+}
+this._rgbString=rval;
+}
+return rval;
+},asRGB:function(){
+return MochiKit.Base.clone(this.rgb);
+},toHexString:function(){
+var m=MochiKit.Color;
+var c=this.rgb;
+var ccc=MochiKit.Color.clampColorComponent;
+var rval=this._hexString;
+if(!rval){
+rval=("#"+m.toColorPart(ccc(c.r,255))+m.toColorPart(ccc(c.g,255))+m.toColorPart(ccc(c.b,255)));
+this._hexString=rval;
+}
+return rval;
+},asHSV:function(){
+var hsv=this.hsv;
+var c=this.rgb;
+if(typeof (hsv)=="undefined"||hsv===null){
+hsv=MochiKit.Color.rgbToHSV(this.rgb);
+this.hsv=hsv;
+}
+return MochiKit.Base.clone(hsv);
+},asHSL:function(){
+var hsl=this.hsl;
+var c=this.rgb;
+if(typeof (hsl)=="undefined"||hsl===null){
+hsl=MochiKit.Color.rgbToHSL(this.rgb);
+this.hsl=hsl;
+}
+return MochiKit.Base.clone(hsl);
+},toString:function(){
+return this.toRGBString();
+},repr:function(){
+var c=this.rgb;
+var col=[c.r,c.g,c.b,c.a];
+return this.__class__.NAME+"("+col.join(", ")+")";
+}};
+MochiKit.Base.update(MochiKit.Color.Color,{fromRGB:function(red,_524,blue,_525){
+var _526=MochiKit.Color.Color;
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_524=rgb.g;
+blue=rgb.b;
+if(typeof (rgb.a)=="undefined"){
+_525=undefined;
+}else{
+_525=rgb.a;
+}
+}
+return new _526(red,_524,blue,_525);
+},fromHSL:function(hue,_527,_528,_529){
+var m=MochiKit.Color;
+return m.Color.fromRGB(m.hslToRGB.apply(m,arguments));
+},fromHSV:function(hue,_530,_531,_532){
+var m=MochiKit.Color;
+return m.Color.fromRGB(m.hsvToRGB.apply(m,arguments));
+},fromName:function(name){
+var _533=MochiKit.Color.Color;
+if(name.charAt(0)=="\""){
+name=name.substr(1,name.length-2);
+}
+var _534=_533._namedColors[name.toLowerCase()];
+if(typeof (_534)=="string"){
+return _533.fromHexString(_534);
+}else{
+if(name=="transparent"){
+return _533.transparentColor();
+}
+}
+return null;
+},fromString:function(_535){
+var self=MochiKit.Color.Color;
+var _536=_535.substr(0,3);
+if(_536=="rgb"){
+return self.fromRGBString(_535);
+}else{
+if(_536=="hsl"){
+return self.fromHSLString(_535);
+}else{
+if(_535.charAt(0)=="#"){
+return self.fromHexString(_535);
+}
+}
+}
+return self.fromName(_535);
+},fromHexString:function(_537){
+if(_537.charAt(0)=="#"){
+_537=_537.substring(1);
+}
+var _538=[];
+var i,hex;
+if(_537.length==3){
+for(i=0;i<3;i++){
+hex=_537.substr(i,1);
+_538.push(parseInt(hex+hex,16)/255);
+}
+}else{
+for(i=0;i<6;i+=2){
+hex=_537.substr(i,2);
+_538.push(parseInt(hex,16)/255);
+}
+}
+var _539=MochiKit.Color.Color;
+return _539.fromRGB.apply(_539,_538);
+},_fromColorString:function(pre,_541,_542,_543){
+if(_543.indexOf(pre)===0){
+_543=_543.substring(_543.indexOf("(",3)+1,_543.length-1);
+}
+var _544=_543.split(/\s*,\s*/);
+var _545=[];
+for(var i=0;i<_544.length;i++){
+var c=_544[i];
+var val;
+var _546=c.substring(c.length-3);
+if(c.charAt(c.length-1)=="%"){
+val=0.01*parseFloat(c.substring(0,c.length-1));
+}else{
+if(_546=="deg"){
+val=parseFloat(c)/360;
+}else{
+if(_546=="rad"){
+val=parseFloat(c)/(Math.PI*2);
+}else{
+val=_542[i]*parseFloat(c);
+}
+}
+}
+_545.push(val);
+}
+return this[_541].apply(this,_545);
+},fromComputedStyle:function(elem,_547){
+var d=MochiKit.DOM;
+var cls=MochiKit.Color.Color;
+for(elem=d.getElement(elem);elem;elem=elem.parentNode){
+var _548=MochiKit.Style.computedStyle.apply(d,arguments);
+if(!_548){
+continue;
+}
+var _549=cls.fromString(_548);
+if(!_549){
+break;
+}
+if(_549.asRGB().a>0){
+return _549;
+}
+}
+return null;
+},fromBackground:function(elem){
+var cls=MochiKit.Color.Color;
+return cls.fromComputedStyle(elem,"backgroundColor","background-color")||cls.whiteColor();
+},fromText:function(elem){
+var cls=MochiKit.Color.Color;
+return cls.fromComputedStyle(elem,"color","color")||cls.blackColor();
+},namedColors:function(){
+return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
+}});
+MochiKit.Base.update(MochiKit.Color,{clampColorComponent:function(v,_550){
+v*=_550;
+if(v<0){
+return 0;
+}else{
+if(v>_550){
+return _550;
+}else{
+return v;
+}
+}
+},_hslValue:function(n1,n2,hue){
+if(hue>6){
+hue-=6;
+}else{
+if(hue<0){
+hue+=6;
+}
+}
+var val;
+if(hue<1){
+val=n1+(n2-n1)*hue;
+}else{
+if(hue<3){
+val=n2;
+}else{
+if(hue<4){
+val=n1+(n2-n1)*(4-hue);
+}else{
+val=n1;
+}
+}
+}
+return val;
+},hsvToRGB:function(hue,_553,_554,_555){
+if(arguments.length==1){
+var hsv=hue;
+hue=hsv.h;
+_553=hsv.s;
+_554=hsv.v;
+_555=hsv.a;
+}
+var red;
+var _556;
+var blue;
+if(_553===0){
+red=0;
+_556=0;
+blue=0;
+}else{
+var i=Math.floor(hue*6);
+var f=(hue*6)-i;
+var p=_554*(1-_553);
+var q=_554*(1-(_553*f));
+var t=_554*(1-(_553*(1-f)));
+switch(i){
+case 1:
+red=q;
+_556=_554;
+blue=p;
+break;
+case 2:
+red=p;
+_556=_554;
+blue=t;
+break;
+case 3:
+red=p;
+_556=q;
+blue=_554;
+break;
+case 4:
+red=t;
+_556=p;
+blue=_554;
+break;
+case 5:
+red=_554;
+_556=p;
+blue=q;
+break;
+case 6:
+case 0:
+red=_554;
+_556=t;
+blue=p;
+break;
+}
+}
+return {r:red,g:_556,b:blue,a:_555};
+},hslToRGB:function(hue,_558,_559,_560){
+if(arguments.length==1){
+var hsl=hue;
+hue=hsl.h;
+_558=hsl.s;
+_559=hsl.l;
+_560=hsl.a;
+}
+var red;
+var _561;
+var blue;
+if(_558===0){
+red=_559;
+_561=_559;
+blue=_559;
+}else{
+var m2;
+if(_559<=0.5){
+m2=_559*(1+_558);
+}else{
+m2=_559+_558-(_559*_558);
+}
+var m1=(2*_559)-m2;
+var f=MochiKit.Color._hslValue;
+var h6=hue*6;
+red=f(m1,m2,h6+2);
+_561=f(m1,m2,h6);
+blue=f(m1,m2,h6-2);
+}
+return {r:red,g:_561,b:blue,a:_560};
+},rgbToHSV:function(red,_565,blue,_566){
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_565=rgb.g;
+blue=rgb.b;
+_566=rgb.a;
+}
+var max=Math.max(Math.max(red,_565),blue);
+var min=Math.min(Math.min(red,_565),blue);
+var hue;
+var _569;
+var _570=max;
+if(min==max){
+hue=0;
+_569=0;
+}else{
+var _571=(max-min);
+_569=_571/max;
+if(red==max){
+hue=(_565-blue)/_571;
+}else{
+if(_565==max){
+hue=2+((blue-red)/_571);
+}else{
+hue=4+((red-_565)/_571);
+}
+}
+hue/=6;
+if(hue<0){
+hue+=1;
+}
+if(hue>1){
+hue-=1;
+}
+}
+return {h:hue,s:_569,v:_570,a:_566};
+},rgbToHSL:function(red,_572,blue,_573){
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_572=rgb.g;
+blue=rgb.b;
+_573=rgb.a;
+}
+var max=Math.max(red,Math.max(_572,blue));
+var min=Math.min(red,Math.min(_572,blue));
+var hue;
+var _574;
+var _575=(max+min)/2;
+var _576=max-min;
+if(_576===0){
+hue=0;
+_574=0;
+}else{
+if(_575<=0.5){
+_574=_576/(max+min);
+}else{
+_574=_576/(2-max-min);
+}
+if(red==max){
+hue=(_572-blue)/_576;
+}else{
+if(_572==max){
+hue=2+((blue-red)/_576);
+}else{
+hue=4+((red-_572)/_576);
+}
+}
+hue/=6;
+if(hue<0){
+hue+=1;
+}
+if(hue>1){
+hue-=1;
+}
+}
+return {h:hue,s:_574,l:_575,a:_573};
+},toColorPart:function(num){
+num=Math.round(num);
+var _577=num.toString(16);
+if(num<16){
+return "0"+_577;
+}
+return _577;
+},__new__:function(){
+var m=MochiKit.Base;
+this.Color.fromRGBString=m.bind(this.Color._fromColorString,this.Color,"rgb","fromRGB",[1/255,1/255,1/255,1]);
+this.Color.fromHSLString=m.bind(this.Color._fromColorString,this.Color,"hsl","fromHSL",[1/360,0.01,0.01,1]);
+var _578=1/3;
+var _579={black:[0,0,0],blue:[0,0,1],brown:[0.6,0.4,0.2],cyan:[0,1,1],darkGray:[_578,_578,_578],gray:[0.5,0.5,0.5],green:[0,1,0],lightGray:[2*_578,2*_578,2*_578],magenta:[1,0,1],orange:[1,0.5,0],purple:[0.5,0,0.5],red:[1,0,0],transparent:[0,0,0,0],white:[1,1,1],yellow:[1,1,0]};
+var _580=function(name,r,g,b,a){
+var rval=this.fromRGB(r,g,b,a);
+this[name]=function(){
+return rval;
+};
+return rval;
+};
+for(var k in _579){
+var name=k+"Color";
+var _582=m.concat([_580,this.Color,name],_579[k]);
+this.Color[name]=m.bind.apply(null,_582);
+}
+var _583=function(){
+for(var i=0;i<arguments.length;i++){
+if(!(arguments[i] instanceof Color)){
+return false;
+}
+}
+return true;
+};
+var _584=function(a,b){
+return a.compareRGB(b);
+};
+m.nameFunctions(this);
+m.registerComparator(this.Color.NAME,_583,_584);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+}});
+MochiKit.Color.EXPORT=["Color"];
+MochiKit.Color.EXPORT_OK=["clampColorComponent","rgbToHSL","hslToRGB","rgbToHSV","hsvToRGB","toColorPart"];
+MochiKit.Color.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Color);
+MochiKit.Color.Color._namedColors={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Signal");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Style");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Style",[]);
+}
+try{
+if(typeof (MochiKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Signal depends on MochiKit.Base!";
+}
+try{
+if(typeof (MochiKit.DOM)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Signal depends on MochiKit.DOM!";
+}
+try{
+if(typeof (MochiKit.Style)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Signal depends on MochiKit.Style!";
+}
+if(typeof (MochiKit.Signal)=="undefined"){
+MochiKit.Signal={};
+}
+MochiKit.Signal.NAME="MochiKit.Signal";
+MochiKit.Signal.VERSION="1.4";
+MochiKit.Signal._observers=[];
+MochiKit.Signal.Event=function(src,e){
+this._event=e||window.event;
+this._src=src;
+};
+MochiKit.Base.update(MochiKit.Signal.Event.prototype,{__repr__:function(){
+var repr=MochiKit.Base.repr;
+var str="{event(): "+repr(this.event())+", src(): "+repr(this.src())+", type(): "+repr(this.type())+", target(): "+repr(this.target())+", modifier(): "+"{alt: "+repr(this.modifier().alt)+", ctrl: "+repr(this.modifier().ctrl)+", meta: "+repr(this.modifier().meta)+", shift: "+repr(this.modifier().shift)+", any: "+repr(this.modifier().any)+"}";
+if(this.type()&&this.type().indexOf("key")===0){
+str+=", key(): {code: "+repr(this.key().code)+", string: "+repr(this.key().string)+"}";
+}
+if(this.type()&&(this.type().indexOf("mouse")===0||this.type().indexOf("click")!=-1||this.type()=="contextmenu")){
+str+=", mouse(): {page: "+repr(this.mouse().page)+", client: "+repr(this.mouse().client);
+if(this.type()!="mousemove"){
+str+=", button: {left: "+repr(this.mouse().button.left)+", middle: "+repr(this.mouse().button.middle)+", right: "+repr(this.mouse().button.right)+"}}";
+}else{
+str+="}";
+}
+}
+if(this.type()=="mouseover"||this.type()=="mouseout"){
+str+=", relatedTarget(): "+repr(this.relatedTarget());
+}
+str+="}";
+return str;
+},toString:function(){
+return this.__repr__();
+},src:function(){
+return this._src;
+},event:function(){
+return this._event;
+},type:function(){
+return this._event.type||undefined;
+},target:function(){
+return this._event.target||this._event.srcElement;
+},_relatedTarget:null,relatedTarget:function(){
+if(this._relatedTarget!==null){
+return this._relatedTarget;
+}
+var elem=null;
+if(this.type()=="mouseover"){
+elem=(this._event.relatedTarget||this._event.fromElement);
+}else{
+if(this.type()=="mouseout"){
+elem=(this._event.relatedTarget||this._event.toElement);
+}
+}
+if(elem!==null){
+this._relatedTarget=elem;
+return elem;
+}
+return undefined;
+},_modifier:null,modifier:function(){
+if(this._modifier!==null){
+return this._modifier;
+}
+var m={};
+m.alt=this._event.altKey;
+m.ctrl=this._event.ctrlKey;
+m.meta=this._event.metaKey||false;
+m.shift=this._event.shiftKey;
+m.any=m.alt||m.ctrl||m.shift||m.meta;
+this._modifier=m;
+return m;
+},_key:null,key:function(){
+if(this._key!==null){
+return this._key;
+}
+var k={};
+if(this.type()&&this.type().indexOf("key")===0){
+if(this.type()=="keydown"||this.type()=="keyup"){
+k.code=this._event.keyCode;
+k.string=(MochiKit.Signal._specialKeys[k.code]||"KEY_UNKNOWN");
+this._key=k;
+return k;
+}else{
+if(this.type()=="keypress"){
+k.code=0;
+k.string="";
+if(typeof (this._event.charCode)!="undefined"&&this._event.charCode!==0&&!MochiKit.Signal._specialMacKeys[this._event.charCode]){
+k.code=this._event.charCode;
+k.string=String.fromCharCode(k.code);
+}else{
+if(this._event.keyCode&&typeof (this._event.charCode)=="undefined"){
+k.code=this._event.keyCode;
+k.string=String.fromCharCode(k.code);
+}
+}
+this._key=k;
+return k;
+}
+}
+}
+return undefined;
+},_mouse:null,mouse:function(){
+if(this._mouse!==null){
+return this._mouse;
+}
+var m={};
+var e=this._event;
+if(this.type()&&(this.type().indexOf("mouse")===0||this.type().indexOf("click")!=-1||this.type()=="contextmenu")){
+m.client=new MochiKit.Style.Coordinates(0,0);
+if(e.clientX||e.clientY){
+m.client.x=(!e.clientX||e.clientX<0)?0:e.clientX;
+m.client.y=(!e.clientY||e.clientY<0)?0:e.clientY;
+}
+m.page=new MochiKit.Style.Coordinates(0,0);
+if(e.pageX||e.pageY){
+m.page.x=(!e.pageX||e.pageX<0)?0:e.pageX;
+m.page.y=(!e.pageY||e.pageY<0)?0:e.pageY;
+}else{
+var de=MochiKit.DOM._document.documentElement;
+var b=MochiKit.DOM._document.body;
+m.page.x=e.clientX+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||0);
+m.page.y=e.clientY+(de.scrollTop||b.scrollTop)-(de.clientTop||0);
+}
+if(this.type()!="mousemove"){
+m.button={};
+m.button.left=false;
+m.button.right=false;
+m.button.middle=false;
+if(e.which){
+m.button.left=(e.which==1);
+m.button.middle=(e.which==2);
+m.button.right=(e.which==3);
+}else{
+m.button.left=!!(e.button&1);
+m.button.right=!!(e.button&2);
+m.button.middle=!!(e.button&4);
+}
+}
+this._mouse=m;
+return m;
+}
+return undefined;
+},stop:function(){
+this.stopPropagation();
+this.preventDefault();
+},stopPropagation:function(){
+if(this._event.stopPropagation){
+this._event.stopPropagation();
+}else{
+this._event.cancelBubble=true;
+}
+},preventDefault:function(){
+if(this._event.preventDefault){
+this._event.preventDefault();
+}else{
+if(this._confirmUnload===null){
+this._event.returnValue=false;
+}
+}
+},_confirmUnload:null,confirmUnload:function(msg){
+if(this.type()=="beforeunload"){
+this._confirmUnload=msg;
+this._event.returnValue=msg;
+}
+}});
+MochiKit.Signal._specialMacKeys={3:"KEY_ENTER",63289:"KEY_NUM_PAD_CLEAR",63276:"KEY_PAGE_UP",63277:"KEY_PAGE_DOWN",63275:"KEY_END",63273:"KEY_HOME",63234:"KEY_ARROW_LEFT",63232:"KEY_ARROW_UP",63235:"KEY_ARROW_RIGHT",63233:"KEY_ARROW_DOWN",63302:"KEY_INSERT",63272:"KEY_DELETE"};
+(function(){
+var _585=MochiKit.Signal._specialMacKeys;
+for(i=63236;i<=63242;i++){
+_585[i]="KEY_F"+(i-63236+1);
+}
+})();
+MochiKit.Signal._specialKeys={8:"KEY_BACKSPACE",9:"KEY_TAB",12:"KEY_NUM_PAD_CLEAR",13:"KEY_ENTER",16:"KEY_SHIFT",17:"KEY_CTRL",18:"KEY_ALT",19:"KEY_PAUSE",20:"KEY_CAPS_LOCK",27:"KEY_ESCAPE",32:"KEY_SPACEBAR",33:"KEY_PAGE_UP",34:"KEY_PAGE_DOWN",35:"KEY_END",36:"KEY_HOME",37:"KEY_ARROW_LEFT",38:"KEY_ARROW_UP",39:"KEY_ARROW_RIGHT",40:"KEY_ARROW_DOWN",44:"KEY_PRINT_SCREEN",45:"KEY_INSERT",46:"KEY_DELETE",59:"KEY_SEMICOLON",91:"KEY_WINDOWS_LEFT",92:"KEY_WINDOWS_RIGHT",93:"KEY_SELECT",106:"KEY_NUM_PAD_ASTERISK",107:"KEY_NUM_PAD_PLUS_SIGN",109:"KEY_NUM_PAD_HYPHEN-MINUS",110:"KEY_NUM_PAD_FULL_STOP",111:"KEY_NUM_PAD_SOLIDUS",144:"KEY_NUM_LOCK",145:"KEY_SCROLL_LOCK",186:"KEY_SEMICOLON",187:"KEY_EQUALS_SIGN",188:"KEY_COMMA",189:"KEY_HYPHEN-MINUS",190:"KEY_FULL_STOP",191:"KEY_SOLIDUS",192:"KEY_GRAVE_ACCENT",219:"KEY_LEFT_SQUARE_BRACKET",220:"KEY_REVERSE_SOLIDUS",221:"KEY_RIGHT_SQUARE_BRACKET",222:"KEY_APOSTROPHE"};
+(function(){
+var _586=MochiKit.Signal._specialKeys;
+for(var i=48;i<=57;i++){
+_586[i]="KEY_"+(i-48);
+}
+for(i=65;i<=90;i++){
+_586[i]="KEY_"+String.fromCharCode(i);
+}
+for(i=96;i<=105;i++){
+_586[i]="KEY_NUM_PAD_"+(i-96);
+}
+for(i=112;i<=123;i++){
+_586[i]="KEY_F"+(i-112+1);
+}
+})();
+MochiKit.Base.update(MochiKit.Signal,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},_unloadCache:function(){
+var self=MochiKit.Signal;
+var _587=self._observers;
+for(var i=0;i<_587.length;i++){
+self._disconnect(_587[i]);
+}
+delete self._observers;
+try{
+window.onload=undefined;
+}
+catch(e){
+}
+try{
+window.onunload=undefined;
+}
+catch(e){
+}
+},_listener:function(src,func,obj,_588){
+var self=MochiKit.Signal;
+var E=self.Event;
+if(!_588){
+return MochiKit.Base.bind(func,obj);
+}
+obj=obj||src;
+if(typeof (func)=="string"){
+return function(_590){
+obj[func].apply(obj,[new E(src,_590)]);
+};
+}else{
+return function(_591){
+func.apply(obj,[new E(src,_591)]);
+};
+}
+},_browserAlreadyHasMouseEnterAndLeave:function(){
+return /MSIE/.test(navigator.userAgent);
+},_mouseEnterListener:function(src,sig,func,obj){
+var E=MochiKit.Signal.Event;
+return function(_593){
+var e=new E(src,_593);
+try{
+e.relatedTarget().nodeName;
+}
+catch(err){
+return;
+}
+e.stop();
+if(MochiKit.DOM.isChildNode(e.relatedTarget(),src)){
+return;
+}
+e.type=function(){
+return sig;
+};
+if(typeof (func)=="string"){
+return obj[func].apply(obj,[e]);
+}else{
+return func.apply(obj,[e]);
+}
+};
+},_getDestPair:function(_594,_595){
+var obj=null;
+var func=null;
+if(typeof (_595)!="undefined"){
+obj=_594;
+func=_595;
+if(typeof (_595)=="string"){
+if(typeof (_594[_595])!="function"){
+throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
+}
+}else{
+if(typeof (_595)!="function"){
+throw new Error("'funcOrStr' must be a function or string");
+}
+}
+}else{
+if(typeof (_594)!="function"){
+throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
+}else{
+func=_594;
+}
+}
+return [obj,func];
+},connect:function(src,sig,_596,_597){
+src=MochiKit.DOM.getElement(src);
+var self=MochiKit.Signal;
+if(typeof (sig)!="string"){
+throw new Error("'sig' must be a string");
+}
+var _598=self._getDestPair(_596,_597);
+var obj=_598[0];
+var func=_598[1];
+if(typeof (obj)=="undefined"||obj===null){
+obj=src;
+}
+var _599=!!(src.addEventListener||src.attachEvent);
+if(_599&&(sig==="onmouseenter"||sig==="onmouseleave")&&!self._browserAlreadyHasMouseEnterAndLeave()){
+var _600=self._mouseEnterListener(src,sig.substr(2),func,obj);
+if(sig==="onmouseenter"){
+sig="onmouseover";
+}else{
+sig="onmouseout";
+}
+}else{
+var _600=self._listener(src,func,obj,_599);
+}
+if(src.addEventListener){
+src.addEventListener(sig.substr(2),_600,false);
+}else{
+if(src.attachEvent){
+src.attachEvent(sig,_600);
+}
+}
+var _601=[src,sig,_600,_599,_596,_597,true];
+self._observers.push(_601);
+if(!_599&&typeof (src.__connect__)=="function"){
+var args=MochiKit.Base.extend([_601],arguments,1);
+src.__connect__.apply(src,args);
+}
+return _601;
+},_disconnect:function(_602){
+if(!_602[6]){
+return;
+}
+_602[6]=false;
+if(!_602[3]){
+return;
+}
+var src=_602[0];
+var sig=_602[1];
+var _603=_602[2];
+if(src.removeEventListener){
+src.removeEventListener(sig.substr(2),_603,false);
+}else{
+if(src.detachEvent){
+src.detachEvent(sig,_603);
+}else{
+throw new Error("'src' must be a DOM element");
+}
+}
+},disconnect:function(_604){
+var self=MochiKit.Signal;
+var _605=self._observers;
+var m=MochiKit.Base;
+if(arguments.length>1){
+var src=MochiKit.DOM.getElement(arguments[0]);
+var sig=arguments[1];
+var obj=arguments[2];
+var func=arguments[3];
+for(var i=_605.length-1;i>=0;i--){
+var o=_605[i];
+if(o[0]===src&&o[1]===sig&&o[4]===obj&&o[5]===func){
+self._disconnect(o);
+if(!self._lock){
+_605.splice(i,1);
+}else{
+self._dirty=true;
+}
+return true;
+}
+}
+}else{
+var idx=m.findIdentical(_605,_604);
+if(idx>=0){
+self._disconnect(_604);
+if(!self._lock){
+_605.splice(idx,1);
+}else{
+self._dirty=true;
+}
+return true;
+}
+}
+return false;
+},disconnectAllTo:function(_606,_607){
+var self=MochiKit.Signal;
+var _608=self._observers;
+var _609=self._disconnect;
+var _610=self._lock;
+var _611=self._dirty;
+if(typeof (_607)==="undefined"){
+_607=null;
+}
+for(var i=_608.length-1;i>=0;i--){
+var _612=_608[i];
+if(_612[4]===_606&&(_607===null||_612[5]===_607)){
+_609(_612);
+if(_610){
+_611=true;
+}else{
+_608.splice(i,1);
+}
+}
+}
+self._dirty=_611;
+},disconnectAll:function(src,sig){
+src=MochiKit.DOM.getElement(src);
+var m=MochiKit.Base;
+var _613=m.flattenArguments(m.extend(null,arguments,1));
+var self=MochiKit.Signal;
+var _614=self._disconnect;
+var _615=self._observers;
+var i,ident;
+var _616=self._lock;
+var _617=self._dirty;
+if(_613.length===0){
+for(i=_615.length-1;i>=0;i--){
+ident=_615[i];
+if(ident[0]===src){
+_614(ident);
+if(!_616){
+_615.splice(i,1);
+}else{
+_617=true;
+}
+}
+}
+}else{
+var sigs={};
+for(i=0;i<_613.length;i++){
+sigs[_613[i]]=true;
+}
+for(i=_615.length-1;i>=0;i--){
+ident=_615[i];
+if(ident[0]===src&&ident[1] in sigs){
+_614(ident);
+if(!_616){
+_615.splice(i,1);
+}else{
+_617=true;
+}
+}
+}
+}
+self._dirty=_617;
+},signal:function(src,sig){
+var self=MochiKit.Signal;
+var _619=self._observers;
+src=MochiKit.DOM.getElement(src);
+var args=MochiKit.Base.extend(null,arguments,2);
+var _620=[];
+self._lock=true;
+for(var i=0;i<_619.length;i++){
+var _621=_619[i];
+if(_621[0]===src&&_621[1]===sig){
+try{
+_621[2].apply(src,args);
+}
+catch(e){
+_620.push(e);
+}
+}
+}
+self._lock=false;
+if(self._dirty){
+self._dirty=false;
+for(var i=_619.length-1;i>=0;i--){
+if(!_619[i][6]){
+_619.splice(i,1);
+}
+}
+}
+if(_620.length==1){
+throw _620[0];
+}else{
+if(_620.length>1){
+var e=new Error("Multiple errors thrown in handling 'sig', see errors property");
+e.errors=_620;
+throw e;
+}
+}
+}});
+MochiKit.Signal.EXPORT_OK=[];
+MochiKit.Signal.EXPORT=["connect","disconnect","signal","disconnectAll","disconnectAllTo"];
+MochiKit.Signal.__new__=function(win){
+var m=MochiKit.Base;
+this._document=document;
+this._window=win;
+this._lock=false;
+this._dirty=false;
+try{
+this.connect(window,"onunload",this._unloadCache);
+}
+catch(e){
+}
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Signal.__new__(this);
+if(MochiKit.__export__){
+connect=MochiKit.Signal.connect;
+disconnect=MochiKit.Signal.disconnect;
+disconnectAll=MochiKit.Signal.disconnectAll;
+signal=MochiKit.Signal.signal;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.Signal);
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Visual");
+dojo.require("MochiKit.Base");
+dojo.require("MochiKit.DOM");
+dojo.require("MochiKit.Style");
+dojo.require("MochiKit.Color");
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit.Base",[]);
+JSAN.use("MochiKit.DOM",[]);
+JSAN.use("MochiKit.Style",[]);
+JSAN.use("MochiKit.Color",[]);
+}
+try{
+if(typeof (MochiKit.Base)==="undefined"||typeof (MochiKit.DOM)==="undefined"||typeof (MochiKit.Style)==="undefined"||typeof (MochiKit.Color)==="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM, MochiKit.Style and MochiKit.Color!";
+}
+if(typeof (MochiKit.Visual)=="undefined"){
+MochiKit.Visual={};
+}
+MochiKit.Visual.NAME="MochiKit.Visual";
+MochiKit.Visual.VERSION="1.4";
+MochiKit.Visual.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Visual.toString=function(){
+return this.__repr__();
+};
+MochiKit.Visual._RoundCorners=function(e,_622){
+e=MochiKit.DOM.getElement(e);
+this._setOptions(_622);
+if(this.options.__unstable__wrapElement){
+e=this._doWrap(e);
+}
+var _623=this.options.color;
+var C=MochiKit.Color.Color;
+if(this.options.color==="fromElement"){
+_623=C.fromBackground(e);
+}else{
+if(!(_623 instanceof C)){
+_623=C.fromString(_623);
+}
+}
+this.isTransparent=(_623.asRGB().a<=0);
+var _625=this.options.bgColor;
+if(this.options.bgColor==="fromParent"){
+_625=C.fromBackground(e.offsetParent);
+}else{
+if(!(_625 instanceof C)){
+_625=C.fromString(_625);
+}
+}
+this._roundCornersImpl(e,_623,_625);
+};
+MochiKit.Visual._RoundCorners.prototype={_doWrap:function(e){
+var _626=e.parentNode;
+var doc=MochiKit.DOM.currentDocument();
+if(typeof (doc.defaultView)==="undefined"||doc.defaultView===null){
+return e;
+}
+var _627=doc.defaultView.getComputedStyle(e,null);
+if(typeof (_627)==="undefined"||_627===null){
+return e;
+}
+var _628=MochiKit.DOM.DIV({"style":{display:"block",marginTop:_627.getPropertyValue("padding-top"),marginRight:_627.getPropertyValue("padding-right"),marginBottom:_627.getPropertyValue("padding-bottom"),marginLeft:_627.getPropertyValue("padding-left"),padding:"0px"}});
+_628.innerHTML=e.innerHTML;
+e.innerHTML="";
+e.appendChild(_628);
+return e;
+},_roundCornersImpl:function(e,_629,_630){
+if(this.options.border){
+this._renderBorder(e,_630);
+}
+if(this._isTopRounded()){
+this._roundTopCorners(e,_629,_630);
+}
+if(this._isBottomRounded()){
+this._roundBottomCorners(e,_629,_630);
+}
+},_renderBorder:function(el,_632){
+var _633="1px solid "+this._borderColor(_632);
+var _634="border-left: "+_633;
+var _635="border-right: "+_633;
+var _636="style='"+_634+";"+_635+"'";
+el.innerHTML="<div "+_636+">"+el.innerHTML+"</div>";
+},_roundTopCorners:function(el,_637,_638){
+var _639=this._createCorner(_638);
+for(var i=0;i<this.options.numSlices;i++){
+_639.appendChild(this._createCornerSlice(_637,_638,i,"top"));
+}
+el.style.paddingTop=0;
+el.insertBefore(_639,el.firstChild);
+},_roundBottomCorners:function(el,_640,_641){
+var _642=this._createCorner(_641);
+for(var i=(this.options.numSlices-1);i>=0;i--){
+_642.appendChild(this._createCornerSlice(_640,_641,i,"bottom"));
+}
+el.style.paddingBottom=0;
+el.appendChild(_642);
+},_createCorner:function(_643){
+var dom=MochiKit.DOM;
+return dom.DIV({style:{backgroundColor:_643.toString()}});
+},_createCornerSlice:function(_644,_645,n,_646){
+var _647=MochiKit.DOM.SPAN();
+var _648=_647.style;
+_648.backgroundColor=_644.toString();
+_648.display="block";
+_648.height="1px";
+_648.overflow="hidden";
+_648.fontSize="1px";
+var _649=this._borderColor(_644,_645);
+if(this.options.border&&n===0){
+_648.borderTopStyle="solid";
+_648.borderTopWidth="1px";
+_648.borderLeftWidth="0px";
+_648.borderRightWidth="0px";
+_648.borderBottomWidth="0px";
+_648.height="0px";
+_648.borderColor=_649.toString();
+}else{
+if(_649){
+_648.borderColor=_649.toString();
+_648.borderStyle="solid";
+_648.borderWidth="0px 1px";
+}
+}
+if(!this.options.compact&&(n==(this.options.numSlices-1))){
+_648.height="2px";
+}
+this._setMargin(_647,n,_646);
+this._setBorder(_647,n,_646);
+return _647;
+},_setOptions:function(_650){
+this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false,__unstable__wrapElement:false};
+MochiKit.Base.update(this.options,_650);
+this.options.numSlices=(this.options.compact?2:4);
+},_whichSideTop:function(){
+var _651=this.options.corners;
+if(this._hasString(_651,"all","top")){
+return "";
+}
+var _652=(_651.indexOf("tl")!=-1);
+var _653=(_651.indexOf("tr")!=-1);
+if(_652&&_653){
+return "";
+}
+if(_652){
+return "left";
+}
+if(_653){
+return "right";
+}
+return "";
+},_whichSideBottom:function(){
+var _654=this.options.corners;
+if(this._hasString(_654,"all","bottom")){
+return "";
+}
+var _655=(_654.indexOf("bl")!=-1);
+var _656=(_654.indexOf("br")!=-1);
+if(_655&&_656){
+return "";
+}
+if(_655){
+return "left";
+}
+if(_656){
+return "right";
+}
+return "";
+},_borderColor:function(_657,_658){
+if(_657=="transparent"){
+return _658;
+}else{
+if(this.options.border){
+return this.options.border;
+}else{
+if(this.options.blend){
+return _658.blendedColor(_657);
+}
+}
+}
+return "";
+},_setMargin:function(el,n,_659){
+var _660=this._marginSize(n)+"px";
+var _661=(_659=="top"?this._whichSideTop():this._whichSideBottom());
+var _662=el.style;
+if(_661=="left"){
+_662.marginLeft=_660;
+_662.marginRight="0px";
+}else{
+if(_661=="right"){
+_662.marginRight=_660;
+_662.marginLeft="0px";
+}else{
+_662.marginLeft=_660;
+_662.marginRight=_660;
+}
+}
+},_setBorder:function(el,n,_663){
+var _664=this._borderSize(n)+"px";
+var _665=(_663=="top"?this._whichSideTop():this._whichSideBottom());
+var _666=el.style;
+if(_665=="left"){
+_666.borderLeftWidth=_664;
+_666.borderRightWidth="0px";
+}else{
+if(_665=="right"){
+_666.borderRightWidth=_664;
+_666.borderLeftWidth="0px";
+}else{
+_666.borderLeftWidth=_664;
+_666.borderRightWidth=_664;
+}
+}
+},_marginSize:function(n){
+if(this.isTransparent){
+return 0;
+}
+var o=this.options;
+if(o.compact&&o.blend){
+var _667=[1,0];
+return _667[n];
+}else{
+if(o.compact){
+var _668=[2,1];
+return _668[n];
+}else{
+if(o.blend){
+var _669=[3,2,1,0];
+return _669[n];
+}else{
+var _670=[5,3,2,1];
+return _670[n];
+}
+}
+}
+},_borderSize:function(n){
+var o=this.options;
+var _671;
+if(o.compact&&(o.blend||this.isTransparent)){
+return 1;
+}else{
+if(o.compact){
+_671=[1,0];
+}else{
+if(o.blend){
+_671=[2,1,1,1];
+}else{
+if(o.border){
+_671=[0,2,0,0];
+}else{
+if(this.isTransparent){
+_671=[5,3,2,1];
+}else{
+return 0;
+}
+}
+}
+}
+}
+return _671[n];
+},_hasString:function(str){
+for(var i=1;i<arguments.length;i++){
+if(str.indexOf(arguments[i])!=-1){
+return true;
+}
+}
+return false;
+},_isTopRounded:function(){
+return this._hasString(this.options.corners,"all","top","tl","tr");
+},_isBottomRounded:function(){
+return this._hasString(this.options.corners,"all","bottom","bl","br");
+},_hasSingleTextChild:function(el){
+return (el.childNodes.length==1&&el.childNodes[0].nodeType==3);
+}};
+MochiKit.Visual.roundElement=function(e,_672){
+new MochiKit.Visual._RoundCorners(e,_672);
+};
+MochiKit.Visual.roundClass=function(_673,_674,_675){
+var _676=MochiKit.DOM.getElementsByTagAndClassName(_673,_674);
+for(var i=0;i<_676.length;i++){
+MochiKit.Visual.roundElement(_676[i],_675);
+}
+};
+MochiKit.Visual.tagifyText=function(_677,_678){
+var _678=_678||"position:relative";
+if(/MSIE/.test(navigator.userAgent)){
+_678+=";zoom:1";
+}
+_677=MochiKit.DOM.getElement(_677);
+var ma=MochiKit.Base.map;
+ma(function(_680){
+if(_680.nodeType==3){
+ma(function(_681){
+_677.insertBefore(MochiKit.DOM.SPAN({style:_678},_681==" "?String.fromCharCode(160):_681),_680);
+},_680.nodeValue.split(""));
+MochiKit.DOM.removeElement(_680);
+}
+},_677.childNodes);
+};
+MochiKit.Visual.forceRerendering=function(_682){
+try{
+_682=MochiKit.DOM.getElement(_682);
+var n=document.createTextNode(" ");
+_682.appendChild(n);
+_682.removeChild(n);
+}
+catch(e){
+}
+};
+MochiKit.Visual.multiple=function(_683,_684,_685){
+_685=MochiKit.Base.update({speed:0.1,delay:0},_685||{});
+var _686=_685.delay;
+var _687=0;
+MochiKit.Base.map(function(_688){
+_685.delay=_687*_685.speed+_686;
+new _684(_688,_685);
+_687+=1;
+},_683);
+};
+MochiKit.Visual.PAIRS={"slide":["slideDown","slideUp"],"blind":["blindDown","blindUp"],"appear":["appear","fade"],"size":["grow","shrink"]};
+MochiKit.Visual.toggle=function(_689,_690,_691){
+_689=MochiKit.DOM.getElement(_689);
+_690=(_690||"appear").toLowerCase();
+_691=MochiKit.Base.update({queue:{position:"end",scope:(_689.id||"global"),limit:1}},_691||{});
+var v=MochiKit.Visual;
+v[_689.style.display!="none"?v.PAIRS[_690][1]:v.PAIRS[_690][0]](_689,_691);
+};
+MochiKit.Visual.Transitions={};
+MochiKit.Visual.Transitions.linear=function(pos){
+return pos;
+};
+MochiKit.Visual.Transitions.sinoidal=function(pos){
+return (-Math.cos(pos*Math.PI)/2)+0.5;
+};
+MochiKit.Visual.Transitions.reverse=function(pos){
+return 1-pos;
+};
+MochiKit.Visual.Transitions.flicker=function(pos){
+return ((-Math.cos(pos*Math.PI)/4)+0.75)+Math.random()/4;
+};
+MochiKit.Visual.Transitions.wobble=function(pos){
+return (-Math.cos(pos*Math.PI*(9*pos))/2)+0.5;
+};
+MochiKit.Visual.Transitions.pulse=function(pos){
+return (Math.floor(pos*10)%2==0?(pos*10-Math.floor(pos*10)):1-(pos*10-Math.floor(pos*10)));
+};
+MochiKit.Visual.Transitions.none=function(pos){
+return 0;
+};
+MochiKit.Visual.Transitions.full=function(pos){
+return 1;
+};
+MochiKit.Visual.ScopedQueue=function(){
+this.__init__();
+};
+MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype,{__init__:function(){
+this.effects=[];
+this.interval=null;
+},add:function(_693){
+var _694=new Date().getTime();
+var _695=(typeof (_693.options.queue)=="string")?_693.options.queue:_693.options.queue.position;
+var ma=MochiKit.Base.map;
+switch(_695){
+case "front":
+ma(function(e){
+if(e.state=="idle"){
+e.startOn+=_693.finishOn;
+e.finishOn+=_693.finishOn;
+}
+},this.effects);
+break;
+case "end":
+var _696;
+ma(function(e){
+var i=e.finishOn;
+if(i>=(_696||i)){
+_696=i;
+}
+},this.effects);
+_694=_696||_694;
+break;
+case "break":
+ma(function(e){
+e.finalize();
+},this.effects);
+break;
+}
+_693.startOn+=_694;
+_693.finishOn+=_694;
+if(!_693.options.queue.limit||this.effects.length<_693.options.queue.limit){
+this.effects.push(_693);
+}
+if(!this.interval){
+this.interval=this.startLoop(MochiKit.Base.bind(this.loop,this),40);
+}
+},startLoop:function(func,_697){
+return setInterval(func,_697);
+},remove:function(_698){
+this.effects=MochiKit.Base.filter(function(e){
+return e!=_698;
+},this.effects);
+if(this.effects.length==0){
+this.stopLoop(this.interval);
+this.interval=null;
+}
+},stopLoop:function(_699){
+clearInterval(_699);
+},loop:function(){
+var _700=new Date().getTime();
+MochiKit.Base.map(function(_701){
+_701.loop(_700);
+},this.effects);
+}});
+MochiKit.Visual.Queues={instances:{},get:function(_702){
+if(typeof (_702)!="string"){
+return _702;
+}
+if(!this.instances[_702]){
+this.instances[_702]=new MochiKit.Visual.ScopedQueue();
+}
+return this.instances[_702];
+}};
+MochiKit.Visual.Queue=MochiKit.Visual.Queues.get("global");
+MochiKit.Visual.DefaultOptions={transition:MochiKit.Visual.Transitions.sinoidal,duration:1,fps:25,sync:false,from:0,to:1,delay:0,queue:"parallel"};
+MochiKit.Visual.Base=function(){
+};
+MochiKit.Visual.Base.prototype={__class__:MochiKit.Visual.Base,start:function(_703){
+var v=MochiKit.Visual;
+this.options=MochiKit.Base.setdefault(_703||{},v.DefaultOptions);
+this.currentFrame=0;
+this.state="idle";
+this.startOn=this.options.delay*1000;
+this.finishOn=this.startOn+(this.options.duration*1000);
+this.event("beforeStart");
+if(!this.options.sync){
+v.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).add(this);
+}
+},loop:function(_704){
+if(_704>=this.startOn){
+if(_704>=this.finishOn){
+return this.finalize();
+}
+var pos=(_704-this.startOn)/(this.finishOn-this.startOn);
+var _705=Math.round(pos*this.options.fps*this.options.duration);
+if(_705>this.currentFrame){
+this.render(pos);
+this.currentFrame=_705;
+}
+}
+},render:function(pos){
+if(this.state=="idle"){
+this.state="running";
+this.event("beforeSetup");
+this.setup();
+this.event("afterSetup");
+}
+if(this.state=="running"){
+if(this.options.transition){
+pos=this.options.transition(pos);
+}
+pos*=(this.options.to-this.options.from);
+pos+=this.options.from;
+this.event("beforeUpdate");
+this.update(pos);
+this.event("afterUpdate");
+}
+},cancel:function(){
+if(!this.options.sync){
+MochiKit.Visual.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).remove(this);
+}
+this.state="finished";
+},finalize:function(){
+this.render(1);
+this.cancel();
+this.event("beforeFinish");
+this.finish();
+this.event("afterFinish");
+},setup:function(){
+},finish:function(){
+},update:function(_706){
+},event:function(_707){
+if(this.options[_707+"Internal"]){
+this.options[_707+"Internal"](this);
+}
+if(this.options[_707]){
+this.options[_707](this);
+}
+},repr:function(){
+return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]";
+}};
+MochiKit.Visual.Parallel=function(_708,_709){
+this.__init__(_708,_709);
+};
+MochiKit.Visual.Parallel.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Parallel.prototype,{__init__:function(_710,_711){
+this.effects=_710||[];
+this.start(_711);
+},update:function(_712){
+MochiKit.Base.map(function(_713){
+_713.render(_712);
+},this.effects);
+},finish:function(){
+MochiKit.Base.map(function(_714){
+_714.finalize();
+},this.effects);
+}});
+MochiKit.Visual.Opacity=function(_715,_716){
+this.__init__(_715,_716);
+};
+MochiKit.Visual.Opacity.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Opacity.prototype,{__init__:function(_717,_718){
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+this.element=MochiKit.DOM.getElement(_717);
+if(this.element.currentStyle&&(!this.element.currentStyle.hasLayout)){
+s.setStyle(this.element,{zoom:1});
+}
+_718=b.update({from:s.getOpacity(this.element)||0,to:1},_718||{});
+this.start(_718);
+},update:function(_719){
+MochiKit.Style.setOpacity(this.element,_719);
+}});
+MochiKit.Visual.Move=function(_720,_721){
+this.__init__(_720,_721);
+};
+MochiKit.Visual.Move.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Move.prototype,{__init__:function(_722,_723){
+this.element=MochiKit.DOM.getElement(_722);
+_723=MochiKit.Base.update({x:0,y:0,mode:"relative"},_723||{});
+this.start(_723);
+},setup:function(){
+MochiKit.DOM.makePositioned(this.element);
+var s=this.element.style;
+var _724=s.visibility;
+var _725=s.display;
+if(_725=="none"){
+s.visibility="hidden";
+s.display="";
+}
+this.originalLeft=parseFloat(MochiKit.Style.getStyle(this.element,"left")||"0");
+this.originalTop=parseFloat(MochiKit.Style.getStyle(this.element,"top")||"0");
+if(this.options.mode=="absolute"){
+this.options.x-=this.originalLeft;
+this.options.y-=this.originalTop;
+}
+if(_725=="none"){
+s.visibility=_724;
+s.display=_725;
+}
+},update:function(_726){
+MochiKit.Style.setStyle(this.element,{left:Math.round(this.options.x*_726+this.originalLeft)+"px",top:Math.round(this.options.y*_726+this.originalTop)+"px"});
+}});
+MochiKit.Visual.Scale=function(_727,_728,_729){
+this.__init__(_727,_728,_729);
+};
+MochiKit.Visual.Scale.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Scale.prototype,{__init__:function(_730,_731,_732){
+this.element=MochiKit.DOM.getElement(_730);
+_732=MochiKit.Base.update({scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:"box",scaleFrom:100,scaleTo:_731},_732||{});
+this.start(_732);
+},setup:function(){
+this.restoreAfterFinish=this.options.restoreAfterFinish||false;
+this.elementPositioning=MochiKit.Style.getStyle(this.element,"position");
+var ma=MochiKit.Base.map;
+var b=MochiKit.Base.bind;
+this.originalStyle={};
+ma(b(function(k){
+this.originalStyle[k]=this.element.style[k];
+},this),["top","left","width","height","fontSize"]);
+this.originalTop=this.element.offsetTop;
+this.originalLeft=this.element.offsetLeft;
+var _733=MochiKit.Style.getStyle(this.element,"font-size")||"100%";
+ma(b(function(_734){
+if(_733.indexOf(_734)>0){
+this.fontSize=parseFloat(_733);
+this.fontSizeType=_734;
+}
+},this),["em","px","%"]);
+this.factor=(this.options.scaleTo-this.options.scaleFrom)/100;
+if(/^content/.test(this.options.scaleMode)){
+this.dims=[this.element.scrollHeight,this.element.scrollWidth];
+}else{
+if(this.options.scaleMode=="box"){
+this.dims=[this.element.offsetHeight,this.element.offsetWidth];
+}else{
+this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth];
+}
+}
+},update:function(_735){
+var _736=(this.options.scaleFrom/100)+(this.factor*_735);
+if(this.options.scaleContent&&this.fontSize){
+MochiKit.Style.setStyle(this.element,{fontSize:this.fontSize*_736+this.fontSizeType});
+}
+this.setDimensions(this.dims[0]*_736,this.dims[1]*_736);
+},finish:function(){
+if(this.restoreAfterFinish){
+MochiKit.Style.setStyle(this.element,this.originalStyle);
+}
+},setDimensions:function(_737,_738){
+var d={};
+var r=Math.round;
+if(/MSIE/.test(navigator.userAgent)){
+r=Math.ceil;
+}
+if(this.options.scaleX){
+d.width=r(_738)+"px";
+}
+if(this.options.scaleY){
+d.height=r(_737)+"px";
+}
+if(this.options.scaleFromCenter){
+var topd=(_737-this.dims[0])/2;
+var _740=(_738-this.dims[1])/2;
+if(this.elementPositioning=="absolute"){
+if(this.options.scaleY){
+d.top=this.originalTop-topd+"px";
+}
+if(this.options.scaleX){
+d.left=this.originalLeft-_740+"px";
+}
+}else{
+if(this.options.scaleY){
+d.top=-topd+"px";
+}
+if(this.options.scaleX){
+d.left=-_740+"px";
+}
+}
+}
+MochiKit.Style.setStyle(this.element,d);
+}});
+MochiKit.Visual.Highlight=function(_741,_742){
+this.__init__(_741,_742);
+};
+MochiKit.Visual.Highlight.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Highlight.prototype,{__init__:function(_743,_744){
+this.element=MochiKit.DOM.getElement(_743);
+_744=MochiKit.Base.update({startcolor:"#ffff99"},_744||{});
+this.start(_744);
+},setup:function(){
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+if(s.getStyle(this.element,"display")=="none"){
+this.cancel();
+return;
+}
+this.oldStyle={backgroundImage:s.getStyle(this.element,"background-image")};
+s.setStyle(this.element,{backgroundImage:"none"});
+if(!this.options.endcolor){
+this.options.endcolor=MochiKit.Color.Color.fromBackground(this.element).toHexString();
+}
+if(b.isUndefinedOrNull(this.options.restorecolor)){
+this.options.restorecolor=s.getStyle(this.element,"background-color");
+}
+this._base=b.map(b.bind(function(i){
+return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16);
+},this),[0,1,2]);
+this._delta=b.map(b.bind(function(i){
+return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i];
+},this),[0,1,2]);
+},update:function(_745){
+var m="#";
+MochiKit.Base.map(MochiKit.Base.bind(function(i){
+m+=MochiKit.Color.toColorPart(Math.round(this._base[i]+this._delta[i]*_745));
+},this),[0,1,2]);
+MochiKit.Style.setStyle(this.element,{backgroundColor:m});
+},finish:function(){
+MochiKit.Style.setStyle(this.element,MochiKit.Base.update(this.oldStyle,{backgroundColor:this.options.restorecolor}));
+}});
+MochiKit.Visual.ScrollTo=function(_746,_747){
+this.__init__(_746,_747);
+};
+MochiKit.Visual.ScrollTo.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype,{__init__:function(_748,_749){
+this.element=MochiKit.DOM.getElement(_748);
+this.start(_749||{});
+},setup:function(){
+var p=MochiKit.Position;
+p.prepare();
+var _750=p.cumulativeOffset(this.element);
+if(this.options.offset){
+_750.y+=this.options.offset;
+}
+var max;
+if(window.innerHeight){
+max=window.innerHeight-window.height;
+}else{
+if(document.documentElement&&document.documentElement.clientHeight){
+max=document.documentElement.clientHeight-document.body.scrollHeight;
+}else{
+if(document.body){
+max=document.body.clientHeight-document.body.scrollHeight;
+}
+}
+}
+this.scrollStart=p.windowOffset.y;
+this.delta=(_750.y>max?max:_750.y)-this.scrollStart;
+},update:function(_751){
+var p=MochiKit.Position;
+p.prepare();
+window.scrollTo(p.windowOffset.x,this.scrollStart+(_751*this.delta));
+}});
+MochiKit.Visual.fade=function(_752,_753){
+var s=MochiKit.Style;
+var _754=MochiKit.DOM.getElement(_752).style.opacity||"";
+_753=MochiKit.Base.update({from:s.getOpacity(_752)||1,to:0,afterFinishInternal:function(_755){
+if(_755.options.to!==0){
+return;
+}
+s.hideElement(_755.element);
+s.setStyle(_755.element,{opacity:_754});
+}},_753||{});
+return new MochiKit.Visual.Opacity(_752,_753);
+};
+MochiKit.Visual.appear=function(_756,_757){
+var s=MochiKit.Style;
+var v=MochiKit.Visual;
+_757=MochiKit.Base.update({from:(s.getStyle(_756,"display")=="none"?0:s.getOpacity(_756)||0),to:1,afterFinishInternal:function(_758){
+v.forceRerendering(_758.element);
+},beforeSetupInternal:function(_759){
+s.setOpacity(_759.element,_759.options.from);
+s.showElement(_759.element);
+}},_757||{});
+return new v.Opacity(_756,_757);
+};
+MochiKit.Visual.puff=function(_760,_761){
+var s=MochiKit.Style;
+var v=MochiKit.Visual;
+_760=MochiKit.DOM.getElement(_760);
+var _762={opacity:_760.style.opacity||"",position:s.getStyle(_760,"position"),top:_760.style.top,left:_760.style.left,width:_760.style.width,height:_760.style.height};
+_761=MochiKit.Base.update({beforeSetupInternal:function(_763){
+MochiKit.Position.absolutize(_763.effects[0].element);
+},afterFinishInternal:function(_764){
+s.hideElement(_764.effects[0].element);
+s.setStyle(_764.effects[0].element,_762);
+}},_761||{});
+return new v.Parallel([new v.Scale(_760,200,{sync:true,scaleFromCenter:true,scaleContent:true,restoreAfterFinish:true}),new v.Opacity(_760,{sync:true,to:0})],_761);
+};
+MochiKit.Visual.blindUp=function(_765,_766){
+var d=MochiKit.DOM;
+_765=d.getElement(_765);
+var _767=d.makeClipping(_765);
+_766=MochiKit.Base.update({scaleContent:false,scaleX:false,restoreAfterFinish:true,afterFinishInternal:function(_768){
+MochiKit.Style.hideElement(_768.element);
+d.undoClipping(_768.element,_767);
+}},_766||{});
+return new MochiKit.Visual.Scale(_765,0,_766);
+};
+MochiKit.Visual.blindDown=function(_769,_770){
+var d=MochiKit.DOM;
+var s=MochiKit.Style;
+_769=d.getElement(_769);
+var _771=s.getElementDimensions(_769);
+var _772;
+_770=MochiKit.Base.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_771.h,originalWidth:_771.w},restoreAfterFinish:true,afterSetupInternal:function(_773){
+_772=d.makeClipping(_773.element);
+s.setStyle(_773.element,{height:"0px"});
+s.showElement(_773.element);
+},afterFinishInternal:function(_774){
+d.undoClipping(_774.element,_772);
+}},_770||{});
+return new MochiKit.Visual.Scale(_769,100,_770);
+};
+MochiKit.Visual.switchOff=function(_775,_776){
+var d=MochiKit.DOM;
+_775=d.getElement(_775);
+var _777=_775.style.opacity||"";
+var _778;
+var _776=MochiKit.Base.update({duration:0.3,scaleFromCenter:true,scaleX:false,scaleContent:false,restoreAfterFinish:true,beforeSetupInternal:function(_779){
+d.makePositioned(_779.element);
+_778=d.makeClipping(_779.element);
+},afterFinishInternal:function(_780){
+MochiKit.Style.hideElement(_780.element);
+d.undoClipping(_780.element,_778);
+d.undoPositioned(_780.element);
+MochiKit.Style.setStyle(_780.element,{opacity:_777});
+}},_776||{});
+var v=MochiKit.Visual;
+return new v.appear(_775,{duration:0.4,from:0,transition:v.Transitions.flicker,afterFinishInternal:function(_781){
+new v.Scale(_781.element,1,_776);
+}});
+};
+MochiKit.Visual.dropOut=function(_782,_783){
+var d=MochiKit.DOM;
+var s=MochiKit.Style;
+_782=d.getElement(_782);
+var _784={top:s.getStyle(_782,"top"),left:s.getStyle(_782,"left"),opacity:_782.style.opacity||""};
+_783=MochiKit.Base.update({duration:0.5,beforeSetupInternal:function(_785){
+d.makePositioned(_785.effects[0].element);
+},afterFinishInternal:function(_786){
+s.hideElement(_786.effects[0].element);
+d.undoPositioned(_786.effects[0].element);
+s.setStyle(_786.effects[0].element,_784);
+}},_783||{});
+var v=MochiKit.Visual;
+return new v.Parallel([new v.Move(_782,{x:0,y:100,sync:true}),new v.Opacity(_782,{sync:true,to:0})],_783);
+};
+MochiKit.Visual.shake=function(_787,_788){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_787=d.getElement(_787);
+_788=MochiKit.Base.update({x:-20,y:0,duration:0.05,afterFinishInternal:function(_789){
+d.undoPositioned(_789.element);
+s.setStyle(_789.element,oldStyle);
+}},_788||{});
+var _790={top:s.getStyle(_787,"top"),left:s.getStyle(_787,"left")};
+return new v.Move(_787,{x:20,y:0,duration:0.05,afterFinishInternal:function(_791){
+new v.Move(_791.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(_791){
+new v.Move(_791.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(_791){
+new v.Move(_791.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(_791){
+new v.Move(_791.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(_791){
+new v.Move(_791.element,_788);
+}});
+}});
+}});
+}});
+}});
+};
+MochiKit.Visual.slideDown=function(_792,_793){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+_792=d.getElement(_792);
+if(!_792.firstChild){
+throw "MochiKit.Visual.slideDown must be used on a element with a child";
+}
+d.removeEmptyTextNodes(_792);
+var _794=s.getStyle(_792.firstChild,"bottom")||0;
+var _795=s.getElementDimensions(_792);
+var _796;
+_793=b.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_795.h,originalWidth:_795.w},restoreAfterFinish:true,afterSetupInternal:function(_797){
+d.makePositioned(_797.element);
+d.makePositioned(_797.element.firstChild);
+if(/Opera/.test(navigator.userAgent)){
+s.setStyle(_797.element,{top:""});
+}
+_796=d.makeClipping(_797.element);
+s.setStyle(_797.element,{height:"0px"});
+s.showElement(_797.element);
+},afterUpdateInternal:function(_798){
+s.setStyle(_798.element.firstChild,{bottom:(_798.dims[0]-_798.element.clientHeight)+"px"});
+},afterFinishInternal:function(_799){
+d.undoClipping(_799.element,_796);
+if(/MSIE/.test(navigator.userAgent)){
+d.undoPositioned(_799.element);
+d.undoPositioned(_799.element.firstChild);
+}else{
+d.undoPositioned(_799.element.firstChild);
+d.undoPositioned(_799.element);
+}
+s.setStyle(_799.element.firstChild,{bottom:_794});
+}},_793||{});
+return new MochiKit.Visual.Scale(_792,100,_793);
+};
+MochiKit.Visual.slideUp=function(_800,_801){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+_800=d.getElement(_800);
+if(!_800.firstChild){
+throw "MochiKit.Visual.slideUp must be used on a element with a child";
+}
+d.removeEmptyTextNodes(_800);
+var _802=s.getStyle(_800.firstChild,"bottom");
+var _803;
+_801=b.update({scaleContent:false,scaleX:false,scaleMode:"box",scaleFrom:100,restoreAfterFinish:true,beforeStartInternal:function(_804){
+d.makePositioned(_804.element);
+d.makePositioned(_804.element.firstChild);
+if(/Opera/.test(navigator.userAgent)){
+s.setStyle(_804.element,{top:""});
+}
+_803=d.makeClipping(_804.element);
+s.showElement(_804.element);
+},afterUpdateInternal:function(_805){
+s.setStyle(_805.element.firstChild,{bottom:(_805.dims[0]-_805.element.clientHeight)+"px"});
+},afterFinishInternal:function(_806){
+s.hideElement(_806.element);
+d.undoClipping(_806.element,_803);
+d.undoPositioned(_806.element.firstChild);
+d.undoPositioned(_806.element);
+s.setStyle(_806.element.firstChild,{bottom:_802});
+}},_801||{});
+return new MochiKit.Visual.Scale(_800,0,_801);
+};
+MochiKit.Visual.squish=function(_807,_808){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var _809;
+_808=b.update({restoreAfterFinish:true,beforeSetupInternal:function(_810){
+_809=d.makeClipping(_810.element);
+},afterFinishInternal:function(_811){
+MochiKit.Style.hideElement(_811.element);
+d.undoClipping(_811.element,_809);
+}},_808||{});
+return new MochiKit.Visual.Scale(_807,/Opera/.test(navigator.userAgent)?1:0,_808);
+};
+MochiKit.Visual.grow=function(_812,_813){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_812=d.getElement(_812);
+_813=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.full},_813||{});
+var _814={top:_812.style.top,left:_812.style.left,height:_812.style.height,width:_812.style.width,opacity:_812.style.opacity||""};
+var dims=s.getElementDimensions(_812);
+var _816,initialMoveY;
+var _817,moveY;
+switch(_813.direction){
+case "top-left":
+_816=initialMoveY=_817=moveY=0;
+break;
+case "top-right":
+_816=dims.w;
+initialMoveY=moveY=0;
+_817=-dims.w;
+break;
+case "bottom-left":
+_816=_817=0;
+initialMoveY=dims.h;
+moveY=-dims.h;
+break;
+case "bottom-right":
+_816=dims.w;
+initialMoveY=dims.h;
+_817=-dims.w;
+moveY=-dims.h;
+break;
+case "center":
+_816=dims.w/2;
+initialMoveY=dims.h/2;
+_817=-dims.w/2;
+moveY=-dims.h/2;
+break;
+}
+var _818=MochiKit.Base.update({beforeSetupInternal:function(_819){
+s.setStyle(_819.effects[0].element,{height:"0px"});
+s.showElement(_819.effects[0].element);
+},afterFinishInternal:function(_820){
+d.undoClipping(_820.effects[0].element);
+d.undoPositioned(_820.effects[0].element);
+s.setStyle(_820.effects[0].element,_814);
+}},_813||{});
+return new v.Move(_812,{x:_816,y:initialMoveY,duration:0.01,beforeSetupInternal:function(_821){
+s.hideElement(_821.element);
+d.makeClipping(_821.element);
+d.makePositioned(_821.element);
+},afterFinishInternal:function(_822){
+new v.Parallel([new v.Opacity(_822.element,{sync:true,to:1,from:0,transition:_813.opacityTransition}),new v.Move(_822.element,{x:_817,y:moveY,sync:true,transition:_813.moveTransition}),new v.Scale(_822.element,100,{scaleMode:{originalHeight:dims.h,originalWidth:dims.w},sync:true,scaleFrom:/Opera/.test(navigator.userAgent)?1:0,transition:_813.scaleTransition,restoreAfterFinish:true})],_818);
+}});
+};
+MochiKit.Visual.shrink=function(_823,_824){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_823=d.getElement(_823);
+_824=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.none},_824||{});
+var _825={top:_823.style.top,left:_823.style.left,height:_823.style.height,width:_823.style.width,opacity:_823.style.opacity||""};
+var dims=s.getElementDimensions(_823);
+var _826,moveY;
+switch(_824.direction){
+case "top-left":
+_826=moveY=0;
+break;
+case "top-right":
+_826=dims.w;
+moveY=0;
+break;
+case "bottom-left":
+_826=0;
+moveY=dims.h;
+break;
+case "bottom-right":
+_826=dims.w;
+moveY=dims.h;
+break;
+case "center":
+_826=dims.w/2;
+moveY=dims.h/2;
+break;
+}
+var _827;
+var _828=MochiKit.Base.update({beforeStartInternal:function(_829){
+_827=d.makePositioned(_829.effects[0].element);
+d.makeClipping(_829.effects[0].element);
+},afterFinishInternal:function(_830){
+s.hideElement(_830.effects[0].element);
+d.undoClipping(_830.effects[0].element,_827);
+d.undoPositioned(_830.effects[0].element);
+s.setStyle(_830.effects[0].element,_825);
+}},_824||{});
+return new v.Parallel([new v.Opacity(_823,{sync:true,to:0,from:1,transition:_824.opacityTransition}),new v.Scale(_823,/Opera/.test(navigator.userAgent)?1:0,{sync:true,transition:_824.scaleTransition,restoreAfterFinish:true}),new v.Move(_823,{x:_826,y:moveY,sync:true,transition:_824.moveTransition})],_828);
+};
+MochiKit.Visual.pulsate=function(_831,_832){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var b=MochiKit.Base;
+var _833=d.getElement(_831).style.opacity||"";
+_832=b.update({duration:3,from:0,afterFinishInternal:function(_834){
+MochiKit.Style.setStyle(_834.element,{opacity:_833});
+}},_832||{});
+var _835=_832.transition||v.Transitions.sinoidal;
+var _836=b.bind(function(pos){
+return _835(1-v.Transitions.pulse(pos));
+},_835);
+b.bind(_836,_835);
+return new v.Opacity(_831,b.update({transition:_836},_832));
+};
+MochiKit.Visual.fold=function(_837,_838){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_837=d.getElement(_837);
+var _839={top:_837.style.top,left:_837.style.left,width:_837.style.width,height:_837.style.height};
+var _840=d.makeClipping(_837);
+_838=MochiKit.Base.update({scaleContent:false,scaleX:false,afterFinishInternal:function(_841){
+new v.Scale(_837,1,{scaleContent:false,scaleY:false,afterFinishInternal:function(_841){
+s.hideElement(_841.element);
+d.undoClipping(_841.element,_840);
+s.setStyle(_841.element,_839);
+}});
+}},_838||{});
+return new v.Scale(_837,5,_838);
+};
+MochiKit.Visual.Color=MochiKit.Color.Color;
+MochiKit.Visual.getElementsComputedStyle=MochiKit.DOM.computedStyle;
+MochiKit.Visual.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+MochiKit.Visual.EXPORT=["roundElement","roundClass","tagifyText","multiple","toggle","Base","Parallel","Opacity","Move","Scale","Highlight","ScrollTo","fade","appear","puff","blindUp","blindDown","switchOff","dropOut","shake","slideDown","slideUp","squish","grow","shrink","pulsate","fold"];
+MochiKit.Visual.EXPORT_OK=["PAIRS"];
+MochiKit.Visual.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Visual);
+if(typeof (MochiKit)=="undefined"){
+MochiKit={};
+}
+if(typeof (MochiKit.MochiKit)=="undefined"){
+MochiKit.MochiKit={};
+}
+MochiKit.MochiKit.NAME="MochiKit.MochiKit";
+MochiKit.MochiKit.VERSION="1.4";
+MochiKit.MochiKit.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.MochiKit.toString=function(){
+return this.__repr__();
+};
+MochiKit.MochiKit.SUBMODULES=["Base","Iter","Logging","DateTime","Format","Async","DOM","Style","LoggingPane","Color","Signal","Visual"];
+if(typeof (JSAN)!="undefined"||typeof (dojo)!="undefined"){
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.MochiKit");
+dojo.require("MochiKit.*");
+}
+if(typeof (JSAN)!="undefined"){
+(function(lst){
+for(var i=0;i<lst.length;i++){
+JSAN.use("MochiKit."+lst[i],[]);
+}
+})(MochiKit.MochiKit.SUBMODULES);
+}
+(function(){
+var _842=MochiKit.Base.extend;
+var self=MochiKit.MochiKit;
+var _843=self.SUBMODULES;
+var _844=[];
+var _845=[];
+var _846={};
+var i,k,m,all;
+for(i=0;i<_843.length;i++){
+m=MochiKit[_843[i]];
+_842(_844,m.EXPORT);
+_842(_845,m.EXPORT_OK);
+for(k in m.EXPORT_TAGS){
+_846[k]=_842(_846[k],m.EXPORT_TAGS[k]);
+}
+all=m.EXPORT_TAGS[":all"];
+if(!all){
+all=_842(null,m.EXPORT,m.EXPORT_OK);
+}
+var j;
+for(j=0;j<all.length;j++){
+k=all[j];
+self[k]=m[k];
+}
+}
+self.EXPORT=_844;
+self.EXPORT_OK=_845;
+self.EXPORT_TAGS=_846;
+}());
+}else{
+if(typeof (MochiKit.__compat__)=="undefined"){
+MochiKit.__compat__=true;
+}
+(function(){
+if(typeof (document)=="undefined"){
+return;
+}
+var _847=document.getElementsByTagName("script");
+var _848="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+var base=null;
+var _849=null;
+var _850={};
+var i;
+for(i=0;i<_847.length;i++){
+var src=_847[i].getAttribute("src");
+if(!src){
+continue;
+}
+_850[src]=true;
+if(src.match(/MochiKit.js$/)){
+base=src.substring(0,src.lastIndexOf("MochiKit.js"));
+_849=_847[i];
+}
+}
+if(base===null){
+return;
+}
+var _851=MochiKit.MochiKit.SUBMODULES;
+for(var i=0;i<_851.length;i++){
+if(MochiKit[_851[i]]){
+continue;
+}
+var uri=base+_851[i]+".js";
+if(uri in _850){
+continue;
+}
+if(document.documentElement&&document.documentElement.namespaceURI==_848){
+var s=document.createElementNS(_848,"script");
+s.setAttribute("id","MochiKit_"+base+_851[i]);
+s.setAttribute("src",uri);
+s.setAttribute("type","application/x-javascript");
+_849.parentNode.appendChild(s);
+}else{
+document.write("<script src=\""+uri+"\" type=\"text/javascript\"></script>");
+}
+}
+})();
+}
+
+
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/ajax/lib/SimpleTest.js
@@ -0,0 +1,419 @@
+/**
+ * SimpleTest, a partial Test.Simple/Test.More API compatible test library.
+ *
+ * Why?
+ *
+ * Test.Simple doesn't work on IE < 6.
+ * TODO:
+ *  * Support the Test.Simple API used by MochiKit, to be able to test MochiKit 
+ * itself against IE 5.5
+ *
+**/
+
+if (typeof(SimpleTest) == "undefined") {
+    var SimpleTest = {};
+}
+
+var parentRunner = null;
+if (typeof(parent) != "undefined" && parent.TestRunner) {
+    parentRunner = parent.TestRunner;
+} else if (parent && parent.wrappedJSObject &&
+	   parent.wrappedJSObject.TestRunner) {
+    parentRunner = parent.wrappedJSObject.TestRunner;
+}
+
+// Check to see if the TestRunner is present and has logging
+if (parentRunner) {
+    SimpleTest._logEnabled = parentRunner.logEnabled;
+}
+
+SimpleTest._tests = [];
+SimpleTest._stopOnLoad = true;
+
+/**
+ * Something like assert.
+**/
+SimpleTest.ok = function (condition, name, diag) {
+    var test = {'result': !!condition, 'name': name, 'diag': diag || ""};
+    if (SimpleTest._logEnabled)
+        SimpleTest._logResult(test, "PASS", "FAIL");
+    SimpleTest._tests.push(test);
+};
+
+/**
+ * Roughly equivalent to ok(a==b, name)
+**/
+SimpleTest.is = function (a, b, name) {
+    var repr = MochiKit.Base.repr;
+    SimpleTest.ok(a == b, name, "got " + repr(a) + ", expected " + repr(b));
+};
+
+SimpleTest.isnot = function (a, b, name) {
+    var repr = MochiKit.Base.repr;
+    SimpleTest.ok(a != b, name, "Didn't expect " + repr(a) + ", but got it.");
+};
+
+//  --------------- Test.Builder/Test.More todo() -----------------
+
+SimpleTest.todo = function(condition, name, diag) {
+  var test = {'result': !!condition, 'name': name, 'diag': diag || "", todo: true};
+  if (SimpleTest._logEnabled)
+      SimpleTest._logResult(test, "TODO WORKED?", "TODO");
+  SimpleTest._tests.push(test);
+}
+
+SimpleTest._logResult = function(test, passString, failString) {
+  var msg = test.result ? passString : failString;
+  msg += " | " + test.name;
+  if (test.result) {
+      if (test.todo)
+          parentRunner.logger.error(msg)
+      else
+          parentRunner.logger.log(msg);
+  } else {
+      msg += " | " + test.diag;
+      if (test.todo)
+          parentRunner.logger.log(msg)
+      else
+          parentRunner.logger.error(msg);
+  }
+}
+
+
+/**
+ * Makes a test report, returns it as a DIV element.
+**/
+SimpleTest.report = function () {
+    var DIV = MochiKit.DOM.DIV;
+    var passed = 0;
+    var failed = 0;
+    var todo = 0;
+    var results = MochiKit.Base.map(
+        function (test) {
+            var cls, msg;
+            if (test.todo && !test.result) {
+                todo++;
+                cls = "test_todo"
+                msg = "todo - " + test.name;   
+            } else if (test.result &&!test.todo) {
+                passed++;
+                cls = "test_ok";
+                msg = "ok - " + test.name;
+            } else {
+                failed++;
+                cls = "test_not_ok";
+                msg = "not ok - " + test.name + " " + test.diag;
+            }
+            return DIV({"class": cls}, msg);
+        },
+        SimpleTest._tests
+    );
+    var summary_class = ((failed == 0) ? 'all_pass' : 'some_fail');
+    return DIV({'class': 'tests_report'},
+        DIV({'class': 'tests_summary ' + summary_class},
+            DIV({'class': 'tests_passed'}, "Passed: " + passed),
+            DIV({'class': 'tests_failed'}, "Failed: " + failed),
+            DIV({'class': 'tests_todo'}, "Todo: " + todo)),
+        results
+    );
+};
+
+/**
+ * Toggle element visibility
+**/
+SimpleTest.toggle = function(el) {
+    if (MochiKit.Style.computedStyle(el, 'display') == 'block') {
+        el.style.display = 'none';
+    } else {
+        el.style.display = 'block';
+    }
+};
+
+/**
+ * Toggle visibility for divs with a specific class.
+**/
+SimpleTest.toggleByClass = function (cls) {
+    var elems = getElementsByTagAndClassName('div', cls);
+    MochiKit.Base.map(SimpleTest.toggle, elems);
+};
+
+/**
+ * Shows the report in the browser
+**/
+
+SimpleTest.showReport = function() {
+    var togglePassed = A({'href': '#'}, "Toggle passed tests");
+    var toggleFailed = A({'href': '#'}, "Toggle failed tests");
+    togglePassed.onclick = partial(SimpleTest.toggleByClass, 'test_ok');
+    toggleFailed.onclick = partial(SimpleTest.toggleByClass, 'test_not_ok');
+    var body = document.getElementsByTagName("body")[0];
+    var firstChild = body.childNodes[0];
+    var addNode;
+    if (firstChild) {
+        addNode = function (el) {
+            body.insertBefore(el, firstChild);
+        };
+    } else {
+        addNode = function (el) {
+            body.appendChild(el)
+        };
+    }
+    addNode(togglePassed);
+    addNode(SPAN(null, " "));
+    addNode(toggleFailed);
+    addNode(SimpleTest.report());
+};
+
+/**
+ * Tells SimpleTest to don't finish the test when the document is loaded,
+ * useful for asynchronous tests.
+ *
+ * When SimpleTest.waitForExplicitFinish is called,
+ * explicit SimpleTest.finish() is required.
+**/
+SimpleTest.waitForExplicitFinish = function () {
+    SimpleTest._stopOnLoad = false;
+};
+
+/**
+ * Talks to the TestRunner if being ran on a iframe and the parent has a 
+ * TestRunner object.
+**/
+SimpleTest.talkToRunner = function () {
+    if (parentRunner) {
+        parentRunner.testFinished(document);
+    }
+};
+
+/**
+ * Finishes the tests. This is automatically called, except when 
+ * SimpleTest.waitForExplicitFinish() has been invoked.
+**/
+SimpleTest.finish = function () {
+    SimpleTest.showReport();
+    SimpleTest.talkToRunner();
+};
+
+
+addLoadEvent(function() {
+    if (SimpleTest._stopOnLoad) {
+        SimpleTest.finish();
+    }
+});
+
+//  --------------- Test.Builder/Test.More isDeeply() -----------------
+
+
+SimpleTest.DNE = {dne: 'Does not exist'};
+SimpleTest.LF = "\r\n";
+SimpleTest._isRef = function (object) {
+    var type = typeof(object);
+    return type == 'object' || type == 'function';
+};
+
+
+SimpleTest._deepCheck = function (e1, e2, stack, seen) {
+    var ok = false;
+    // Either they're both references or both not.
+    var sameRef = !(!SimpleTest._isRef(e1) ^ !SimpleTest._isRef(e2));
+    if (e1 == null && e2 == null) {
+        ok = true;
+    } else if (e1 != null ^ e2 != null) {
+        ok = false;
+    } else if (e1 == SimpleTest.DNE ^ e2 == SimpleTest.DNE) {
+        ok = false;
+    } else if (sameRef && e1 == e2) {
+        // Handles primitives and any variables that reference the same
+        // object, including functions.
+        ok = true;
+    } else if (SimpleTest.isa(e1, 'Array') && SimpleTest.isa(e2, 'Array')) {
+        ok = SimpleTest._eqArray(e1, e2, stack, seen);
+    } else if (typeof e1 == "object" && typeof e2 == "object") {
+        ok = SimpleTest._eqAssoc(e1, e2, stack, seen);
+    } else {
+        // If we get here, they're not the same (function references must
+        // always simply rererence the same function).
+        stack.push({ vals: [e1, e2] });
+        ok = false;
+    }
+    return ok;
+};
+
+SimpleTest._eqArray = function (a1, a2, stack, seen) {
+    // Return if they're the same object.
+    if (a1 == a2) return true;
+
+    // JavaScript objects have no unique identifiers, so we have to store
+    // references to them all in an array, and then compare the references
+    // directly. It's slow, but probably won't be much of an issue in
+    // practice. Start by making a local copy of the array to as to avoid
+    // confusing a reference seen more than once (such as [a, a]) for a
+    // circular reference.
+    for (var j = 0; j < seen.length; j++) {
+        if (seen[j][0] == a1) {
+            return seen[j][1] == a2;
+        }
+    }
+
+    // If we get here, we haven't seen a1 before, so store it with reference
+    // to a2.
+    seen.push([ a1, a2 ]);
+
+    var ok = true;
+    // Only examines enumerable attributes. Only works for numeric arrays!
+    // Associative arrays return 0. So call _eqAssoc() for them, instead.
+    var max = a1.length > a2.length ? a1.length : a2.length;
+    if (max == 0) return SimpleTest._eqAssoc(a1, a2, stack, seen);
+    for (var i = 0; i < max; i++) {
+        var e1 = i > a1.length - 1 ? SimpleTest.DNE : a1[i];
+        var e2 = i > a2.length - 1 ? SimpleTest.DNE : a2[i];
+        stack.push({ type: 'Array', idx: i, vals: [e1, e2] });
+        if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) {
+            stack.pop();
+        } else {
+            break;
+        }
+    }
+    return ok;
+};
+
+SimpleTest._eqAssoc = function (o1, o2, stack, seen) {
+    // Return if they're the same object.
+    if (o1 == o2) return true;
+
+    // JavaScript objects have no unique identifiers, so we have to store
+    // references to them all in an array, and then compare the references
+    // directly. It's slow, but probably won't be much of an issue in
+    // practice. Start by making a local copy of the array to as to avoid
+    // confusing a reference seen more than once (such as [a, a]) for a
+    // circular reference.
+    seen = seen.slice(0);
+    for (var j = 0; j < seen.length; j++) {
+        if (seen[j][0] == o1) {
+            return seen[j][1] == o2;
+        }
+    }
+
+    // If we get here, we haven't seen o1 before, so store it with reference
+    // to o2.
+    seen.push([ o1, o2 ]);
+
+    // They should be of the same class.
+
+    var ok = true;
+    // Only examines enumerable attributes.
+    var o1Size = 0; for (var i in o1) o1Size++;
+    var o2Size = 0; for (var i in o2) o2Size++;
+    var bigger = o1Size > o2Size ? o1 : o2;
+    for (var i in bigger) {
+        var e1 = o1[i] == undefined ? SimpleTest.DNE : o1[i];
+        var e2 = o2[i] == undefined ? SimpleTest.DNE : o2[i];
+        stack.push({ type: 'Object', idx: i, vals: [e1, e2] });
+        if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) {
+            stack.pop();
+        } else {
+            break;
+        }
+    }
+    return ok;
+};
+
+SimpleTest._formatStack = function (stack) {
+    var variable = '$Foo';
+    for (var i = 0; i < stack.length; i++) {
+        var entry = stack[i];
+        var type = entry['type'];
+        var idx = entry['idx'];
+        if (idx != null) {
+            if (/^\d+$/.test(idx)) {
+                // Numeric array index.
+                variable += '[' + idx + ']';
+            } else {
+                // Associative array index.
+                idx = idx.replace("'", "\\'");
+                variable += "['" + idx + "']";
+            }
+        }
+    }
+
+    var vals = stack[stack.length-1]['vals'].slice(0, 2);
+    var vars = [
+        variable.replace('$Foo',     'got'),
+        variable.replace('$Foo',     'expected')
+    ];
+
+    var out = "Structures begin differing at:" + SimpleTest.LF;
+    for (var i = 0; i < vals.length; i++) {
+        var val = vals[i];
+        if (val == null) {
+            val = 'undefined';
+        } else {
+             val == SimpleTest.DNE ? "Does not exist" : "'" + val + "'";
+        }
+    }
+
+    out += vars[0] + ' = ' + vals[0] + SimpleTest.LF;
+    out += vars[1] + ' = ' + vals[1] + SimpleTest.LF;
+    
+    return '    ' + out;
+};
+
+
+SimpleTest.isDeeply = function (it, as, name) {
+    var ok;
+    // ^ is the XOR operator.
+    if (SimpleTest._isRef(it) ^ SimpleTest._isRef(as)) {
+        // One's a reference, one isn't.
+        ok = false;
+    } else if (!SimpleTest._isRef(it) && !SimpleTest._isRef(as)) {
+        // Neither is an object.
+        ok = SimpleTest.is(it, as, name);
+    } else {
+        // We have two objects. Do a deep comparison.
+        var stack = [], seen = [];
+        if ( SimpleTest._deepCheck(it, as, stack, seen)) {
+            ok = SimpleTest.ok(true, name);
+        } else {
+            ok = SimpleTest.ok(false, name, SimpleTest._formatStack(stack));
+        }
+    }
+    return ok;
+};
+
+SimpleTest.typeOf = function (object) {
+    var c = Object.prototype.toString.apply(object);
+    var name = c.substring(8, c.length - 1);
+    if (name != 'Object') return name;
+    // It may be a non-core class. Try to extract the class name from
+    // the constructor function. This may not work in all implementations.
+    if (/function ([^(\s]+)/.test(Function.toString.call(object.constructor))) {
+        return RegExp.$1;
+    }
+    // No idea. :-(
+    return name;
+};
+
+SimpleTest.isa = function (object, clas) {
+    return SimpleTest.typeOf(object) == clas;
+};
+
+// Global symbols:
+var ok = SimpleTest.ok;
+var is = SimpleTest.is;
+var isnot = SimpleTest.isnot;
+var todo = SimpleTest.todo;
+var isDeeply = SimpleTest.isDeeply;
+var oldOnError = window.onerror;
+window.onerror = function (ev) {
+    is(0, 1, "Error thrown during test: " + ev);
+    if (oldOnError) {
+	try {
+	  oldOnError(ev);
+	} catch (e) {
+	}
+    }
+    if (SimpleTest._stopOnLoad == false) {
+      // Need to finish() manually here
+      SimpleTest.finish();
+    }
+}
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/ajax/lib/test.css
@@ -0,0 +1,28 @@
+.test_ok {
+	color: green;
+	display: none;
+}
+.test_not_ok {
+	color: red;
+	display: block;
+}
+
+.test_ok, .test_not_ok {
+   border-bottom-width: 2px;
+   border-bottom-style: solid;
+   border-bottom-color: black;
+}
+
+.all_pass {
+    background-color: lime;
+}
+
+.some_fail {
+    background-color: red;
+}
+
+.tests_report {
+	border-width: 2px;
+	border-style: solid;
+	width: 20em;
+}
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/ajax/prototype/Makefile.in
@@ -0,0 +1,55 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir	= dom/tests/mochitest/ajax/prototype
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES	= \
+        test_Prototype.html \
+        manifest.json \
+        dist \
+        test \
+        $(NULL)
+
+libs::	$(_TEST_FILES)
+	$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/ajax/prototype/dist/prototype.js
@@ -0,0 +1,3239 @@
+/*  Prototype JavaScript framework, version 1.5.1_rc2
+ *  (c) 2005-2007 Sam Stephenson
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+/*--------------------------------------------------------------------------*/
+
+var Prototype = {
+  Version: '1.5.1_rc2',
+
+  Browser: {
+    IE:     !!(window.attachEvent && !window.opera),
+    Opera:  !!window.opera,
+    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
+  },
+  BrowserFeatures: {
+    XPath: !!document.evaluate,
+    ElementExtensions: !!window.HTMLElement,
+    SpecificElementExtensions:
+      (document.createElement('div').__proto__ !==
+       document.createElement('form').__proto__)
+  },
+
+  ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)</script>',
+  emptyFunction: function() {},
+  K: function(x) { return x }
+}
+
+var Class = {
+  create: function() {
+    return function() {
+      this.initialize.apply(this, arguments);
+    }
+  }
+}
+
+var Abstract = new Object();
+
+Object.extend = function(destination, source) {
+  for (var property in source) {
+    destination[property] = source[property];
+  }
+  return destination;
+}
+
+Object.extend(Object, {
+  inspect: function(object) {
+    try {
+      if (object === undefined) return 'undefined';
+      if (object === null) return 'null';
+      return object.inspect ? object.inspect() : object.toString();
+    } catch (e) {
+      if (e instanceof RangeError) return '...';
+      throw e;
+    }
+  },
+
+  toJSON: function(object) {
+    var type = typeof object;
+    switch(type) {
+      case 'undefined':
+      case 'function':
+      case 'unknown': return;
+      case 'boolean': return object.toString();
+    }
+    if (object === null) return 'null';
+    if (object.toJSON) return object.toJSON();
+    if (object.ownerDocument === document) return;
+    var results = [];
+    for (var property in object) {
+      var value = Object.toJSON(object[property]);
+      if (value !== undefined)
+        results.push(property.toJSON() + ':' + value);
+    }
+    return '{' + results.join(',') + '}';
+  },
+
+  keys: function(object) {
+    var keys = [];
+    for (var property in object)
+      keys.push(property);
+    return keys;
+  },
+
+  values: function(object) {
+    var values = [];
+    for (var property in object)
+      values.push(object[property]);
+    return values;
+  },
+
+  clone: function(object) {
+    return Object.extend({}, object);
+  }
+});
+
+Function.prototype.bind = function() {
+  var __method = this, args = $A(arguments), object = args.shift();
+  return function() {
+    return __method.apply(object, args.concat($A(arguments)));
+  }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+  var __method = this, args = $A(arguments), object = args.shift();
+  return function(event) {
+    return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
+  }
+}
+
+Object.extend(Number.prototype, {
+  toColorPart: function() {
+    return this.toPaddedString(2, 16);
+  },
+
+  succ: function() {
+    return this + 1;
+  },
+
+  times: function(iterator) {
+    $R(0, this, true).each(iterator);
+    return this;
+  },
+
+  toPaddedString: function(length, radix) {
+    var string = this.toString(radix || 10);
+    return '0'.times(length - string.length) + string;
+  },
+
+  toJSON: function() {
+    return isFinite(this) ? this.toString() : 'null';
+  }
+});
+
+Date.prototype.toJSON = function() {
+  return '"' + this.getFullYear() + '-' +
+    (this.getMonth() + 1).toPaddedString(2) + '-' +
+    this.getDate().toPaddedString(2) + 'T' +
+    this.getHours().toPaddedString(2) + ':' +
+    this.getMinutes().toPaddedString(2) + ':' +
+    this.getSeconds().toPaddedString(2) + '"';
+};
+
+var Try = {
+  these: function() {
+    var returnValue;
+
+    for (var i = 0, length = arguments.length; i < length; i++) {
+      var lambda = arguments[i];
+      try {
+        returnValue = lambda();
+        break;
+      } catch (e) {}
+    }
+
+    return returnValue;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create();
+PeriodicalExecuter.prototype = {
+  initialize: function(callback, frequency) {
+    this.callback = callback;
+    this.frequency = frequency;
+    this.currentlyExecuting = false;
+
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  stop: function() {
+    if (!this.timer) return;
+    clearInterval(this.timer);
+    this.timer = null;
+  },
+
+  onTimerEvent: function() {
+    if (!this.currentlyExecuting) {
+      try {
+        this.currentlyExecuting = true;
+        this.callback(this);
+      } finally {
+        this.currentlyExecuting = false;
+      }
+    }
+  }
+}
+Object.extend(String, {
+  interpret: function(value) {
+    return value == null ? '' : String(value);
+  },
+  specialChar: {
+    '\b': '\\b',
+    '\t': '\\t',
+    '\n': '\\n',
+    '\f': '\\f',
+    '\r': '\\r',
+    '\\': '\\\\'
+  }
+});
+
+Object.extend(String.prototype, {
+  gsub: function(pattern, replacement) {
+    var result = '', source = this, match;
+    replacement = arguments.callee.prepareReplacement(replacement);
+
+    while (source.length > 0) {
+      if (match = source.match(pattern)) {
+        result += source.slice(0, match.index);
+        result += String.interpret(replacement(match));
+        source  = source.slice(match.index + match[0].length);
+      } else {
+        result += source, source = '';
+      }
+    }
+    return result;
+  },
+
+  sub: function(pattern, replacement, count) {
+    replacement = this.gsub.prepareReplacement(replacement);
+    count = count === undefined ? 1 : count;
+
+    return this.gsub(pattern, function(match) {
+      if (--count < 0) return match[0];
+      return replacement(match);
+    });
+  },
+
+  scan: function(pattern, iterator) {
+    this.gsub(pattern, iterator);
+    return this;
+  },
+
+  truncate: function(length, truncation) {
+    length = length || 30;
+    truncation = truncation === undefined ? '...' : truncation;
+    return this.length > length ?
+      this.slice(0, length - truncation.length) + truncation : this;
+  },
+
+  strip: function() {
+    return this.replace(/^\s+/, '').replace(/\s+$/, '');
+  },
+
+  stripTags: function() {
+    return this.replace(/<\/?[^>]+>/gi, '');
+  },
+
+  stripScripts: function() {
+    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+  },
+
+  extractScripts: function() {
+    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+    return (this.match(matchAll) || []).map(function(scriptTag) {
+      return (scriptTag.match(matchOne) || ['', ''])[1];
+    });
+  },
+
+  evalScripts: function() {
+    return this.extractScripts().map(function(script) { return eval(script) });
+  },
+
+  escapeHTML: function() {
+    var self = arguments.callee;
+    self.text.data = this;
+    return self.div.innerHTML;
+  },
+
+  unescapeHTML: function() {
+    var div = document.createElement('div');
+    div.innerHTML = this.stripTags();
+    return div.childNodes[0] ? (div.childNodes.length > 1 ?
+      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+      div.childNodes[0].nodeValue) : '';
+  },
+
+  toQueryParams: function(separator) {
+    var match = this.strip().match(/([^?#]*)(#.*)?$/);
+    if (!match) return {};
+
+    return match[1].split(separator || '&').inject({}, function(hash, pair) {
+      if ((pair = pair.split('='))[0]) {
+        var key = decodeURIComponent(pair.shift());
+        var value = pair.length > 1 ? pair.join('=') : pair[0];
+        if (value != undefined) value = decodeURIComponent(value);
+
+        if (key in hash) {
+          if (hash[key].constructor != Array) hash[key] = [hash[key]];
+          hash[key].push(value);
+        }
+        else hash[key] = value;
+      }
+      return hash;
+    });
+  },
+
+  toArray: function() {
+    return this.split('');
+  },
+
+  succ: function() {
+    return this.slice(0, this.length - 1) +
+      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+  },
+
+  times: function(count) {
+    var result = '';
+    for (var i = 0; i < count; i++) result += this;
+    return result;
+  },
+
+  camelize: function() {
+    var parts = this.split('-'), len = parts.length;
+    if (len == 1) return parts[0];
+
+    var camelized = this.charAt(0) == '-'
+      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+      : parts[0];
+
+    for (var i = 1; i < len; i++)
+      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+    return camelized;
+  },
+
+  capitalize: function() {
+    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+  },
+
+  underscore: function() {
+    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+  },
+
+  dasherize: function() {
+    return this.gsub(/_/,'-');
+  },
+
+  inspect: function(useDoubleQuotes) {
+    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+      var character = String.specialChar[match[0]];
+      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+    });
+    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+  },
+
+  toJSON: function() {
+    return this.inspect(true);
+  },
+
+  evalJSON: function(sanitize) {
+    try {
+      if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(this)))
+        return eval('(' + this + ')');
+    } catch (e) {}
+    throw new SyntaxError('Badly formated JSON string: ' + this.inspect());
+  },
+
+  include: function(pattern) {
+    return this.indexOf(pattern) > -1;
+  },
+
+  startsWith: function(pattern) {
+    return this.indexOf(pattern) === 0;
+  },
+
+  endsWith: function(pattern) {
+    var d = this.length - pattern.length;
+    return d >= 0 && this.lastIndexOf(pattern) === d;
+  },
+
+  empty: function() {
+    return this == '';
+  },
+
+  blank: function() {
+    return /^\s*$/.test(this);
+  }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+  escapeHTML: function() {
+    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+  },
+  unescapeHTML: function() {
+    return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+  }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+  if (typeof replacement == 'function') return replacement;
+  var template = new Template(replacement);
+  return function(match) { return template.evaluate(match) };
+}
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+  div:  document.createElement('div'),
+  text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create();
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+Template.prototype = {
+  initialize: function(template, pattern) {
+    this.template = template.toString();
+    this.pattern  = pattern || Template.Pattern;
+  },
+
+  evaluate: function(object) {
+    return this.template.gsub(this.pattern, function(match) {
+      var before = match[1];
+      if (before == '\\') return match[2];
+      return before + String.interpret(object[match[3]]);
+    });
+  }
+}
+
+var $break    = new Object();
+var $continue = new Object();
+
+var Enumerable = {
+  each: function(iterator) {
+    var index = 0;
+    try {
+      this._each(function(value) {
+        iterator(value, index++);
+      });
+    } catch (e) {
+      if (e != $break) throw e;
+    }
+    return this;
+  },
+
+  eachSlice: function(number, iterator) {
+    var index = -number, slices = [], array = this.toArray();
+    while ((index += number) < array.length)
+      slices.push(array.slice(index, index+number));
+    return slices.map(iterator);
+  },
+
+  all: function(iterator) {
+    var result = true;
+    this.each(function(value, index) {
+      result = result && !!(iterator || Prototype.K)(value, index);
+      if (!result) throw $break;
+    });
+    return result;
+  },
+
+  any: function(iterator) {
+    var result = false;
+    this.each(function(value, index) {
+      if (result = !!(iterator || Prototype.K)(value, index))
+        throw $break;
+    });
+    return result;
+  },
+
+  collect: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      results.push((iterator || Prototype.K)(value, index));
+    });
+    return results;
+  },
+
+  detect: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      if (iterator(value, index)) {
+        result = value;
+        throw $break;
+      }
+    });
+    return result;
+  },
+
+  findAll: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      if (iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  grep: function(pattern, iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      var stringValue = value.toString();
+      if (stringValue.match(pattern))
+        results.push((iterator || Prototype.K)(value, index));
+    })
+    return results;
+  },
+
+  include: function(object) {
+    var found = false;
+    this.each(function(value) {
+      if (value == object) {
+        found = true;
+        throw $break;
+      }
+    });
+    return found;
+  },
+
+  inGroupsOf: function(number, fillWith) {
+    fillWith = fillWith === undefined ? null : fillWith;
+    return this.eachSlice(number, function(slice) {
+      while(slice.length < number) slice.push(fillWith);
+      return slice;
+    });
+  },
+
+  inject: function(memo, iterator) {
+    this.each(function(value, index) {
+      memo = iterator(memo, value, index);
+    });
+    return memo;
+  },
+
+  invoke: function(method) {
+    var args = $A(arguments).slice(1);
+    return this.map(function(value) {
+      return value[method].apply(value, args);
+    });
+  },
+
+  max: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      value = (iterator || Prototype.K)(value, index);
+      if (result == undefined || value >= result)
+        result = value;
+    });
+    return result;
+  },
+
+  min: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      value = (iterator || Prototype.K)(value, index);
+      if (result == undefined || value < result)
+        result = value;
+    });
+    return result;
+  },
+
+  partition: function(iterator) {
+    var trues = [], falses = [];
+    this.each(function(value, index) {
+      ((iterator || Prototype.K)(value, index) ?
+        trues : falses).push(value);
+    });
+    return [trues, falses];
+  },
+
+  pluck: function(property) {
+    var results = [];
+    this.each(function(value, index) {
+      results.push(value[property]);
+    });
+    return results;
+  },
+
+  reject: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      if (!iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  sortBy: function(iterator) {
+    return this.map(function(value, index) {
+      return {value: value, criteria: iterator(value, index)};
+    }).sort(function(left, right) {
+      var a = left.criteria, b = right.criteria;
+      return a < b ? -1 : a > b ? 1 : 0;
+    }).pluck('value');
+  },
+
+  toArray: function() {
+    return this.map();
+  },
+
+  zip: function() {
+    var iterator = Prototype.K, args = $A(arguments);
+    if (typeof args.last() == 'function')
+      iterator = args.pop();
+
+    var collections = [this].concat(args).map($A);
+    return this.map(function(value, index) {
+      return iterator(collections.pluck(index));
+    });
+  },
+
+  size: function() {
+    return this.toArray().length;
+  },
+
+  inspect: function() {
+    return '#<Enumerable:' + this.toArray().inspect() + '>';
+  }
+}
+
+Object.extend(Enumerable, {
+  map:     Enumerable.collect,
+  find:    Enumerable.detect,
+  select:  Enumerable.findAll,
+  member:  Enumerable.include,
+  entries: Enumerable.toArray
+});
+var $A = Array.from = function(iterable) {
+  if (!iterable) return [];
+  if (iterable.toArray) {
+    return iterable.toArray();
+  } else {
+    var results = [];
+    for (var i = 0, length = iterable.length; i < length; i++)
+      results.push(iterable[i]);
+    return results;
+  }
+}
+
+if (Prototype.Browser.WebKit) {
+  $A = Array.from = function(iterable) {
+    if (!iterable) return [];
+    if (!(typeof iterable == 'function' && iterable == '[object NodeList]') &&
+      iterable.toArray) {
+      return iterable.toArray();
+    } else {
+      var results = [];
+      for (var i = 0, length = iterable.length; i < length; i++)
+        results.push(iterable[i]);
+      return results;
+    }
+  }
+}
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse)
+  Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+  _each: function(iterator) {
+    for (var i = 0, length = this.length; i < length; i++)
+      iterator(this[i]);
+  },
+
+  clear: function() {
+    this.length = 0;
+    return this;
+  },
+
+  first: function() {
+    return this[0];
+  },
+
+  last: function() {
+    return this[this.length - 1];
+  },
+
+  compact: function() {
+    return this.select(function(value) {
+      return value != null;
+    });
+  },
+
+  flatten: function() {
+    return this.inject([], function(array, value) {
+      return array.concat(value && value.constructor == Array ?
+        value.flatten() : [value]);
+    });
+  },
+
+  without: function() {
+    var values = $A(arguments);
+    return this.select(function(value) {
+      return !values.include(value);
+    });
+  },
+
+  indexOf: function(object) {
+    for (var i = 0, length = this.length; i < length; i++)
+      if (this[i] == object) return i;
+    return -1;
+  },
+
+  reverse: function(inline) {
+    return (inline !== false ? this : this.toArray())._reverse();
+  },
+
+  reduce: function() {
+    return this.length > 1 ? this : this[0];
+  },
+
+  uniq: function(sorted) {
+    return this.inject([], function(array, value, index) {
+      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+        array.push(value);
+      return array;
+    });
+  },
+
+  clone: function() {
+    return [].concat(this);
+  },
+
+  size: function() {
+    return this.length;
+  },
+
+  inspect: function() {
+    return '[' + this.map(Object.inspect).join(', ') + ']';
+  },
+
+  toJSON: function() {
+    var results = [];
+    this.each(function(object) {
+      var value = Object.toJSON(object);
+      if (value !== undefined) results.push(value);
+    });
+    return '[' + results.join(',') + ']';
+  }
+});
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+  string = string.strip();
+  return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+  Array.prototype.concat = function() {
+    var array = [];
+    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+    for (var i = 0, length = arguments.length; i < length; i++) {
+      if (arguments[i].constructor == Array) {
+        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+          array.push(arguments[i][j]);
+      } else {
+        array.push(arguments[i]);
+      }
+    }
+    return array;
+  }
+}
+var Hash = function(object) {
+  if (object instanceof Hash) this.merge(object);
+  else Object.extend(this, object || {});
+};
+
+Object.extend(Hash, {
+  toQueryString: function(obj) {
+    var parts = [];
+    parts.add = arguments.callee.addPair;
+
+    this.prototype._each.call(obj, function(pair) {
+      if (!pair.key) return;
+      var value = pair.value;
+
+      if (value && typeof value == 'object') {
+        if (value.constructor == Array) value.each(function(value) {
+          parts.add(pair.key, value);
+        });
+        return;
+      }
+      parts.add(pair.key, value);
+    });
+
+    return parts.join('&');
+  },
+
+  toJSON: function(object) {
+    var results = [];
+    this.prototype._each.call(object, function(pair) {
+      var value = Object.toJSON(pair.value);
+      if (value !== undefined) results.push(pair.key.toJSON() + ':' + value);
+    });
+    return '{' + results.join(',') + '}';
+  }
+});
+
+Hash.toQueryString.addPair = function(key, value, prefix) {
+  key = encodeURIComponent(key);
+  if (value === undefined) this.push(key);
+  else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value)));
+}
+
+Object.extend(Hash.prototype, Enumerable);
+Object.extend(Hash.prototype, {
+  _each: function(iterator) {
+    for (var key in this) {
+      var value = this[key];
+      if (value && value == Hash.prototype[key]) continue;
+
+      var pair = [key, value];
+      pair.key = key;
+      pair.value = value;
+      iterator(pair);
+    }
+  },
+
+  keys: function() {
+    return this.pluck('key');
+  },
+
+  values: function() {
+    return this.pluck('value');
+  },
+
+  merge: function(hash) {
+    return $H(hash).inject(this, function(mergedHash, pair) {
+      mergedHash[pair.key] = pair.value;
+      return mergedHash;
+    });
+  },
+
+  remove: function() {
+    var result;
+    for(var i = 0, length = arguments.length; i < length; i++) {
+      var value = this[arguments[i]];
+      if (value !== undefined){
+        if (result === undefined) result = value;
+        else {
+          if (result.constructor != Array) result = [result];
+          result.push(value)
+        }
+      }
+      delete this[arguments[i]];
+    }
+    return result;
+  },
+
+  toQueryString: function() {
+    return Hash.toQueryString(this);
+  },
+
+  inspect: function() {
+    return '#<Hash:{' + this.map(function(pair) {
+      return pair.map(Object.inspect).join(': ');
+    }).join(', ') + '}>';
+  },
+
+  toJSON: function() {
+    return Hash.toJSON(this);
+  }
+});
+
+function $H(object) {
+  if (object instanceof Hash) return object;
+  return new Hash(object);
+};
+
+// Safari iterates over shadowed properties
+if (function() {
+  var i = 0, Test = function(value) { this.key = value };
+  Test.prototype.key = 'foo';
+  for (var property in new Test('bar')) i++;
+  return i > 1;
+}()) Hash.prototype._each = function(iterator) {
+  var cache = [];
+  for (var key in this) {
+    var value = this[key];
+    if ((value && value == Hash.prototype[key]) || cache.include(key)) continue;
+    cache.push(key);
+    var pair = [key, value];
+    pair.key = key;
+    pair.value = value;
+    iterator(pair);
+  }
+};
+ObjectRange = Class.create();
+Object.extend(ObjectRange.prototype, Enumerable);
+Object.extend(ObjectRange.prototype, {
+  initialize: function(start, end, exclusive) {
+    this.start = start;
+    this.end = end;
+    this.exclusive = exclusive;
+  },
+
+  _each: function(iterator) {
+    var value = this.start;
+    while (this.include(value)) {
+      iterator(value);
+      value = value.succ();
+    }
+  },
+
+  include: function(value) {
+    if (value < this.start)
+      return false;
+    if (this.exclusive)
+      return value < this.end;
+    return value <= this.end;
+  }
+});
+
+var $R = function(start, end, exclusive) {
+  return new ObjectRange(start, end, exclusive);
+}
+
+var Ajax = {
+  getTransport: function() {
+    return Try.these(
+      function() {return new XMLHttpRequest()},
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+    ) || false;
+  },
+
+  activeRequestCount: 0
+}
+
+Ajax.Responders = {
+  responders: [],
+
+  _each: function(iterator) {
+    this.responders._each(iterator);
+  },
+
+  register: function(responder) {
+    if (!this.include(responder))
+      this.responders.push(responder);
+  },
+
+  unregister: function(responder) {
+    this.responders = this.responders.without(responder);
+  },
+
+  dispatch: function(callback, request, transport, json) {
+    this.each(function(responder) {
+      if (typeof responder[callback] == 'function') {
+        try {
+          responder[callback].apply(responder, [request, transport, json]);
+        } catch (e) {}
+      }
+    });
+  }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+  onCreate: function() {
+    Ajax.activeRequestCount++;
+  },
+  onComplete: function() {
+    Ajax.activeRequestCount--;
+  }
+});
+
+Ajax.Base = function() {};
+Ajax.Base.prototype = {
+  setOptions: function(options) {
+    this.options = {
+      method:       'post',
+      asynchronous: true,
+      contentType:  'application/x-www-form-urlencoded',
+      encoding:     'UTF-8',
+      parameters:   ''
+    }
+    Object.extend(this.options, options || {});
+
+    this.options.method = this.options.method.toLowerCase();
+    if (typeof this.options.parameters == 'string')
+      this.options.parameters = this.options.parameters.toQueryParams();
+  }
+}
+
+Ajax.Request = Class.create();
+Ajax.Request.Events =
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
+  _complete: false,
+
+  initialize: function(url, options) {
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+    this.request(url);
+  },
+
+  request: function(url) {
+    this.url = url;
+    this.method = this.options.method;
+    var params = Object.clone(this.options.parameters);
+
+    if (!['get', 'post'].include(this.method)) {
+      // simulate other verbs over post
+      params['_method'] = this.method;
+      this.method = 'post';
+    }
+
+    this.parameters = params;
+
+    if (params = Hash.toQueryString(params)) {
+      // when GET, append parameters to URL
+      if (this.method == 'get')
+        this.url += (this.url.include('?') ? '&' : '?') + params;
+      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+        params += '&_=';
+    }
+
+    try {
+      Ajax.Responders.dispatch('onCreate', this, this.transport);
+
+      this.transport.open(this.method.toUpperCase(), this.url,
+        this.options.asynchronous);
+
+      if (this.options.asynchronous)
+        setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
+
+      this.transport.onreadystatechange = this.onStateChange.bind(this);
+      this.setRequestHeaders();
+
+      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+      this.transport.send(this.body);
+
+      /* Force Firefox to handle ready state 4 for synchronous requests */
+      if (!this.options.asynchronous && this.transport.overrideMimeType)
+        this.onStateChange();
+
+    }
+    catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  onStateChange: function() {
+    var readyState = this.transport.readyState;
+    if (readyState > 1 && !((readyState == 4) && this._complete))
+      this.respondToReadyState(this.transport.readyState);
+  },
+
+  setRequestHeaders: function() {
+    var headers = {
+      'X-Requested-With': 'XMLHttpRequest',
+      'X-Prototype-Version': Prototype.Version,
+      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+    };
+
+    if (this.method == 'post') {
+      headers['Content-type'] = this.options.contentType +
+        (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+      /* Force "Connection: close" for older Mozilla browsers to work
+       * around a bug where XMLHttpRequest sends an incorrect
+       * Content-length header. See Mozilla Bugzilla #246651.
+       */
+      if (this.transport.overrideMimeType &&
+          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+            headers['Connection'] = 'close';
+    }
+
+    // user-defined headers
+    if (typeof this.options.requestHeaders == 'object') {
+      var extras = this.options.requestHeaders;
+
+      if (typeof extras.push == 'function')
+        for (var i = 0, length = extras.length; i < length; i += 2)
+          headers[extras[i]] = extras[i+1];
+      else
+        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+    }
+
+    for (var name in headers)
+      this.transport.setRequestHeader(name, headers[name]);
+  },
+
+  success: function() {
+    return !this.transport.status
+        || (this.transport.status >= 200 && this.transport.status < 300);
+  },
+
+  respondToReadyState: function(readyState) {
+    var state = Ajax.Request.Events[readyState];
+    var transport = this.transport, json = this.evalJSON();
+
+    if (state == 'Complete') {
+      try {
+        this._complete = true;
+        (this.options['on' + this.transport.status]
+         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+         || Prototype.emptyFunction)(transport, json);
+      } catch (e) {
+        this.dispatchException(e);
+      }
+
+      if ((this.getHeader('Content-type') || 'text/javascript').strip().
+        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
+          this.evalResponse();
+    }
+
+    try {
+      (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
+      Ajax.Responders.dispatch('on' + state, this, transport, json);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+
+    if (state == 'Complete') {
+      // avoid memory leak in MSIE: clean up
+      this.transport.onreadystatechange = Prototype.emptyFunction;
+    }
+  },
+
+  getHeader: function(name) {
+    try {
+      return this.transport.getResponseHeader(name);
+    } catch (e) { return null }
+  },
+
+  evalJSON: function() {
+    try {
+      var json = this.getHeader('X-JSON');
+      return json ? eval('(' + json + ')') : null;
+    } catch (e) { return null }
+  },
+
+  evalResponse: function() {
+    try {
+      return eval(this.transport.responseText);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  dispatchException: function(exception) {
+    (this.options.onException || Prototype.emptyFunction)(this, exception);
+    Ajax.Responders.dispatch('onException', this, exception);
+  }
+});
+
+Ajax.Updater = Class.create();
+
+Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
+  initialize: function(container, url, options) {
+    this.container = {
+      success: (container.success || container),
+      failure: (container.failure || (container.success ? null : container))
+    }
+
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+
+    var onComplete = this.options.onComplete || Prototype.emptyFunction;
+    this.options.onComplete = (function(transport, param) {
+      this.updateContent();
+      onComplete(transport, param);
+    }).bind(this);
+
+    this.request(url);
+  },
+
+  updateContent: function() {
+    var receiver = this.container[this.success() ? 'success' : 'failure'];
+    var response = this.transport.responseText;
+
+    if (!this.options.evalScripts) response = response.stripScripts();
+
+    if (receiver = $(receiver)) {
+      if (this.options.insertion)
+        new this.options.insertion(receiver, response);
+      else
+        receiver.update(response);
+    }
+
+    if (this.success()) {
+      if (this.onComplete)
+        setTimeout(this.onComplete.bind(this), 10);
+    }
+  }
+});
+
+Ajax.PeriodicalUpdater = Class.create();
+Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
+  initialize: function(container, url, options) {
+    this.setOptions(options);
+    this.onComplete = this.options.onComplete;
+
+    this.frequency = (this.options.frequency || 2);
+    this.decay = (this.options.decay || 1);
+
+    this.updater = {};
+    this.container = container;
+    this.url = url;
+
+    this.start();
+  },
+
+  start: function() {
+    this.options.onComplete = this.updateComplete.bind(this);
+    this.onTimerEvent();
+  },
+
+  stop: function() {
+    this.updater.options.onComplete = undefined;
+    clearTimeout(this.timer);
+    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+  },
+
+  updateComplete: function(request) {
+    if (this.options.decay) {
+      this.decay = (request.responseText == this.lastText ?
+        this.decay * this.options.decay : 1);
+
+      this.lastText = request.responseText;
+    }
+    this.timer = setTimeout(this.onTimerEvent.bind(this),
+      this.decay * this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    this.updater = new Ajax.Updater(this.container, this.url, this.options);
+  }
+});
+function $(element) {
+  if (arguments.length > 1) {
+    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+      elements.push($(arguments[i]));
+    return elements;
+  }
+  if (typeof element == 'string')
+    element = document.getElementById(element);
+  return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+  document._getElementsByXPath = function(expression, parentElement) {
+    var results = [];
+    var query = document.evaluate(expression, $(parentElement) || document,
+      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+    for (var i = 0, length = query.snapshotLength; i < length; i++)
+      results.push(query.snapshotItem(i));
+    return results;
+  };
+
+  document.getElementsByClassName = function(className, parentElement) {
+    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
+    return document._getElementsByXPath(q, parentElement);
+  }
+
+} else document.getElementsByClassName = function(className, parentElement) {
+  var children = ($(parentElement) || document.body).getElementsByTagName('*');
+  var elements = [], child;
+  for (var i = 0, length = children.length; i < length; i++) {
+    child = children[i];
+    if (Element.hasClassName(child, className))
+      elements.push(Element.extend(child));
+  }
+  return elements;
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Element) var Element = {};
+
+Element.extend = function(element) {
+  var F = Prototype.BrowserFeatures;
+  if (!element || !element.tagName || element.nodeType == 3 ||
+   element._extended || F.SpecificElementExtensions || element == window)
+    return element;
+
+  var methods = {}, tagName = element.tagName, cache = Element.extend.cache,
+   T = Element.Methods.ByTag;
+
+  // extend methods for all tags (Safari doesn't need this)
+  if (!F.ElementExtensions) {
+    Object.extend(methods, Element.Methods),
+    Object.extend(methods, Element.Methods.Simulated);
+  }
+
+  // extend methods for specific tags
+  if (T[tagName]) Object.extend(methods, T[tagName]);
+
+  for (var property in methods) {
+    var value = methods[property];
+    if (typeof value == 'function' && !(property in element))
+      element[property] = cache.findOrStore(value);
+  }
+
+  element._extended = Prototype.emptyFunction;
+  return element;
+};
+
+Element.extend.cache = {
+  findOrStore: function(value) {
+    return this[value] = this[value] || function() {
+      return value.apply(null, [this].concat($A(arguments)));
+    }
+  }
+};
+
+Element.Methods = {
+  visible: function(element) {
+    return $(element).style.display != 'none';
+  },
+
+  toggle: function(element) {
+    element = $(element);
+    Element[Element.visible(element) ? 'hide' : 'show'](element);
+    return element;
+  },
+
+  hide: function(element) {
+    $(element).style.display = 'none';
+    return element;
+  },
+
+  show: function(element) {
+    $(element).style.display = '';
+    return element;
+  },
+
+  remove: function(element) {
+    element = $(element);
+    element.parentNode.removeChild(element);
+    return element;
+  },
+
+  update: function(element, html) {
+    html = typeof html == 'undefined' ? '' : html.toString();
+    $(element).innerHTML = html.stripScripts();
+    setTimeout(function() {html.evalScripts()}, 10);
+    return element;
+  },
+
+  replace: function(element, html) {
+    element = $(element);
+    html = typeof html == 'undefined' ? '' : html.toString();
+    if (element.outerHTML) {
+      element.outerHTML = html.stripScripts();
+    } else {
+      var range = element.ownerDocument.createRange();
+      range.selectNodeContents(element);
+      element.parentNode.replaceChild(
+        range.createContextualFragment(html.stripScripts()), element);
+    }
+    setTimeout(function() {html.evalScripts()}, 10);
+    return element;
+  },
+
+  inspect: function(element) {
+    element = $(element);
+    var result = '<' + element.tagName.toLowerCase();
+    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+      var property = pair.first(), attribute = pair.last();
+      var value = (element[property] || '').toString();
+      if (value) result += ' ' + attribute + '=' + value.inspect(true);
+    });
+    return result + '>';
+  },
+
+  recursivelyCollect: function(element, property) {
+    element = $(element);
+    var elements = [];
+    while (element = element[property])
+      if (element.nodeType == 1)
+        elements.push(Element.extend(element));
+    return elements;
+  },
+
+  ancestors: function(element) {
+    return $(element).recursivelyCollect('parentNode');
+  },
+
+  descendants: function(element) {
+    return $A($(element).getElementsByTagName('*')).each(Element.extend);
+  },
+
+  immediateDescendants: function(element) {
+    if (!(element = $(element).firstChild)) return [];
+    while (element && element.nodeType != 1) element = element.nextSibling;
+    if (element) return [element].concat($(element).nextSiblings());
+    return [];
+  },
+
+  previousSiblings: function(element) {
+    return $(element).recursivelyCollect('previousSibling');
+  },
+
+  nextSiblings: function(element) {
+    return $(element).recursivelyCollect('nextSibling');
+  },
+
+  siblings: function(element) {
+    element = $(element);
+    return element.previousSiblings().reverse().concat(element.nextSiblings());
+  },
+
+  match: function(element, selector) {
+    if (typeof selector == 'string')
+      selector = new Selector(selector);
+    return selector.match($(element));
+  },
+
+  up: function(element, expression, index) {
+    var ancestors = $(element).ancestors();
+    return expression ? Selector.findElement(ancestors, expression, index) :
+      ancestors[index || 0];
+  },
+
+  down: function(element, expression, index) {
+    var descendants = $(element).descendants();
+    return expression ? Selector.findElement(descendants, expression, index) :
+      descendants[index || 0];
+  },
+
+  previous: function(element, expression, index) {
+    var previousSiblings = $(element).previousSiblings();
+    return expression ? Selector.findElement(previousSiblings, expression, index) :
+      previousSiblings[index || 0];
+  },
+
+  next: function(element, expression, index) {
+    var nextSiblings = $(element).nextSiblings();
+    return expression ? Selector.findElement(nextSiblings, expression, index) :
+      nextSiblings[index || 0];
+  },
+
+  getElementsBySelector: function() {
+    var args = $A(arguments), element = $(args.shift());
+    return Selector.findChildElements(element, args);
+  },
+
+  getElementsByClassName: function(element, className) {
+    return document.getElementsByClassName(className, element);
+  },
+
+  readAttribute: function(element, name) {
+    element = $(element);
+    if (Prototype.Browser.IE) {
+      if (!element.attributes) return null;
+      var t = Element._attributeTranslations;
+      if (t.values[name]) return t.values[name](element, name);
+      if (t.names[name])  name = t.names[name];
+      var attribute = element.attributes[name];
+      return attribute ? attribute.nodeValue : null;
+    }
+    return element.getAttribute(name);
+  },
+
+  getHeight: function(element) {
+    return $(element).getDimensions().height;
+  },
+
+  getWidth: function(element) {
+    return $(element).getDimensions().width;
+  },
+
+  classNames: function(element) {
+    return new Element.ClassNames(element);
+  },
+
+  hasClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    var elementClassName = element.className;
+    if (elementClassName.length == 0) return false;
+    if (elementClassName == className ||
+        elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
+      return true;
+    return false;
+  },
+
+  addClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    Element.classNames(element).add(className);
+    return element;
+  },
+
+  removeClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    Element.classNames(element).remove(className);
+    return element;
+  },
+
+  toggleClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
+    return element;
+  },
+
+  observe: function() {
+    Event.observe.apply(Event, arguments);
+    return $A(arguments).first();
+  },
+
+  stopObserving: function() {
+    Event.stopObserving.apply(Event, arguments);
+    return $A(arguments).first();
+  },
+
+  // removes whitespace-only text node children
+  cleanWhitespace: function(element) {
+    element = $(element);
+    var node = element.firstChild;
+    while (node) {
+      var nextNode = node.nextSibling;
+      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+        element.removeChild(node);
+      node = nextNode;
+    }
+    return element;
+  },
+
+  empty: function(element) {
+    return $(element).innerHTML.blank();
+  },
+
+  descendantOf: function(element, ancestor) {
+    element = $(element), ancestor = $(ancestor);
+    while (element = element.parentNode)
+      if (element == ancestor) return true;
+    return false;
+  },
+
+  scrollTo: function(element) {
+    element = $(element);
+    var pos = Position.cumulativeOffset(element);
+    window.scrollTo(pos[0], pos[1]);
+    return element;
+  },
+
+  getStyle: function(element, style) {
+    element = $(element);
+    style = style == 'float' ? 'cssFloat' : style.camelize();
+    var value = element.style[style];
+    if (!value) {
+      var css = document.defaultView.getComputedStyle(element, null);
+      value = css ? css[style] : null;
+    }
+    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+    return value == 'auto' ? null : value;
+  },
+
+  getOpacity: function(element) {
+    return $(element).getStyle('opacity');
+  },
+
+  setStyle: function(element, styles, camelized) {
+    element = $(element);
+    var elementStyle = element.style;
+
+    for (var property in styles)
+      if (property == 'opacity') element.setOpacity(styles[property])
+      else
+        elementStyle[(property == 'float' || property == 'cssFloat') ?
+          (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
+          (camelized ? property : property.camelize())] = styles[property];
+
+    return element;
+  },
+
+  setOpacity: function(element, value) {
+    element = $(element);
+    element.style.opacity = (value == 1 || value === '') ? '' :
+      (value < 0.00001) ? 0 : value;
+    return element;
+  },
+
+  getDimensions: function(element) {
+    element = $(element);
+    var display = $(element).getStyle('display');
+    if (display != 'none' && display != null) // Safari bug
+      return {width: element.offsetWidth, height: element.offsetHeight};
+
+    // All *Width and *Height properties give 0 on elements with display none,
+    // so enable the element temporarily
+    var els = element.style;
+    var originalVisibility = els.visibility;
+    var originalPosition = els.position;
+    var originalDisplay = els.display;
+    els.visibility = 'hidden';
+    els.position = 'absolute';
+    els.display = 'block';
+    var originalWidth = element.clientWidth;
+    var originalHeight = element.clientHeight;
+    els.display = originalDisplay;
+    els.position = originalPosition;
+    els.visibility = originalVisibility;
+    return {width: originalWidth, height: originalHeight};
+  },
+
+  makePositioned: function(element) {
+    element = $(element);
+    var pos = Element.getStyle(element, 'position');
+    if (pos == 'static' || !pos) {
+      element._madePositioned = true;
+      element.style.position = 'relative';
+      // Opera returns the offset relative to the positioning context, when an
+      // element is position relative but top and left have not been defined
+      if (window.opera) {
+        element.style.top = 0;
+        element.style.left = 0;
+      }
+    }
+    return element;
+  },
+
+  undoPositioned: function(element) {
+    element = $(element);
+    if (element._madePositioned) {
+      element._madePositioned = undefined;
+      element.style.position =
+        element.style.top =
+        element.style.left =
+        element.style.bottom =
+        element.style.right = '';
+    }
+    return element;
+  },
+
+  makeClipping: function(element) {
+    element = $(element);
+    if (element._overflow) return element;
+    element._overflow = element.style.overflow || 'auto';
+    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
+      element.style.overflow = 'hidden';
+    return element;
+  },
+
+  undoClipping: function(element) {
+    element = $(element);
+    if (!element._overflow) return element;
+    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+    element._overflow = null;
+    return element;
+  }
+};
+
+Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});
+
+if (Prototype.Browser.Opera) {
+  Element.Methods._getStyle = Element.Methods.getStyle;
+  Element.Methods.getStyle = function(element, style) {
+    switch(style) {
+      case 'left':
+      case 'top':
+      case 'right':
+      case 'bottom':
+        if (Element._getStyle(element, 'position') == 'static') return null;
+      default: return Element._getStyle(element, style);
+    }
+  };
+}
+else if (Prototype.Browser.IE) {
+  Element.Methods.getStyle = function(element, style) {
+    element = $(element);
+    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+    var value = element.style[style];
+    if (!value && element.currentStyle) value = element.currentStyle[style];
+
+    if (style == 'opacity') {
+      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+        if (value[1]) return parseFloat(value[1]) / 100;
+      return 1.0;
+    }
+
+    if (value == 'auto') {
+      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+        return element['offset'+style.capitalize()] + 'px';
+      return null;
+    }
+    return value;
+  };
+
+  Element.Methods.setOpacity = function(element, value) {
+    element = $(element);
+    var filter = element.getStyle('filter'), style = element.style;
+    if (value == 1 || value === '') {
+      style.filter = filter.replace(/alpha\([^\)]*\)/gi,'');
+      return element;
+    } else if (value < 0.00001) value = 0;
+    style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') +
+      'alpha(opacity=' + (value * 100) + ')';
+    return element;
+  };
+
+  // IE is missing .innerHTML support for TABLE-related elements
+  Element.Methods.update = function(element, html) {
+    element = $(element);
+    html = typeof html == 'undefined' ? '' : html.toString();
+    var tagName = element.tagName.toUpperCase();
+    if (['THEAD','TBODY','TR','TD'].include(tagName)) {
+      var div = document.createElement('div');
+      switch (tagName) {
+        case 'THEAD':
+        case 'TBODY':
+          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';
+          depth = 2;
+          break;
+        case 'TR':
+          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';
+          depth = 3;
+          break;
+        case 'TD':
+          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';
+          depth = 4;
+      }
+      $A(element.childNodes).each(function(node) { element.removeChild(node) });
+      depth.times(function() { div = div.firstChild });
+      $A(div.childNodes).each(function(node) { element.appendChild(node) });
+    } else {
+      element.innerHTML = html.stripScripts();
+    }
+    setTimeout(function() { html.evalScripts() }, 10);
+    return element;
+  }
+}
+else if (Prototype.Browser.Gecko) {
+  Element.Methods.setOpacity = function(element, value) {
+    element = $(element);
+    element.style.opacity = (value == 1) ? 0.999999 :
+      (value === '') ? '' : (value < 0.00001) ? 0 : value;
+    return element;
+  };
+}
+
+Element._attributeTranslations = {
+  names: {
+    colspan:   "colSpan",
+    rowspan:   "rowSpan",
+    valign:    "vAlign",
+    datetime:  "dateTime",
+    accesskey: "accessKey",
+    tabindex:  "tabIndex",
+    enctype:   "encType",
+    maxlength: "maxLength",
+    readonly:  "readOnly",
+    longdesc:  "longDesc"
+  },
+  values: {
+    _getAttr: function(element, attribute) {
+      return element.getAttribute(attribute, 2);
+    },
+    _flag: function(element, attribute) {
+      return $(element).hasAttribute(attribute) ? attribute : null;
+    },
+    style: function(element) {
+      return element.style.cssText.toLowerCase();
+    },
+    title: function(element) {
+      var node = element.getAttributeNode('title');
+      return node.specified ? node.nodeValue : null;
+    }
+  }
+};
+
+(function() {
+  Object.extend(this, {
+    href: this._getAttr,
+    src:  this._getAttr,
+    disabled: this._flag,
+    checked:  this._flag,
+    readonly: this._flag,
+    multiple: this._flag
+  });
+}).call(Element._attributeTranslations.values);
+
+Element.Methods.Simulated = {
+  hasAttribute: function(element, attribute) {
+    var t = Element._attributeTranslations, node;
+    attribute = t.names[attribute] || attribute;
+    node = $(element).getAttributeNode(attribute);
+    return node && node.specified;
+  }
+};
+
+Element.Methods.ByTag = {};
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+  window.HTMLElement = {};
+  window.HTMLElement.prototype = document.createElement('div').__proto__;
+  Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.hasAttribute = function(element, attribute) {
+  if (element.hasAttribute) return element.hasAttribute(attribute);
+  return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+  if (arguments.length == 2) {
+    var tagName = methods;
+    methods = arguments[1];
+  }
+
+  if (!tagName) Object.extend(Element.Methods, methods || {});
+  else {
+    if (tagName.constructor == Array) tagName.each(extend);
+    else extend(tagName);
+  }
+
+  function extend(tagName) {
+    tagName = tagName.toUpperCase();
+    if (!Element.Methods.ByTag[tagName])
+      Element.Methods.ByTag[tagName] = {};
+    Object.extend(Element.Methods.ByTag[tagName], methods);
+  }
+
+  function copy(methods, destination, onlyIfAbsent) {
+    onlyIfAbsent = onlyIfAbsent || false;
+    var cache = Element.extend.cache;
+    for (var property in methods) {
+      var value = methods[property];
+      if (!onlyIfAbsent || !(property in destination))
+        destination[property] = cache.findOrStore(value);
+    }
+  }
+
+  function findDOMClass(tagName) {
+    var klass;
+    var trans = {
+      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+      "FrameSet", "IFRAME": "IFrame"
+    };
+    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+    if (window[klass]) return window[klass];
+    klass = 'HTML' + tagName + 'Element';
+    if (window[klass]) return window[klass];
+    klass = 'HTML' + tagName.capitalize() + 'Element';
+    if (window[klass]) return window[klass];
+
+    window[klass] = {};
+    window[klass].prototype = document.createElement(tagName).__proto__;
+    return window[klass];
+  }
+
+  if (F.ElementExtensions) {
+    copy(Element.Methods, HTMLElement.prototype);
+    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+  }
+
+  if (F.SpecificElementExtensions) {
+    for (var tag in Element.Methods.ByTag) {
+      var klass = findDOMClass(tag);
+      if (typeof klass == "undefined") continue;
+      copy(T[tag], klass.prototype);
+    }
+  }
+};
+
+var Toggle = { display: Element.toggle };
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.Insertion = function(adjacency) {
+  this.adjacency = adjacency;
+}
+
+Abstract.Insertion.prototype = {
+  initialize: function(element, content) {
+    this.element = $(element);
+    this.content = content.stripScripts();
+
+    if (this.adjacency && this.element.insertAdjacentHTML) {
+      try {
+        this.element.insertAdjacentHTML(this.adjacency, this.content);
+      } catch (e) {
+        var tagName = this.element.tagName.toUpperCase();
+        if (['TBODY', 'TR'].include(tagName)) {
+          this.insertContent(this.contentFromAnonymousTable());
+        } else {
+          throw e;
+        }
+      }
+    } else {
+      this.range = this.element.ownerDocument.createRange();
+      if (this.initializeRange) this.initializeRange();
+      this.insertContent([this.range.createContextualFragment(this.content)]);
+    }
+
+    setTimeout(function() {content.evalScripts()}, 10);
+  },
+
+  contentFromAnonymousTable: function() {
+    var div = document.createElement('div');
+    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
+    return $A(div.childNodes[0].childNodes[0].childNodes);
+  }
+}
+
+var Insertion = new Object();
+
+Insertion.Before = Class.create();
+Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
+  initializeRange: function() {
+    this.range.setStartBefore(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.parentNode.insertBefore(fragment, this.element);
+    }).bind(this));
+  }
+});
+
+Insertion.Top = Class.create();
+Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(true);
+  },
+
+  insertContent: function(fragments) {
+    fragments.reverse(false).each((function(fragment) {
+      this.element.insertBefore(fragment, this.element.firstChild);
+    }).bind(this));
+  }
+});
+
+Insertion.Bottom = Class.create();
+Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.appendChild(fragment);
+    }).bind(this));
+  }
+});
+
+Insertion.After = Class.create();
+Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
+  initializeRange: function() {
+    this.range.setStartAfter(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.parentNode.insertBefore(fragment,
+        this.element.nextSibling);
+    }).bind(this));
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+  initialize: function(element) {
+    this.element = $(element);
+  },
+
+  _each: function(iterator) {
+    this.element.className.split(/\s+/).select(function(name) {
+      return name.length > 0;
+    })._each(iterator);
+  },
+
+  set: function(className) {
+    this.element.className = className;
+  },
+
+  add: function(classNameToAdd) {
+    if (this.include(classNameToAdd)) return;
+    this.set($A(this).concat(classNameToAdd).join(' '));
+  },
+
+  remove: function(classNameToRemove) {
+    if (!this.include(classNameToRemove)) return;
+    this.set($A(this).without(classNameToRemove).join(' '));
+  },
+
+  toString: function() {
+    return $A(this).join(' ');
+  }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license.  Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create();
+
+Selector.prototype = {
+  initialize: function(expression) {
+    this.expression = expression.strip();
+    this.compileMatcher();
+  },
+
+  compileMatcher: function() {
+    // Selectors with namespaced attributes can't use the XPath version
+    if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression))
+      return this.compileXPathMatcher();
+
+    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+        c = Selector.criteria, le, p, m;
+
+    if (Selector._cache[e]) {
+      this.matcher = Selector._cache[e]; return;
+    }
+    this.matcher = ["this.matcher = function(root) {",
+                    "var r = root, h = Selector.handlers, c = false, n;"];
+
+    while (e && le != e && (/\S/).test(e)) {
+      le = e;
+      for (var i in ps) {
+        p = ps[i];
+        if (m = e.match(p)) {
+          this.matcher.push(typeof c[i] == 'function' ? c[i](m) :
+    	      new Template(c[i]).evaluate(m));
+          e = e.replace(m[0], '');
+          break;
+        }
+      }
+    }
+
+    this.matcher.push("return h.unique(n);\n}");
+    eval(this.matcher.join('\n'));
+    Selector._cache[this.expression] = this.matcher;
+  },
+
+  compileXPathMatcher: function() {
+    var e = this.expression, ps = Selector.patterns,
+        x = Selector.xpath, le,  m;
+
+    if (Selector._cache[e]) {
+      this.xpath = Selector._cache[e]; return;
+    }
+
+    this.matcher = ['.//*'];
+    while (e && le != e && (/\S/).test(e)) {
+      le = e;
+      for (var i in ps) {
+        if (m = e.match(ps[i])) {
+          this.matcher.push(typeof x[i] == 'function' ? x[i](m) :
+            new Template(x[i]).evaluate(m));
+          e = e.replace(m[0], '');
+          break;
+        }
+      }
+    }
+
+    this.xpath = this.matcher.join('');
+    Selector._cache[this.expression] = this.xpath;
+  },
+
+  findElements: function(root) {
+    root = root || document;
+    if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+    return this.matcher(root);
+  },
+
+  match: function(element) {
+    return this.findElements(document).include(element);
+  },
+
+  toString: function() {
+    return this.expression;
+  },
+
+  inspect: function() {
+    return "#<Selector:" + this.expression.inspect() + ">";
+  }
+};
+
+Object.extend(Selector, {
+  _cache: {},
+
+  xpath: {
+    descendant:   "//*",
+    child:        "/*",
+    adjacent:     "/following-sibling::*[1]",
+    laterSibling: '/following-sibling::*',
+    tagName:      function(m) {
+      if (m[1] == '*') return '';
+      return "[local-name()='" + m[1].toLowerCase() +
+             "' or local-name()='" + m[1].toUpperCase() + "']";
+    },
+    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+    id:           "[@id='#{1}']",
+    attrPresence: "[@#{1}]",
+    attr: function(m) {
+      m[3] = m[5] || m[6];
+      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+    },
+    pseudo: function(m) {
+      var h = Selector.xpath.pseudos[m[1]];
+      if (!h) return '';
+      if (typeof h === 'function') return h(m);
+      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+    },
+    operators: {
+      '=':  "[@#{1}='#{3}']",
+      '!=': "[@#{1}!='#{3}']",
+      '^=': "[starts-with(@#{1}, '#{3}')]",
+      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+      '*=': "[contains(@#{1}, '#{3}')]",
+      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+    },
+    pseudos: {
+      'first-child': '[not(preceding-sibling::*)]',
+      'last-child':  '[not(following-sibling::*)]',
+      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',
+      'empty':       "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+      'checked':     "[@checked]",
+      'disabled':    "[@disabled]",
+      'enabled':     "[not(@disabled)]",
+      'not': function(m) {
+        var e = m[6], p = Selector.patterns,
+            x = Selector.xpath, le, m, v;
+
+        var exclusion = [];
+        while (e && le != e && (/\S/).test(e)) {
+          le = e;
+          for (var i in p) {
+            if (m = e.match(p[i])) {
+              v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m);
+              exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+              e = e.replace(m[0], '');
+              break;
+            }
+          }
+        }
+        return "[not(" + exclusion.join(" and ") + ")]";
+      },
+      'nth-child':      function(m) {
+        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+      },
+      'nth-last-child': function(m) {
+        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+      },
+      'nth-of-type':    function(m) {
+        return Selector.xpath.pseudos.nth("position() ", m);
+      },
+      'nth-last-of-type': function(m) {
+        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+      },
+      'first-of-type':  function(m) {
+        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+      },
+      'last-of-type':   function(m) {
+        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+      },
+      'only-of-type':   function(m) {
+        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+      },
+      nth: function(fragment, m) {
+        var mm, formula = m[6], predicate;
+        if (formula == 'even') formula = '2n+0';
+        if (formula == 'odd')  formula = '2n+1';
+        if (mm = formula.match(/^(\d+)$/)) // digit only
+          return '[' + fragment + "= " + mm[1] + ']';
+        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+          if (mm[1] == "-") mm[1] = -1;
+          var a = mm[1] ? Number(mm[1]) : 1;
+          var b = mm[2] ? Number(mm[2]) : 0;
+          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+          "((#{fragment} - #{b}) div #{a} >= 0)]";
+          return new Template(predicate).evaluate({
+            fragment: fragment, a: a, b: b });
+        }
+      }
+    }
+  },
+
+  criteria: {
+    tagName:      'n = h.tagName(n, r, "#{1}", c);   c = false;',
+    className:    'n = h.className(n, r, "#{1}", c); c = false;',
+    id:           'n = h.id(n, r, "#{1}", c);        c = false;',
+    attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
+    attr: function(m) {
+      m[3] = (m[5] || m[6]);
+      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
+    },
+    pseudo:       function(m) {
+      if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+    },
+    descendant:   'c = "descendant";',
+    child:        'c = "child";',
+    adjacent:     'c = "adjacent";',
+    laterSibling: 'c = "laterSibling";'
+  },
+
+  patterns: {
+    // combinators must be listed first
+    // (and descendant needs to be last combinator)
+    laterSibling: /^\s*~\s*/,
+    child:        /^\s*>\s*/,
+    adjacent:     /^\s*\+\s*/,
+    descendant:   /^\s/,
+
+    // selectors follow
+    tagName:      /^\s*(\*|[\w\-]+)(\b|$)?/,
+    id:           /^#([\w\-\*]+)(\b|$)/,
+    className:    /^\.([\w\-\*]+)(\b|$)/,
+    pseudo:       /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s)/,
+    attrPresence: /^\[([\w]+)\]/,
+    attr:         /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/
+  },
+
+  handlers: {
+    // UTILITY FUNCTIONS
+    // joins two collections
+    concat: function(a, b) {
+      for (var i = 0, node; node = b[i]; i++)
+        a.push(node);
+      return a;
+    },
+
+    // marks an array of nodes for counting
+    mark: function(nodes) {
+      for (var i = 0, node; node = nodes[i]; i++)
+        node._counted = true;
+      return nodes;
+    },
+
+    unmark: function(nodes) {
+      for (var i = 0, node; node = nodes[i]; i++)
+        node._counted = undefined;
+      return nodes;
+    },
+
+    // mark each child node with its position (for nth calls)
+    // "ofType" flag indicates whether we're indexing for nth-of-type
+    // rather than nth-child
+    index: function(parentNode, reverse, ofType) {
+      parentNode._counted = true;
+      if (reverse) {
+        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+          node = nodes[i];
+          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+        }
+      } else {
+        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+      }
+    },
+
+    // filters out duplicates and extends all nodes
+    unique: function(nodes) {
+      if (nodes.length == 0) return nodes;
+      var results = [], n;
+      for (var i = 0, l = nodes.length; i < l; i++)
+        if (!(n = nodes[i])._counted) {
+          n._counted = true;
+          results.push(Element.extend(n));
+        }
+      return Selector.handlers.unmark(results);
+    },
+
+    // COMBINATOR FUNCTIONS
+    descendant: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        h.concat(results, node.getElementsByTagName('*'));
+      return results;
+    },
+
+    child: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
+          if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+      }
+      return results;
+    },
+
+    adjacent: function(nodes) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        var next = this.nextElementSibling(node);
+        if (next) results.push(next);
+      }
+      return results;
+    },
+
+    laterSibling: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        h.concat(results, Element.nextSiblings(node));
+      return results;
+    },
+
+    nextElementSibling: function(node) {
+      while (node = node.nextSibling)
+	      if (node.nodeType == 1) return node;
+      return null;
+    },
+
+    previousElementSibling: function(node) {
+      while (node = node.previousSibling)
+        if (node.nodeType == 1) return node;
+      return null;
+    },
+
+    // TOKEN FUNCTIONS
+    tagName: function(nodes, root, tagName, combinator) {
+      tagName = tagName.toUpperCase();
+      var results = [], h = Selector.handlers;
+      if (nodes) {
+        if (combinator) {
+          // fastlane for ordinary descendant combinators
+          if (combinator == "descendant") {
+            for (var i = 0, node; node = nodes[i]; i++)
+              h.concat(results, node.getElementsByTagName(tagName));
+            return results;
+          } else nodes = this[combinator](nodes);
+          if (tagName == "*") return nodes;
+        }
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node.tagName.toUpperCase() == tagName) results.push(node);
+        return results;
+      } else return root.getElementsByTagName(tagName);
+    },
+
+    id: function(nodes, root, id, combinator) {
+      var targetNode = $(id), h = Selector.handlers;
+      if (!nodes && root == document) return targetNode ? [targetNode] : [];
+      if (nodes) {
+        if (combinator) {
+          if (combinator == 'child') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (targetNode.parentNode == node) return [targetNode];
+          } else if (combinator == 'descendant') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (Element.descendantOf(targetNode, node)) return [targetNode];
+          } else if (combinator == 'adjacent') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (Selector.handlers.previousElementSibling(targetNode) == node)
+                return [targetNode];
+          } else nodes = h[combinator](nodes);
+        }
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node == targetNode) return [targetNode];
+        return [];
+      }
+      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+    },
+
+    className: function(nodes, root, className, combinator) {
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      return Selector.handlers.byClassName(nodes, root, className);
+    },
+
+    byClassName: function(nodes, root, className) {
+      if (!nodes) nodes = Selector.handlers.descendant([root]);
+      var needle = ' ' + className + ' ';
+      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+        nodeClassName = node.className;
+        if (nodeClassName.length == 0) continue;
+        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+          results.push(node);
+      }
+      return results;
+    },
+
+    attrPresence: function(nodes, root, attr) {
+      var results = [];
+      for (var i = 0, node; node = nodes[i]; i++)
+        if (Element.hasAttribute(node, attr)) results.push(node);
+      return results;
+    },
+
+    attr: function(nodes, root, attr, value, operator) {
+      if (!nodes) nodes = root.getElementsByTagName("*");
+      var handler = Selector.operators[operator], results = [];
+      for (var i = 0, node; node = nodes[i]; i++) {
+        var nodeValue = Element.readAttribute(node, attr);
+        if (nodeValue === null) continue;
+        if (handler(nodeValue, value)) results.push(node);
+      }
+      return results;
+    },
+
+    pseudo: function(nodes, name, value, root, combinator) {
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      if (!nodes) nodes = root.getElementsByTagName("*");
+      return Selector.pseudos[name](nodes, value, root);
+    }
+  },
+
+  pseudos: {
+    'first-child': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        if (Selector.handlers.previousElementSibling(node)) continue;
+          results.push(node);
+      }
+      return results;
+    },
+    'last-child': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        if (Selector.handlers.nextElementSibling(node)) continue;
+          results.push(node);
+      }
+      return results;
+    },
+    'only-child': function(nodes, value, root) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+          results.push(node);
+      return results;
+    },
+    'nth-child':        function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root);
+    },
+    'nth-last-child':   function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, true);
+    },
+    'nth-of-type':      function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, false, true);
+    },
+    'nth-last-of-type': function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, true, true);
+    },
+    'first-of-type':    function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, "1", root, false, true);
+    },
+    'last-of-type':     function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, "1", root, true, true);
+    },
+    'only-of-type':     function(nodes, formula, root) {
+      var p = Selector.pseudos;
+      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+    },
+
+    // handles the an+b logic
+    getIndices: function(a, b, total) {
+      if (a == 0) return b > 0 ? [b] : [];
+      return $R(1, total).inject([], function(memo, i) {
+        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+        return memo;
+      });
+    },
+
+    // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+    nth: function(nodes, formula, root, reverse, ofType) {
+      if (nodes.length == 0) return [];
+      if (formula == 'even') formula = '2n+0';
+      if (formula == 'odd')  formula = '2n+1';
+      var h = Selector.handlers, results = [], indexed = [], m;
+      h.mark(nodes);
+      for (var i = 0, node; node = nodes[i]; i++) {
+        if (!node.parentNode._counted) {
+          h.index(node.parentNode, reverse, ofType);
+          indexed.push(node.parentNode);
+        }
+      }
+      if (formula.match(/^\d+$/)) { // just a number
+        formula = Number(formula);
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node.nodeIndex == formula) results.push(node);
+      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+        if (m[1] == "-") m[1] = -1;
+        var a = m[1] ? Number(m[1]) : 1;
+        var b = m[2] ? Number(m[2]) : 0;
+        var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+          for (var j = 0; j < l; j++)
+            if (node.nodeIndex == indices[j]) results.push(node);
+        }
+      }
+      h.unmark(nodes);
+      h.unmark(indexed);
+      return results;
+    },
+
+    'empty': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        // IE treats comments as element nodes
+        if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+        results.push(node);
+      }
+      return results;
+    },
+
+    'not': function(nodes, selector, root) {
+      var h = Selector.handlers, selectorType, m;
+      var exclusions = new Selector(selector).findElements(root);
+      h.mark(exclusions);
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!node._counted) results.push(node);
+      h.unmark(exclusions);
+      return results;
+    },
+
+    'enabled': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!node.disabled) results.push(node);
+      return results;
+    },
+
+    'disabled': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (node.disabled) results.push(node);
+      return results;
+    },
+
+    'checked': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (node.checked) results.push(node);
+      return results;
+    }
+  },
+
+  operators: {
+    '=':  function(nv, v) { return nv == v; },
+    '!=': function(nv, v) { return nv != v; },
+    '^=': function(nv, v) { return nv.startsWith(v); },
+    '$=': function(nv, v) { return nv.endsWith(v); },
+    '*=': function(nv, v) { return nv.include(v); },
+    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+    '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+  },
+
+  matchElements: function(elements, expression) {
+    var matches = new Selector(expression).findElements(), h = Selector.handlers;
+    h.mark(matches);
+    for (var i = 0, results = [], element; element = elements[i]; i++)
+      if (element._counted) results.push(element);
+    h.unmark(matches);
+    return results;
+  },
+
+  findElement: function(elements, expression, index) {
+    if (typeof expression == 'number') {
+      index = expression; expression = false;
+    }
+    return Selector.matchElements(elements, expression || '*')[index || 0];
+  },
+
+  findChildElements: function(element, expressions) {
+    var exprs = expressions.join(','), expressions = [];
+    exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+      expressions.push(m[1].strip());
+    });
+    var results = [], h = Selector.handlers;
+    for (var i = 0, l = expressions.length, selector; i < l; i++) {
+      selector = new Selector(expressions[i].strip());
+      h.concat(results, selector.findElements(element));
+    }
+    return (l > 1) ? h.unique(results) : results;
+  }
+});
+
+function $$() {
+  return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+  reset: function(form) {
+    $(form).reset();
+    return form;
+  },
+
+  serializeElements: function(elements, getHash) {
+    var data = elements.inject({}, function(result, element) {
+      if (!element.disabled && element.name) {
+        var key = element.name, value = $(element).getValue();
+        if (value != null) {
+         	if (key in result) {
+            if (result[key].constructor != Array) result[key] = [result[key]];
+            result[key].push(value);
+          }
+          else result[key] = value;
+        }
+      }
+      return result;
+    });
+
+    return getHash ? data : Hash.toQueryString(data);
+  }
+};
+
+Form.Methods = {
+  serialize: function(form, getHash) {
+    return Form.serializeElements(Form.getElements(form), getHash);
+  },
+
+  getElements: function(form) {
+    return $A($(form).getElementsByTagName('*')).inject([],
+      function(elements, child) {
+        if (Form.Element.Serializers[child.tagName.toLowerCase()])
+          elements.push(Element.extend(child));
+        return elements;
+      }
+    );
+  },
+
+  getInputs: function(form, typeName, name) {
+    form = $(form);
+    var inputs = form.getElementsByTagName('input');
+
+    if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+      var input = inputs[i];
+      if ((typeName && input.type != typeName) || (name && input.name != name))
+        continue;
+      matchingInputs.push(Element.extend(input));
+    }
+
+    return matchingInputs;
+  },
+
+  disable: function(form) {
+    form = $(form);
+    Form.getElements(form).invoke('disable');
+    return form;
+  },
+
+  enable: function(form) {
+    form = $(form);
+    Form.getElements(form).invoke('enable');
+    return form;
+  },
+
+  findFirstElement: function(form) {
+    return $(form).getElements().find(function(element) {
+      return element.type != 'hidden' && !element.disabled &&
+        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+    });
+  },
+
+  focusFirstElement: function(form) {
+    form = $(form);
+    form.findFirstElement().activate();
+    return form;
+  },
+
+  request: function(form, options) {
+    form = $(form), options = Object.clone(options || {});
+
+    var params = options.parameters;
+    options.parameters = form.serialize(true);
+
+    if (params) {
+      if (typeof params == 'string') params = params.toQueryParams();
+      Object.extend(options.parameters, params);
+    }
+
+    if (form.hasAttribute('method') && !options.method)
+      options.method = form.method;
+
+    return new Ajax.Request(form.readAttribute('action'), options);
+  }
+}
+
+Object.extend(Form, Form.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+  focus: function(element) {
+    $(element).focus();
+    return element;
+  },
+
+  select: function(element) {
+    $(element).select();
+    return element;
+  }
+}
+
+Form.Element.Methods = {
+  serialize: function(element) {
+    element = $(element);
+    if (!element.disabled && element.name) {
+      var value = element.getValue();
+      if (value != undefined) {
+        var pair = {};
+        pair[element.name] = value;
+        return Hash.toQueryString(pair);
+      }
+    }
+    return '';
+  },
+
+  getValue: function(element) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    return Form.Element.Serializers[method](element);
+  },
+
+  clear: function(element) {
+    $(element).value = '';
+    return element;
+  },
+
+  present: function(element) {
+    return $(element).value != '';
+  },
+
+  activate: function(element) {
+    element = $(element);
+    try {
+      element.focus();
+      if (element.select && (element.tagName.toLowerCase() != 'input' ||
+        !['button', 'reset', 'submit'].include(element.type)))
+        element.select();
+    } catch (e) {}
+    return element;
+  },
+
+  disable: function(element) {
+    element = $(element);
+    element.blur();
+    element.disabled = true;
+    return element;
+  },
+
+  enable: function(element) {
+    element = $(element);
+    element.disabled = false;
+    return element;
+  }
+}
+
+Object.extend(Form.Element, Form.Element.Methods);
+Object.extend(Element.Methods.ByTag, {
+  "FORM":     Object.clone(Form.Methods),
+  "INPUT":    Object.clone(Form.Element.Methods),
+  "SELECT":   Object.clone(Form.Element.Methods),
+  "TEXTAREA": Object.clone(Form.Element.Methods)
+});
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+  input: function(element) {
+    switch (element.type.toLowerCase()) {
+      case 'checkbox':
+      case 'radio':
+        return Form.Element.Serializers.inputSelector(element);
+      default:
+        return Form.Element.Serializers.textarea(element);
+    }
+  },
+
+  inputSelector: function(element) {
+    return element.checked ? element.value : null;
+  },
+
+  textarea: function(element) {
+    return element.value;
+  },
+
+  select: function(element) {
+    return this[element.type == 'select-one' ?
+      'selectOne' : 'selectMany'](element);
+  },
+
+  selectOne: function(element) {
+    var index = element.selectedIndex;
+    return index >= 0 ? this.optionValue(element.options[index]) : null;
+  },
+
+  selectMany: function(element) {
+    var values, length = element.length;
+    if (!length) return null;
+
+    for (var i = 0, values = []; i < length; i++) {
+      var opt = element.options[i];
+      if (opt.selected) values.push(this.optionValue(opt));
+    }
+    return values;
+  },
+
+  optionValue: function(opt) {
+    // extend element because hasAttribute may not be native
+    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = function() {}
+Abstract.TimedObserver.prototype = {
+  initialize: function(element, frequency, callback) {
+    this.frequency = frequency;
+    this.element   = $(element);
+    this.callback  = callback;
+
+    this.lastValue = this.getValue();
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    var value = this.getValue();
+    var changed = ('string' == typeof this.lastValue && 'string' == typeof value
+      ? this.lastValue != value : String(this.lastValue) != String(value));
+    if (changed) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  }
+}
+
+Form.Element.Observer = Class.create();
+Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.Observer = Class.create();
+Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = function() {}
+Abstract.EventObserver.prototype = {
+  initialize: function(element, callback) {
+    this.element  = $(element);
+    this.callback = callback;
+
+    this.lastValue = this.getValue();
+    if (this.element.tagName.toLowerCase() == 'form')
+      this.registerFormCallbacks();
+    else
+      this.registerCallback(this.element);
+  },
+
+  onElementEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  },
+
+  registerFormCallbacks: function() {
+    Form.getElements(this.element).each(this.registerCallback.bind(this));
+  },
+
+  registerCallback: function(element) {
+    if (element.type) {
+      switch (element.type.toLowerCase()) {
+        case 'checkbox':
+        case 'radio':
+          Event.observe(element, 'click', this.onElementEvent.bind(this));
+          break;
+        default:
+          Event.observe(element, 'change', this.onElementEvent.bind(this));
+          break;
+      }
+    }
+  }
+}
+
+Form.Element.EventObserver = Class.create();
+Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.EventObserver = Class.create();
+Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+if (!window.Event) {
+  var Event = new Object();
+}
+
+Object.extend(Event, {
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+  KEY_HOME:     36,
+  KEY_END:      35,
+  KEY_PAGEUP:   33,
+  KEY_PAGEDOWN: 34,
+
+  element: function(event) {
+    return $(event.target || event.srcElement);
+  },
+
+  isLeftClick: function(event) {
+    return (((event.which) && (event.which == 1)) ||
+            ((event.button) && (event.button == 1)));
+  },
+
+  pointerX: function(event) {
+    return event.pageX || (event.clientX +
+      (document.documentElement.scrollLeft || document.body.scrollLeft));
+  },
+
+  pointerY: function(event) {
+    return event.pageY || (event.clientY +
+      (document.documentElement.scrollTop || document.body.scrollTop));
+  },
+
+  stop: function(event) {
+    if (event.preventDefault) {
+      event.preventDefault();
+      event.stopPropagation();
+    } else {
+      event.returnValue = false;
+      event.cancelBubble = true;
+    }
+  },
+
+  // find the first node with the given tagName, starting from the
+  // node the event was triggered on; traverses the DOM upwards
+  findElement: function(event, tagName) {
+    var element = Event.element(event);
+    while (element.parentNode && (!element.tagName ||
+        (element.tagName.toUpperCase() != tagName.toUpperCase())))
+      element = element.parentNode;
+    return element;
+  },
+
+  observers: false,
+
+  _observeAndCache: function(element, name, observer, useCapture) {
+    if (!this.observers) this.observers = [];
+    if (element.addEventListener) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.addEventListener(name, observer, useCapture);
+    } else if (element.attachEvent) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.attachEvent('on' + name, observer);
+    }
+  },
+
+  unloadCache: function() {
+    if (!Event.observers) return;
+    for (var i = 0, length = Event.observers.length; i < length; i++) {
+      Event.stopObserving.apply(this, Event.observers[i]);
+      Event.observers[i][0] = null;
+    }
+    Event.observers = false;
+  },
+
+  observe: function(element, name, observer, useCapture) {
+    element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+      (Prototype.Browser.WebKit || element.attachEvent))
+      name = 'keydown';
+
+    Event._observeAndCache(element, name, observer, useCapture);
+  },
+
+  stopObserving: function(element, name, observer, useCapture) {
+    element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+        (Prototype.Browser.WebKit || element.attachEvent))
+      name = 'keydown';
+
+    if (element.removeEventListener) {
+      element.removeEventListener(name, observer, useCapture);
+    } else if (element.detachEvent) {
+      try {
+        element.detachEvent('on' + name, observer);
+      } catch (e) {}
+    }
+  }
+});
+
+/* prevent memory leaks in IE */
+if (Prototype.Browser.IE)
+  Event.observe(window, 'unload', Event.unloadCache, false);
+var Position = {
+  // set to true if needed, warning: firefox performance problems
+  // NOT neeeded for page scrolling, only if draggable contained in
+  // scrollable elements
+  includeScrollOffsets: false,
+
+  // must be called before calling withinIncludingScrolloffset, every time the
+  // page is scrolled
+  prepare: function() {
+    this.deltaX =  window.pageXOffset
+                || document.documentElement.scrollLeft
+                || document.body.scrollLeft
+                || 0;
+    this.deltaY =  window.pageYOffset
+                || document.documentElement.scrollTop
+                || document.body.scrollTop
+                || 0;
+  },
+
+  realOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.scrollTop  || 0;
+      valueL += element.scrollLeft || 0;
+      element = element.parentNode;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  cumulativeOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  positionedOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+      if (element) {
+        if(element.tagName=='BODY') break;
+        var p = Element.getStyle(element, 'position');
+        if (p == 'relative' || p == 'absolute') break;
+      }
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  offsetParent: function(element) {
+    if (element.offsetParent) return element.offsetParent;
+    if (element == document.body) return element;
+
+    while ((element = element.parentNode) && element != document.body)
+      if (Element.getStyle(element, 'position') != 'static')
+        return element;
+
+    return document.body;
+  },
+
+  // caches x/y coordinate pair to use with overlap
+  within: function(element, x, y) {
+    if (this.includeScrollOffsets)
+      return this.withinIncludingScrolloffsets(element, x, y);
+    this.xcomp = x;
+    this.ycomp = y;
+    this.offset = this.cumulativeOffset(element);
+
+    return (y >= this.offset[1] &&
+            y <  this.offset[1] + element.offsetHeight &&
+            x >= this.offset[0] &&
+            x <  this.offset[0] + element.offsetWidth);
+  },
+
+  withinIncludingScrolloffsets: function(element, x, y) {
+    var offsetcache = this.realOffset(element);
+
+    this.xcomp = x + offsetcache[0] - this.deltaX;
+    this.ycomp = y + offsetcache[1] - this.deltaY;
+    this.offset = this.cumulativeOffset(element);
+
+    return (this.ycomp >= this.offset[1] &&
+            this.ycomp <  this.offset[1] + element.offsetHeight &&
+            this.xcomp >= this.offset[0] &&
+            this.xcomp <  this.offset[0] + element.offsetWidth);
+  },
+
+  // within must be called directly before
+  overlap: function(mode, element) {
+    if (!mode) return 0;
+    if (mode == 'vertical')
+      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+        element.offsetHeight;
+    if (mode == 'horizontal')
+      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+        element.offsetWidth;
+  },
+
+  page: function(forElement) {
+    var valueT = 0, valueL = 0;
+
+    var element = forElement;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+
+      // Safari fix
+      if (element.offsetParent == document.body)
+        if (Element.getStyle(element,'position')=='absolute') break;
+
+    } while (element = element.offsetParent);
+
+    element = forElement;
+    do {
+      if (!window.opera || element.tagName=='BODY') {
+        valueT -= element.scrollTop  || 0;
+        valueL -= element.scrollLeft || 0;
+      }
+    } while (element = element.parentNode);
+
+    return [valueL, valueT];
+  },
+
+  clone: function(source, target) {
+    var options = Object.extend({
+      setLeft:    true,
+      setTop:     true,
+      setWidth:   true,
+      setHeight:  true,
+      offsetTop:  0,
+      offsetLeft: 0
+    }, arguments[2] || {})
+
+    // find page position of source
+    source = $(source);
+    var p = Position.page(source);
+
+    // find coordinate system to use
+    target = $(target);
+    var delta = [0, 0];
+    var parent = null;
+    // delta [0,0] will do fine with position: fixed elements,
+    // position:absolute needs offsetParent deltas
+    if (Element.getStyle(target,'position') == 'absolute') {
+      parent = Position.offsetParent(target);
+      delta = Position.page(parent);
+    }
+
+    // correct by body offsets (fixes Safari)
+    if (parent == document.body) {
+      delta[0] -= document.body.offsetLeft;
+      delta[1] -= document.body.offsetTop;
+    }
+
+    // set position
+    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
+    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
+    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
+    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
+  },
+
+  absolutize: function(element) {
+    element = $(element);
+    if (element.style.position == 'absolute') return;
+    Position.prepare();
+
+    var offsets = Position.positionedOffset(element);
+    var top     = offsets[1];
+    var left    = offsets[0];
+    var width   = element.clientWidth;
+    var height  = element.clientHeight;
+
+    element._originalLeft   = left - parseFloat(element.style.left  || 0);
+    element._originalTop    = top  - parseFloat(element.style.top || 0);
+    element._originalWidth  = element.style.width;
+    element._originalHeight = element.style.height;
+
+    element.style.position = 'absolute';
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.width  = width + 'px';
+    element.style.height = height + 'px';
+  },
+
+  relativize: function(element) {
+    element = $(element);
+    if (element.style.position == 'relative') return;
+    Position.prepare();
+
+    element.style.position = 'relative';
+    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
+    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.height = element._originalHeight;
+    element.style.width  = element._originalWidth;
+  }
+}
+
+// Safari returns margins on body which is incorrect if the child is absolutely
+// positioned.  For performance reasons, redefine Position.cumulativeOffset for
+// KHTML/WebKit only.
+if (Prototype.Browser.WebKit) {
+  Position.cumulativeOffset = function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      if (element.offsetParent == document.body)
+        if (Element.getStyle(element, 'position') == 'absolute') break;
+
+      element = element.offsetParent;
+    } while (element);
+
+    return [valueL, valueT];
+  }
+}
+
+Element.addMethods();
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/ajax/prototype/manifest.json
@@ -0,0 +1,1 @@
+{testcases:["test/unit/ajax.html","test/unit/array.html","test/unit/base.html","test/unit/dom.html","test/unit/element_mixins.html","test/unit/enumerable.html","test/unit/form.html","test/unit/hash.html","test/unit/position.html","test/unit/range.html","test/unit/selector.html","test/unit/string.html","test/unit/unit_tests.html"]}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/ajax/prototype/test/lib/unittest.js
@@ -0,0 +1,553 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005 Jon Tirsen (http://www.tirsen.com)
+//           (c) 2005 Michael Schuerig (http://www.schuerig.de/michael/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+// experimental, Firefox-only
+Event.simulateMouse = function(element, eventName) {
+  var options = Object.extend({
+    pointerX: 0,
+    pointerY: 0,
+    buttons: 0
+  }, arguments[2] || {});
+  var oEvent = document.createEvent("MouseEvents");
+  oEvent.initMouseEvent(eventName, true, true, document.defaultView, 
+    options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY, 
+    false, false, false, false, 0, $(element));
+  
+  if(this.mark) Element.remove(this.mark);
+  this.mark = document.createElement('div');
+  this.mark.appendChild(document.createTextNode(" "));
+  document.body.appendChild(this.mark);
+  this.mark.style.position = 'absolute';
+  this.mark.style.top = options.pointerY + "px";
+  this.mark.style.left = options.pointerX + "px";
+  this.mark.style.width = "5px";
+  this.mark.style.height = "5px;";
+  this.mark.style.borderTop = "1px solid red;"
+  this.mark.style.borderLeft = "1px solid red;"
+  
+  if(this.step)
+    alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
+  
+  $(element).dispatchEvent(oEvent);
+};
+
+// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
+// You need to downgrade to 1.0.4 for now to get this working
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
+Event.simulateKey = function(element, eventName) {
+  var options = Object.extend({
+    ctrlKey: false,
+    altKey: false,
+    shiftKey: false,
+    metaKey: false,
+    keyCode: 0,
+    charCode: 0
+  }, arguments[2] || {});
+
+  var oEvent = document.createEvent("KeyEvents");
+  oEvent.initKeyEvent(eventName, true, true, window, 
+    options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
+    options.keyCode, options.charCode );
+  $(element).dispatchEvent(oEvent);
+};
+
+Event.simulateKeys = function(element, command) {
+  for(var i=0; i<command.length; i++) {
+    Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
+  }
+};
+
+var Test = {}
+Test.Unit = {};
+
+// security exception workaround
+Test.Unit.inspect = Object.inspect;
+
+Test.Unit.Logger = Class.create();
+Test.Unit.Logger.prototype = {
+  initialize: function(log) {
+    this.log = $(log);
+    if (this.log) {
+      this._createLogTable();
+    }
+  },
+  start: function(testName) {
+    if (!this.log) return;
+    this.testName = testName;
+    this.lastLogLine = document.createElement('tr');
+    this.statusCell = document.createElement('td');
+    this.nameCell = document.createElement('td');
+    this.nameCell.appendChild(document.createTextNode(testName));
+    this.messageCell = document.createElement('td');
+    this.lastLogLine.appendChild(this.statusCell);
+    this.lastLogLine.appendChild(this.nameCell);
+    this.lastLogLine.appendChild(this.messageCell);
+    this.loglines.appendChild(this.lastLogLine);
+  },
+  finish: function(status, summary) {
+    if (!this.log) return;
+    this.lastLogLine.className = status;
+    this.statusCell.innerHTML = status;
+    this.messageCell.innerHTML = this._toHTML(summary);
+  },
+  message: function(message) {
+    if (!this.log) return;
+    this.messageCell.innerHTML = this._toHTML(message);
+  },
+  summary: function(summary) {
+    if (!this.log) return;
+    this.logsummary.innerHTML = this._toHTML(summary);
+  },
+  _createLogTable: function() {
+    this.log.innerHTML =
+    '<div id="logsummary"></div>' +
+    '<table id="logtable">' +
+    '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
+    '<tbody id="loglines"></tbody>' +
+    '</table>';
+    this.logsummary = $('logsummary')
+    this.loglines = $('loglines');
+  },
+  _toHTML: function(txt) {
+    return txt.escapeHTML().replace(/\n/g,"<br/>");
+  }
+}
+
+Test.Unit.Runner = Class.create();
+Test.Unit.Runner.prototype = {
+  initialize: function(testcases) {
+    this.options = Object.extend({
+      testLog: 'testlog'
+    }, arguments[1] || {});
+    th