]> jfr.im git - irc/quakenet/qwebirc.git/commitdiff
Add MochaUI.
authorChris Porter <redacted>
Tue, 16 Sep 2008 23:52:24 +0000 (00:52 +0100)
committerChris Porter <redacted>
Tue, 16 Sep 2008 23:52:24 +0000 (00:52 +0100)
Currently unfinished.

43 files changed:
.hgignore
compile.bat
compile.sh
js/ui/mochaui.js [new file with mode: 0644]
static/css/mochaui/content.css [new file with mode: 0644]
static/css/mochaui/layout.css [new file with mode: 0644]
static/css/mochaui/ui.css [new file with mode: 0644]
static/css/style.css [new file with mode: 0644]
static/images/mochaui/arrow-right.gif [new file with mode: 0644]
static/images/mochaui/bg-desktopTitlebar-bk.gif [new file with mode: 0644]
static/images/mochaui/bg-desktopTitlebar.gif [new file with mode: 0644]
static/images/mochaui/bg-panel-header.gif [new file with mode: 0644]
static/images/mochaui/icons/help.gif [new file with mode: 0644]
static/images/mochaui/icons/page.gif [new file with mode: 0644]
static/images/mochaui/icons/page_green.gif [new file with mode: 0644]
static/images/mochaui/icons/page_red.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/I.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/L.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/Lminus.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/Lplus.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/Rminus.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/Rplus.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/T.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/Tminus.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/Tplus.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/_closed.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/_doc.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/_open.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/minus.gif [new file with mode: 0644]
static/images/mochaui/icons/tree/plus.gif [new file with mode: 0644]
static/images/mochaui/logo.gif [new file with mode: 0644]
static/images/mochaui/panel-corners.gif [new file with mode: 0644]
static/images/mochaui/spacer.gif [new file with mode: 0644]
static/images/mochaui/tabs.gif [new file with mode: 0644]
static/images/mochaui/view-toggle.gif [new file with mode: 0644]
static/js/excanvas-compressed.js [new file with mode: 0644]
static/js/mocha.js [new file with mode: 0644]
static/js/mochaui.js [new file with mode: 0644]
static/js/mootools-1.2-core.js
static/js/mootools-1.2-more.js [new file with mode: 0644]
static/mochaui.html [new file with mode: 0644]
static/mochauidebug.html [new file with mode: 0644]
twisted/plugins/webirc.py

index f9a7ef2758f6e3ccc1c28fe5e8a967e78f3cf54d..03477ae60e2b7b154ba18d519df95aa192caf61e 100644 (file)
--- a/.hgignore
+++ b/.hgignore
@@ -10,3 +10,4 @@ dropin.cache
 *.log*
 *.pid
 defargs.conf
+Thumbs.db
index a66e1a2165167f5137934fb0fb5b9dfc54ba7fce..2262ef699ce212de5f33a1bae605ea2cd7ec7a5d 100644 (file)
@@ -1,4 +1,4 @@
-rem @echo off\r
+@echo off\r
 mkdir compiled\r
 del /q compiled\*.js\r
 \r
@@ -15,8 +15,11 @@ if not %errorlevel% == 0 goto error
 \r
 java -jar ..\bin\yuicompressor-2.3.5.jar swmui-concat.js > swmui-compiled.js\r
 if not %errorlevel% == 0 goto error\r
-goto ok\r
 \r
+java -jar ..\bin\yuicompressor-2.3.5.jar ..\js\ui\mochaui.js > mochaui-compiled.js\r
+if not %errorlevel% == 0 goto error\r
+\r
+goto ok\r
 :error\r
 cd ..\r
 del /q compiled\*-compiled.js\r
@@ -28,6 +31,7 @@ cd ..
 copy js\copyright.js + compiled\qwebirc-compiled.js /b static\js\qwebirc.js\r
 copy js\copyright.js + compiled\uglyui-compiled.js /b static\js\uglyui.js\r
 copy js\copyright.js + compiled\swmui-compiled.js /b static\js\swmui.js\r
+copy js\copyright.js + compiled\mochaui-compiled.js /b static\js\mochaui.js\r
 del /q compiled\*.js\r
 rmdir compiled\r
 \r
index 16ead5739791549797341c0c2813ddb8f53c5e1b..66072a1488e9d2bfac575cac76105fe41a3d5db7 100755 (executable)
@@ -5,7 +5,6 @@ rm -f compiled/*.js
 cd js
 cat version.js jslib.js irc/ircconnection.js irc/irclib.js irc/baseircclient.js irc/irctracker.js irc/commandparser.js irc/ircclient.js ui/baseui.js ui/baseuiwindow.js ui/colour.js ui/theme.js qwebircinterface.js > ../compiled/qwebirc-concat.js
 cat ui/swmlayout.js ui/swmui.js > ../compiled/swmui-concat.js
-cd ../compiled
 
 error() {
   cd ..
@@ -13,24 +12,26 @@ error() {
   exit 1
 }
 
+catit() {
+  cat js/copyright.js compiled/$1-compiled.js > static/js/$1.js
+}
+
 jarit() {
-  java -jar ../bin/yuicompressor-2.3.5.jar $1.js > $2-compiled.js
+  SRC=$1
+  DST=$2
+  cd ../compiled
+  java -jar ../bin/yuicompressor-2.3.5.jar $SRC.js > $DST-compiled.js
   if [ "$?" != 0 ]; then
     error
   fi
-}
-
-catit() {
-  cat js/copyright.js compiled/$1-compiled.js > static/js/$1.js
+  cd ..
+  catit $DST
+  rm $DST-compiled.js
 }
 
 jarit qwebirc-concat qwebirc
 jarit ../js/ui/uglyui uglyui
 jarit swmui-concat swmui
+jarit ..\js\ui\mochaui.js mochaui
 
-cd ..
-catit qwebirc
-catit uglyui
-catit swmui
-rm -f compiled/*.js
 rmdir compiled
diff --git a/js/ui/mochaui.js b/js/ui/mochaui.js
new file mode 100644 (file)
index 0000000..865b5a3
--- /dev/null
@@ -0,0 +1,186 @@
+var QMochaUIWindow = new Class({
+  Extends: UIWindow,
+  
+  initialize: function(parentObject, client, type, name) {
+    this.parent(parentObject, client, type, name);
+
+    this.lines = new Element("div", {styles: {overflow: "auto", "width": "90"}});
+
+    this.form = new Element("form");
+    this.inputbox = new Element("input", {styles: {border: 0, width: "100%"}});
+    this.inputbox.addClass("input");
+  
+    this.form.addEvent("submit", function(e) {
+      new Event(e).stop();
+    
+      this.client.exec(this.inputbox.value);
+      this.inputbox.value = "";
+    }.bind(this));
+    //this.container.appendChild(form);  
+    this.form.appendChild(this.inputbox);
+    
+    var prefs = {
+      width: 500,
+      height: 400,
+      title: name,
+      footerHeight: 0,
+      toolbar: true,
+      container: $("pageWrapper"),
+      toolbarHeight: parentObject.inputHeight,
+      toolbarPosition: "bottom",
+      toolbarContent: "",
+      content: this.lines,
+      onFocus: function() {
+        parentObject.selectWindow(this);
+      }.bind(this),
+      onClose: function() {
+        if(type == WINDOW_CHANNEL)
+          this.client.exec("/PART " + name);
+
+        this.close();
+      }.bind(this)
+    };
+    
+    if(type == WINDOW_STATUS)
+      prefs.closable = false;
+    
+    var nw = new MochaUI.Window(prefs);
+    /* HACK */
+    var toolbar = $(nw.options.id + "_toolbar");
+    toolbar.appendChild(this.form);
+    
+    return;
+/*    
+    if(type == WINDOW_CHANNEL) {
+      this.nicklist = new Element("div");
+      this.nicklist.addClass("nicklist");
+      
+      this.outerContainer.appendChild(this.nicklist);
+    }
+    
+    var innerContainer = new Element("div");
+    innerContainer.addClass("innercontainer");
+    this.outerContainer.appendChild(innerContainer);
+    
+    if(type == WINDOW_CHANNEL) {
+      this.topic = new Element("div");
+      this.topic.addClass("topic");
+      innerContainer.appendChild(this.topic);
+    }
+    */
+  },
+  updateNickList: function(nicks) {
+    this.parent(nicks);
+    
+    return;
+    var n = this.nicklist;
+    while(n.firstChild)
+      n.removeChild(n.firstChild);
+
+    nicks.each(function(nick) {
+      var e = new Element("div");
+      n.appendChild(e);
+      e.appendChild(document.createTextNode(nick));
+    });
+  },
+  updateTopic: function(topic) {
+    this.parent(topic);
+    return;
+    var t = this.topic;
+    
+    while(t.firstChild)
+      t.removeChild(t.firstChild);
+
+    Colourise(topic, t);
+  },
+  addLine: function(type, line, colour) {
+    this.parent(type, line, colour);
+    
+    var e = new Element("div");
+
+    if(colour) {
+      e.setStyles({"background": colour});
+    } else if(this.lastcolour) {
+      e.addClass("linestyle1");
+    } else {
+      e.addClass("linestyle2");
+    }
+    
+    if(type)
+      line = this.parentObject.theme.message(type, line);
+    
+    Colourise(IRCTimestamp(new Date()) + " " + line, e);
+    
+    this.lastcolour = !this.lastcolour;
+    
+    var prev = this.lines.getScroll();
+    var prevbottom = this.lines.getScrollSize().y;
+    var prevsize = this.lines.getSize();
+    this.lines.appendChild(e);
+    
+    //if(prev.y + prevsize.y == prevbottom)
+    this.lines.scrollTo(prev.x, this.lines.getScrollSize().y);
+      
+    if(!this.active)
+      this.lines.showLoadingIcon();
+  }
+});
+
+var QMochaUI = new Class({
+  Extends: UI,
+    initialize: function(parentElement, theme) {
+    this.parent(parentElement, QMochaUIWindow, "mochaui");
+    this.theme = theme;
+    this.parentElement = parentElement;
+    
+    window.addEvent("domready", function() {
+      /* determine input size */
+      var l = new Element("input", {styles: {border: 0}});
+      this.parentElement.appendChild(l);
+      this.inputHeight = l.getSize().y;
+      this.parentElement.removeChild(l);
+      
+      MochaUI.Desktop = new MochaUI.Desktop();
+      MochaUI.Dock = new MochaUI.Dock();
+      MochaUI.Modal = new MochaUI.Modal();
+      MochaUI.options.useEffects = false;
+    }.bind(this));
+    
+    window.addEvent("unload", function() {
+      if(MochaUI)
+        MochaUI.garbageCleanUp();
+    });
+  },
+  postInitialize: function() {    
+    return;
+    this.tabs = new Element("div");
+    this.tabs.addClass("tabbar");
+    
+    this.parentElement.appendChild(this.tabs);
+    
+    this.container = new Element("div");
+    this.container.addClass("container");
+    
+    this.parentElement.appendChild(this.container);
+  
+    var form = new Element("form");
+    var inputbox = new Element("input");
+    inputbox.addClass("input");
+  
+    form.addEvent("submit", function(e) {
+      new Event(e).stop();
+    
+      this.getActiveWindow().client.exec(inputbox.value);
+      inputbox.value = "";
+    }.bind(this));
+    this.parentElement.appendChild(form);  
+    form.appendChild(inputbox);
+    inputbox.focus();
+  },
+  loginBox: function(callbackfn, intialNickname, initialChannels) {
+    this.parent(function(options) {
+      this.postInitialize();
+      callbackfn(options);
+    }.bind(this), intialNickname, initialChannels);
+  }
+});
diff --git a/static/css/mochaui/content.css b/static/css/mochaui/content.css
new file mode 100644 (file)
index 0000000..26ad691
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+
+CSS for Mocha UI
+
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
+       
+License:
+       MIT-style license.
+
+Note:  
+       If you are adding MochaUI to an existing site, this CSS file may not be necessary.
+   
+*/
+
+
+/* Reset */
+
+ul,ol,dl,li,dt,dd,h1,h2,h3,h4,h5,h6,pre,form,body,html,p,blockquote,fieldset,input,object,iframe { margin: 0; padding: 0; }
+a img,:link img,:visited img { border: none; }
+table { border-collapse: collapse; border-spacing: 0; }
+:focus { outline: none; }
+
+/* Structure */
+
+body {
+       text-align: left;
+       font-family: Arial, Helvetica, sans-serif;
+       font-size: 12px;
+       line-height: 18px;
+       color: #3f3f3f; 
+}
+
+/* Typography */
+       
+h2, h3, h4 {
+       margin: 0;
+       padding: 0 0 5px 0;
+       font-size: 12px;
+       font-weight: bold;      
+}
+       
+h2 {
+       font-size: 14px;
+       font-weight: bold;      
+}
+       
+#mochaPage h3 {
+       display: block;
+       font-size: 12px;
+       padding: 6px 0 6px 0;
+       margin: 0 0 8px 0;
+       border-bottom: 1px solid #bbb;
+}
+
+h4 {
+       font-size: 11px;
+}
+       
+a {
+       color: #0983d1;
+       text-decoration: none;
+       cursor: pointer;
+}
+
+a:hover {
+       text-decoration: none;
+}
+       
+p {
+       margin: 0;
+       padding: 0 0 9px 0;
+}
+
+.lite {
+       color: #999;
+}
+       
+/* List Elements */
+
+ul {
+       list-style: outside;
+       margin: 0 0 9px 16px;
+       list-style-type: square;
+}
+
+dt {
+       font-weight: bold;
+}
+
+dd {
+       padding: 0 0 9px 0;
+}
+
+/* Forms */
+
+textarea, input {
+       font-family: Arial, Helvetica, sans-serif;
+       font-size: 12px;                
+}      
+
+/* Code */
+       
+pre {
+       background-color: #f6f6f6;
+       color: #006600;
+       display: block;
+       font-family: 'Courier New', Courier, monospace;
+       font-size: 11px;
+       max-height: 250px;
+       overflow: auto;
+       margin: 5px 0 10px 0;
+       padding: 10px;
+       border: 1px solid #d1d7dc;      
+}
+       
+/* Dividers */
+
+hr {
+       background-color: #ddd;
+       color: #ccc;
+       height: 1px;
+       border: 0px;
+}
\ No newline at end of file
diff --git a/static/css/mochaui/layout.css b/static/css/mochaui/layout.css
new file mode 100644 (file)
index 0000000..997149b
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+
+CSS for Mocha UI
+
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
+       
+License:
+       MIT-style license.
+   
+*/
+
+.column {
+       visibility: hidden;
+       position: relative;     
+       float: left;
+       height: 100%;
+       min-height: 100%;
+       overflow: hidden;
+}
+
+.panel {
+       overflow: auto;
+       background: #f1f1f1;
+}
+
+.panel.color2 {
+       background: #f1f1f1;    
+}
+
+.panel.color3 {
+       background: #202A33;
+       color: #fff;    
+}      
+
+#mainPanel {
+       background: #fff;       
+}      
+
+.row {
+       position: relative;
+       overflow: hidden;
+}
+
+.horizontalHandle {
+       height: 2px;
+       line-height: 1px;
+       font-size: 1px;
+       overflow: hidden;
+       background: #d0d0d0;    
+}      
+
+.columnHandle {
+       height: 100%;
+       min-height: 10px;       
+       float: left;
+       width: 2px;
+       overflow: hidden;
+       background: #d0d0d0;            
+}
+
+.panel-header {
+       position: relative;     
+       background: #e9e9e9 url(../images/bg-desktopTitlebar.gif)  repeat-x;
+       height: 29px;
+       overflow: hidden;
+}
+
+.panel-corner-nw {
+       position: absolute;
+       top: 0;
+       left: 0;
+       background: #e9e9e9 url(../images/panel-corners.gif) no-repeat;
+       width: 4px;
+       height: 4px;
+       overflow: hidden;       
+}
+
+.panel-corner-ne {
+       position: absolute;
+       top: 0;
+       right: 0;       
+       background: #e9e9e9 url(../images/panel-corners.gif) right top no-repeat;
+       width: 4px;
+       height: 4px;
+       overflow: hidden;       
+}      
+
+.panel-footer {
+       background: #fafafa;
+       padding: 5px 8px;
+}
+
+.panel-header h2 {
+       font-size: 12px;
+       margin: 0;
+       padding: 5px 8px 0 8px;
+       height: 22px;   
+       overflow: hidden;       
+}
+
+.pad {
+       padding: 8px;   
+}
+
+/* Components */
+
+.viewToggle {
+       position: absolute;
+       top: 4px;
+       right: 5px;
+       width: 60px;
+       text-align: right;
+}
+
+.viewToggle img.viewToggleList, .viewToggle img.viewToggleGrid {
+       width: 28px;
+       height: 22px;   
+}      
+
+.viewToggle img.viewToggleList {
+       background: url(../images/view-toggle.gif) no-repeat;
+       background-position: 0 -66px;
+}
+
+.viewToggle img.viewToggleGrid {
+       background: url(../images/view-toggle.gif) no-repeat;
+       background-position: 0 0;
+}                      
diff --git a/static/css/mochaui/ui.css b/static/css/mochaui/ui.css
new file mode 100644 (file)
index 0000000..787ff3f
--- /dev/null
@@ -0,0 +1,761 @@
+/*
+
+CSS for Mocha UI
+
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
+       
+License:
+       MIT-style license.
+   
+*/   
+
+html, body {
+       height: 100%;
+       overflow: auto; /* Removes empty vertical scrollbars in IE */
+}              
+
+body {
+       margin: 0; /* Required */
+       background: #fff;
+}
+
+#desktop {
+       position: relative;
+       top: 0;
+       left: 0;
+       width: 100%;
+       min-width: 750px; /* Helps keep header content from wrapping */         
+       height: 100%;
+       min-height: 100%;       
+       overflow: hidden;
+       cursor: default; /* Fix for issue in IE7. IE7 wants to use the I-bar text cursor */     
+}                                                      
+
+#desktopHeader {
+       background: #fff; /* Will be the margin color between toolbars */
+}
+
+#desktopTitlebarWrapper {
+       position: relative;
+       height: 40px;
+       overflow: hidden;
+       background: #333 url(../images/bg-desktopTitlebar-bk.gif) repeat-x;     
+}
+       
+#desktopTitlebar {
+       padding: 7px 8px 6px 125px;
+       height: 23px;
+       background: url(../images/logo.gif) no-repeat;
+       background-position: 10px 0;            
+}      
+       
+#desktopTitlebar h1.applicationTitle {
+       display: none;  
+       margin: 0;
+       padding: 5px 0 0 0;
+       font-size: 20px;
+       font-weight: bold;
+       color: #fff;
+}
+       
+#desktopTitlebar h1.tagline {
+       font-size: 12px;
+       color: #d9d9d9;
+       font-weight: normal;
+       padding: 5px 0 0 0;     
+}
+
+#desktopTitlebar h1.tagline .taglineEm {
+       color: #fff;
+       font-weight: bold;      
+}      
+
+#topNav {
+       float: right;
+       color: #d9d9d9;
+       text-align: right;
+       padding: 5px 5px 0 0;
+}
+
+#topNav a {
+       color: #fff;
+       font-weight: bold;
+}
+
+#topNav a:hover {
+       color: #fff;
+       text-decoration: underline;
+}
+
+/* Toolboxes */
+
+.toolbox {     
+       float: right;
+       margin-top: 3px;
+       padding: 4px 10px 0 10px;
+       border-left: 1px solid #ccc;
+       height: 20px;
+       overflow: hidden;       
+}                              
+
+/* Navbar */
+
+#desktopNavbar {
+       background: #f1f1f1;
+       height: 30px;
+}
+
+#desktopNavbar ul {    
+       padding: 0;
+       margin: 0;
+       list-style: none;
+       font-size: 12px;
+}
+
+#desktopNavbar li {
+       float: left;                    
+}
+
+#desktopNavbar a {
+       display: block;
+}      
+       
+#desktopNavbar ul li a {
+       padding: 6px 10px 6px 10px;     
+       color: #3f3f3f;
+}
+
+#desktopNavbar ul li a:hover {
+       background-color: #ddd;
+}
+
+#desktopNavbar ul li a.arrow-right, #desktopNavbar ul li a:hover.arrow-right {
+       background-image: url(../images/arrow-right.gif);
+       background-repeat: no-repeat;
+       background-position: right 6px; 
+} 
+       
+#desktopNavbar li ul {
+       padding: 2px;
+       border: 1px solid #333;
+       background: #fff;
+       position: absolute;
+       width: 158px;
+       left: -999em;
+       z-index: 8000;
+}
+
+#desktopNavbar li:hover ul ul,
+#desktopNavbar li.ieHover ul ul,
+#desktopNavbar li:hover ul ul ul,
+#desktopNavbar li.ieHover ul ul ul {
+       left: -999em;
+}
+
+#desktopNavbar li ul ul { /* third-and-above-level lists */
+       margin: -22px 0 0 158px;
+} 
+
+#desktopNavbar li ul li .check {
+       position: absolute;
+       top: 7px;
+       left: 6px;
+       width: 5px;
+       height: 5px;
+       background: #00CC33;
+       overflow: hidden;
+       line-height: 1px;
+       font-size: 1px;
+}
+
+#desktopNavbar li ul li a {
+       position: relative;
+       padding: 1px 9px 1px 19px;
+       width: 130px;
+       color: #333;
+       font-weight: normal;
+}
+
+#desktopNavbar li ul li a:hover {
+       background: #eee;
+}
+
+#desktopNavbar li:hover ul,
+#desktopNavbar li.ieHover ul,
+#desktopNavbar li li.ieHover ul,
+#desktopNavbar li li li.ieHover ul,
+#desktopNavbar li li:hover ul,
+#desktopNavbar li li li:hover ul { /* lists nested under hovered list items */
+      left: auto;
+}
+
+#desktopNavbar li:hover { /* For IE7 */
+    position: static;
+}
+
+.divider {
+       margin-top: 2px;
+       padding-top: 3px;       
+       border-top: 1px solid #ddd;
+}      
+
+#pageWrapper {
+       position: relative;
+       overflow: hidden; /* This can be set to hidden or auto */
+}
+
+/* Footer */
+#desktopFooterWrapper {
+       background: #888;
+       padding: 1px 0 0 0;
+}
+
+#desktopFooter {
+       font-size: 11px;
+       height: 21px;
+       padding: 4px 10px 0 10px;
+       background: #343E47;
+       color: #fff;
+       border: 1px solid #202A33;
+}
+
+#desktopFooter a {
+       color: #fff;
+       font-weight: bold;      
+}
+
+#desktopFooter a:hover {
+       text-decoration: underline;
+}              
+
+/* Menus */
+
+.menu-right li {
+       list-style-type: none;
+       display: inline;        
+       margin: 0 0 0 15px;
+}      
+       
+/* Windows */
+       
+.mocha {
+       position: absolute;
+       top: 0;
+       left: 0;
+       display: none;
+       overflow: hidden;       
+}
+
+.mocha.isFocused {     
+}      
+
+.mochaOverlay {
+       position: absolute;
+       top: 0;
+       left: 0;        
+}
+       
+.mochaTitlebar {
+       width: 100%;
+       overflow: hidden;       
+}
+
+.mochaTitlebar h3 {
+       font-size: 12px;
+       line-height: 15px;      
+       font-weight: bold;
+       margin: 5px 10px 4px 12px;
+       padding: 0;
+       color: #888;
+}
+
+.mocha.isFocused .mochaTitlebar h3 {
+       color: #141414; 
+}
+       
+.mochaToolbarWrapper {
+       width: 100%; /* For IE */
+       position: relative;
+       height: 29px;
+       background: #fff;       
+       overflow: hidden;
+       border-top: 1px solid #d9d9d9;
+}
+
+.mochaToolbar {
+       width: 100%; /* For IE */
+       border-top: 1px solid #fff;
+}
+
+.toolbarTabs { 
+       padding: 0 5px 2px 2px;
+       background: #e4e4e4 url(../images/tabs.gif) repeat-x;
+       background-position: left -60px;        
+}
+
+.tab-menu {
+       padding-top: 1px;
+       list-style:     none;
+       margin: 0;
+       padding: 0;
+       line-height: 16px;
+       font-size: 11px;        
+}
+
+.tab-menu li {
+       display: block;
+       float: left;
+       margin: 0;
+       cursor: pointer;        
+       background: url(../images/tabs.gif) repeat-x;
+       background-position: left -30px;        
+}
+
+.tab-menu li.selected {
+       background: url(../images/tabs.gif) repeat-x;
+       background-position: left 0;    
+}
+
+.tab-menu li a {
+       display: block;
+       margin-left: 8px;
+       padding: 6px 16px 5px 10px;
+       text-align: center;
+       font-weight: normal;
+       color: #141414;
+       background: url(../images/tabs.gif) repeat-x;
+       background-position: right -30px;       
+}
+
+.tab-menu li.selected a {
+       color: #141414;
+       font-weight: bold;      
+       background: url(../images/tabs.gif) repeat-x;
+       background-position: right 0;   
+}      
+
+.mochaContentBorder {
+       border-top: 1px solid #dadada;  
+       border-bottom: 1px solid #dadada;
+}
+       
+.mochaContentWrapper { /* Has a fixed height and scrollbars if required. */
+       font-size: 12px;
+       overflow: auto; 
+}
+       
+.mochaContent {
+       padding: 10px 12px;
+}              
+
+.mocha .handle {
+       position: absolute;
+       background: #0f0;
+       width: 3px;
+       height: 3px;
+       z-index: 2;
+       opacity: .0;
+       filter: alpha(opacity=0);
+       -moz-opacity: .0;
+       overflow: hidden;
+       font-size: 1px; /* For IE6 */   
+}
+
+.mocha .corner { /* Corner resize handles */
+       background: #f00;
+       width: 10px;
+       height: 10px;
+}
+
+.mocha .cornerSE { /* Bottom right resize handle */
+       background: #f00;
+       width: 20px;
+       height: 20px;
+}
+
+.mochaCanvasHeader {
+       position: absolute;
+       top: 0;
+       left: 0;
+       background: transparent;
+       z-index: -1;
+       display: none;          
+       overflow: hidden;                       
+}
+
+.mochaControls {
+       position: absolute;
+       width: 52px;
+       top: 8px;
+       right: 8px;
+       height: 14px;
+       z-index: 4;
+       background: transparent;                
+}
+
+.mochaCanvasControls {
+       position: absolute;     
+       top: 8px;
+       right: 8px;     
+       z-index: 3;
+       background: transparent;                
+}
+
+/*
+       To use images for these buttons:
+       1. Set the useCanvasControls window option to false.
+       2. If you use a different button size you may need to reposition the controls.
+          Modify the controlsOffset window option.             
+       2. Add background images to each button.
+
+*/
+.mochaMinimizeButton, .mochaMaximizeButton, .mochaCloseButton {
+       float: right;
+       width: 14px;
+       height: 14px;
+       font-size: 1px; 
+       cursor: pointer;
+       z-index: 4;
+       background: #f00;       
+       margin-left: 5px;               
+}
+
+.mochaMinimizeButton {
+       margin-left: 0;         
+}
+
+.mochaMaximizeButton { 
+}
+
+.mochaCloseButton {            
+}
+
+.mochaLoadingIcon {
+       position: absolute;
+       bottom: 7px;
+       left: 6px;      
+}
+
+.mochaIframe {
+       width: 100%;
+}  
+       
+/* Sliders */
+
+.slider {
+       clear: both;
+       position: relative;
+       font-size: 12px;
+       font-weight: bold;
+       width: 200px;
+       margin-bottom: 15px;    
+}
+
+.sliderarea {
+       position: relative;
+       height: 6px;
+       width: 200px;
+       font-size: 1px;
+       line-height: 1px;
+       background: #dfdfdf;
+       margin: 0;
+       padding: 0;
+}
+.sliderknob {
+       position: absolute;
+       top: 0px;
+       height: 6px;
+       width: 13px;
+       font-size: 1px;
+       line-height: 1px;       
+       background: #888;
+       border-right: 1px solid #eee;
+       border-left: 1px solid #eee;    
+       cursor: pointer;
+       overflow: hidden;
+}
+       
+.update {
+       padding-bottom: 5px;    
+}      
+       
+.clear {
+       clear: both;
+       height: 0;
+}
+
+*html .clear {
+       height: 1%;
+       font-size: 1px;
+       line-height: 1px;
+       overflow: hidden;
+       visibility: hidden;
+}
+       
+/* Window Builder Form Elements */
+       
+#desktop form {
+       margin: 0 0 0 0;
+       padding: 5px 0 0 0;
+       width: 320px;
+}
+
+#desktop .input {
+       width: 225px;
+       padding: 1px 0 1px 3px;
+       border: 1px solid #bbb; 
+}
+
+#desktop textarea {
+       width: 225px;
+       height: 100px;
+       padding: 1px 0 1px 3px;
+       border: 1px solid #bbb; 
+}              
+
+#desktop .formLabel {
+       float: left;    
+       text-align: right;
+       width: 80px;
+       margin: 0 0 5px 0;      
+}
+       
+#desktop .formField {
+       float: right;
+       margin: 0 0 5px 0;
+       padding: 0 0 0 0;
+       width: 230px;
+}
+       
+#desktop form .number {
+       width: 40px;
+}
+       
+/* Modal Windows */
+#modalOverlay {
+       display: none;
+       position: fixed;
+       top: 0;
+       left: 0;
+       width: 100%;
+       background: #000;
+       opacity: 0;
+       filter: alpha(opacity=0);
+       -moz-opacity: 0;
+       z-index: 10000;
+}
+
+* html         #modalOverlay {
+       position: absolute;
+}
+
+/* Fix for IE6 select z-index issue */
+#modalFix {
+       display: none;
+       position: absolute;
+       top: 0;
+       left: 0;
+       width: 100%;
+       opacity: 0;
+       filter: alpha(opacity=0);
+       -moz-opacity: 0;
+       z-index: 9999;
+}
+
+/* Overlay */
+
+#windowUnderlay { 
+       position: fixed;
+       top: 0;
+       left: 0;
+       width: 100%;
+       background: #fff;       
+}
+
+* html #windowUnderlay { 
+       position: absolute;
+}      
+
+/* Fix for IE6 select z-index issue */
+iframe.zIndexFix {
+       display: block;
+       position: absolute;
+       top: 0;
+       left: 0;
+       z-index: -1;
+       filter: mask();
+       width: 100px;
+       height: 100px;
+       border: 1px solid transparent;
+}
+       
+/* Window Minimize Dock */
+
+#dockWrapper {
+       display: none;
+       background: #f1f1f1;
+       width: 100%;    
+}
+
+#dockWrapper.top {
+       border-top: 1px solid #d0d0d0;
+}
+
+#dock {
+       position: relative;
+       padding: 3px 15px 1px 15px;
+       bottom: 0;
+       left: 0;
+       width: 100%;
+       background: #f1f1f1;
+       border: 1px solid #f1f1f1;
+       min-height: 26px;
+       height: auto;
+   _height: 26px; /* IE 6.0 hack, for not supporting min-height */
+}
+
+.dockTab {
+       float: left;
+       font-size: 11px;
+       position: relative;
+       width: 140px;
+       height: 22px;
+       margin: 0 2px 2px 0;
+       overflow: hidden;       
+       cursor: pointer;
+       background: transparent url(../images/bg-desktopTitlebar.gif)  repeat-x;
+       border: 1px solid #c0c0c0;
+}      
+
+.dockTab.activeDockTab {
+       background: #fff;
+}      
+
+.dockText {
+       position: absolute;
+       top: 0;
+       left: 0;
+       display: block;
+       text-align: left;
+       padding: 2px 0 0 23px;
+       width: 115px;
+       height: 19px;
+       overflow: hidden;
+       background: url(../images/icons/page.gif) 2px 3px no-repeat;            
+}                      
+
+#dockCanvas {
+       position: absolute;
+       top: 4px;
+       left: 2px;
+       z-index: 2;
+}
+
+#dockPlacement {
+       position: absolute;
+       top: 3px;
+       left: 2px;
+       width: 10px;
+       height: 9px;
+       opacity: 0;
+       filter: alpha(opacity=0);
+       -moz-opacity: 0;
+       background: #f00; /* for troubleshooting */
+       cursor: pointer;
+       z-index: 3; /* for IE */        
+}
+
+#dockAutoHide {
+       position: absolute;
+       top: 13px;
+       left: 2px;
+       width: 10px;
+       height: 9px;
+       opacity: 0;
+       filter: alpha(opacity=0);
+       -moz-opacity: 0;
+       background: #f00; /* for troubleshooting */
+       cursor: pointer;
+       z-index: 3; /* for IE */                
+}
+
+/* Accordian */
+
+.accordianWrapper {
+       padding: 0;
+       background: #fff;       
+}
+
+.accordianToggler {
+       margin: 0;
+       padding: 6px 10px;
+       background: #fff url(../images/bg-desktopTitlebar.gif) repeat-x;
+       font-size: 12px;
+       cursor: pointer;
+       border-top: 1px solid #e3e3e3;  
+}
+
+.topToggler {
+       border-top: none;
+}
+
+.accordianToggler.open {
+       background: #fff url(../images/bg-desktopTitlebar.gif) repeat-x;        
+}
+
+.accordianContent {
+       padding: 10px 10px 5px 10px;
+}
+
+/* Window Themes */
+
+.mocha.transparent .mochaTitlebar h3 {
+       color: #fff;
+       display: none;  
+}
+
+.mocha.notification .mochaTitlebar {
+       opacity: .0;
+       filter: alpha(opacity=0);
+       -moz-opacity: 0;
+}
+
+.mocha.notification .mochaContentBorder {
+       border-width: 0px;
+}
+
+.mocha.notification .mochaContentWrapper {
+       text-align: center;
+       font-size: 12px;
+       font-weight: bold;
+}
+
+/* Folder Tree */
+
+.tree {
+       font-size: 11px;
+       line-height: 15px;
+       margin: 0;
+}
+
+.tree ul {
+       margin: 0;      
+}
+
+.tree li {
+       list-style-type: none;
+       white-space: nowrap;    
+}
+
+.tree li img {
+       vertical-align: middle;
+       width: 18px;
+       height: 18px;
+       overflow: hidden;
+}
+
+.tree li span {
+       padding-left: 2px;
+}       
\ No newline at end of file
diff --git a/static/css/style.css b/static/css/style.css
new file mode 100644 (file)
index 0000000..0eefa0f
--- /dev/null
@@ -0,0 +1,101 @@
+/* Reset */\r
+\r
+ul,ol,dl,li,dt,dd,h1,h2,h3,h4,h5,h6,pre,form,body,html,p,blockquote,fieldset,input,object,iframe { margin: 0; padding: 0; }\r
+a img,:link img,:visited img { border: none; }\r
+table { border-collapse: collapse; border-spacing: 0; }\r
+:focus { outline: none; }\r
+\r
+/* Structure */\r
+\r
+body {\r
+       margin: 0;\r
+       text-align: left;\r
+       font-family: Arial, Helvetica, sans-serif;\r
+       font-size: 12px;\r
+       line-height: 18px;\r
+       color: #141414; \r
+}\r
+\r
+/* Typography */\r
+       \r
+h2, h3, h4 {\r
+       margin: 0;\r
+       padding: 0 0 5px 0;\r
+       font-size: 12px;\r
+       font-weight: bold;      \r
+}\r
+       \r
+h2 {\r
+       font-size: 14px;\r
+       font-weight: bold;      \r
+}\r
+       \r
+#mochaPage h3 {\r
+       display: block;\r
+       font-size: 12px;\r
+       padding: 6px 0 6px 0;\r
+       margin: 0 0 8px 0;\r
+       border-bottom: 1px solid #bbb;\r
+}\r
+\r
+h4 {\r
+       font-size: 11px;\r
+}\r
+       \r
+a {\r
+       color: #ce1717;\r
+       text-decoration: none;\r
+       cursor: pointer;\r
+}\r
+\r
+a:hover {\r
+       text-decoration: none;\r
+}\r
+       \r
+p {\r
+       margin: 0;\r
+       padding: 0 0 9px 0;\r
+}\r
+\r
+.lite {\r
+       color: #999;\r
+}\r
+       \r
+/* List Elements */\r
+\r
+ul {\r
+       list-style: outside;\r
+       margin: 0 0 9px 16px;\r
+}\r
+\r
+dt {\r
+       font-weight: bold;\r
+}\r
+\r
+dd {\r
+       padding: 0 0 9px 0;\r
+}      \r
+\r
+/* Code */\r
+       \r
+pre {\r
+       background-color: #f6f6f6;\r
+       color: #006600;\r
+       display: block;\r
+       font-family: 'Courier New', Courier, monospace;\r
+       font-size: 11px;\r
+       max-height: 250px;\r
+       overflow: auto;\r
+       margin: 5px 0 10px 0;\r
+       padding: 10px;\r
+       border: 1px solid #d1d7dc;      \r
+}\r
+       \r
+/* Dividers */\r
+\r
+hr {\r
+       background-color: #ddd;\r
+       color: #ccc;\r
+       height: 1px;\r
+       border: 0px;\r
+}
\ No newline at end of file
diff --git a/static/images/mochaui/arrow-right.gif b/static/images/mochaui/arrow-right.gif
new file mode 100644 (file)
index 0000000..da97e68
Binary files /dev/null and b/static/images/mochaui/arrow-right.gif differ
diff --git a/static/images/mochaui/bg-desktopTitlebar-bk.gif b/static/images/mochaui/bg-desktopTitlebar-bk.gif
new file mode 100644 (file)
index 0000000..32517a0
Binary files /dev/null and b/static/images/mochaui/bg-desktopTitlebar-bk.gif differ
diff --git a/static/images/mochaui/bg-desktopTitlebar.gif b/static/images/mochaui/bg-desktopTitlebar.gif
new file mode 100644 (file)
index 0000000..e4dbdea
Binary files /dev/null and b/static/images/mochaui/bg-desktopTitlebar.gif differ
diff --git a/static/images/mochaui/bg-panel-header.gif b/static/images/mochaui/bg-panel-header.gif
new file mode 100644 (file)
index 0000000..33bbe5a
Binary files /dev/null and b/static/images/mochaui/bg-panel-header.gif differ
diff --git a/static/images/mochaui/icons/help.gif b/static/images/mochaui/icons/help.gif
new file mode 100644 (file)
index 0000000..40545aa
Binary files /dev/null and b/static/images/mochaui/icons/help.gif differ
diff --git a/static/images/mochaui/icons/page.gif b/static/images/mochaui/icons/page.gif
new file mode 100644 (file)
index 0000000..5f39482
Binary files /dev/null and b/static/images/mochaui/icons/page.gif differ
diff --git a/static/images/mochaui/icons/page_green.gif b/static/images/mochaui/icons/page_green.gif
new file mode 100644 (file)
index 0000000..17d30ae
Binary files /dev/null and b/static/images/mochaui/icons/page_green.gif differ
diff --git a/static/images/mochaui/icons/page_red.gif b/static/images/mochaui/icons/page_red.gif
new file mode 100644 (file)
index 0000000..1c91343
Binary files /dev/null and b/static/images/mochaui/icons/page_red.gif differ
diff --git a/static/images/mochaui/icons/tree/I.gif b/static/images/mochaui/icons/tree/I.gif
new file mode 100644 (file)
index 0000000..1a259ee
Binary files /dev/null and b/static/images/mochaui/icons/tree/I.gif differ
diff --git a/static/images/mochaui/icons/tree/L.gif b/static/images/mochaui/icons/tree/L.gif
new file mode 100644 (file)
index 0000000..48b81c8
Binary files /dev/null and b/static/images/mochaui/icons/tree/L.gif differ
diff --git a/static/images/mochaui/icons/tree/Lminus.gif b/static/images/mochaui/icons/tree/Lminus.gif
new file mode 100644 (file)
index 0000000..26c2b34
Binary files /dev/null and b/static/images/mochaui/icons/tree/Lminus.gif differ
diff --git a/static/images/mochaui/icons/tree/Lplus.gif b/static/images/mochaui/icons/tree/Lplus.gif
new file mode 100644 (file)
index 0000000..775619d
Binary files /dev/null and b/static/images/mochaui/icons/tree/Lplus.gif differ
diff --git a/static/images/mochaui/icons/tree/Rminus.gif b/static/images/mochaui/icons/tree/Rminus.gif
new file mode 100644 (file)
index 0000000..e62222a
Binary files /dev/null and b/static/images/mochaui/icons/tree/Rminus.gif differ
diff --git a/static/images/mochaui/icons/tree/Rplus.gif b/static/images/mochaui/icons/tree/Rplus.gif
new file mode 100644 (file)
index 0000000..1c40a78
Binary files /dev/null and b/static/images/mochaui/icons/tree/Rplus.gif differ
diff --git a/static/images/mochaui/icons/tree/T.gif b/static/images/mochaui/icons/tree/T.gif
new file mode 100644 (file)
index 0000000..34dd476
Binary files /dev/null and b/static/images/mochaui/icons/tree/T.gif differ
diff --git a/static/images/mochaui/icons/tree/Tminus.gif b/static/images/mochaui/icons/tree/Tminus.gif
new file mode 100644 (file)
index 0000000..025840f
Binary files /dev/null and b/static/images/mochaui/icons/tree/Tminus.gif differ
diff --git a/static/images/mochaui/icons/tree/Tplus.gif b/static/images/mochaui/icons/tree/Tplus.gif
new file mode 100644 (file)
index 0000000..4659651
Binary files /dev/null and b/static/images/mochaui/icons/tree/Tplus.gif differ
diff --git a/static/images/mochaui/icons/tree/_closed.gif b/static/images/mochaui/icons/tree/_closed.gif
new file mode 100644 (file)
index 0000000..c2d3b32
Binary files /dev/null and b/static/images/mochaui/icons/tree/_closed.gif differ
diff --git a/static/images/mochaui/icons/tree/_doc.gif b/static/images/mochaui/icons/tree/_doc.gif
new file mode 100644 (file)
index 0000000..155a632
Binary files /dev/null and b/static/images/mochaui/icons/tree/_doc.gif differ
diff --git a/static/images/mochaui/icons/tree/_open.gif b/static/images/mochaui/icons/tree/_open.gif
new file mode 100644 (file)
index 0000000..7064a30
Binary files /dev/null and b/static/images/mochaui/icons/tree/_open.gif differ
diff --git a/static/images/mochaui/icons/tree/minus.gif b/static/images/mochaui/icons/tree/minus.gif
new file mode 100644 (file)
index 0000000..1647fea
Binary files /dev/null and b/static/images/mochaui/icons/tree/minus.gif differ
diff --git a/static/images/mochaui/icons/tree/plus.gif b/static/images/mochaui/icons/tree/plus.gif
new file mode 100644 (file)
index 0000000..3fe8590
Binary files /dev/null and b/static/images/mochaui/icons/tree/plus.gif differ
diff --git a/static/images/mochaui/logo.gif b/static/images/mochaui/logo.gif
new file mode 100644 (file)
index 0000000..f550b9a
Binary files /dev/null and b/static/images/mochaui/logo.gif differ
diff --git a/static/images/mochaui/panel-corners.gif b/static/images/mochaui/panel-corners.gif
new file mode 100644 (file)
index 0000000..3477226
Binary files /dev/null and b/static/images/mochaui/panel-corners.gif differ
diff --git a/static/images/mochaui/spacer.gif b/static/images/mochaui/spacer.gif
new file mode 100644 (file)
index 0000000..099c95f
Binary files /dev/null and b/static/images/mochaui/spacer.gif differ
diff --git a/static/images/mochaui/tabs.gif b/static/images/mochaui/tabs.gif
new file mode 100644 (file)
index 0000000..9be4ec4
Binary files /dev/null and b/static/images/mochaui/tabs.gif differ
diff --git a/static/images/mochaui/view-toggle.gif b/static/images/mochaui/view-toggle.gif
new file mode 100644 (file)
index 0000000..52b3308
Binary files /dev/null and b/static/images/mochaui/view-toggle.gif differ
diff --git a/static/js/excanvas-compressed.js b/static/js/excanvas-compressed.js
new file mode 100644 (file)
index 0000000..9d71658
--- /dev/null
@@ -0,0 +1,19 @@
+if(!window.CanvasRenderingContext2D){(function(){var I=Math,i=I.round,L=I.sin,M=I.cos,m=10,A=m/2,Q={init:function(a){var b=a||document;if(/MSIE/.test(navigator.userAgent)&&!window.opera){var c=this;b.attachEvent("onreadystatechange",function(){c.r(b)})}},r:function(a){if(a.readyState=="complete"){if(!a.namespaces["s"]){a.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml")}var b=a.createStyleSheet();b.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}";
+var c=a.getElementsByTagName("canvas");for(var d=0;d<c.length;d++){if(!c[d].getContext){this.initElement(c[d])}}}},q:function(a){var b=a.outerHTML,c=a.ownerDocument.createElement(b);if(b.slice(-2)!="/>"){var d="/"+a.tagName,e;while((e=a.nextSibling)&&e.tagName!=d){e.removeNode()}if(e){e.removeNode()}}a.parentNode.replaceChild(c,a);return c},initElement:function(a){a=this.q(a);a.getContext=function(){if(this.l){return this.l}return this.l=new K(this)};a.attachEvent("onpropertychange",V);a.attachEvent("onresize",
+W);var b=a.attributes;if(b.width&&b.width.specified){a.style.width=b.width.nodeValue+"px"}else{a.width=a.clientWidth}if(b.height&&b.height.specified){a.style.height=b.height.nodeValue+"px"}else{a.height=a.clientHeight}return a}};function V(a){var b=a.srcElement;switch(a.propertyName){case "width":b.style.width=b.attributes.width.nodeValue+"px";b.getContext().clearRect();break;case "height":b.style.height=b.attributes.height.nodeValue+"px";b.getContext().clearRect();break}}function W(a){var b=a.srcElement;
+if(b.firstChild){b.firstChild.style.width=b.clientWidth+"px";b.firstChild.style.height=b.clientHeight+"px"}}Q.init();var R=[];for(var E=0;E<16;E++){for(var F=0;F<16;F++){R[E*16+F]=E.toString(16)+F.toString(16)}}function J(){return[[1,0,0],[0,1,0],[0,0,1]]}function G(a,b){var c=J();for(var d=0;d<3;d++){for(var e=0;e<3;e++){var g=0;for(var h=0;h<3;h++){g+=a[d][h]*b[h][e]}c[d][e]=g}}return c}function N(a,b){b.fillStyle=a.fillStyle;b.lineCap=a.lineCap;b.lineJoin=a.lineJoin;b.lineWidth=a.lineWidth;b.miterLimit=
+a.miterLimit;b.shadowBlur=a.shadowBlur;b.shadowColor=a.shadowColor;b.shadowOffsetX=a.shadowOffsetX;b.shadowOffsetY=a.shadowOffsetY;b.strokeStyle=a.strokeStyle;b.d=a.d;b.e=a.e}function O(a){var b,c=1;a=String(a);if(a.substring(0,3)=="rgb"){var d=a.indexOf("(",3),e=a.indexOf(")",d+1),g=a.substring(d+1,e).split(",");b="#";for(var h=0;h<3;h++){b+=R[Number(g[h])]}if(g.length==4&&a.substr(3,1)=="a"){c=g[3]}}else{b=a}return[b,c]}function S(a){switch(a){case "butt":return"flat";case "round":return"round";
+case "square":default:return"square"}}function K(a){this.a=J();this.m=[];this.k=[];this.c=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=m*1;this.globalAlpha=1;this.canvas=a;var b=a.ownerDocument.createElement("div");b.style.width=a.clientWidth+"px";b.style.height=a.clientHeight+"px";b.style.overflow="hidden";b.style.position="absolute";a.appendChild(b);this.j=b;this.d=1;this.e=1}var j=K.prototype;j.clearRect=function(){this.j.innerHTML=
+"";this.c=[]};j.beginPath=function(){this.c=[]};j.moveTo=function(a,b){this.c.push({type:"moveTo",x:a,y:b});this.f=a;this.g=b};j.lineTo=function(a,b){this.c.push({type:"lineTo",x:a,y:b});this.f=a;this.g=b};j.bezierCurveTo=function(a,b,c,d,e,g){this.c.push({type:"bezierCurveTo",cp1x:a,cp1y:b,cp2x:c,cp2y:d,x:e,y:g});this.f=e;this.g=g};j.quadraticCurveTo=function(a,b,c,d){var e=this.f+0.6666666666666666*(a-this.f),g=this.g+0.6666666666666666*(b-this.g),h=e+(c-this.f)/3,l=g+(d-this.g)/3;this.bezierCurveTo(e,
+g,h,l,c,d)};j.arc=function(a,b,c,d,e,g){c*=m;var h=g?"at":"wa",l=a+M(d)*c-A,n=b+L(d)*c-A,o=a+M(e)*c-A,f=b+L(e)*c-A;if(l==o&&!g){l+=0.125}this.c.push({type:h,x:a,y:b,radius:c,xStart:l,yStart:n,xEnd:o,yEnd:f})};j.rect=function(a,b,c,d){this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath()};j.strokeRect=function(a,b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.stroke()};j.fillRect=function(a,
+b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.fill()};j.createLinearGradient=function(a,b,c,d){var e=new H("gradient");return e};j.createRadialGradient=function(a,b,c,d,e,g){var h=new H("gradientradial");h.n=c;h.o=g;h.i.x=a;h.i.y=b;return h};j.drawImage=function(a,b){var c,d,e,g,h,l,n,o,f=a.runtimeStyle.width,k=a.runtimeStyle.height;a.runtimeStyle.width="auto";a.runtimeStyle.height="auto";var q=a.width,r=a.height;a.runtimeStyle.width=
+f;a.runtimeStyle.height=k;if(arguments.length==3){c=arguments[1];d=arguments[2];h=(l=0);n=(e=q);o=(g=r)}else if(arguments.length==5){c=arguments[1];d=arguments[2];e=arguments[3];g=arguments[4];h=(l=0);n=q;o=r}else if(arguments.length==9){h=arguments[1];l=arguments[2];n=arguments[3];o=arguments[4];c=arguments[5];d=arguments[6];e=arguments[7];g=arguments[8]}else{throw"Invalid number of arguments";}var s=this.b(c,d),t=[],v=10,w=10;t.push(" <g_vml_:group",' coordsize="',m*v,",",m*w,'"',' coordorigin="0,0"',
+' style="width:',v,";height:",w,";position:absolute;");if(this.a[0][0]!=1||this.a[0][1]){var x=[];x.push("M11='",this.a[0][0],"',","M12='",this.a[1][0],"',","M21='",this.a[0][1],"',","M22='",this.a[1][1],"',","Dx='",i(s.x/m),"',","Dy='",i(s.y/m),"'");var p=s,y=this.b(c+e,d),z=this.b(c,d+g),B=this.b(c+e,d+g);p.x=Math.max(p.x,y.x,z.x,B.x);p.y=Math.max(p.y,y.y,z.y,B.y);t.push("padding:0 ",i(p.x/m),"px ",i(p.y/m),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",x.join(""),", sizingmethod='clip');")}else{t.push("top:",
+i(s.y/m),"px;left:",i(s.x/m),"px;")}t.push(' ">','<g_vml_:image src="',a.src,'"',' style="width:',m*e,";"," height:",m*g,';"',' cropleft="',h/q,'"',' croptop="',l/r,'"',' cropright="',(q-h-n)/q,'"',' cropbottom="',(r-l-o)/r,'"'," />","</g_vml_:group>");this.j.insertAdjacentHTML("BeforeEnd",t.join(""))};j.stroke=function(a){var b=[],c=O(a?this.fillStyle:this.strokeStyle),d=c[0],e=c[1]*this.globalAlpha,g=10,h=10;b.push("<g_vml_:shape",' fillcolor="',d,'"',' filled="',Boolean(a),'"',' style="position:absolute;width:',
+g,";height:",h,';"',' coordorigin="0 0" coordsize="',m*g," ",m*h,'"',' stroked="',!a,'"',' strokeweight="',this.lineWidth,'"',' strokecolor="',d,'"',' path="');var l={x:null,y:null},n={x:null,y:null};for(var o=0;o<this.c.length;o++){var f=this.c[o];if(f.type=="moveTo"){b.push(" m ");var k=this.b(f.x,f.y);b.push(i(k.x),",",i(k.y))}else if(f.type=="lineTo"){b.push(" l ");var k=this.b(f.x,f.y);b.push(i(k.x),",",i(k.y))}else if(f.type=="close"){b.push(" x ")}else if(f.type=="bezierCurveTo"){b.push(" c ");
+var k=this.b(f.x,f.y),q=this.b(f.cp1x,f.cp1y),r=this.b(f.cp2x,f.cp2y);b.push(i(q.x),",",i(q.y),",",i(r.x),",",i(r.y),",",i(k.x),",",i(k.y))}else if(f.type=="at"||f.type=="wa"){b.push(" ",f.type," ");var k=this.b(f.x,f.y),s=this.b(f.xStart,f.yStart),t=this.b(f.xEnd,f.yEnd);b.push(i(k.x-this.d*f.radius),",",i(k.y-this.e*f.radius)," ",i(k.x+this.d*f.radius),",",i(k.y+this.e*f.radius)," ",i(s.x),",",i(s.y)," ",i(t.x),",",i(t.y))}if(k){if(l.x==null||k.x<l.x){l.x=k.x}if(n.x==null||k.x>n.x){n.x=k.x}if(l.y==
+null||k.y<l.y){l.y=k.y}if(n.y==null||k.y>n.y){n.y=k.y}}}b.push(' ">');if(typeof this.fillStyle=="object"){var v={x:"50%",y:"50%"},w=n.x-l.x,x=n.y-l.y,p=w>x?w:x;v.x=i(this.fillStyle.i.x/w*100+50)+"%";v.y=i(this.fillStyle.i.y/x*100+50)+"%";var y=[];if(this.fillStyle.p=="gradientradial"){var z=this.fillStyle.n/p*100,B=this.fillStyle.o/p*100-z}else{var z=0,B=100}var C={offset:null,color:null},D={offset:null,color:null};this.fillStyle.h.sort(function(T,U){return T.offset-U.offset});for(var o=0;o<this.fillStyle.h.length;o++){var u=
+this.fillStyle.h[o];y.push(u.offset*B+z,"% ",u.color,",");if(u.offset>C.offset||C.offset==null){C.offset=u.offset;C.color=u.color}if(u.offset<D.offset||D.offset==null){D.offset=u.offset;D.color=u.color}}y.pop();b.push("<g_vml_:fill",' color="',D.color,'"',' color2="',C.color,'"',' type="',this.fillStyle.p,'"',' focusposition="',v.x,", ",v.y,'"',' colors="',y.join(""),'"',' opacity="',e,'" />')}else if(a){b.push('<g_vml_:fill color="',d,'" opacity="',e,'" />')}else{b.push("<g_vml_:stroke",' opacity="',
+e,'"',' joinstyle="',this.lineJoin,'"',' miterlimit="',this.miterLimit,'"',' endcap="',S(this.lineCap),'"',' weight="',this.lineWidth,'px"',' color="',d,'" />')}b.push("</g_vml_:shape>");this.j.insertAdjacentHTML("beforeEnd",b.join(""));this.c=[]};j.fill=function(){this.stroke(true)};j.closePath=function(){this.c.push({type:"close"})};j.b=function(a,b){return{x:m*(a*this.a[0][0]+b*this.a[1][0]+this.a[2][0])-A,y:m*(a*this.a[0][1]+b*this.a[1][1]+this.a[2][1])-A}};j.save=function(){var a={};N(this,a);
+this.k.push(a);this.m.push(this.a);this.a=G(J(),this.a)};j.restore=function(){N(this.k.pop(),this);this.a=this.m.pop()};j.translate=function(a,b){var c=[[1,0,0],[0,1,0],[a,b,1]];this.a=G(c,this.a)};j.rotate=function(a){var b=M(a),c=L(a),d=[[b,c,0],[-c,b,0],[0,0,1]];this.a=G(d,this.a)};j.scale=function(a,b){this.d*=a;this.e*=b;var c=[[a,0,0],[0,b,0],[0,0,1]];this.a=G(c,this.a)};j.clip=function(){};j.arcTo=function(){};j.createPattern=function(){return new P};function H(a){this.p=a;this.n=0;this.o=
+0;this.h=[];this.i={x:0,y:0}}H.prototype.addColorStop=function(a,b){b=O(b);this.h.push({offset:1-a,color:b})};function P(){}G_vmlCanvasManager=Q;CanvasRenderingContext2D=K;CanvasGradient=H;CanvasPattern=P})()};
diff --git a/static/js/mocha.js b/static/js/mocha.js
new file mode 100644 (file)
index 0000000..a4f3751
--- /dev/null
@@ -0,0 +1,3520 @@
+/* 
+
+Script: Core.js
+       MochaUI - A Web Applications User Interface Framework.
+       
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
+       
+License:
+       MIT-style license.
+
+Contributors:
+       - Scott F. Frederick
+       - Joel Lindau
+       
+Note:
+       This documentation is taken directly from the javascript source files. It is built using Natural Docs.
+       
+*/
+
+var MochaUI = new Hash({
+       options: new Hash({
+               useEffects: true,     // Toggles the majority of window fade and move effects.
+               useLoadingIcon: true  // Toggles whether or not the ajax spinners are displayed in window footers.
+
+       }),     
+       Windows: {        
+               instances:      new Hash(),
+               indexLevel:     100,          // Used for z-Index
+               windowIDCount:  0,                // Used for windows without an ID defined by the user
+               windowsVisible: true          // Ctrl-Alt-Q to toggle window visibility         
+       },
+       ieSupport:  'excanvas',   // Makes it easier to switch between Excanvas and Moocanvas for testing
+       focusingWindow: 'false',
+       /*
+       
+       Function: updateContent
+               Replace the content of a window.
+               
+       Arguments:
+               windowEl, content, url
+               
+       */      
+       updateContent: function(windowEl, content, url, element, loadMethod){
+               
+               if (!windowEl) return;          
+               
+               //alert('test');
+               
+               var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
+               var contentEl = currentInstance.contentEl;
+               var options = currentInstance.options;
+               if (element != null){
+                       var contentContainer = element; 
+               }
+               else {
+                       var contentContainer = currentInstance.contentEl;
+               }
+               var canvasIconEl = currentInstance.canvasIconEl;
+               
+               // Remove old content.
+               if (contentContainer == contentEl){
+                       currentInstance.contentEl.empty();
+               }               
+               
+               //alert(loadMethod);
+               var loadMethod = loadMethod ? loadMethod : currentInstance.options.loadMethod;
+
+               // Load new content.
+               switch(loadMethod) {
+                       case 'xhr':
+                               new Request.HTML({
+                                       url: url,
+                                       update: contentContainer,
+                                       evalScripts: options.evalScripts,
+                                       evalResponse: options.evalResponse,
+                                       onRequest: function(){
+                                               if (contentContainer == contentEl){
+                                                       currentInstance.showLoadingIcon(canvasIconEl);
+                                               }
+                                       }.bind(this),
+                                       onFailure: function(){
+                                               if (contentContainer == contentEl){
+                                                       contentContainer.set('html','<p><strong>Error Loading XMLHttpRequest</strong></p>');
+                                                       currentInstance.hideLoadingIcon(canvasIconEl);
+                                               }
+                                       }.bind(this),
+                                       onSuccess: function() {
+                                               if (contentContainer == contentEl){
+                                                       currentInstance.hideLoadingIcon(canvasIconEl);
+                                                       currentInstance.fireEvent('onContentLoaded', windowEl);
+                                               }
+                                       }.bind(this)
+                               }).get();
+                               break;
+                       case 'iframe': // May be able to streamline this if the iframe already exists.
+                               if ( options.contentURL == '' || contentContainer != contentEl) {
+                                       break;
+                               }
+                               currentInstance.iframeEl = new Element('iframe', {
+                                       'id': currentInstance.options.id + '_iframe',
+                                       'name':  currentInstance.options.id + '_iframe',
+                                       'class': 'mochaIframe',
+                                       'src': url,
+                                       'marginwidth':  0,
+                                       'marginheight': 0,
+                                       'frameBorder':  0,
+                                       'scrolling':    'auto',
+                                       'styles': {
+                                               'height': currentInstance.contentWrapperEl.offsetHeight 
+                                       }
+                               }).injectInside(contentEl);
+                               
+                               // Add onload event to iframe so we can stop the loading icon and run onContentLoaded()
+                               currentInstance.iframeEl.addEvent('load', function(e) {
+                                       currentInstance.hideLoadingIcon.delay(150, currentInstance, canvasIconEl);
+                                       currentInstance.fireEvent('onContentLoaded', windowEl);
+                               }.bind(this));
+                               currentInstance.showLoadingIcon(canvasIconEl);
+                               break;
+                       case 'html':
+                       default:
+                               // Need to test injecting elements as content.
+                               var elementTypes = new Array('element', 'textnode', 'whitespace', 'collection');
+                               if (elementTypes.contains($type(content))) {
+                                       content.inject(contentContainer);
+                               } else {
+                                       contentContainer.set('html', content);
+                               }                               
+                               currentInstance.fireEvent('onContentLoaded', windowEl);
+                               break;
+               }
+
+       },
+       collapseToggle: function(windowEl){
+               var instances = MochaUI.Windows.instances;
+               var currentInstance = instances.get(windowEl.id);
+               var handles = currentInstance.windowEl.getElements('.handle');          
+               if (currentInstance.isCollapsed == false) {
+                       currentInstance.isCollapsed = true;
+                       handles.setStyle('display', 'none');
+                       if ( currentInstance.iframe ) {
+                               currentInstance.iframeEl.setStyle('visibility', 'hidden');
+                       }                       
+                       currentInstance.contentBorderEl.setStyles({
+                               visibility: 'hidden',
+                               position: 'absolute',
+                               top: -10000,
+                               left: -10000
+                       });
+                       if(currentInstance.toolbarWrapperEl){
+                               currentInstance.toolbarWrapperEl.setStyles({
+                                       visibility: 'hidden',
+                                       position: 'absolute',
+                                       top: -10000,
+                                       left: -10000
+                               });
+                       }
+                       currentInstance.drawWindowCollapsed(windowEl);
+               }
+               else {                  
+                       currentInstance.isCollapsed = false;
+                       currentInstance.drawWindow(windowEl);                                   
+                       currentInstance.contentBorderEl.setStyles({
+                               visibility: 'visible',
+                               position: null,
+                               top: null,
+                               left: null
+                       });
+                       if(currentInstance.toolbarWrapperEl){
+                               currentInstance.toolbarWrapperEl.setStyles({
+                                       visibility: 'visible',
+                                       position: null,
+                                       top: null,
+                                       left: null
+                               });                             
+                       }
+                       if ( currentInstance.iframe ) {
+                               currentInstance.iframeEl.setStyle('visibility', 'visible');
+                       }
+                       handles.setStyle('display', 'block');                   
+               }               
+       },
+       /*
+       
+       Function: closeWindow
+               Closes a window.
+
+       Syntax:
+       (start code)
+               MochaUI.closeWindow();
+       (end)
+
+       Arguments: 
+               windowEl - the ID of the window to be closed
+               
+       Returns:
+               true - the window was closed
+               false - the window was not closed
+               
+       */
+       closeWindow: function(windowEl){
+               // Does window exist and is not already in process of closing ?         
+
+               var instances = MochaUI.Windows.instances;
+               var currentInstance = instances.get(windowEl.id);
+               if (windowEl != $(windowEl) || currentInstance.isClosing) return;
+                       
+               currentInstance.isClosing = true;
+               currentInstance.fireEvent('onClose', windowEl);
+
+               if (MochaUI.options.useEffects == false){
+                       if (currentInstance.options.type == 'modal'){
+                               $('modalOverlay').setStyle('opacity', 0);
+                               if (Browser.Engine.trident4) {
+                                       $('modalFix').setStyle('display', 'block');
+                               }
+                       }               
+                       this.closingJobs(windowEl);
+                       return true;    
+               }
+               else {
+                       // Redraws IE windows without shadows since IE messes up canvas alpha when you change element opacity
+                       if (Browser.Engine.trident) currentInstance.drawWindow(windowEl, false);
+                       if (currentInstance.options.type == 'modal'){
+                               MochaUI.Modal.modalOverlayCloseMorph.start({
+                                       'opacity': 0
+                               });                             
+                       }
+                       var closeMorph = new Fx.Morph(windowEl, {
+                               duration: 180,
+                               onComplete: function(){                                 
+                                       MochaUI.closingJobs(windowEl);
+                                       return true;                                    
+                               }.bind(this)
+                       });
+                       closeMorph.start({
+                               'opacity': .4
+                       });
+               }
+               
+               if (currentInstance.check) currentInstance.check.destroy();             
+       },
+       closingJobs: function(windowEl){
+
+               windowEl.destroy();
+               var instances = MochaUI.Windows.instances;
+               var currentInstance = instances.get(windowEl.id);
+               currentInstance.fireEvent('onCloseComplete');
+               
+               if (this.options.type != 'modal' && this.options.type != 'notification') {
+                       var newFocus = this.getWindowWithHighestZindex();
+                       this.focusWindow(newFocus);
+               }
+                                       
+               instances.erase(currentInstance.options.id);
+               if (this.loadingWorkspace == true) {
+                       this.windowUnload();
+               }
+               
+               if (MochaUI.Dock && $(MochaUI.options.dock) && currentInstance.options.type == 'window') {
+                       currentButton = $(currentInstance.options.id + '_dockTab');
+                       MochaUI.Dock.dockSortables.removeItems(currentButton).destroy();
+                       // Need to resize everything in case the dock becomes smaller when a tab is removed
+                       MochaUI.Desktop.setDesktopSize();
+               }
+       },      
+       /*
+       
+       Function: closeAll      
+               Close all open windows.
+
+       */
+       closeAll: function() {          
+               $$('div.mocha').each(function(windowEl){
+                       this.closeWindow(windowEl);                     
+               }.bind(this));
+       },
+       /*
+       
+       Function: toggleWindowVisibility
+               Toggle window visibility with Ctrl-Alt-Q.
+       
+       */      
+       toggleWindowVisibility: function(){             
+               MochaUI.Windows.instances.each(function(instance){
+                       if (instance.options.type == 'modal' || instance.isMinimized == true) return;                                                                   
+                       var id = $(instance.options.id);                                                                        
+                       if (id.getStyle('visibility') == 'visible'){
+                               if (instance.iframe){
+                                       instance.iframeEl.setStyle('visibility', 'hidden');
+                               }
+                               if (instance.toolbarEl){
+                                       instance.toolbarWrapperEl.setStyle('visibility', 'hidden');             
+                               }
+                               instance.contentBorderEl.setStyle('visibility', 'hidden');                              
+                               id.setStyle('visibility', 'hidden');                            
+                               MochaUI.Windows.windowsVisible = false;
+                       }
+                       else {
+                               id.setStyle('visibility', 'visible');
+                               instance.contentBorderEl.setStyle('visibility', 'visible');
+                               if (instance.iframe){
+                                       instance.iframeEl.setStyle('visibility', 'visible');
+                               }
+                               if (instance.toolbarEl){
+                                       instance.toolbarWrapperEl.setStyle('visibility', 'visible');            
+                               }                               
+                               MochaUI.Windows.windowsVisible = true;
+                       }
+               }.bind(this));
+
+       },      
+       focusWindow: function(windowEl, fireEvent){
+
+               // This is used with blurAll
+               MochaUI.focusingWindow = 'true';
+               var windowClicked = function(){
+                       MochaUI.focusingWindow = 'false';
+               }               
+               windowClicked.delay(170, this);
+
+               // Only focus when needed                               
+               if (windowEl != $(windowEl) || windowEl.hasClass('isFocused')) return;          
+
+               var instances =  MochaUI.Windows.instances;             
+               var currentInstance = instances.get(windowEl.id);                       
+
+               MochaUI.Windows.indexLevel++;
+               windowEl.setStyle('zIndex', MochaUI.Windows.indexLevel);
+
+               // Fire onBlur for the window that lost focus.
+               instances.each(function(instance){
+                       if (instance.windowEl.hasClass('isFocused')){
+                               instance.fireEvent('onBlur', instance.windowEl);
+                       }
+                       instance.windowEl.removeClass('isFocused');                     
+               });
+               
+               if (MochaUI.Dock && $(MochaUI.options.dock) && currentInstance.options.type == 'window') {
+                       MochaUI.Dock.makeActiveTab();
+               }
+               currentInstance.windowEl.addClass('isFocused');
+               
+               if (fireEvent != false){
+                       currentInstance.fireEvent('onFocus', windowEl);
+               }               
+       
+       },
+       getWindowWithHighestZindex: function(){
+               this.highestZindex = 0;
+               $$('div.mocha').each(function(element){
+                       this.zIndex = element.getStyle('zIndex');
+                       if (this.zIndex >= this.highestZindex) {
+                               this.highestZindex = this.zIndex;
+                       }       
+               }.bind(this));
+               $$('div.mocha').each(function(element){                 
+                       if (element.getStyle('zIndex') == this.highestZindex) {
+                               this.windowWithHighestZindex = element;
+                       }       
+               }.bind(this));
+               return this.windowWithHighestZindex;
+       },
+       blurAll: function(){
+               //alert(MochaUI.focusingWindow);
+               if (MochaUI.focusingWindow == 'false') {
+                       $$('.mocha').each(function(windowEl){
+                               var instances =  MochaUI.Windows.instances;
+                               var currentInstance = instances.get(windowEl.id);
+                               windowEl.removeClass('isFocused');                              
+                       });
+                       $$('div.dockTab').removeClass('activeDockTab');
+               }
+       },      
+       roundedRect: function(ctx, x, y, width, height, radius, rgb, a){
+               ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';
+               ctx.beginPath();
+               ctx.moveTo(x, y + radius);
+               ctx.lineTo(x, y + height - radius);
+               ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
+               ctx.lineTo(x + width - radius, y + height);
+               ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
+               ctx.lineTo(x + width, y + radius);
+               ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
+               ctx.lineTo(x + radius, y);
+               ctx.quadraticCurveTo(x, y, x, y + radius);
+               ctx.fill(); 
+       },      
+       triangle: function(ctx, x, y, width, height, rgb, a){
+               ctx.beginPath();
+               ctx.moveTo(x + width, y);
+               ctx.lineTo(x, y + height);
+               ctx.lineTo(x + width, y + height);
+               ctx.closePath();
+               ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';
+               ctx.fill();
+       },      
+       circle: function(ctx, x, y, diameter, rgb, a){
+               ctx.beginPath();
+               ctx.moveTo(x, y);
+               ctx.arc(x, y, diameter, 0, Math.PI*2, true);
+               ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';
+               ctx.fill();
+       },
+       /*
+       
+       Function: centerWindow
+               Center a window in it's container. If windowEl is undefined it will center the window that has focus.
+               
+       */      
+       centerWindow: function(windowEl){
+               
+               if(!windowEl){
+                       MochaUI.Windows.instances.each(function(instance){
+                               if (instance.windowEl.hasClass('isFocused')){
+                                       windowEl = instance.windowEl;
+                               }                               
+                       });             
+               }
+               
+               var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
+               var options = currentInstance.options;
+               var dimensions = options.container.getCoordinates();
+               var windowPosTop = (dimensions.height * .5) - ((options.height + currentInstance.headerFooterShadow) * .5);
+               var windowPosLeft =     (dimensions.width * .5) - (options.width * .5);
+               
+               if (MochaUI.options.useEffects == true){
+                       currentInstance.morph.start({
+                               'top': windowPosTop,
+                               'left': windowPosLeft
+                       });
+               }
+               else {
+                       windowEl.setStyles({
+                               'top': windowPosTop,
+                               'left': windowPosLeft
+                       });
+               }
+       },
+       /*
+       
+       Function: dynamicResize
+               Use with a timer to resize a window as the window's content size changes, such as with an accordian.
+               
+       */              
+       dynamicResize: function(windowEl){
+               var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
+               var contentWrapperEl = currentInstance.contentWrapperEl;
+               var contentEl = currentInstance.contentEl;
+               
+               contentWrapperEl.setStyle('height', contentEl.offsetHeight);
+               contentWrapperEl.setStyle('width', contentEl.offsetWidth);                      
+               currentInstance.drawWindow(windowEl);
+       },      
+       /*
+       
+       Function: garbageCleanUp
+               Empties all windows of their children, and removes and garbages the windows. It is does not trigger onClose() or onCloseComplete(). This is useful to clear memory before the pageUnload.
+               
+       Syntax:
+       (start code)
+               MochaUI.garbageCleanUp();
+       (end)
+       
+       */      
+       garbageCleanUp: function(){
+               $$('div.mocha').each(function(el){
+                       el.destroy();
+               }.bind(this));          
+       }       
+});
+
+// Toggle window visibility with Ctrl-Alt-Q
+document.addEvent('keydown', function(event){                                                   
+       if (event.key == 'q' && event.control && event.alt) {
+               MochaUI.toggleWindowVisibility();
+       }
+});
+
+// Blur all windows if user clicks anywhere else on the page
+document.addEvent('click', function(event){
+       MochaUI.blurAll.delay(50);      
+});
+/*
+
+Script: Window.js
+       Build windows.
+       
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.  
+
+License:
+       MIT-style license.      
+
+Requires:
+       Core.js
+
+*/
+   
+/*
+Class: Window
+       Creates a single MochaUI window.
+       
+Syntax:
+       (start code)
+       new MochaUI.Window(options);
+       (end)   
+
+Arguments:
+       options
+
+Options:
+       id - The ID of the window. If not defined, it will be set to 'win' + windowIDCount.     
+       title - The title of the window.
+       type - ('window', 'modal' or 'notification') Defaults to 'window'.      
+       loadMethod - ('html', 'xhr', or 'iframe') Defaults to 'html'.
+       contentURL - Used if loadMethod is set to 'xhr' or 'iframe'.
+       evalScripts - (boolean) An xhr loadMethod option. Defaults to true.    
+       evalResponse - (boolean) An xhr loadMethod option. Defaults to false.
+       content - (string or element) An html loadMethod option.
+       toolbar - (boolean) Create window toolbar. Defaults to false. This can be used for tabs, media controls, and so forth.
+       toolbarPosition - ('top' or 'bottom') Defaults to top.
+       toolbarHeight - (number)
+       toolbarURL - (url) Defaults to 'pages/lipsum.html'.     
+       toolbarContent - (string)       
+       container - (element ID) Element the window is injected in. The container defaults to 'desktop'. If no desktop then to document.body. Use 'pageWrapper' if you don't want the windows to overlap the toolbars.
+       restrict - (boolean) Restrict window to container when dragging.
+       shape - ('box' or 'gauge') Shape of window. Defaults to 'box'.
+       collapsible - (boolean) Defaults to true.
+       minimizable - (boolean) Requires MochaUI.Desktop and MochaUI.Dock. Defaults to true if dependenices are met. 
+       maximizable - (boolean) Requires MochaUI.Desktop. Defaults to true if dependenices are met.
+       closable - (boolean) Defaults to true. 
+       draggable - (boolean) Defaults to false for modals; otherwise true.
+       draggableGrid - (false or number) Distance in pixels for snap-to-grid dragging. Defaults to false. 
+       draggableLimit - (false or number) An object with x and y properties used to limit the movement of the Window. Defaults to false.       
+       draggableSnap - (boolean) The distance to drag before the Window starts to respond to the drag. Defaults to false.
+       resizable - (boolean) Defaults to false for modals, notifications and gauges; otherwise true.
+       resizeLimit - (object) Minimum and maximum width and height of window when resized.
+       addClass - (string) Add a class to your window to give you more control over styling.   
+       width - (number) Width of content area. 
+       height - (number) Height of content area.
+       x - (number) If x and y are left undefined the window is centered on the page.
+       y - (number)    
+       scrollbars - (boolean)
+       padding - (object)
+       shadowBlur -(number) Width of shadows.          
+       headerHeight - (number) Height of window titlebar.
+       footerHeight - (number) Height of window footer.
+       cornerRadius - (number)
+       contentBgColor - (hex) Body background color
+       headerStartColor - ([r,g,b,]) Titlebar gradient's top color
+       headerStopColor - ([r,g,b,]) Titlebar gradient's bottom color
+       bodyBgColor - ([r,g,b,]) Background color of the main canvas shape
+       minimizeBgColor - ([r,g,b,]) Minimize button background color
+       minimizeColor - ([r,g,b,]) Minimize button color        
+       maximizeBgColor - ([r,g,b,]) Maximize button background color
+       maximizeColor - ([r,g,b,]) Maximize button color        
+       closeBgColor - ([r,g,b,]) Close button background color
+       closeColor - ([r,g,b,]) Close button color      
+       resizableColor - ([r,g,b,]) Resizable icon color
+       onBeforeBuild - (function) Fired just before the window is built.
+       onContentLoaded - (function) Fired when content is successfully loaded via XHR or Iframe.
+       onFocus - (function)  Fired when the window is focused.
+       onBlur - (function) Fired when window loses focus.
+       onResize - (function) Fired when the window is resized.
+       onMinimize - (function) Fired when the window is minimized.
+       onMaximize - (function) Fired when the window is maximized.
+       onRestore - (function) Fired when a window is restored from minimized or maximized.
+       onClose - (function) Fired just before the window is closed.
+       onCloseComplete - (function) Fired after the window is closed.
+
+Returns:
+       Window object.
+       
+Example:
+       Define a window. It is suggested you name the function the same as your window ID + "Window".
+       (start code)
+       var mywindowWindow = function(){ 
+               new MochaUI.Window({
+                       id: 'mywindow',
+                       title: 'My Window',
+                       loadMethod: 'xhr',
+                       contentURL: 'pages/lipsum.html',
+                       width: 340,
+                       height: 150
+               });
+       }
+       (end)
+       
+Example:
+       Create window onDomReady.
+       (start code)    
+       window.addEvent('domready', function(){
+               mywindow();
+       });
+       (end)
+       
+Example:       
+       Add link events to build future windows. It is suggested you give your anchor the same ID as your window + "WindowLink" or + "WindowLinkCheck". Use the latter if it is a link in the menu toolbar.
+       
+       If you wish to add links in windows that open other windows remember to add events to those links when the windows are created. 
+       
+       (start code)    
+       // Javascript:
+       if ($('mywindowLink')){
+               $('mywindowLink').addEvent('click', function(e) {
+                       new Event(e).stop();
+                       mywindow();                     
+               });
+       }
+       
+       // HTML:
+       <a id="mywindowLink" href="pages/lipsum.html">My Window</a>     
+       (end)
+       
+
+       Loading Content with an XMLHttpRequest(xhr):
+               For content to load via xhr all the files must be online and in the same domain. If you need to load content from another domain or wish to have it work offline, load the content in an iframe instead of using the xhr option.
+       
+       Iframes:
+               If you use the iframe loadMethod your iframe will automatically be resized when the window it is in is resized. If you want this same functionality when using one of the other load options simply add class="mochaIframe" to those iframes and they will be resized for you as well.
+
+*/   
+
+// Having these options outside of the Class allows us to add, change, and remove
+// individual options without rewriting all of them.
+
+MochaUI.Windows.windowOptions = {
+       id:                null,
+       title:             'New Window',
+       icon:              false,
+       type:              'window',
+       
+       loadMethod:        'html',
+       contentURL:        'pages/lipsum.html',
+       
+       closeAfter:        false, // Close the window after a certain period of time in milliseconds. This is particularly useful for notifications.
+               
+       // xhr options
+       evalScripts:       true,
+       evalResponse:      false,
+       
+       // html options
+       content:           'Window content',
+       
+       // Toolbar
+       toolbar:           false, 
+       toolbarPosition:   'top',
+       toolbarHeight:     29,
+       toolbarURL:        'pages/lipsum.html', 
+       toolbarContent:    '',
+       
+       // Container options
+       container:         null,
+       restrict:          true,
+       shape:             'box',
+       
+       // Window Controls
+       collapsible:       true,
+       minimizable:       true,
+       maximizable:       true,
+       closable:          true,  
+
+       // Draggable
+       draggable:         null,
+       draggableGrid:     false,
+       draggableLimit:    false,
+       draggableSnap:     false,
+
+       // Resizable
+       resizable:         null,
+       resizeLimit:       {'x': [250, 2500], 'y': [125, 2000]},
+       
+       // Style options:
+       addClass:          '',
+       width:             300,
+       height:            125, 
+       x:                 null,
+       y:                 null,    
+       scrollbars:        true,
+       padding:                   { top: 10, right: 12, bottom: 10, left: 12 },
+       shadowBlur:        5,
+       shadowOffset:      {'x': 0, 'y': 1},       // Should be positive and not be greater than the ShadowBlur.
+       controlsOffset:    {'right': 6, 'top': 6}, // Change this if you want to reposition the window controls.
+       useCanvasControls: true,                   // Set this to false if you wish to use images for the buttons.
+       
+       // Color options:               
+       headerHeight:      25,
+       footerHeight:      25,
+       cornerRadius:      10,
+       contentBgColor:    '#fff',
+       headerStartColor:  [250, 250, 250],
+       headerStopColor:   [229, 229, 229],
+       bodyBgColor:       [229, 229, 229],
+       minimizeBgColor:   [255, 255, 255],
+       minimizeColor:     [0, 0, 0],
+       maximizeBgColor:   [255, 255, 255],
+       maximizeColor:     [0, 0, 0],
+       closeBgColor:      [255, 255, 255],
+       closeColor:        [0, 0, 0],
+       resizableColor:    [254, 254, 254],
+
+       // Events
+       onBeforeBuild:     $empty,
+       onContentLoaded:   $empty,
+       onFocus:           $empty,
+       onBlur:            $empty,
+       onResize:          $empty,
+       onMinimize:        $empty,
+       onMaximize:        $empty,
+       onRestore:         $empty,
+       onMove:            $empty, // NOT YET IMPLEMENTED
+       onClose:           $empty,
+       onCloseComplete:   $empty
+};
+
+MochaUI.Window = new Class({
+       options: MochaUI.Windows.windowOptions,
+       initialize: function(options){
+               this.setOptions(options);
+
+               // Shorten object chain
+               var options = this.options;
+
+               $extend(this, {         
+                       accordianTimer: '', // Used with accordian - should go somewhere else maybe?
+                       mochaControlsWidth: 0,
+                       minimizebuttonX:  0,  // Minimize button horizontal position
+                       maximizebuttonX: 0,  // Maximize button horizontal position
+                       closebuttonX: 0,  // Close button horizontal position
+                       headerFooterShadow: options.headerHeight + options.footerHeight + (options.shadowBlur * 2),
+                       oldTop: 0,
+                       oldLeft: 0,
+                       iframe: options.loadMethod == 'iframe' ? true : false,
+                       isMaximized: false,
+                       isMinimized: false,
+                       isCollapsed: false,
+                       timestamp: $time()
+               });
+               
+               // May be better to use if type != window
+               if (options.type == 'modal' || options.type == 'notification'){
+                       options.container = document.body;
+                       options.minimizable = false;                     
+               }               
+               if (!options.container){
+                       options.container = MochaUI.Desktop.desktop ? MochaUI.Desktop.desktop : document.body;                   
+               }
+
+               // Set this.options.resizable to default if it was not defined
+               if (options.resizable == null){
+                       if (options.type == 'modal' || options.shape == 'gauge' || options.type == 'notification'){
+                               options.resizable = false;
+                       }
+                       else {
+                               options.resizable = true;       
+                       }
+               }
+               
+               // Set this.options.draggable if it was not defined
+               if (options.draggable == null){
+                       if (options.type == 'modal' || options.type == 'notification'){
+                               options.draggable = false;
+                       }
+                       else {
+                               options.draggable = true;       
+                       }
+               }               
+               
+               // Gauges are not maximizable or resizable
+               if (options.shape == 'gauge' || options.type == 'notification'){
+                       options.collapsible = false;
+                       options.maximizable = false;
+                       options.contentBgColor = 'transparent';
+                       options.scrollbars = false;
+                       options.footerHeight = 0;                       
+               }
+               if (options.type == 'notification'){
+                       options.closable = false;
+                       options.headerHeight = 0;
+               }
+               
+               // Minimizable, dock is required and window cannot be modal
+               if (MochaUI.Dock){
+                       if (MochaUI.Dock.dock && options.type != 'modal'){
+                               options.minimizable = options.minimizable;
+                       }
+               }
+               else {
+                       options.minimizable = false;                    
+               }
+
+               // Maximizable, desktop is required
+               options.maximizable = MochaUI.Desktop.desktop && options.maximizable && options.type != 'modal';
+               
+               // If window has no ID, give it one.
+               if (options.id == null){
+                       options.id = 'win' + (++MochaUI.Windows.windowIDCount);         
+               }
+               this.windowEl = $(options.id);
+               
+               this.newWindow();
+               
+               // Return window object
+               return this;
+       },
+       saveValues: function(){ 
+               var coordinates = this.windowEl.getCoordinates();
+               this.options.x = coordinates.left.toInt();
+               this.options.y = coordinates.top.toInt();       
+       },      
+       /*
+       
+       Internal Function: newWindow
+       
+       Arguments: 
+               properties
+
+       */      
+       newWindow: function(properties){ // options is not doing anything
+
+               // Shorten object chain
+               var instances = MochaUI.Windows.instances;
+               var instanceID = instances.get(this.options.id);
+       
+               // Here we check to see if there is already a class instance for this window
+               if (instanceID){                        
+                       var currentInstance = instanceID;               
+               }
+               
+               // Check if window already exists and is not in progress of closing
+               if ( this.windowEl && !this.isClosing ) {
+                        // Restore if minimized
+                       if (currentInstance.isMinimized) {
+                               MochaUI.Dock.restoreMinimized(this.windowEl);
+                       }
+                       // Expand and focus if collapsed                        
+                       if (currentInstance.isCollapsed) {
+                               MochaUI.collapseToggle(this.windowEl);
+                               setTimeout(MochaUI.focusWindow.pass(this.windowEl, this),10);                                   
+                       }                       
+                       // Else focus
+                       else {
+                               setTimeout(MochaUI.focusWindow.pass(this.windowEl, this),10);   
+                       }
+                       return;
+               }
+               else {                  
+                       instances.set(this.options.id, this);
+               }
+               
+               this.isClosing = false;         
+               this.fireEvent('onBeforeBuild');                
+               
+               // Create window div
+               MochaUI.Windows.indexLevel++;           
+               this.windowEl = new Element('div', {
+                       'class': 'mocha',
+                       'id':    this.options.id,
+                       'styles': {
+                               'width':   this.options.width,
+                               'height':  this.options.height,
+                               'display': 'block',
+                               'opacity': 0,
+                               'zIndex': MochaUI.Windows.indexLevel
+                       }
+               });             
+
+               this.windowEl.addClass(this.options.addClass);
+               
+               // Fix a mouseover issue with gauges in IE7
+               if ( Browser.Engine.trident && this.options.shape == 'gauge') {
+                       this.windowEl.setStyle('background', 'url(../images/spacer.gif)');
+               }               
+
+               if ((this.options.type == 'modal' && !Browser.Engine.gecko && !Browser.Engine.trident) || (Browser.Platform.mac && Browser.Engine.gecko)){
+                       this.windowEl.setStyle('position', 'fixed');    
+               }
+
+               if (this.options.loadMethod == 'iframe') {
+                       // Iframes have their own scrollbars and padding.
+                       this.options.scrollbars = false;
+                       this.options.padding = { top: 0, right: 0, bottom: 0, left: 0 };
+               }
+               
+               // Insert sub elements inside windowEl
+               this.insertWindowElements();
+                               
+               // Set title            
+               this.titleEl.set('html',this.options.title);
+
+               // Set scrollbars, always use 'hidden' for iframe windows
+               this.contentWrapperEl.setStyles({
+                       'overflow': this.options.scrollbars && !this.options.iframe ? 'auto' : 'hidden',
+                       'background': this.options.contentBgColor
+               });
+
+               this.contentEl.setStyles({
+                       'padding-top': this.options.padding.top,
+                       'padding-bottom': this.options.padding.bottom,
+                       'padding-left': this.options.padding.left,
+                       'padding-right': this.options.padding.right
+               });             
+               
+               
+               if (this.options.shape == 'gauge'){
+                       if (this.options.useCanvasControls){
+                               this.canvasControlsEl.setStyle('display', 'none');
+                       }
+                       else {
+                               this.controlsEl.setStyle('display', 'none');                    
+                       }
+                       this.windowEl.addEvent('mouseover', function(){
+                               this.mouseover = true;                                                                           
+                               var showControls = function(){
+                                       if (this.mouseover != false){
+                                               if (this.options.useCanvasControls){
+                                                       this.canvasControlsEl.setStyle('display', 'block');
+                                               }
+                                               else {
+                                                       this.controlsEl.setStyle('display', 'block');                   
+                                               }                                               
+                                               this.canvasHeaderEl.setStyle('display', 'block');
+                                               this.titleEl.setStyle('display', 'block');                                                      
+                                       }
+                               };
+                               showControls.delay(150, this);
+                               
+                       }.bind(this));
+                       this.windowEl.addEvent('mouseleave', function(){
+                               this.mouseover = false;
+                               if (this.options.useCanvasControls){
+                                       this.canvasControlsEl.setStyle('display', 'none');
+                               }
+                               else {
+                                       this.controlsEl.setStyle('display', 'none');                    
+                               }                               
+                               this.canvasHeaderEl.setStyle('display', 'none');
+                               this.titleEl.setStyle('display', 'none');                               
+                       }.bind(this));                  
+               }
+
+               // Inject window into DOM               
+               this.windowEl.injectInside(this.options.container);
+               
+               if (this.options.type != 'notification'){
+                       this.setMochaControlsWidth();
+               }               
+
+               // Add content to window.
+               MochaUI.updateContent(this.windowEl, this.options.content, this.options.contentURL);    
+               
+               // Add content to window toolbar.
+               if (this.options.toolbar == true){
+      /* SLUG */
+                       //MochaUI.updateContent(this.windowEl, this.options.toolbarContent, this.options.toolbarURL, this.toolbarEl, 'xhr');
+      MochaUI.updateContent(this.windowEl, this.options.toolbarContent, this.options.toolbarURL, this.toolbarEl, this.options.toolbarContent==undefined?'xhr':'html');
+               }
+               
+               this.drawWindow(this.windowEl);                 
+               
+               // Attach events to the window
+               this.attachDraggable(this.windowEl);            
+               this.attachResizable(this.windowEl);
+               this.setupEvents(this.windowEl);
+               
+               if (this.options.resizable){
+                       this.adjustHandles();
+               }
+
+               // Move window into position. If position not specified by user then center the window on the page.             
+               if (this.options.container == document.body || this.options.container == MochaUI.Desktop.desktop){
+                       var dimensions = window.getSize();
+               }
+               else {
+                       var dimensions = $(this.options.container).getSize();                   
+               }
+
+               if (!this.options.y) {
+                       var y = (dimensions.y * .5) - ((this.options.height + this.headerFooterShadow) * .5);
+               }
+               else {
+                       var y = this.options.y - this.options.shadowBlur;
+               }
+
+               if (!this.options.x) {
+                       var x = (dimensions.x * .5) - (this.options.width * .5);
+               }
+               else {
+                       var x = this.options.x - this.options.shadowBlur;
+               }
+
+               this.windowEl.setStyles({
+                       'top': y,
+                       'left': x
+               });
+               
+               // Create opacityMorph
+               if (MochaUI.options.useEffects == true){
+                       // IE cannot handle both element opacity and VML alpha at the same time.
+                       if (Browser.Engine.trident){
+                               this.drawWindow(this.windowEl, false);
+                       }
+                       this.opacityMorph = new Fx.Morph(this.windowEl, {
+                               'duration': 500,
+                               onComplete: function(){
+                                       if (Browser.Engine.trident){
+                                               this.drawWindow(this.windowEl);
+                                       }
+                               }.bind(this)
+                       });
+               }
+
+               if (this.options.type == 'modal') {
+                       if (Browser.Engine.trident4){
+                               $('modalFix').setStyle('display', 'block');     
+                       }
+                       $('modalOverlay').setStyle('display', 'block');                 
+                       if (MochaUI.options.useEffects == false){                       
+                               $('modalOverlay').setStyle('opacity', .55);
+                               this.windowEl.setStyles({
+                                       'zIndex': 11000,
+                                       'opacity': 1
+                               });                     
+                       }
+                       else {
+                               MochaUI.Modal.modalOverlayCloseMorph.cancel();
+                               MochaUI.Modal.modalOverlayOpenMorph.start({
+                                       'opacity': .55
+                               });
+                               this.windowEl.setStyles({
+                                       'zIndex': 11000
+                               });                             
+                               this.opacityMorph.start({
+                                       'opacity': 1
+                               });                             
+                       }
+
+                       $$('.dockTab').removeClass('activeDockTab');                    
+                       $$('.mocha').removeClass('isFocused');
+                       this.windowEl.addClass('isFocused');
+                       
+               }
+               else if (MochaUI.options.useEffects == false){
+                       this.windowEl.setStyle('opacity', 1);
+                       setTimeout(MochaUI.focusWindow.pass(this.windowEl, this), 10);                  
+               }
+               else {
+                       this.opacityMorph.start({
+                               'opacity': 1
+                       });
+                       setTimeout(MochaUI.focusWindow.pass(this.windowEl, this), 10);
+               }
+
+               // This is a generic morph that can be reused later by functions like centerWindow()
+               this.morph = new Fx.Morph(this.windowEl, {
+                       'duration': 200
+               });
+
+               // Add check mark to menu if link exists in menu
+               // Need to make sure the check mark is not added to links not in menu           
+       
+               if ($(this.windowEl.id + 'LinkCheck')){
+                       this.check = new Element('div', {
+                               'class': 'check',
+                               'id': this.options.id + '_check'
+                       }).injectInside(this.windowEl.id + 'LinkCheck');
+               }
+               
+               if (this.options.closeAfter != false){                  
+                       MochaUI.closeWindow.delay(this.options.closeAfter, this, this.windowEl);        
+               }
+
+               if (MochaUI.Dock && $(MochaUI.options.dock) && this.options.type == 'window' ) {
+                       MochaUI.Dock.createDockTab(this.windowEl);
+               }
+
+       },
+       setupEvents: function(windowEl) {
+
+               // Set events
+               // Note: if a button does not exist, its due to properties passed to newWindow() stating otherwice
+               if (this.closeButtonEl){
+                       this.closeButtonEl.addEvent('click', function(e) {
+                               new Event(e).stop();
+                               MochaUI.closeWindow(windowEl);
+                       }.bind(this));
+               }
+
+               if (this.options.type == 'window'){             
+                       windowEl.addEvent('click', function() {
+                               MochaUI.focusWindow(windowEl);
+                       }.bind(this));
+               }
+
+               if (this.minimizeButtonEl) {
+                       this.minimizeButtonEl.addEvent('click', function(e) {
+                               new Event(e).stop();
+                               MochaUI.Dock.minimizeWindow(windowEl);
+               }.bind(this));
+               }
+
+               if (this.maximizeButtonEl) {
+                       this.maximizeButtonEl.addEvent('click', function(e) {
+                               new Event(e).stop(); 
+                               if (this.isMaximized) {
+                                       MochaUI.Desktop.restoreWindow(windowEl);                                        
+                               } else {
+                                       MochaUI.Desktop.maximizeWindow(windowEl);                                       
+                               }
+                       }.bind(this));                  
+               }
+               
+               if (this.options.collapsible == true){
+                       // Keep titlebar text from being selected on double click in Safari.
+                       this.titleEl.addEvent('selectstart', function(e) {
+                               e = new Event(e).stop();                                                                                                                                                                   
+                       }.bind(this));
+                       // Keep titlebar text from being selected on double click in Opera.                     
+                       this.titleBarEl.addEvent('mousedown', function(e) {
+                               e = new Event(e).stop();                                                                                                                                                                   
+                       }.bind(this));          
+                       this.titleBarEl.addEvent('dblclick', function(e) {
+                               e = new Event(e).stop();
+                               MochaUI.collapseToggle(this.windowEl);
+                       }.bind(this));                  
+               }               
+               
+       },
+       /*
+       
+       Internal Function: attachDraggable()
+               Make window draggable.
+               
+       Arguments:
+               windowEl
+               
+       */
+       attachDraggable: function(windowEl){
+               if (!this.options.draggable) return;
+               this.windowDrag = new Drag.Move(windowEl, {
+                       handle: this.titleBarEl,
+                       container: this.options.restrict == true ? $(this.options.container) : false,                   
+                       grid: this.options.draggableGrid,
+                       limit: this.options.draggableLimit,
+                       snap: this.options.draggableSnap,
+                       onStart: function() {
+                               if (this.options.type != 'modal'){ 
+                                       MochaUI.focusWindow(windowEl);
+                               }
+                               if ( this.iframe )
+                                       this.iframeEl.setStyle('visibility', 'hidden');
+                       }.bind(this),
+                       onComplete: function() {
+                               if ( this.iframe ){
+                                       this.iframeEl.setStyle('visibility', 'visible');
+                               }
+                               // Store new position in options.
+                               this.saveValues();
+                       }.bind(this)
+               });
+       },
+       /*
+       
+       Internal Function: attachResizable
+               Make window resizable.
+               
+       Arguments:
+               windowEl
+               
+       */
+       attachResizable: function(windowEl){
+               if (!this.options.resizable) return;    
+               this.windowEl.makeResizable({
+                       handle: [this.n, this.ne, this.nw],
+                       limit: {
+                               y: [
+                                       function(){
+                                               return this.windowEl.getStyle('top').toInt() + this.windowEl.getStyle('height').toInt() - this.options.resizeLimit.y[1];
+                                       }.bind(this),
+                                  function(){
+                                          return this.windowEl.getStyle('top').toInt() + this.windowEl.getStyle('height').toInt() - this.options.resizeLimit.y[0];
+                                       }.bind(this)
+                               ]
+                       },      
+                       modifiers: {x: false, y: 'top'},
+                       onBeforeStart: function(){
+                               this.resizeOnBeforeStart();
+                       }.bind(this),           
+                       onStart: function(){
+                               this.coords = this.contentWrapperEl.getCoordinates();                   
+                               this.y2 = this.coords.top.toInt() + this.contentWrapperEl.offsetHeight;
+                       }.bind(this),
+                       onDrag: function(){
+                               this.coords = this.contentWrapperEl.getCoordinates();
+                               this.contentWrapperEl.setStyle('height', this.y2 - this.coords.top.toInt());
+                               this.drawWindow(windowEl);
+                               this.adjustHandles();
+                       }.bind(this),
+                       onComplete: function(){
+                               this.resizeOnComplete();
+                       }.bind(this)            
+               });
+       
+               this.contentWrapperEl.makeResizable({
+                       handle: [this.e, this.ne],
+                       limit: {
+                               x: [this.options.resizeLimit.x[0] - (this.options.shadowBlur * 2), this.options.resizeLimit.x[1] - (this.options.shadowBlur * 2) ]              
+                       },      
+                       modifiers: {x: 'width', y: false},
+                       onBeforeStart: function(){
+                               this.resizeOnBeforeStart();
+                       }.bind(this),           
+                       onDrag: function(){
+                               this.drawWindow(windowEl);
+                               this.adjustHandles();
+                       }.bind(this),
+                       onComplete: function(){
+                               this.resizeOnComplete();
+                       }.bind(this)    
+               });     
+       
+               this.contentWrapperEl.makeResizable({
+                       container: this.options.restrict == true ? $(this.options.container) : false,                                                                                   
+                       handle: this.se,
+                       limit: {
+                               x: [this.options.resizeLimit.x[0] - (this.options.shadowBlur * 2), this.options.resizeLimit.x[1] - (this.options.shadowBlur * 2) ],
+                               y: [this.options.resizeLimit.y[0] - this.headerFooterShadow, this.options.resizeLimit.y[1] - this.headerFooterShadow]                                   
+                       },      
+                       modifiers: {x: 'width', y: 'height'},
+                       onBeforeStart: function(){
+                               this.resizeOnBeforeStart();
+                       }.bind(this),           
+                       onDrag: function(){
+                               this.drawWindow(windowEl);      
+                               this.adjustHandles();
+                       }.bind(this),
+                       onComplete: function(){
+                               this.resizeOnComplete();
+                       }.bind(this)    
+               });             
+               
+               this.contentWrapperEl.makeResizable({
+                       handle: [this.s, this.sw],
+                       limit: {
+                               y: [this.options.resizeLimit.y[0] - this.headerFooterShadow, this.options.resizeLimit.y[1] - this.headerFooterShadow]   
+                       },      
+                       modifiers: {x: false, y: 'height'},
+                       onBeforeStart: function(){
+                               this.resizeOnBeforeStart();
+                       }.bind(this),           
+                       onDrag: function(){
+                               this.drawWindow(windowEl);                      
+                               this.adjustHandles();
+                       }.bind(this),
+                       onComplete: function(){
+                               this.resizeOnComplete();
+                       }.bind(this)    
+               });
+               
+               this.windowEl.makeResizable({
+                       handle: [this.w, this.sw, this.nw],
+                       limit: {
+                               x: [
+                                       function(){
+                                               return this.windowEl.getStyle('left').toInt() + this.windowEl.getStyle('width').toInt() - this.options.resizeLimit.x[1];
+                                       }.bind(this),
+                                  function(){
+                                          return this.windowEl.getStyle('left').toInt() + this.windowEl.getStyle('width').toInt() - this.options.resizeLimit.x[0];
+                                       }.bind(this)
+                               ]
+                       },      
+                       modifiers: {x: 'left', y: false},
+                       onBeforeStart: function(){
+                               this.resizeOnBeforeStart();
+                       }.bind(this),           
+                       onStart: function(){
+                               this.coords = this.contentWrapperEl.getCoordinates();                   
+                               this.x2 = this.coords.left.toInt() + this.contentWrapperEl.offsetWidth;
+                       }.bind(this),
+                       onDrag: function(){
+                               this.coords = this.contentWrapperEl.getCoordinates();
+                               this.contentWrapperEl.setStyle('width', this.x2 - this.coords.left.toInt());
+                               this.drawWindow(windowEl);
+                               this.adjustHandles();
+                       }.bind(this),
+                       onComplete: function(){
+                               this.resizeOnComplete();
+                       }.bind(this)
+               });
+       
+       },
+       resizeOnBeforeStart: function(){
+               if (this.iframeEl){
+                       this.iframeEl.setStyle('visibility', 'hidden');
+               }       
+       },      
+       resizeOnComplete: function(){
+               if (this.iframeEl){
+                       this.iframeEl.setStyle('visibility', 'visible');
+               }
+               this.fireEvent('onResize', this.windowEl);      
+       },
+       adjustHandles: function(){
+               
+               var shadowBlur = this.options.shadowBlur;
+               var shadowBlur2x = shadowBlur * 2;              
+               var shadowOffset = this.options.shadowOffset;
+               var top = shadowBlur - shadowOffset.y - 1;
+               var right = shadowBlur + shadowOffset.x - 1;
+               var bottom = shadowBlur + shadowOffset.y - 1;
+               var left = shadowBlur - shadowOffset.x - 1;
+               
+               var coordinates = this.windowEl.getCoordinates();               
+               var width = coordinates.width - shadowBlur2x + 2;
+               var height = coordinates.height - shadowBlur2x + 2;             
+
+               this.n.setStyles({
+                       'top': top,     
+                       'left': left + 10,                              
+                       'width': width - 20
+               });
+               this.e.setStyles({
+                       'top': top + 10,                                                 
+                       'right': right,                  
+                       'height': height - 30
+               });
+               this.s.setStyles({
+                       'bottom': bottom,
+                       'left': left + 10,                      
+                       'width': width - 30
+               });
+               this.w.setStyles({
+                       'top': top + 10,                                                 
+                       'left': left,                    
+                       'height': height - 20
+               });
+               this.ne.setStyles({
+                       'top': top,                      
+                       'right': right  
+               });
+               this.se.setStyles({
+                       'bottom': bottom,                        
+                       'right': right
+               });
+               this.sw.setStyles({
+                       'bottom': bottom,                        
+                       'left': left
+               });
+               this.nw.setStyles({
+                       'top': top,                      
+                       'left': left
+               });                     
+       },      
+       /*
+       
+       Internal Function: insertWindowElements
+       
+       Arguments:
+               windowEl
+                       
+       */
+       insertWindowElements: function(){
+               
+               var options = this.options;
+               var height = options.height;
+               var width = options.width;
+               var id = options.id;
+               
+               var cache = {};
+               
+               if (Browser.Engine.trident4){
+                       cache.zIndexFixEl = new Element('iframe', {
+                               'id': id + '_zIndexFix',                                                                                        
+                               'class': 'zIndexFix',
+                               'scrolling': 'no',
+                               'marginWidth': 0,
+                               'marginHeight': 0,
+                               'src': ''
+                       }).inject(this.windowEl);
+               }
+               
+               cache.overlayEl = new Element('div', {
+                       'id': id + '_overlay',                                                                    
+                       'class': 'mochaOverlay'
+               }).inject(this.windowEl);
+
+               cache.titleBarEl = new Element('div', {
+                       'id': id + '_titleBar',                                                                    
+                       'class': 'mochaTitlebar',
+                       'styles': {
+                               'cursor': options.draggable ? 'move' : 'default'
+                       }
+               }).inject(cache.overlayEl, 'top');
+               
+               cache.titleEl = new Element('h3', {
+                       'id': id + '_title',                                                                    
+                       'class': 'mochaTitle'
+               }).inject(cache.titleBarEl);
+
+               if (options.icon != false){
+                       cache.titleBarEl.setStyles({
+                               'padding-left': 15,
+                               'background': 'url(' + options.icon + ') 5px 5px no-repeat'
+                       })      
+               }
+               
+               cache.contentBorderEl = new Element('div', {
+                       'id': id + '_contentBorder',                                                                                    
+                       'class': 'mochaContentBorder'
+               }).inject(cache.overlayEl);
+
+               if (options.toolbar){
+                       cache.toolbarWrapperEl = new Element('div', {
+                               'id': id + '_toolbarWrapper',                                                                                   
+                               'class': 'mochaToolbarWrapper'
+                       }).inject(cache.contentBorderEl, options.toolbarPosition == 'bottom' ? 'after' : 'before');
+                       
+                       cache.toolbarEl = new Element('div', {
+                               'id': id + '_toolbar',                                                                                  
+                               'class': 'mochaToolbar'
+                       }).inject(cache.toolbarWrapperEl);
+                       
+               }
+
+               cache.contentWrapperEl = new Element('div', {
+                       'id': id + '_contentWrapper',
+                       'class': 'mochaContentWrapper',
+                       'styles': {
+                               'width': width + 'px',
+                               'height': height + 'px'
+                       }
+               }).inject(cache.contentBorderEl);
+               
+               if (this.options.shape == 'gauge'){
+                       cache.contentBorderEl.setStyle('borderWidth', 0);                       
+               }               
+               
+               cache.contentEl = new Element('div', {
+                       'id': id + '_content',
+                       'class': 'mochaContent'
+               }).inject(cache.contentWrapperEl);
+
+               cache.canvasEl = new Element('canvas', {
+                       'id': id + '_canvas',
+                       'class': 'mochaCanvas',
+                       'width': 1,
+                       'height': 1
+               }).inject(this.windowEl);
+               
+               if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas') {
+                       G_vmlCanvasManager.initElement(cache.canvasEl);
+                       cache.canvasEl = this.windowEl.getElement('.mochaCanvas');                      
+               }
+               
+               cache.controlsEl = new Element('div', {
+                       'id': id + '_controls',
+                       'class': 'mochaControls'
+               }).inject(cache.overlayEl, 'after');
+               
+               if (options.useCanvasControls == true){
+                       cache.canvasControlsEl = new Element('canvas', {
+                               'id': id + '_canvasControls',
+                               'class': 'mochaCanvasControls',
+                               'width': 14,
+                               'height': 14
+                       }).inject(this.windowEl);
+               
+                       if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas') {
+                               G_vmlCanvasManager.initElement(cache.canvasControlsEl);
+                               cache.canvasControlsEl = this.windowEl.getElement('.mochaCanvasControls');                      
+                       }
+               }
+               
+               if (options.closable){
+                       cache.closeButtonEl = new Element('div', {
+                               'id': id + '_closeButton',
+                               'class': 'mochaCloseButton',
+                               'title': 'Close'
+                       }).inject(cache.controlsEl);
+                       if (options.useCanvasControls == true){
+                               cache.closeButtonEl.setStyle('background', 'none');                     
+                       }                       
+               }
+
+               if (options.maximizable){
+                       cache.maximizeButtonEl = new Element('div', {
+                               'id': id + '_maximizeButton',
+                               'class': 'mochaMaximizeButton',
+                               'title': 'Maximize'
+                       }).inject(cache.controlsEl);
+                       if (options.useCanvasControls == true){
+                               cache.maximizeButtonEl.setStyle('background', 'none');                  
+                       }                       
+               }
+
+               if (options.minimizable){
+                       cache.minimizeButtonEl = new Element('div', {
+                               'id': id + '_minimizeButton',
+                               'class': 'mochaMinimizeButton',
+                               'title': 'Minimize'
+                       }).inject(cache.controlsEl);
+                       if (options.useCanvasControls == true){
+                               cache.minimizeButtonEl.setStyle('background', 'none');                  
+                       }                       
+               }
+
+               if (options.shape != 'gauge' && options.type != 'notification'){
+                       cache.canvasIconEl = new Element('canvas', {
+                               'id': id + '_canvasIcon',
+                               'class': 'mochaLoadingIcon',
+                               'width': 18,
+                               'height': 18
+                       }).inject(this.windowEl, 'bottom');     
+               
+                       if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas') {
+                               G_vmlCanvasManager.initElement(cache.canvasIconEl);
+                               cache.canvasIconEl = this.windowEl.getElement('.mochaLoadingIcon');
+                       }
+               }
+               
+               if (this.options.shape == 'gauge'){
+                       cache.canvasHeaderEl = new Element('canvas', {
+                               'id': id + '_canvasHeader',                                                                                        
+                               'class': 'mochaCanvasHeader',
+                               'width': this.options.width,
+                               'height': 26
+                       }).inject(this.windowEl, 'bottom');
+               
+                       if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas') {
+                               G_vmlCanvasManager.initElement(cache.canvasHeaderEl);
+                               cache.canvasHeaderEl = this.windowEl.getElement('.mochaCanvasHeader');                  
+                       }               
+               }               
+               
+               if ( Browser.Engine.trident ) {
+                       cache.overlayEl.setStyle('zIndex', 2);
+               }
+
+               // For Mac Firefox 2 to help reduce scrollbar bugs in that browser
+               if (Browser.Platform.mac && Browser.Engine.gecko) {
+                       cache.overlayEl.setStyle('overflow', 'auto');
+               }
+
+               if (options.resizable){                 
+                       cache.n = new Element('div', {
+                               'id': id + '_resizeHandle_n',
+                               'class': 'handle',              
+                               'styles': {
+                                       'top': 0,
+                                       'left': 10,
+                                       'cursor': 'n-resize'
+                               }
+                       }).inject(cache.overlayEl, 'after');
+                       
+                       cache.ne = new Element('div', {
+                               'id': id + '_resizeHandle_ne',
+                               'class': 'handle corner',               
+                               'styles': {
+                                       'top': 0,
+                                       'right': 0,
+                                       'cursor': 'ne-resize'
+                               }
+                       }).inject(cache.overlayEl, 'after');
+                       
+                       cache.e = new Element('div', {
+                               'id': id + '_resizeHandle_e',
+                               'class': 'handle',              
+                               'styles': {
+                                       'top': 10,
+                                       'right': 0,
+                                       'cursor': 'e-resize'
+                               }
+                       }).inject(cache.overlayEl, 'after');
+                       
+                       cache.se = new Element('div', {
+                               'id': id + '_resizeHandle_se',
+                               'class': 'handle cornerSE',             
+                               'styles': {
+                                       'bottom': 0,
+                                       'right': 0,
+                                       'cursor': 'se-resize'
+                               }
+                       }).inject(cache.overlayEl, 'after');
+                       
+                       cache.s = new Element('div', {
+                               'id': id + '_resizeHandle_s',
+                               'class': 'handle',              
+                               'styles': {
+                                       'bottom': 0,
+                                       'left': 10,
+                                       'cursor': 's-resize'
+                               }
+                       }).inject(cache.overlayEl, 'after');
+                       
+                       cache.sw = new Element('div', {
+                               'id': id + '_resizeHandle_sw',
+                               'class': 'handle corner',               
+                               'styles': {
+                                       'bottom': 0,
+                                       'left': 0,
+                                       'cursor': 'sw-resize'
+                               }
+                       }).inject(cache.overlayEl, 'after');
+                       
+                       cache.w = new Element('div', {
+                               'id': id + '_resizeHandle_w',
+                               'class': 'handle',              
+                               'styles': {
+                                       'top': 10,
+                                       'left': 0,
+                                       'cursor': 'w-resize'
+                               }
+                       }).inject(cache.overlayEl, 'after');
+                       
+                       cache.nw = new Element('div', {
+                               'id': id + '_resizeHandle_nw',
+                               'class': 'handle corner',               
+                               'styles': {
+                                       'top': 0,
+                                       'left': 0,
+                                       'cursor': 'nw-resize'
+                               }
+                       }).inject(cache.overlayEl, 'after');
+               }
+               $extend(this, cache);
+               
+       },
+       /*
+
+       Internal function: drawWindow
+               This is where we create the canvas GUI  
+
+       Arguments: 
+               windowEl: the $(window)
+               shadows: (boolean) false will draw a window without shadows
+
+       */      
+       drawWindow: function(windowEl, shadows) {
+               
+               if (this.isCollapsed){
+                       this.drawWindowCollapsed(windowEl, shadows);
+                       return;
+               }
+                               
+               var options = this.options;
+               var shadowBlur = options.shadowBlur;
+               var shadowBlur2x = shadowBlur * 2;
+               var shadowOffset = this.options.shadowOffset;           
+
+               /*
+               var borderHeight = 0;
+               var styleDimensions = this.contentBorderEl.getStyles('margin-top', 'margin-bottom', 'border-top', 'border-bottom');             
+               for(var style in styleDimensions){
+                       borderHeight += styleDimensions[style].toInt();
+               }
+               
+               var borderWidth = 0;
+               var styleDimensions = this.contentBorderEl.getStyles('margin-left', 'margin-right', 'border-left', 'border-right');             
+               for(var style in styleDimensions){
+                       borderWidth += styleDimensions[style].toInt();
+               }
+               */
+
+               this.overlayEl.setStyles({
+                       'width': this.contentWrapperEl.offsetWidth
+               });
+
+               // Resize iframe when window is resized
+               if (this.iframe) {
+                       this.iframeEl.setStyles({
+                               'height': this.contentWrapperEl.offsetHeight
+                       });
+               }
+               
+               var borderHeight = this.contentBorderEl.getStyle('border-top').toInt() + this.contentBorderEl.getStyle('border-bottom').toInt();
+               var toolbarHeight = this.toolbarWrapperEl ? this.toolbarWrapperEl.getStyle('height').toInt() + this.toolbarWrapperEl.getStyle('border-top').toInt() : 0;
+               
+               this.headerFooterShadow = options.headerHeight + options.footerHeight + shadowBlur2x;
+               var height = this.contentWrapperEl.getStyle('height').toInt() + this.headerFooterShadow + toolbarHeight + borderHeight;
+               var width = this.contentWrapperEl.getStyle('width').toInt() + shadowBlur2x;
+               this.windowEl.setStyles({
+                       'height': height,
+                       'width': width
+               });
+               
+               this.overlayEl.setStyles({
+                       'height': height,
+                       'top': shadowBlur - shadowOffset.y,
+                       'left': shadowBlur - shadowOffset.x
+               });             
+
+               // Opera requires the canvas height and width be set this way when resizing:
+               this.canvasEl.height = height;
+               this.canvasEl.width = width;
+
+               // Part of the fix for IE6 select z-index bug and FF on Mac scrollbar z-index bug
+               if (Browser.Engine.trident4){
+                       this.zIndexFixEl.setStyles({
+                               'width': width,
+                               'height': height
+                       })
+               }
+
+               this.titleBarEl.setStyles({
+                       'width': width - shadowBlur2x,
+                       'height': options.headerHeight
+               });
+       
+               // Make sure loading icon is placed correctly.
+               if (options.shape != 'gauge' && options.type != 'notification'){
+                       this.canvasIconEl.setStyles({
+                               'left': shadowBlur - shadowOffset.x + 3,
+                               'bottom': shadowBlur + shadowOffset.y +  4
+                       });
+               }
+               
+               // Draw Window
+               var ctx = this.canvasEl.getContext('2d');
+               ctx.clearRect(0, 0, width, height);     
+
+               switch(options.shape) {
+                       case 'box':
+                               this.drawBox(ctx, width, height, shadowBlur, shadowOffset, shadows);
+                               break;
+                       case 'gauge':
+                               this.drawGauge(ctx, width, height, shadowBlur, shadowOffset, shadows);
+                               break;                          
+               }               
+               
+               if (options.type != 'notification' && options.useCanvasControls == true){
+                       this.drawControls(width, height, shadows);
+               }
+
+               if (options.resizable){ 
+                       MochaUI.triangle(
+                               ctx,
+                               width - (shadowBlur + shadowOffset.x + 17),
+                               height - (shadowBlur + shadowOffset.y + 18),
+                               11,
+                               11,
+                               options.resizableColor,
+                               1.0
+                       );
+               }
+
+               // Invisible dummy object. The last element drawn is not rendered consistently while resizing in IE6 and IE7
+               if (Browser.Engine.trident){
+                       MochaUI.triangle(ctx, 0, 0, 10, 10, options.resizableColor, 0);
+               }               
+
+       },
+       drawWindowCollapsed: function(windowEl, shadows) {
+               
+               var options = this.options;
+               var shadowBlur = options.shadowBlur;
+               var shadowBlur2x = shadowBlur * 2;
+               var shadowOffset = options.shadowOffset;                
+               
+               var headerShadow = options.headerHeight + shadowBlur2x + 2;
+               var height = headerShadow;
+               var width = this.contentWrapperEl.getStyle('width').toInt() + shadowBlur2x;
+               this.windowEl.setStyle('height', height);
+               
+               this.overlayEl.setStyles({
+                       'height': height,
+                       'top': shadowBlur - shadowOffset.y,
+                       'left': shadowBlur - shadowOffset.x
+               });             
+
+               // Opera height and width must be set like this, when resizing:
+               this.canvasEl.height = height;
+               this.canvasEl.width = width;
+
+               // Part of the fix for IE6 select z-index bug and FF on Mac scrollbar z-index bug
+               if (Browser.Engine.trident4){
+                       this.zIndexFixEl.setStyles({
+                               'width': width,
+                               'height': height
+                       });
+               }
+
+               // Set width
+               this.windowEl.setStyle('width', width);
+               this.overlayEl.setStyle('width', width);
+               this.titleBarEl.setStyles({
+                       'width': width - shadowBlur2x,
+                       'height': options.headerHeight
+               });
+       
+               // Draw Window
+               var ctx = this.canvasEl.getContext('2d');
+               ctx.clearRect(0, 0, width, height);
+               
+               this.drawBoxCollapsed(ctx, width, height, shadowBlur, shadowOffset, shadows);           
+               if (options.useCanvasControls == true){
+                       this.drawControls(width, height, shadows);
+               }
+
+               // Invisible dummy object. The last element drawn is not rendered consistently while resizing in IE6 and IE7
+               if ( Browser.Engine.trident ){
+                       MochaUI.triangle(ctx, 0, 0, 10, 10, options.resizableColor, 0);
+               }               
+
+       },      
+       drawControls : function(width, height, shadows){
+               var options = this.options;
+               var shadowBlur = options.shadowBlur;
+               var shadowOffset = options.shadowOffset;
+               var controlsOffset = options.controlsOffset;
+               
+               // Make sure controls are placed correctly.
+               this.controlsEl.setStyles({
+                       'right': shadowBlur + shadowOffset.x + controlsOffset.right,
+                       'top': shadowBlur - shadowOffset.y + controlsOffset.top
+               });
+
+               this.canvasControlsEl.setStyles({
+                       'right': shadowBlur + shadowOffset.x + controlsOffset.right,
+                       'top': shadowBlur - shadowOffset.y + controlsOffset.top
+               });
+
+               // Calculate X position for controlbuttons
+               //var mochaControlsWidth = 52;
+               this.closebuttonX = options.closable ? this.mochaControlsWidth - 7 : this.mochaControlsWidth + 12;
+               this.maximizebuttonX = this.closebuttonX - (options.maximizable ? 19 : 0);
+               this.minimizebuttonX = this.maximizebuttonX - (options.minimizable ? 19 : 0);
+               
+               var ctx2 = this.canvasControlsEl.getContext('2d');
+               ctx2.clearRect(0, 0, 100, 100);
+
+               if (this.options.closable){
+                       this.closebutton(
+                               ctx2,
+                               this.closebuttonX,
+                               7,
+                               options.closeBgColor,
+                               1.0,
+                               options.closeColor,
+                               1.0
+                       );
+               }
+               if (this.options.maximizable){
+                       this.maximizebutton(
+                               ctx2,
+                               this.maximizebuttonX,
+                               7,
+                               options.maximizeBgColor,
+                               1.0,
+                               options.maximizeColor,
+                               1.0
+                       );
+               }
+               if (this.options.minimizable){
+                       this.minimizebutton(
+                               ctx2,
+                               this.minimizebuttonX,
+                               7,
+                               options.minimizeBgColor,
+                               1.0,
+                               options.minimizeColor,
+                               1.0
+                       );
+               }               
+               
+       },
+       drawBox: function(ctx, width, height, shadowBlur, shadowOffset, shadows){       
+
+               var shadowBlur2x = shadowBlur * 2;      
+               var cornerRadius = this.options.cornerRadius;           
+       
+               // This is the drop shadow. It is created onion style.
+               if ( shadows != false ) {       
+                       for (var x = 0; x <= shadowBlur; x++){
+                               MochaUI.roundedRect(
+                                       ctx,
+                                       shadowOffset.x + x,
+                                       shadowOffset.y + x,
+                                       width - (x * 2) - shadowOffset.x,
+                                       height - (x * 2) - shadowOffset.y,
+                                       cornerRadius + (shadowBlur - x),
+                                       [0, 0, 0],
+                                       x == shadowBlur ? .29 : .065 + (x * .01)
+                               );
+                       }
+               }
+               // Window body.
+               this.bodyRoundedRect(
+                       ctx,                          // context
+                       shadowBlur - shadowOffset.x,  // x
+                       shadowBlur - shadowOffset.y,  // y
+                       width - shadowBlur2x,         // width
+                       height - shadowBlur2x,        // height
+                       cornerRadius,                 // corner radius
+                       this.options.bodyBgColor      // Footer color
+               );
+
+               if (this.options.type != 'notification'){
+               // Window header.
+                       this.topRoundedRect(
+                               ctx,                            // context
+                               shadowBlur - shadowOffset.x,    // x
+                               shadowBlur - shadowOffset.y,    // y
+                               width - shadowBlur2x,           // width
+                               this.options.headerHeight,      // height
+                               cornerRadius,                   // corner radius
+                               this.options.headerStartColor,  // Header gradient's top color
+                               this.options.headerStopColor    // Header gradient's bottom color
+                       );              
+               }       
+       },
+       drawBoxCollapsed: function(ctx, width, height, shadowBlur, shadowOffset, shadows){      
+
+               var options = this.options;
+               var shadowBlur2x = shadowBlur * 2;              
+               var cornerRadius = options.cornerRadius;                
+       
+               // This is the drop shadow. It is created onion style.
+               if ( shadows != false ) {       
+                       for (var x = 0; x <= shadowBlur; x++){
+                               MochaUI.roundedRect(
+                                       ctx,
+                                       shadowOffset.x + x,
+                                       shadowOffset.y + x,
+                                       width - (x * 2) - shadowOffset.x,
+                                       height - (x * 2) - shadowOffset.y,
+                                       cornerRadius + (shadowBlur - x),
+                                       [0, 0, 0],
+                                       x == shadowBlur ? .3 : .06 + (x * .01)
+                               );
+                       }
+               }
+
+               // Window header
+               this.topRoundedRect2(
+                       ctx,                          // context
+                       shadowBlur - shadowOffset.x,  // x
+                       shadowBlur - shadowOffset.y,  // y
+                       width - shadowBlur2x,         // width
+                       options.headerHeight + 2,     // height
+                       cornerRadius,                 // corner radius
+                       options.headerStartColor,     // Header gradient's top color
+                       options.headerStopColor       // Header gradient's bottom color
+               );
+
+       },      
+       drawGauge: function(ctx, width, height, shadowBlur, shadowOffset, shadows){
+               var options = this.options;
+               var radius = (width * .5) - (shadowBlur) + 16;
+               if (shadows != false) { 
+                       for (var x = 0; x <= shadowBlur; x++){                          
+                               MochaUI.circle(
+                                       ctx,
+                                       width * .5 + shadowOffset.x,
+                                       (height  + options.headerHeight) * .5 + shadowOffset.x,
+                                       (width *.5) - (x * 2) - shadowOffset.x,
+                                       [0, 0, 0],
+                                       x == shadowBlur ? .7 : .08 + (x * .04)
+                               );
+                       }
+               }
+               MochaUI.circle(
+                       ctx,
+                       width * .5  - shadowOffset.x,
+                       (height + options.headerHeight) * .5  - shadowOffset.y,
+                       (width *.5) - shadowBlur,
+                       options.bodyBgColor,
+                       1
+               );
+               
+               // Draw gauge header
+               this.canvasHeaderEl.setStyles({
+                       'top': shadowBlur - shadowOffset.y,
+                       'left': shadowBlur - shadowOffset.x
+               });             
+               var ctx = this.canvasHeaderEl.getContext('2d');
+               ctx.clearRect(0, 0, width, 100);
+               ctx.beginPath();                
+               ctx.lineWidth = 24;
+               ctx.lineCap = 'round';          
+               ctx.moveTo(13, 13);
+               ctx.lineTo(width - (shadowBlur*2) - 13, 13);
+               ctx.strokeStyle = 'rgba(0, 0, 0, .25)';
+               ctx.stroke();
+       },
+       bodyRoundedRect: function(ctx, x, y, width, height, radius, rgb){
+               ctx.fillStyle = 'rgba(' + rgb.join(',') + ', 100)';
+               ctx.beginPath();
+               ctx.moveTo(x, y + radius);
+               ctx.lineTo(x, y + height - radius);
+               ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
+               ctx.lineTo(x + width - radius, y + height);
+               ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
+               ctx.lineTo(x + width, y + radius);
+               ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
+               ctx.lineTo(x + radius, y);
+               ctx.quadraticCurveTo(x, y, x, y + radius);
+               ctx.fill();
+       
+       },
+       topRoundedRect: function(ctx, x, y, width, height, radius, headerStartColor, headerStopColor){
+               var lingrad = ctx.createLinearGradient(0, 0, 0, height);
+               lingrad.addColorStop(0, 'rgba(' + headerStartColor.join(',') + ', 1)');
+               lingrad.addColorStop(1, 'rgba(' + headerStopColor.join(',') + ', 1)');          
+               ctx.fillStyle = lingrad;
+               ctx.beginPath();
+               ctx.moveTo(x, y);
+               ctx.lineTo(x, y + height);
+               ctx.lineTo(x + width, y + height);
+               ctx.lineTo(x + width, y + radius);
+               ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
+               ctx.lineTo(x + radius, y);
+               ctx.quadraticCurveTo(x, y, x, y + radius);
+               ctx.fill();
+               /*
+               ctx.beginPath();
+               ctx.strokeStyle = '#000';
+               ctx.lineWidth = 1;
+               ctx.moveTo(x, y + height + .5);
+               ctx.lineTo(x + width, y + height + .5);
+               ctx.stroke();
+               */
+               
+       },
+       topRoundedRect2: function(ctx, x, y, width, height, radius, headerStartColor, headerStopColor){
+               var lingrad = ctx.createLinearGradient(0, this.options.shadowBlur - 1, 0, height + this.options.shadowBlur + 3);
+               lingrad.addColorStop(0, 'rgba(' + headerStartColor.join(',') + ', 1)');
+               lingrad.addColorStop(1, 'rgba(' + headerStopColor.join(',') + ', 1)');
+               ctx.fillStyle = lingrad;                
+               ctx.beginPath();
+               ctx.moveTo(x, y + radius);
+               ctx.lineTo(x, y + height - radius);
+               ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
+               ctx.lineTo(x + width - radius, y + height);
+               ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
+               ctx.lineTo(x + width, y + radius);
+               ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
+               ctx.lineTo(x + radius, y);
+               ctx.quadraticCurveTo(x, y, x, y + radius);
+               ctx.fill();     
+       },      
+       maximizebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){
+               // Circle
+               ctx.beginPath();
+               ctx.moveTo(x, y);
+               ctx.arc(x, y, 7, 0, Math.PI*2, true);
+               ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')';
+               ctx.fill();
+               // X sign
+               ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';              
+               ctx.beginPath();
+               ctx.moveTo(x, y - 4);
+               ctx.lineTo(x, y + 4);
+               ctx.stroke();
+               ctx.beginPath();
+               ctx.moveTo(x - 4, y);
+               ctx.lineTo(x + 4, y);
+               ctx.stroke();
+       },
+       closebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){
+               // Circle
+               ctx.beginPath();
+               ctx.moveTo(x, y);
+               ctx.arc(x, y, 7, 0, Math.PI*2, true);
+               ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')';
+               ctx.fill();
+               // Plus sign
+               ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';              
+               ctx.beginPath();
+               ctx.moveTo(x - 3, y - 3);
+               ctx.lineTo(x + 3, y + 3);
+               ctx.stroke();
+               ctx.beginPath();
+               ctx.moveTo(x + 3, y - 3);
+               ctx.lineTo(x - 3, y + 3);
+               ctx.stroke();
+       },
+       minimizebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){
+               // Circle
+               ctx.beginPath();
+               ctx.moveTo(x,y);
+               ctx.arc(x,y,7,0,Math.PI*2,true);
+               ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')';
+               ctx.fill();
+               // Minus sign
+               ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')';              
+               ctx.beginPath();
+               ctx.moveTo(x - 4, y);
+               ctx.lineTo(x + 4, y);
+               ctx.stroke();
+       },
+       /*
+       
+       Function: hideLoadingIcon
+               Hides the spinner.
+               
+       */      
+       hideLoadingIcon: function(canvas) {
+               if (!MochaUI.options.useLoadingIcon || this.options.shape == 'gauge' || this.options.type == 'notification') return;            
+               $(canvas).setStyle('display', 'none');          
+               $clear(canvas.iconAnimation);
+       },
+       /*
+       
+       Function: showLoadingIcon
+               Shows the spinner.
+               
+       */      
+       showLoadingIcon: function(canvas) {
+               if (!MochaUI.options.useLoadingIcon || this.options.shape == 'gauge' || this.options.type == 'notification') return;            
+               $(canvas).setStyles({
+                       'display': 'block'
+               });             
+               var t = 1;              
+               var iconAnimation = function(canvas){ 
+                       var ctx = $(canvas).getContext('2d');
+                       ctx.clearRect(0, 0, 18, 18);
+                       ctx.save();
+                       ctx.translate(9, 9);
+                       ctx.rotate(t*(Math.PI / 8));    
+                       var color = 0;
+                       for (var i=0; i < 8; i++){
+                               color = Math.floor(255 / 8 * i);
+                               ctx.fillStyle = "rgb(" + color + "," + color + "," + color + ")";
+                               ctx.rotate(-Math.PI / 4);
+                               ctx.beginPath();
+                               ctx.arc(0, 7, 2, 0, Math.PI*2, true);
+                               ctx.fill();
+                       }
+                       ctx.restore();
+                       t++;
+               }.bind(this);
+               canvas.iconAnimation = iconAnimation.periodical(125, this, canvas);
+       },      
+       setMochaControlsWidth: function(){
+               this.mochaControlsWidth = 0;
+               var options = this.options;
+               if (options.minimizable){
+                       this.mochaControlsWidth += (this.minimizeButtonEl.getStyle('margin-left').toInt() + this.minimizeButtonEl.getStyle('width').toInt());
+               }
+               if (options.maximizable){
+                       this.mochaControlsWidth += (this.maximizeButtonEl.getStyle('margin-left').toInt() + this.maximizeButtonEl.getStyle('width').toInt());
+               }
+               if (options.closable){
+                       this.mochaControlsWidth += (this.closeButtonEl.getStyle('margin-left').toInt() + this.closeButtonEl.getStyle('width').toInt());
+               }
+               this.controlsEl.setStyle('width', this.mochaControlsWidth);
+               if (options.useCanvasControls == true){
+                       this.canvasControlsEl.setProperty('width', this.mochaControlsWidth);
+               }
+       }
+});
+MochaUI.Window.implement(new Options, new Events);
+/*
+
+Script: Modal.js
+       Create modal dialog windows.
+       
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.  
+
+License:
+       MIT-style license.      
+
+Requires:
+       Core.js, Window.js
+       
+See Also:
+       <Window>        
+       
+*/
+
+MochaUI.Modal = new Class({
+                                                 
+       Extends: MochaUI.Window,
+       
+       Implements: [Events, Options],
+       
+       initialize: function(options){
+               this.modalInitialize();
+               this.installed = true;
+               
+               window.addEvent('resize', function(){
+                       this.setModalSize();
+               }.bind(this));
+
+       },
+       modalInitialize: function(){
+               var modalOverlay = new Element('div', {
+                       'id': 'modalOverlay',
+                       'styles': {
+                               'height': document.getCoordinates().height
+                       }
+               });
+               modalOverlay.inject(document.body);
+               
+               if (Browser.Engine.trident4){
+                       var modalFix = new Element('iframe', {
+                               'id': 'modalFix',                                                        
+                               'scrolling': 'no',
+                               'marginWidth': 0,
+                               'marginHeight': 0,
+                               'src': '',
+                               'styles': {
+                                       'height': document.getCoordinates().height
+                               }                               
+                       }).inject(document.body);
+               }               
+
+               modalOverlay.setStyle('opacity', .4);
+               this.modalOverlayOpenMorph = new Fx.Morph($('modalOverlay'), {
+                               'duration': 200
+                               });
+               this.modalOverlayCloseMorph = new Fx.Morph($('modalOverlay'), {
+                       'duration': 200,
+                       onComplete: function(){
+                               $('modalOverlay').setStyle('display', 'none');
+                               if (Browser.Engine.trident4){
+                                       $('modalFix').setStyle('display', 'none');
+                               }                               
+                       }.bind(this)
+               });
+       },
+       setModalSize: function(){
+               $('modalOverlay').setStyle('height', document.getCoordinates().height);
+               if (Browser.Engine.trident4){
+                       $('modalFix').setStyle('height', document.getCoordinates().height);                     
+               }
+       }
+});
+MochaUI.Modal.implement(new Options, new Events);
+/*
+
+Script: Windows-from-html.js
+       Create windows from html markup in page.
+       
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.  
+
+License:
+       MIT-style license.      
+
+Requires:
+       Core.js, Window.js
+       
+Example:
+       HTML markup.
+       (start code)
+<div class="mocha" id="mywindow" style="width:300px;height:255px;top:50px;left:350px">
+       <h3 class="mochaTitle">My Window</h3>
+       <p>My Window Content</p>
+</div> 
+       (end)
+
+See Also:
+       <Window>
+
+*/
+
+MochaUI.extend({
+       NewWindowsFromHTML: function(){
+               $$('div.mocha').each(function(el) {
+                       // Get the window title and destroy that element, so it does not end up in window content
+                       if ( Browser.Engine.presto || Browser.Engine.trident5 ){
+                               el.setStyle('display','block'); // Required by Opera, and probably IE7
+                       }
+                       var title = el.getElement('h3.mochaTitle');
+                       var elDimensions = el.getStyles('height', 'width');
+                       var properties = {
+                               id: el.getProperty('id'),
+                               height: elDimensions.height.toInt(),
+                               width: elDimensions.width.toInt(),
+                               x: el.getStyle('left').toInt(),
+                               y: el.getStyle('top').toInt()
+                       };
+                       // If there is a title element, set title and destroy the element so it does not end up in window content
+                       if ( title ) {
+                               properties.title = title.innerHTML;
+                               title.destroy();
+                       }
+               
+                       // Get content and destroy the element
+                       properties.content = el.innerHTML;
+                       el.destroy();
+                       
+                       // Create window
+                       new MochaUI.Window(properties, true);
+               }.bind(this));
+       }
+});
+/*
+
+Script: Windows-from-json.js
+       Create one or more windows from JSON data. You can define all the same properties as you can for new MochaUI.Window(). Undefined properties are set to their defaults.
+       
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.  
+
+License:
+       MIT-style license.      
+
+Syntax:
+       (start code)
+       MochaUI.newWindowsFromJSON(properties);
+       (end)
+
+Example:
+       (start code)
+       MochaUI.jsonWindows = function(){
+               var url = 'data/json-windows-data.js';
+               var request = new Request.JSON({
+                       url: url,
+                       method: 'get',                                                                            
+                       onComplete: function(properties) {
+                               MochaUI.newWindowsFromJSON(properties.windows);
+                       }
+               }).send();              
+       }
+       (end)
+       
+See Also:
+       <Window>        
+
+*/
+
+MochaUI.extend({       
+       newWindowsFromJSON: function(properties){
+               properties.each(function(properties) {
+                               new MochaUI.Window(properties);
+               }.bind(this));
+       }
+});
+/*
+
+Script: Arrange-cascade.js
+       Cascade windows.
+       
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.  
+
+License:
+       MIT-style license.      
+
+Requires:
+       Core.js, Window.js
+       
+Syntax:
+       (start code)
+       MochaUI.arrangeCascade();
+       (end)
+
+*/
+
+MochaUI.options.extend({
+       desktopTopOffset:  30,    // Use a negative number if neccessary to place first window where you want it
+       desktopLeftOffset: 20,
+       mochaTopOffset:    50,    // Initial vertical spacing of each window
+       mochaLeftOffset:   40     // Initial horizontal spacing of each window  
+});
+
+MochaUI.extend({   
+       arrangeCascade: function(){
+               var x = this.options.desktopLeftOffset;
+               var y = this.options.desktopTopOffset;
+               $$('div.mocha').each(function(windowEl){
+                       var currentWindowClass = MochaUI.Windows.instances.get(windowEl.id);
+                       if (!currentWindowClass.isMinimized && !currentWindowClass.isMaximized){
+                               id = windowEl.id;
+                               MochaUI.focusWindow(windowEl);
+                               x += this.options.mochaLeftOffset;
+                               y += this.options.mochaTopOffset;
+
+                               if (MochaUI.options.useEffects == false){
+                                       windowEl.setStyles({
+                                               'top': y,
+                                               'left': x
+                                       });
+                               }
+                               else {
+                                       var cascadeMorph = new Fx.Morph(windowEl, {
+                                               'duration': 550
+                                       });
+                                       cascadeMorph.start({
+                                               'top': y,
+                                               'left': x
+                                       });
+                               }
+                       }
+               }.bind(this));
+       }
+});
+/*
+
+Script: Arrange-tile.js
+       Cascade windows.
+       
+Authors:
+       Harry Roberts and Greg Houston
+
+License:
+       MIT-style license.      
+
+Requires:
+       Core.js, Window.js
+       
+Syntax:
+       (start code)
+       MochaUI.arrangeTile();
+       (end)
+
+*/
+        
+MochaUI.extend({        
+       arrangeTile: function(){
+               var x = 10;
+               var y = 10;                     
+       
+               var instances =  MochaUI.Windows.instances;
+
+               var windowsNum = 0;
+
+               instances.each(function(instance){
+                       if (!instance.isMinimized && !instance.isMaximized){
+                               windowsNum++;
+                       }
+               });     
+
+               var cols = 3;
+               var rows = Math.ceil(windowsNum / cols);
+               
+               var coordinates = document.getCoordinates();
+       
+               var col_width = ((coordinates.width - this.options.desktopLeftOffset) / cols);
+               var col_height = ((coordinates.height - this.options.desktopTopOffset) / rows);
+               
+               var row = 0;
+               var col = 0;
+               
+               instances.each(function(instance){
+                       if (!instance.isMinimized && !instance.isMaximized){
+                               
+                               var content = instance.contentWrapperEl;
+                               var content_coords = content.getCoordinates();
+                               var window_coords = instance.windowEl.getCoordinates();
+                               
+                               // Calculate the amount of padding around the content window                            
+                               var padding_top = content_coords.top - window_coords.top;
+                               var padding_bottom = window_coords.height - content_coords.height - padding_top;                                
+                               var padding_left = content_coords.left - window_coords.left;
+                               var padding_right = window_coords.width - content_coords.width - padding_left;
+                               
+                               if (instance.options.shape != 'gauge' && instance.options.resizable == true){
+                                       var width = (col_width - 3 - padding_left - padding_right);
+                                       var height = (col_height - 3 - padding_top - padding_bottom);
+                                       
+                                       if (width > instance.options.resizeLimit.x[0] && width < instance.options.resizeLimit.x[1]){
+                                               content.setStyle('width', width);
+                                       }
+                                       if (height > instance.options.resizeLimit.y[0] && height < instance.options.resizeLimit.y[1]){
+                                               content.setStyle('height', height);
+                                       }
+                               
+                               }
+                               
+                               var left = (x + (col * col_width));
+                               var top = (y + (row * col_height));
+                               
+                               instance.windowEl.setStyles({
+                                       'left': left,
+                                       'top': top                      
+                               });                     
+                                                                                                                               
+                               instance.drawWindow(instance.windowEl);                 
+
+                               MochaUI.focusWindow(instance.windowEl);
+
+                               if (++col === cols) {
+                                       row++;
+                                       col = 0;
+                               }
+                       }
+               }.bind(this));
+       }
+});/*
+
+Script: Tabs.js
+       Functionality for window tabs.
+       
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.  
+       
+License:
+       MIT-style license.
+
+Requires:
+       Core.js, Window.js
+
+To do:
+       - Move to Window
+
+*/
+
+MochaUI.extend({
+       /*
+       
+       Function: initializeTabs
+               Add click event to each list item that fires the selected function. 
+               
+       */      
+       initializeTabs: function(el){
+               $(el).getElements('li').each(function(listitem){
+                       listitem.addEvent('click', function(e){
+                               MochaUI.selected(this, el);                                               
+                       });
+               });
+       },
+       /*
+       
+       Function: selected
+               Add "selected" class to current list item and remove it from sibling list items.
+       
+       Syntax:
+               (start code)
+                       selected(el, parent);
+               (end)   
+
+Arguments:
+       el - the list item
+       parent - the ul
+
+       */      
+       selected: function(el, parent){
+               $(parent).getChildren().each(function(listitem){
+                       listitem.removeClass('selected');                                                  
+               });
+               el.addClass('selected');        
+       }       
+});
+
+/*
+
+Script: Desktop.js
+       Creates a desktop. Enables window maximize. 
+       
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.          
+       
+License:
+       MIT-style license.      
+
+Requires:
+       Core.js, Window.js
+       
+Options:
+       sidebarLimitX - Sidebar minimum and maximum widths when resizing.
+
+*/
+
+MochaUI.Desktop = new Class({
+                                                       
+       Extends: MochaUI.Window,
+       
+       Implements: [Events, Options],
+       
+       options: {                      
+               // Naming options:
+               // If you change the IDs of the Mocha Desktop containers in your HTML, you need to change them here as well.
+               desktop:                'desktop',
+               desktopHeader:          'desktopHeader',
+               desktopNavBar:          'desktopNavbar',
+               pageWrapper:            'pageWrapper',
+               page:                   'page',
+               desktopFooter:          'desktopFooterWrapper',
+               sidebarWrapper:         'sidebarWrapper',               
+               sidebar:                'sidebar',
+               sidebarContentWrapper:  'sidebarContentWrapper',                
+               sidebarMinimize:        'sidebarControl',
+               sidebarHandle:          'sidebarHandle',
+               // Sidebar options:
+               sidebarLimitX:          [180, 280]        // Sidebar minimum and maximum widths when resizing.
+       },      
+       initialize: function(options){
+               this.setOptions(options);
+               this.desktop                = $(this.options.desktop);
+               this.desktopHeader          = $(this.options.desktopHeader);            
+               this.desktopNavBar          = $(this.options.desktopNavBar);
+               this.pageWrapper            = $(this.options.pageWrapper);
+               this.page                   = $(this.options.page);
+               this.desktopFooter          = $(this.options.desktopFooter);            
+               this.sidebarWrapper         = $(this.options.sidebarWrapper);           
+               this.sidebar                = $(this.options.sidebar);
+               this.sidebarContentWrapper  = $(this.options.sidebarContentWrapper);
+               this.sidebarMinimize        = $(this.options.sidebarMinimize);
+               this.sidebarHandle          = $(this.options.sidebarHandle);            
+       
+               this.setDesktopSize();
+               this.menuInitialize();
+               
+               if(this.sidebar){
+                       this.sidebarInitialize();
+               }
+
+               // Resize desktop, page wrapper, modal overlay, and maximized windows when browser window is resized
+               window.addEvent('resize', function(){
+                       this.onBrowserResize();
+               }.bind(this));          
+       },
+       menuInitialize: function(){
+               // Fix for dropdown menus in IE6
+               if (Browser.Engine.trident4 && this.desktopNavBar){
+                       this.desktopNavBar.getElements('li').each(function(element) {
+                               element.addEvent('mouseenter', function(){
+                                       this.addClass('ieHover');
+                               });
+                               element.addEvent('mouseleave', function(){
+                                       this.removeClass('ieHover');
+                               });
+                       });
+               };
+       },
+       onBrowserResize: function(){
+               this.setDesktopSize();
+               // Resize maximized windows to fit new browser window size
+               setTimeout( function(){
+                       MochaUI.Windows.instances.each(function(instance){
+                               if (instance.isMaximized) {
+
+                                       // Hide iframe while resize for better performance
+                                       if ( instance.iframeEl ) {
+                                               instance.iframeEl.setStyle('visibility', 'hidden');
+                                       }
+
+                                       var coordinates = document.getCoordinates();
+                                       var borderHeight = instance.contentBorderEl.getStyle('border-top').toInt() + instance.contentBorderEl.getStyle('border-bottom').toInt();
+                                       var toolbarHeight = instance.toolbarWrapperEl ? instance.toolbarWrapperEl.getStyle('height').toInt() + instance.toolbarWrapperEl.getStyle('border-top').toInt() : 0;                                    
+                                       instance.contentWrapperEl.setStyles({
+                                               'height': coordinates.height - instance.options.headerHeight - instance.options.footerHeight - borderHeight - toolbarHeight,
+                                               'width': coordinates.width
+                                       });
+
+                                       instance.drawWindow($(instance.options.id));
+                                       if ( instance.iframeEl ) {
+                                               instance.iframeEl.setStyles({
+                                                       'height': instance.contentWrapperEl.getStyle('height')
+                                               });
+                                               instance.iframeEl.setStyle('visibility', 'visible');
+                                       }
+
+                               }
+                       }.bind(this));
+               }.bind(this), 100);
+       },
+       setDesktopSize: function(){
+               var windowDimensions = window.getCoordinates();
+
+               // var dock = $(MochaUI.options.dock);
+               var dockWrapper = $(MochaUI.options.dockWrapper);
+               
+               // Setting the desktop height may only be needed by IE7
+               if (this.desktop){
+                       this.desktop.setStyle('height', windowDimensions.height);
+               }
+
+               // Set pageWrapper height so the dock doesn't cover the pageWrapper scrollbars.
+               if (this.pageWrapper && this.desktopHeader) {
+                                       
+                       var dockOffset = MochaUI.dockVisible ? dockWrapper.offsetHeight : 0;                    
+                       var pageWrapperHeight = windowDimensions.height - this.desktopHeader.offsetHeight - this.desktopFooter.offsetHeight - dockOffset;
+                       
+                       if ( pageWrapperHeight < 0 ) {
+                               pageWrapperHeight = 0;
+                       }
+                       this.pageWrapper.setStyle('height', pageWrapperHeight + 'px');
+               }
+               
+               if (this.sidebar){
+                       var sidebarBorderOffset = Browser.Engine.trident4 ? 3 : 2;  
+                       this.sidebarContentWrapper.setStyle('height', pageWrapperHeight - sidebarBorderOffset + 'px');
+                       this.sidebarMinimize.setStyle('top', ((pageWrapperHeight * .5) - (this.sidebarMinimize.offsetHeight * .5))  + 'px');
+                       this.sidebarHandle.setStyle('height', pageWrapperHeight - sidebarBorderOffset + 'px');                  
+               }
+       },
+       /*
+       
+       Function: maximizeWindow
+               Maximize a window.
+       
+       Syntax:
+               (start code)
+               MochaUI.Desktop.maximizeWindow(windowEl);
+               (end)   
+SLUG
+       */      
+       maximizeWindow: function(windowEl) {
+
+               var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
+               var windowDrag = currentInstance.windowDrag;
+
+               // If window no longer exists or is maximized, stop
+               if (windowEl != $(windowEl) || currentInstance.isMaximized ) return;
+               
+               if (currentInstance.isCollapsed){
+                       MochaUI.collapseToggle(windowEl);       
+               }
+
+               currentInstance.isMaximized = true;
+               
+               // If window is restricted to a container, it should not be draggable when maximized.
+               if (currentInstance.options.restrict){
+                       windowDrag.detach();
+                       currentInstance.titleBarEl.setStyle('cursor', 'default');
+               }       
+               
+               // If the window has a container that is not the desktop
+               // temporarily move the window to the desktop while it is minimized.
+               if (currentInstance.options.container != this.desktop){
+                       this.desktop.grab(windowEl);
+                       if (this.options.restrict){
+                       windowDrag.container = this.desktop;
+                       }
+               }               
+               
+               // Save original position
+               currentInstance.oldTop = windowEl.getStyle('top');
+               currentInstance.oldLeft = windowEl.getStyle('left');
+               
+               var contentWrapperEl = currentInstance.contentWrapperEl;
+               
+               // Save original dimensions
+               contentWrapperEl.oldWidth = contentWrapperEl.getStyle('width');
+               contentWrapperEl.oldHeight = contentWrapperEl.getStyle('height');
+               
+               // Hide iframe
+               // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues
+               if ( currentInstance.iframe ) {
+                       currentInstance.iframeEl.setStyle('visibility', 'hidden');
+               }
+
+               //var windowDimensions = document.getCoordinates();
+    var windowDimensions = currentInstance.options.container.getCoordinates();
+               var options = currentInstance.options;
+               var shadowBlur = options.shadowBlur;
+               var shadowOffset = options.shadowOffset;
+
+               if (MochaUI.options.useEffects == false){
+                       windowEl.setStyles({
+                               'top': shadowOffset.y - shadowBlur + windowDimensions.top,
+                               'left': shadowOffset.x - shadowBlur + windowDimensions.left
+                       });
+                       currentInstance.contentWrapperEl.setStyles({
+                               'height': windowDimensions.height - options.headerHeight - options.footerHeight - options.toolbarHeight,
+                               'width':  windowDimensions.width
+                       });
+                       currentInstance.drawWindow(windowEl);
+                       // Show iframe
+                       if ( currentInstance.iframe ) {
+                               currentInstance.iframeEl.setStyle('visibility', 'visible');
+                       }
+                       currentInstance.fireEvent('onMaximize', windowEl);
+               }
+               else {
+                       
+                       // Todo: Initialize the variables for these morphs once in an initialize function and reuse them
+                       
+                       var maximizeMorph = new Fx.Elements([contentWrapperEl, windowEl], { 
+                               duration: 70,
+                               onStart: function(windowEl){
+                                       currentInstance.maximizeAnimation = currentInstance.drawWindow.periodical(20, currentInstance, windowEl);
+                               }.bind(this),
+                               onComplete: function(windowEl){
+                                       $clear(currentInstance.maximizeAnimation);
+                                       currentInstance.drawWindow(windowEl);
+                                       // Show iframe
+                                       if ( currentInstance.iframe ) {
+                                               currentInstance.iframeEl.setStyle('visibility', 'visible');
+                                       }
+                                       currentInstance.fireEvent('onMaximize', windowEl);      
+                               }.bind(this)
+                       });
+                       maximizeMorph.start({
+                               '0': {  'height': function(){ return windowDimensions.height - options.headerHeight - options.footerHeight - currentInstance.contentBorderEl.getStyle('border-top').toInt() - currentInstance.contentBorderEl.getStyle('border-bottom').toInt() - (  currentInstance.toolbarWrapperEl ? currentInstance.toolbarWrapperEl.getStyle('height').toInt() + currentInstance.toolbarWrapperEl.getStyle('border-top').toInt() : 0)},
+                                               'width':  windowDimensions.width
+                               },
+                               '1': {  'top': shadowOffset.y - shadowBlur,
+                                               'left': shadowOffset.x - shadowBlur 
+                               }
+                       });             
+               }
+               currentInstance.maximizeButtonEl.setProperty('title', 'Restore');
+               MochaUI.focusWindow(windowEl);
+
+       },
+       /*
+       
+       Function: restoreWindow
+               Restore a maximized window.
+       
+       Syntax:
+               (start code)
+               MochaUI.Desktop.restoreWindow(windowEl);
+               (end)   
+
+       */      
+       restoreWindow: function(windowEl) {     
+       
+               var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
+               
+               // Window exists and is maximized ?
+               if (windowEl != $(windowEl) || !currentInstance.isMaximized) return;
+                       
+               var options = currentInstance.options;          
+               currentInstance.isMaximized = false;
+               
+               if (options.restrict){
+                       currentInstance.windowDrag.attach();
+                       currentInstance.titleBarEl.setStyle('cursor', 'move');
+               }               
+               
+               // Hide iframe
+               // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues
+               if ( currentInstance.iframe ) {
+                       currentInstance.iframeEl.setStyle('visibility', 'hidden');
+               }
+               
+               var contentWrapperEl = currentInstance.contentWrapperEl;
+               
+               if (MochaUI.options.useEffects == false){
+                       contentWrapperEl.setStyles({
+                               'width':  contentWrapperEl.oldWidth,
+                               'height': contentWrapperEl.oldHeight
+                       });
+                       currentInstance.drawWindow(windowEl);
+                       windowEl.setStyles({
+                               'top': currentInstance.oldTop,
+                               'left': currentInstance.oldLeft
+                       });
+                       if (currentInstance.container != this.desktop){
+                               $(options.container).grab(windowEl);
+                               if (options.restrict){
+                                       currentInstance.windowDrag.container = $(options.container);
+                               }
+                       }
+                       currentInstance.fireEvent('onRestore', windowEl);
+               }
+               else {
+                       var restoreMorph = new Fx.Elements([contentWrapperEl, windowEl], { 
+                               'duration':   150,
+                               'onStart': function(windowEl){
+                                       currentInstance.maximizeAnimation = currentInstance.drawWindow.periodical(20, currentInstance, windowEl);                       
+                               }.bind(this),
+                               'onComplete': function(el){
+                                       $clear(currentInstance.maximizeAnimation);
+                                       currentInstance.drawWindow(windowEl);
+                                       if ( currentInstance.iframe ) {
+                                               currentInstance.iframeEl.setStyle('visibility', 'visible');
+                                       }
+                                       if (options.container != this.desktop){
+                                               $(options.container).grab(windowEl);
+                                               if (options.restrict){  
+                                                       currentInstance.windowDrag.container = $(options.container);
+                                               }
+                                       }
+                                       currentInstance.fireEvent('onRestore', windowEl);
+                               }.bind(this)
+                       });
+                       restoreMorph.start({ 
+                               '0': {  'height': contentWrapperEl.oldHeight,
+                                               'width':  contentWrapperEl.oldWidth
+                               },
+                               '1': {  'top':  currentInstance.oldTop,
+                                               'left': currentInstance.oldLeft
+                               }
+                       });
+               }
+               currentInstance.maximizeButtonEl.setProperty('title', 'Maximize');              
+               
+       },
+       sidebarInitialize: function(){
+               this.sidebarResizable = this.sidebar.makeResizable({
+                       handle: this.sidebarHandle ? this.sidebarHandle : false,
+                       modifiers: {
+                               x: 'width',
+                               y: false                                
+                       },
+                       limit: {
+                               x: this.options.sidebarLimitX
+                       },
+                       onBeforeStart: function(){
+                               // Using postion fixed fixes a minor display glitch while resizing the sidebar in Firefox PC
+                               // Mac Firefox needs position fixed all the time though it does not render as well as absolute
+                               if (!Browser.Platform.mac && Browser.Engine.gecko){
+                                       $$('div.mocha').setStyle('position', 'fixed');  
+                               }
+                       },
+                       onComplete: function(){
+                               if (!Browser.Platform.mac && Browser.Engine.gecko){
+                                       $$('div.mocha').setStyle('position', 'absolute');       
+                               }
+                       }                       
+               });
+               
+               // Part of IE6 3px jox bug fix
+               if (Browser.Engine.trident4){
+                       this.page.set('margin-left', -3);
+               }               
+                       
+               this.sidebarWrapper.setStyle('display', 'block');
+
+               this.sidebarIsMinimized = false;
+               this.sidebarMinimize.addEvent('click', function(event){
+                       this.sidebarMinimizeToggle();
+               }.bind(this));
+               
+               // Add check mark to menu if link exists in menu
+               if ($('sidebarLinkCheck')){                     
+                       this.sidebarCheck = new Element('div', {
+                               'class': 'check',
+                               'id': 'sidebar_check'
+                       }).injectInside($('sidebarLinkCheck'));
+               }               
+       },
+       /*
+       
+       Function: sidebarToggle
+               Toggles the display of the sidebar.
+       
+       Syntax:
+               (start code)
+               MochaUI.Desktop.sidebarToggle();
+               (end)   
+
+       */              
+       sidebarToggle: function(){
+               // Hide sidebar.
+               if (this.sidebarWrapper.getStyle('display') == 'block'){
+                       this.sidebarWrapper.setStyle('display', 'none');
+                       this.sidebarCheck.setStyle('display', 'none');
+                       // Part of IE6 3px jox bug fix                  
+                       if (Browser.Engine.trident4){
+                               this.page.set('margin-left', 0);
+                       }
+               }
+               // Show sidebar.
+               else {
+                       // If the sidebar is minimized when toggling it's visibility on the sidebar will be restored.
+                       if (this.sidebarIsMinimized){                   
+                               this.sidebarMinimizeToggle();                   
+                       }                       
+                       this.sidebarWrapper.setStyle('display', 'block');
+                       this.sidebarCheck.setStyle('display', 'block');
+                       // Part of IE6 3px jox bug fix
+                       if (Browser.Engine.trident4){
+                               this.page.set('margin-left', -3);
+                       }                       
+               }
+       },
+       /*
+       
+       Function: sidebarMinimizeToggle
+               Minimize and restore the sidebar.
+       
+       Syntax:
+               (start code)
+               MochaUI.Desktop.sidebarMinimizeToggle();
+               (end)   
+
+       */              
+       sidebarMinimizeToggle: function(){
+               // Expand sidebar.
+               var windows = $$('div.mocha');
+               if (!this.sidebarIsMinimized){                          
+                       this.sidebarResizable.detach();
+                       this.sidebarHandle.setStyle('cursor', 'default');                                               
+                       this.sidebar.setStyle('display', 'none');
+                       // Part of IE6 3px jox bug fix                  
+                       if (Browser.Engine.trident4){
+                               this.sidebarMinimize.setStyle('margin-right', 0);
+                       }
+                       if (!Browser.Platform.mac && Browser.Engine.gecko){
+                               windows.setStyle('position', 'absolute');       
+                       }                       
+                       this.sidebarIsMinimized = true;                         
+               }
+               // Collapse sidebar
+               else {
+                       this.sidebarResizable.attach(); 
+                       this.sidebarHandle.setStyles({
+                               'cursor': Browser.Engine.presto ? 'e-resize' : 'col-resize'
+                       });                             
+                       this.sidebar.setStyle('display', 'block');                              
+                       if (Browser.Engine.trident4){
+                               this.sidebarMinimize.setStyle('margin-right', 1);
+                       }
+                       if (!Browser.Platform.mac && Browser.Engine.gecko){
+                               windows.setStyle('position', 'absolute');       
+                       }                       
+                       this.sidebarIsMinimized = false;
+               }                               
+       }
+});
+MochaUI.Desktop.implement(new Options, new Events);
+/*
+
+Script: Dock.js
+       Implements the dock/taskbar. Enables window minimize.
+       
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.  
+
+License:
+       MIT-style license.
+
+Requires:
+       Core.js, Window.js, Desktop.js  
+
+Todo:
+       - Make it so the dock requires no initial html markup.
+
+*/
+
+MochaUI.options.extend({                          
+               // Naming options:
+               // If you change the IDs of the Mocha Desktop containers in your HTML, you need to change them here as well.
+               dockWrapper: 'dockWrapper',
+               dock:        'dock'
+});
+
+MochaUI.dockVisible = true;
+
+MochaUI.extend({
+       /*
+
+       Function: minimizeAll
+               Minimize all windows.
+
+       */      
+       minimizeAll: function() {               
+               $$('div.mocha').each(function(windowEl){
+               var currentInstance = MochaUI.Windows.instances.get(windowEl.id);                                                                         
+                       if (!currentInstance.isMinimized){
+                               MochaUI.Dock.minimizeWindow(windowEl);
+                       }                       
+               }.bind(this));          
+       }
+});    
+
+MochaUI.Dock = new Class({
+       Extends: MochaUI.Window,
+       
+       Implements: [Events, Options],
+       
+       options: {
+               useControls:          true,      // Toggles autohide and dock placement controls.
+               useCanvasTabs:        false,     // Toggle use of canvas tab graphics. NOT YET IMPLEMENTED
+               dockPosition:         'top',     // Position the dock starts in, top or bottom.
+               // Style options
+               dockTabColor:         [255, 255, 255],
+               trueButtonColor:      [70, 245, 70],     // Color for autohide on               
+               enabledButtonColor:   [255, 70, 70], 
+               disabledButtonColor:  [150, 150, 150]           
+       },
+       initialize: function(options){
+               // Stops if MochaUI.Desktop is not implemented
+               if (!MochaUI.Desktop) return;
+               this.setOptions(options);
+               
+               this.dockWrapper   = $(MochaUI.options.dockWrapper);            
+               this.dock          = $(MochaUI.options.dock);
+               this.autoHideEvent = null;              
+               this.dockAutoHide  = false;  // True when dock autohide is set to on, false if set to off
+
+               if (!this.options.useControls){
+                       if($('dockPlacement')){
+                               $('dockPlacement').setStyle('cursor', 'default');
+                       }
+                       if($('dockAutoHide')){
+                               $('dockAutoHide').setStyle('cursor', 'default');
+                       }
+               }
+
+               this.dockWrapper.setStyles({
+                       'display':  'block',
+                       'position': 'absolute',
+                       'top':      null,
+                       'bottom':   0,
+                       'left':     0
+               });     
+
+               if (this.options.useControls){
+                       this.initializeDockControls();
+               }
+
+               // Add check mark to menu if link exists in menu
+               if ($('dockLinkCheck')){                        
+                       this.sidebarCheck = new Element('div', {
+                               'class': 'check',
+                               'id': 'dock_check'
+                       }).inject($('dockLinkCheck'));
+               }
+               
+               this.dockSortables = new Sortables('#dockSort', {
+                       opacity: Browser.Engine.trident ? 1 : .5,
+               constrain: true,
+               clone: false,
+               revert: false                   
+               });             
+
+               MochaUI.Desktop.setDesktopSize();
+       },
+       initializeDockControls: function(){
+               
+               if (this.options.useControls){
+                       // Insert canvas
+                       var canvas = new Element('canvas', {
+                               'id':     'dockCanvas',
+                               'width':  '15',
+                               'height': '18'
+                       }).inject(this.dock);
+               
+                       // Dynamically initialize canvas using excanvas. This is only required by IE
+                       if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas'){
+                               G_vmlCanvasManager.initElement(canvas);
+                       }
+               }
+               
+               var dockPlacement = $('dockPlacement');
+               var dockAutoHide = $('dockAutoHide');
+
+               // Position top or bottom selector
+               dockPlacement.setProperty('title','Position Dock Top');
+
+               // Attach event
+               dockPlacement.addEvent('click', function(){
+                       this.moveDock();
+               }.bind(this));
+
+               // Auto Hide toggle switch
+               dockAutoHide.setProperty('title','Turn Auto Hide On');
+               
+               // Attach event Auto Hide 
+               dockAutoHide.addEvent('click', function(event){
+                       if ( this.dockWrapper.getProperty('dockPosition') == 'top' )
+                               return false;
+                       
+                       var ctx = $('dockCanvas').getContext('2d');
+                       this.dockAutoHide = !this.dockAutoHide; // Toggle
+                       if (this.dockAutoHide){
+                               $('dockAutoHide').setProperty('title', 'Turn Auto Hide Off');
+                               //ctx.clearRect(0, 11, 100, 100);                               
+                               MochaUI.circle(ctx, 5 , 14, 3, this.options.trueButtonColor, 1.0); // green
+                               
+                               // Define event
+                               this.autoHideEvent = function(event) {
+                                       if (!this.dockAutoHide)
+                                               return;
+                                       if (event.client.y > (document.getCoordinates().height - 25)){
+                                               if (!MochaUI.dockVisible){
+                                                       this.dockWrapper.setStyle('display', 'block');
+                                                       MochaUI.dockVisible = true;
+                                                       MochaUI.Desktop.setDesktopSize();
+                                               }
+                                       } else {
+                                               if (MochaUI.dockVisible){
+                                                       this.dockWrapper.setStyle('display', 'none');
+                                                       MochaUI.dockVisible = false;
+                                                       MochaUI.Desktop.setDesktopSize();
+                                               }
+                                       }
+                               }.bind(this);
+                               
+                               // Add event
+                               document.addEvent('mousemove', this.autoHideEvent);                             
+                               
+                       } else {
+                               $('dockAutoHide').setProperty('title', 'Turn Auto Hide On');
+                               //ctx.clearRect(0, 11, 100, 100);
+                               MochaUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0); // red
+                               // Remove event
+                               document.removeEvent('mousemove', this.autoHideEvent);
+                       }
+                       
+               }.bind(this));
+               
+               // Draw dock controls
+               var ctx = $('dockCanvas').getContext('2d');
+               ctx.clearRect(0, 0, 100, 100);
+               MochaUI.circle(ctx, 5 , 4, 3, this.options.enabledButtonColor, 1.0);  // red
+               MochaUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0); // red
+               
+               if (this.options.dockPosition == 'top'){
+                       this.moveDock();        
+               }               
+               
+       },
+       moveDock: function(){
+                       var ctx = $('dockCanvas').getContext('2d');
+                       // Move dock to top position
+                       if (this.dockWrapper.getStyle('position') != 'relative'){
+                               this.dockWrapper.setStyles({
+                                       'position': 'relative',
+                                       'bottom':   null
+                               });
+                               this.dockWrapper.addClass('top');
+                               MochaUI.Desktop.setDesktopSize();
+                               this.dockWrapper.setProperty('dockPosition','top');
+                               ctx.clearRect(0, 0, 100, 100);
+                               MochaUI.circle(ctx, 5, 4, 3, this.options.trueButtonColor, 1.0); // green
+                               MochaUI.circle(ctx, 5, 14, 3, this.options.disabledButtonColor, 1.0); // gray
+                               $('dockPlacement').setProperty('title', 'Position Dock Bottom');
+                               $('dockAutoHide').setProperty('title', 'Auto Hide Disabled in Top Dock Position');
+                               this.dockAutoHide = false;
+                       }
+                       // Move dock to bottom position
+                       else {
+                               this.dockWrapper.setStyles({
+                                       'position':      'absolute',
+                                       'bottom':        0
+                               });
+                               this.dockWrapper.removeClass('top');                            
+                               MochaUI.Desktop.setDesktopSize();
+                               this.dockWrapper.setProperty('dockPosition', 'bottom');
+                               ctx.clearRect(0, 0, 100, 100);
+                               MochaUI.circle(ctx, 5, 4, 3, this.options.enabledButtonColor, 1.0); // red
+                               MochaUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0); // red 
+                               $('dockPlacement').setProperty('title', 'Position Dock Top');
+                               $('dockAutoHide').setProperty('title', 'Turn Auto Hide On');
+                       }               
+       },
+       createDockTab: function(windowEl){
+
+               var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
+
+               var dockTab = new Element('div', {
+                       'id': currentInstance.options.id + '_dockTab',
+                       'class': 'dockTab',
+                       'title': titleText
+               }).inject($('dockClear'), 'before');
+               
+               dockTab.addEvent('mousedown', function(e){
+                       this.timeDown = $time();                        
+               });
+               
+               dockTab.addEvent('mouseup', function(e){
+                       this.timeUp = $time();
+                       if ((this.timeUp - this.timeDown) < 275){
+                               // If window is minimized, restore window.
+                               if (currentInstance.isMinimized == true) {
+                                       MochaUI.Dock.restoreMinimized.delay(25, MochaUI.Dock, windowEl);
+                               }
+                               else{
+                                       // If window is maximized and focused, minimize window.
+                                       if (currentInstance.windowEl.hasClass('isFocused')) {
+                                               MochaUI.Dock.minimizeWindow(windowEl)
+                                       }
+                                       // If window is maximized and not focused, focus window.        
+                                       else{
+                                               MochaUI.focusWindow(windowEl);
+                                       }
+                               }                                       
+                       }
+               });                     
+
+               this.dockSortables.addItems(dockTab);
+
+               //Insert canvas
+               if (this.options.useControls){
+                       if (this.options.useCanvasTabs){        
+                               var dockTabCanvas = new Element('canvas', {
+                                       'id': currentInstance.options.id + '_dockTabCanvas',
+                                       'class': 'dockCanvas', 
+                                       'width': 120,
+                                       'height': 20                    
+                               }).inject(dockTab);     
+                               
+                               // Dynamically initialize canvas using excanvas. This is only required by IE
+                               if (Browser.Engine.trident && MochaUI.ieSupport == 'excanvas') {
+                                       G_vmlCanvasManager.initElement(dockTabCanvas);
+                               }
+
+                               var ctx = $(currentInstance.options.id + '_dockTabCanvas').getContext('2d');
+                               MochaUI.roundedRect(ctx, 0, 0, 120, 20, 5, this.options.dockTabColor, 1);
+                       }
+               }
+               
+               var titleText = currentInstance.titleEl.innerHTML;              
+               
+               var dockTabText = new Element('div', {
+                       'id': currentInstance.options.id + '_dockTabText',
+                       'class': 'dockText'
+               }).set('html', titleText.substring(0,18) + (titleText.length > 18 ? '...' : '')).inject($(dockTab));
+               
+               // Need to resize everything in case the dock wraps when a new tab is added
+               MochaUI.Desktop.setDesktopSize();
+                       
+       },
+       makeActiveTab: function(){
+
+
+               // getWindowWith HighestZindex is used in case the currently focused window
+               // is closed.           
+               var windowEl = MochaUI.getWindowWithHighestZindex();
+               var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
+               
+               $$('div.dockTab').removeClass('activeDockTab');         
+               if (currentInstance.isMinimized != true) {
+                       
+                       currentInstance.windowEl.addClass('isFocused');                 
+
+                       currentButton = $(currentInstance.options.id + '_dockTab');                     
+                       currentButton.addClass('activeDockTab');
+               }
+               else {
+                       currentInstance.windowEl.removeClass('isFocused');
+               }       
+       },      
+       minimizeWindow: function(windowEl){             
+               if (windowEl != $(windowEl)) return;
+                       
+               var currentInstance = MochaUI.Windows.instances.get(windowEl.id);               
+               currentInstance.isMinimized = true;             
+
+               // Hide iframe
+               // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues
+               if ( currentInstance.iframe ) {
+                       currentInstance.iframeEl.setStyle('visibility', 'hidden');
+               }
+               
+               // Hide window and add to dock  
+               currentInstance.contentBorderEl.setStyle('visibility', 'hidden');
+               if(currentInstance.toolbarWrapperEl){           
+                       currentInstance.toolbarWrapperEl.setStyle('visibility', 'hidden');
+               }
+               windowEl.setStyle('visibility', 'hidden');
+
+                // Fixes a scrollbar issue in Mac FF2
+               if (Browser.Platform.mac && Browser.Engine.gecko){
+                       currentInstance.contentWrapperEl.setStyle('overflow', 'hidden');
+               }
+       
+               MochaUI.Desktop.setDesktopSize();
+               
+               // Fixes a scrollbar issue in Mac FF2.
+               // Have to use timeout because window gets focused when you click on the minimize button        
+               setTimeout(function(){          
+                       windowEl.setStyle('zIndex', 1);
+                       windowEl.removeClass('isFocused');              
+                       this.makeActiveTab();   
+               }.bind(this),100);      
+
+               currentInstance.fireEvent('onMinimize', windowEl);              
+       },
+       restoreMinimized: function(windowEl) {
+
+               var currentInstance = MochaUI.Windows.instances.get(windowEl.id);
+
+               if (currentInstance.isMinimized == false) return;
+
+               if (MochaUI.Windows.windowsVisible == false){
+                       MochaUI.toggleWindowVisibility();
+               }
+
+               MochaUI.Desktop.setDesktopSize();
+
+                // Part of Mac FF2 scrollbar fix
+               if (currentInstance.options.scrollbars == true && currentInstance.iframe == false){ 
+                       currentInstance.contentWrapperEl.setStyle('overflow', 'auto');
+               }
+
+               if (currentInstance.isCollapsed) {
+                       MochaUI.collapseToggle(windowEl);                                       
+               }
+
+               windowEl.setStyle('visibility', 'visible');
+               currentInstance.contentBorderEl.setStyle('visibility', 'visible');
+               if(currentInstance.toolbarWrapperEl){           
+                       currentInstance.toolbarWrapperEl.setStyle('visibility', 'visible');
+               }               
+
+               // Show iframe
+               if ( currentInstance.iframe ) {
+                       currentInstance.iframeEl.setStyle('visibility', 'visible');
+               }
+
+               currentInstance.isMinimized = false;
+               MochaUI.focusWindow(windowEl);
+               currentInstance.fireEvent('onRestore', windowEl);
+               
+       }       
+});
+MochaUI.Dock.implement(new Options, new Events);
+/*
+
+Script: Workspaces.js
+       Save and load workspaces. The Workspaces emulate Adobe Illustrator functionality remembering what windows are open and where they are positioned. There will be two versions, a limited version that saves state to a cookie, and a fully functional version that saves state to a database.
+
+Copyright:
+       Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.  
+
+License:
+       MIT-style license.
+
+Requires:
+       Core.js, Window.js
+
+To do:
+       - Move to Window
+
+*/
+
+MochaUI.extend({                          
+       /*
+       
+       Function: saveWorkspace
+               Save the current workspace.
+       
+       Syntax:
+       (start code)
+               MochaUI.saveWorkspace();
+       (end)
+       
+       Notes:
+               This is experimental. This version saves the ID of each open window to a cookie, and reloads those windows using the functions in mocha-init.js. This requires that each window have a function in mocha-init.js used to open them. Functions must be named the windowID + "Window". So if your window is called mywindow, it needs a function called mywindowWindow in mocha-init.js.  
+       
+       */      
+       saveWorkspace: function(){
+               this.cookie = new Hash.Cookie('mochaUIworkspaceCookie', {duration: 3600});
+               this.cookie.empty();            
+               MochaUI.Windows.instances.each(function(instance) {
+                       instance.saveValues();                                                                  
+                       this.cookie.set(instance.options.id, {
+                               'id': instance.options.id,
+                               'top': instance.options.y,
+                               'left': instance.options.x
+                       });             
+               }.bind(this));          
+               this.cookie.save();
+               
+               new MochaUI.Window({
+                       loadMethod: 'html',
+                       type: 'notification',
+                       addClass: 'notification',
+                       content: 'Workspace saved.',
+                       closeAfter: '1400',
+                       width: 200,
+                       height: 40,
+                       y: 15,
+                       padding:  { top: 10, right: 12, bottom: 10, left: 12 },
+                       shadowBlur: 5,
+                       bodyBgColor: [255, 255, 255]    
+               });
+               
+       },
+       windowUnload: function(){
+               if ($$('div.mocha').length == 0 && this.myChain){
+                       this.myChain.callChain();                       
+               }               
+       },
+       loadWorkspace2: function(workspaceWindows){             
+               workspaceWindows.each(function(instance) {              
+                       eval('MochaUI.' + instance.id + 'Window();');
+                       $(instance.id).setStyles({
+                               top: instance.top,
+                               left: instance.left
+                       });
+               }.bind(this));
+               this.loadingWorkspace = false;
+       },
+       /*
+               
+       Function: loadWorkspace
+               Load the saved workspace.
+       
+       Syntax:
+       (start code)
+               MochaUI.loadWorkspace();
+       (end)
+       
+       */
+       loadWorkspace: function(){
+               cookie = new Hash.Cookie('mochaUIworkspaceCookie', {duration: 3600});
+               workspaceWindows = cookie.load();
+
+               if(!cookie.getKeys().length){
+                       new MochaUI.Window({
+                               loadMethod: 'html',
+                               type: 'notification',
+                               addClass: 'notification',
+                               content: 'You have no saved workspace.',
+                               width: 220,
+                               height: 40,
+                               y: 25,
+                               padding:  { top: 10, right: 12, bottom: 10, left: 12 },
+                               shadowBlur: 5,
+                               bodyBgColor: [255, 255, 255]    
+                       });
+                       return;
+               }
+               
+               if ($$('div.mocha').length != 0){
+                       this.loadingWorkspace = true;
+                       this.myChain = new Chain();
+                       this.myChain.chain(
+                       function(){                                     
+                                       $$('div.mocha').each(function(el) {
+                                               this.closeWindow(el);
+                                       }.bind(this));
+                               }.bind(this),                   
+                       function(){
+                                       this.loadWorkspace2(workspaceWindows);                  
+                               }.bind(this)
+                       );
+                       this.myChain.callChain();
+               }
+               else {
+                       this.loadWorkspace2(workspaceWindows);
+               }
+       
+       }
+});
diff --git a/static/js/mochaui.js b/static/js/mochaui.js
new file mode 100644 (file)
index 0000000..8b2e9cd
--- /dev/null
@@ -0,0 +1,3 @@
+/* qwebirc -- Copyright (C) 2008 Chris Porter --- All rights reserved. */
+
+var QMochaUIWindow=new Class({Extends:UIWindow,initialize:function(G,B,E,D){this.parent(G,B,E,D);this.lines=new Element("div",{styles:{overflow:"auto",width:"90"}});this.form=new Element("form");this.inputbox=new Element("input",{styles:{border:0,width:"100%"}});this.inputbox.addClass("input");this.form.addEvent("submit",function(H){new Event(H).stop();this.client.exec(this.inputbox.value);this.inputbox.value=""}.bind(this));this.form.appendChild(this.inputbox);var C={width:500,height:400,title:D,footerHeight:0,toolbar:true,container:$("pageWrapper"),toolbarHeight:G.inputHeight,toolbarPosition:"bottom",toolbarContent:"",content:this.lines,onFocus:function(){G.selectWindow(this)}.bind(this),onClose:function(){if(E==WINDOW_CHANNEL){this.client.exec("/PART "+D)}this.close()}.bind(this)};if(E==WINDOW_STATUS){C.closable=false}var A=new MochaUI.Window(C);var F=$(A.options.id+"_toolbar");F.appendChild(this.form);return },updateNickList:function(A){this.parent(A);return ;var B=this.nicklist;while(B.firstChild){B.removeChild(B.firstChild)}A.each(function(C){var D=new Element("div");B.appendChild(D);D.appendChild(document.createTextNode(C))})},updateTopic:function(A){this.parent(A);return ;var B=this.topic;while(B.firstChild){B.removeChild(B.firstChild)}Colourise(A,B)},addLine:function(D,A,G){this.parent(D,A,G);var F=new Element("div");if(G){F.setStyles({background:G})}else{if(this.lastcolour){F.addClass("linestyle1")}else{F.addClass("linestyle2")}}if(D){A=this.parentObject.theme.message(D,A)}Colourise(IRCTimestamp(new Date())+" "+A,F);this.lastcolour=!this.lastcolour;var E=this.lines.getScroll();var C=this.lines.getScrollSize().y;var B=this.lines.getSize();this.lines.appendChild(F);this.lines.scrollTo(E.x,this.lines.getScrollSize().y);if(!this.active){this.lines.showLoadingIcon()}}});var QMochaUI=new Class({Extends:UI,initialize:function(A,B){this.parent(A,QMochaUIWindow,"mochaui");this.theme=B;this.parentElement=A;window.addEvent("domready",function(){var C=new Element("input",{styles:{border:0}});this.parentElement.appendChild(C);this.inputHeight=C.getSize().y;this.parentElement.removeChild(C);MochaUI.Desktop=new MochaUI.Desktop();MochaUI.Dock=new MochaUI.Dock();MochaUI.Modal=new MochaUI.Modal();MochaUI.options.useEffects=false}.bind(this));window.addEvent("unload",function(){if(MochaUI){MochaUI.garbageCleanUp()}})},postInitialize:function(){return ;this.tabs=new Element("div");this.tabs.addClass("tabbar");this.parentElement.appendChild(this.tabs);this.container=new Element("div");this.container.addClass("container");this.parentElement.appendChild(this.container);var B=new Element("form");var A=new Element("input");A.addClass("input");B.addEvent("submit",function(C){new Event(C).stop();this.getActiveWindow().client.exec(A.value);A.value=""}.bind(this));this.parentElement.appendChild(B);B.appendChild(A);A.focus()},loginBox:function(B,C,A){this.parent(function(D){this.postInitialize();B(D)}.bind(this),C,A)}});
\ No newline at end of file
index b39ed7fc3ee67b32cd86c7220490ecd4e253c122..5df5215d4f1e9fdaddb93a80d497e98b4bc8ae5c 100644 (file)
@@ -251,7 +251,64 @@ window.fireEvent("domready");document.fireEvent("domready");};switch(Browser.Eng
 case"array":return"["+String(B.map(JSON.encode).filter($defined))+"]";case"object":case"hash":var A=[];Hash.each(B,function(E,D){var C=JSON.encode(E);if(C){A.push(JSON.encode(D)+":"+C);
 }});return"{"+A+"}";case"number":case"boolean":return String(B);case false:return"null";}return null;},$specialChars:{"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},$replaceChars:function(A){return JSON.$specialChars[A]||"\\u00"+Math.floor(A.charCodeAt()/16).toString(16)+(A.charCodeAt()%16).toString(16);
 },decode:function(string,secure){if($type(string)!="string"||!string.length){return null;}if(secure&&!(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g,"@").replace(/"[^"\\\n\r]*"/g,""))){return null;
-}return eval("("+string+")");}});Native.implement([Hash,Array,String,Number],{toJSON:function(){return JSON.encode(this);}});var Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false},initialize:function(A){this.xhr=new Browser.Request();
+}return eval("("+string+")");}});Native.implement([Hash,Array,String,Number],{toJSON:function(){return JSON.encode(this);}});var Cookie=new Class({Implements:Options,options:{path:false,domain:false,duration:false,secure:false,document:document},initialize:function(B,A){this.key=B;
+this.setOptions(A);},write:function(B){B=encodeURIComponent(B);if(this.options.domain){B+="; domain="+this.options.domain;}if(this.options.path){B+="; path="+this.options.path;
+}if(this.options.duration){var A=new Date();A.setTime(A.getTime()+this.options.duration*24*60*60*1000);B+="; expires="+A.toGMTString();}if(this.options.secure){B+="; secure";
+}this.options.document.cookie=this.key+"="+B;return this;},read:function(){var A=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)");
+return(A)?decodeURIComponent(A[1]):null;},dispose:function(){new Cookie(this.key,$merge(this.options,{duration:-1})).write("");return this;}});Cookie.write=function(B,C,A){return new Cookie(B,A).write(C);
+};Cookie.read=function(A){return new Cookie(A).read();};Cookie.dispose=function(B,A){return new Cookie(B,A).dispose();};var Swiff=new Class({Implements:[Options],options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"transparent",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object;
+},initialize:function(L,M){this.instance="Swiff_"+$time();this.setOptions(M);M=this.options;var B=this.id=M.id||this.instance;var A=$(M.container);Swiff.CallBacks[this.instance]={};
+var E=M.params,G=M.vars,F=M.callBacks;var H=$extend({height:M.height,width:M.width},M.properties);var K=this;for(var D in F){Swiff.CallBacks[this.instance][D]=(function(N){return function(){return N.apply(K.object,arguments);
+};})(F[D]);G[D]="Swiff.CallBacks."+this.instance+"."+D;}E.flashVars=Hash.toQueryString(G);if(Browser.Engine.trident){H.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
+E.movie=L;}else{H.type="application/x-shockwave-flash";H.data=L;}var J='<object id="'+B+'"';for(var I in H){J+=" "+I+'="'+H[I]+'"';}J+=">";for(var C in E){if(E[C]){J+='<param name="'+C+'" value="'+E[C]+'" />';
+}}J+="</object>";this.object=((A)?A.empty():new Element("div")).set("html",J).firstChild;},replaces:function(A){A=$(A,true);A.parentNode.replaceChild(this.toElement(),A);
+return this;},inject:function(A){$(A,true).appendChild(this.toElement());return this;},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].extend(arguments));
+}});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction('<invoke name="'+fn+'" returntype="javascript">'+__flash__argumentsToXML(arguments,2)+"</invoke>");
+return eval(rs);};var Fx=new Class({Implements:[Chain,Events,Options],options:{fps:50,unit:false,duration:500,link:"ignore",transition:function(A){return -(Math.cos(Math.PI*A)-1)/2;
+}},initialize:function(A){this.subject=this.subject||this;this.setOptions(A);this.options.duration=Fx.Durations[this.options.duration]||this.options.duration.toInt();
+var B=this.options.wait;if(B===false){this.options.link="cancel";}},step:function(){var A=$time();if(A<this.time+this.options.duration){var B=this.options.transition((A-this.time)/this.options.duration);
+this.set(this.compute(this.from,this.to,B));}else{this.set(this.compute(this.from,this.to,1));this.complete();}},set:function(A){return A;},compute:function(C,B,A){return Fx.compute(C,B,A);
+},check:function(A){if(!this.timer){return true;}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(A.bind(this,Array.slice(arguments,1)));
+return false;}return false;},start:function(B,A){if(!this.check(arguments.callee,B,A)){return this;}this.from=B;this.to=A;this.time=0;this.startTimer();
+this.onStart();return this;},complete:function(){if(this.stopTimer()){this.onComplete();}return this;},cancel:function(){if(this.stopTimer()){this.onCancel();
+}return this;},onStart:function(){this.fireEvent("start",this.subject);},onComplete:function(){this.fireEvent("complete",this.subject);if(!this.callChain()){this.fireEvent("chainComplete",this.subject);
+}},onCancel:function(){this.fireEvent("cancel",this.subject).clearChain();},pause:function(){this.stopTimer();return this;},resume:function(){this.startTimer();
+return this;},stopTimer:function(){if(!this.timer){return false;}this.time=$time()-this.time;this.timer=$clear(this.timer);return true;},startTimer:function(){if(this.timer){return false;
+}this.time=$time()-this.time;this.timer=this.step.periodical(Math.round(1000/this.options.fps),this);return true;}});Fx.compute=function(C,B,A){return(B-C)*A+C;
+};Fx.Durations={"short":250,normal:500,"long":1000};Fx.CSS=new Class({Extends:Fx,prepare:function(D,E,B){B=$splat(B);var C=B[1];if(!$chk(C)){B[1]=B[0];
+B[0]=D.getStyle(E);}var A=B.map(this.parse);return{from:A[0],to:A[1]};},parse:function(A){A=$lambda(A)();A=(typeof A=="string")?A.split(" "):$splat(A);
+return A.map(function(C){C=String(C);var B=false;Fx.CSS.Parsers.each(function(F,E){if(B){return ;}var D=F.parse(C);if($chk(D)){B={value:D,parser:F};}});
+B=B||{value:C,parser:Fx.CSS.Parsers.String};return B;});},compute:function(D,C,B){var A=[];(Math.min(D.length,C.length)).times(function(E){A.push({value:D[E].parser.compute(D[E].value,C[E].value,B),parser:D[E].parser});
+});A.$family={name:"fx:css:value"};return A;},serve:function(C,B){if($type(C)!="fx:css:value"){C=this.parse(C);}var A=[];C.each(function(D){A=A.concat(D.parser.serve(D.value,B));
+});return A;},render:function(A,D,C,B){A.setStyle(D,this.serve(C,B));},search:function(A){if(Fx.CSS.Cache[A]){return Fx.CSS.Cache[A];}var B={};Array.each(document.styleSheets,function(E,D){var C=E.href;
+if(C&&C.contains("://")&&!C.contains(document.domain)){return ;}var F=E.rules||E.cssRules;Array.each(F,function(I,G){if(!I.style){return ;}var H=(I.selectorText)?I.selectorText.replace(/^\w+/,function(J){return J.toLowerCase();
+}):null;if(!H||!H.test("^"+A+"$")){return ;}Element.Styles.each(function(K,J){if(!I.style[J]||Element.ShortStyles[J]){return ;}K=String(I.style[J]);B[J]=(K.test(/^rgb/))?K.rgbToHex():K;
+});});});return Fx.CSS.Cache[A]=B;}});Fx.CSS.Cache={};Fx.CSS.Parsers=new Hash({Color:{parse:function(A){if(A.match(/^#[0-9a-f]{3,6}$/i)){return A.hexToRgb(true);
+}return((A=A.match(/(\d+),\s*(\d+),\s*(\d+)/)))?[A[1],A[2],A[3]]:false;},compute:function(C,B,A){return C.map(function(E,D){return Math.round(Fx.compute(C[D],B[D],A));
+});},serve:function(A){return A.map(Number);}},Number:{parse:parseFloat,compute:Fx.compute,serve:function(B,A){return(A)?B+A:B;}},String:{parse:$lambda(false),compute:$arguments(1),serve:$arguments(0)}});
+Fx.Tween=new Class({Extends:Fx.CSS,initialize:function(B,A){this.element=this.subject=$(B);this.parent(A);},set:function(B,A){if(arguments.length==1){A=B;
+B=this.property||this.options.property;}this.render(this.element,B,A,this.options.unit);return this;},start:function(C,E,D){if(!this.check(arguments.callee,C,E,D)){return this;
+}var B=Array.flatten(arguments);this.property=this.options.property||B.shift();var A=this.prepare(this.element,this.property,B);return this.parent(A.from,A.to);
+}});Element.Properties.tween={set:function(A){var B=this.retrieve("tween");if(B){B.cancel();}return this.eliminate("tween").store("tween:options",$extend({link:"cancel"},A));
+},get:function(A){if(A||!this.retrieve("tween")){if(A||!this.retrieve("tween:options")){this.set("tween",A);}this.store("tween",new Fx.Tween(this,this.retrieve("tween:options")));
+}return this.retrieve("tween");}};Element.implement({tween:function(A,C,B){this.get("tween").start(arguments);return this;},fade:function(C){var E=this.get("tween"),D="opacity",A;
+C=$pick(C,"toggle");switch(C){case"in":E.start(D,1);break;case"out":E.start(D,0);break;case"show":E.set(D,1);break;case"hide":E.set(D,0);break;case"toggle":var B=this.retrieve("fade:flag",this.get("opacity")==1);
+E.start(D,(B)?0:1);this.store("fade:flag",!B);A=true;break;default:E.start(D,arguments);}if(!A){this.eliminate("fade:flag");}return this;},highlight:function(C,A){if(!A){A=this.retrieve("highlight:original",this.getStyle("background-color"));
+A=(A=="transparent")?"#fff":A;}var B=this.get("tween");B.start("background-color",C||"#ffff88",A).chain(function(){this.setStyle("background-color",this.retrieve("highlight:original"));
+B.callChain();}.bind(this));return this;}});Fx.Morph=new Class({Extends:Fx.CSS,initialize:function(B,A){this.element=this.subject=$(B);this.parent(A);},set:function(A){if(typeof A=="string"){A=this.search(A);
+}for(var B in A){this.render(this.element,B,A[B],this.options.unit);}return this;},compute:function(E,D,C){var A={};for(var B in E){A[B]=this.parent(E[B],D[B],C);
+}return A;},start:function(B){if(!this.check(arguments.callee,B)){return this;}if(typeof B=="string"){B=this.search(B);}var E={},D={};for(var C in B){var A=this.prepare(this.element,C,B[C]);
+E[C]=A.from;D[C]=A.to;}return this.parent(E,D);}});Element.Properties.morph={set:function(A){var B=this.retrieve("morph");if(B){B.cancel();}return this.eliminate("morph").store("morph:options",$extend({link:"cancel"},A));
+},get:function(A){if(A||!this.retrieve("morph")){if(A||!this.retrieve("morph:options")){this.set("morph",A);}this.store("morph",new Fx.Morph(this,this.retrieve("morph:options")));
+}return this.retrieve("morph");}};Element.implement({morph:function(A){this.get("morph").start(A);return this;}});(function(){var A=Fx.prototype.initialize;
+Fx.prototype.initialize=function(B){A.call(this,B);var C=this.options.transition;if(typeof C=="string"&&(C=C.split(":"))){var D=Fx.Transitions;D=D[C[0]]||D[C[0].capitalize()];
+if(C[1]){D=D["ease"+C[1].capitalize()+(C[2]?C[2].capitalize():"")];}this.options.transition=D;}};})();Fx.Transition=function(B,A){A=$splat(A);return $extend(B,{easeIn:function(C){return B(C,A);
+},easeOut:function(C){return 1-B(1-C,A);},easeInOut:function(C){return(C<=0.5)?B(2*C,A)/2:(2-B(2*(1-C),A))/2;}});};Fx.Transitions=new Hash({linear:$arguments(0)});
+Fx.Transitions.extend=function(A){for(var B in A){Fx.Transitions[B]=new Fx.Transition(A[B]);}};Fx.Transitions.extend({Pow:function(B,A){return Math.pow(B,A[0]||6);
+},Expo:function(A){return Math.pow(2,8*(A-1));},Circ:function(A){return 1-Math.sin(Math.acos(A));},Sine:function(A){return 1-Math.sin((1-A)*Math.PI/2);
+},Back:function(B,A){A=A[0]||1.618;return Math.pow(B,2)*((A+1)*B-A);},Bounce:function(D){var C;for(var B=0,A=1;1;B+=A,A/=2){if(D>=(7-4*B)/11){C=-Math.pow((11-6*B-11*D)/4,2)+A*A;
+break;}}return C;},Elastic:function(B,A){return Math.pow(2,10*--B)*Math.cos(20*B*Math.PI*(A[0]||1)/3);}});["Quad","Cubic","Quart","Quint"].each(function(B,A){Fx.Transitions[B]=new Fx.Transition(function(C){return Math.pow(C,[A+2]);
+});});var Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false},initialize:function(A){this.xhr=new Browser.Request();
 this.setOptions(A);this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.headers=new Hash(this.options.headers);},onStateChange:function(){if(this.xhr.readyState!=4||!this.running){return ;
 }this.running=false;this.status=0;$try(function(){this.status=this.xhr.status;}.bind(this));if(this.options.isSuccess.call(this,this.status)){this.response={text:this.xhr.responseText,xml:this.xhr.responseXML};
 this.success(this.response.text,this.response.xml);}else{this.response={text:null,xml:null};this.failure();}this.xhr.onreadystatechange=$empty;},isSuccess:function(){return((this.status>=200)&&(this.status<300));
@@ -272,6 +329,13 @@ this.fireEvent("request");this.xhr.send(E);if(!this.options.async){this.onStateC
 return this.send($extend(C,{method:B.toLowerCase()}));};});Request.implement(A);})();Element.Properties.send={set:function(A){var B=this.retrieve("send");
 if(B){B.cancel();}return this.eliminate("send").store("send:options",$extend({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")},A));
 },get:function(A){if(A||!this.retrieve("send")){if(A||!this.retrieve("send:options")){this.set("send",A);}this.store("send",new Request(this.retrieve("send:options")));
-}return this.retrieve("send");}};Element.implement({send:function(A){var B=this.get("send");B.send({data:this,url:A||B.options.url});return this;}});Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(A){this.parent(A);
-this.headers.extend({Accept:"application/json","X-Request":"JSON"});},success:function(A){this.response.json=JSON.decode(A,this.options.secure);this.onSuccess(this.response.json,A);
-}});
\ No newline at end of file
+}return this.retrieve("send");}};Element.implement({send:function(A){var B=this.get("send");B.send({data:this,url:A||B.options.url});return this;}});Request.HTML=new Class({Extends:Request,options:{update:false,evalScripts:true,filter:false},processHTML:function(C){var B=C.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
+C=(B)?B[1]:C;var A=new Element("div");return $try(function(){var D="<root>"+C+"</root>",G;if(Browser.Engine.trident){G=new ActiveXObject("Microsoft.XMLDOM");
+G.async=false;G.loadXML(D);}else{G=new DOMParser().parseFromString(D,"text/xml");}D=G.getElementsByTagName("root")[0];for(var F=0,E=D.childNodes.length;
+F<E;F++){var H=Element.clone(D.childNodes[F],true,true);if(H){A.grab(H);}}return A;})||A.set("html",C);},success:function(D){var C=this.options,B=this.response;
+B.html=D.stripScripts(function(E){B.javascript=E;});var A=this.processHTML(B.html);B.tree=A.childNodes;B.elements=A.getElements("*");if(C.filter){B.tree=B.elements.filter(C.filter);
+}if(C.update){$(C.update).empty().adopt(B.tree);}if(C.evalScripts){$exec(B.javascript);}this.onSuccess(B.tree,B.elements,B.html,B.javascript);}});Element.Properties.load={set:function(A){var B=this.retrieve("load");
+if(B){send.cancel();}return this.eliminate("load").store("load:options",$extend({data:this,link:"cancel",update:this,method:"get"},A));},get:function(A){if(A||!this.retrieve("load")){if(A||!this.retrieve("load:options")){this.set("load",A);
+}this.store("load",new Request.HTML(this.retrieve("load:options")));}return this.retrieve("load");}};Element.implement({load:function(){this.get("load").send(Array.link(arguments,{data:Object.type,url:String.type}));
+return this;}});Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(A){this.parent(A);this.headers.extend({Accept:"application/json","X-Request":"JSON"});
+},success:function(A){this.response.json=JSON.decode(A,this.options.secure);this.onSuccess(this.response.json,A);}});
\ No newline at end of file
diff --git a/static/js/mootools-1.2-more.js b/static/js/mootools-1.2-more.js
new file mode 100644 (file)
index 0000000..39eaa6e
--- /dev/null
@@ -0,0 +1,153 @@
+//MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2008 Valerio Proietti, <http://mad4milk.net>, MIT Style License.
+
+Fx.Slide=new Class({Extends:Fx,options:{mode:"vertical"},initialize:function(B,A){this.addEvent("complete",function(){this.open=(this.wrapper["offset"+this.layout.capitalize()]!=0);
+if(this.open&&Browser.Engine.webkit419){this.element.dispose().inject(this.wrapper);}},true);this.element=this.subject=$(B);this.parent(A);var C=this.element.retrieve("wrapper");
+this.wrapper=C||new Element("div",{styles:$extend(this.element.getStyles("margin","position"),{overflow:"hidden"})}).wraps(this.element);this.element.store("wrapper",this.wrapper).setStyle("margin",0);
+this.now=[];this.open=true;},vertical:function(){this.margin="margin-top";this.layout="height";this.offset=this.element.offsetHeight;},horizontal:function(){this.margin="margin-left";
+this.layout="width";this.offset=this.element.offsetWidth;},set:function(A){this.element.setStyle(this.margin,A[0]);this.wrapper.setStyle(this.layout,A[1]);
+return this;},compute:function(E,D,C){var B=[];var A=2;A.times(function(F){B[F]=Fx.compute(E[F],D[F],C);});return B;},start:function(B,E){if(!this.check(arguments.callee,B,E)){return this;
+}this[E||this.options.mode]();var D=this.element.getStyle(this.margin).toInt();var C=this.wrapper.getStyle(this.layout).toInt();var A=[[D,C],[0,this.offset]];
+var G=[[D,C],[-this.offset,0]];var F;switch(B){case"in":F=A;break;case"out":F=G;break;case"toggle":F=(this.wrapper["offset"+this.layout.capitalize()]==0)?A:G;
+}return this.parent(F[0],F[1]);},slideIn:function(A){return this.start("in",A);},slideOut:function(A){return this.start("out",A);},hide:function(A){this[A||this.options.mode]();
+this.open=false;return this.set([-this.offset,0]);},show:function(A){this[A||this.options.mode]();this.open=true;return this.set([0,this.offset]);},toggle:function(A){return this.start("toggle",A);
+}});Element.Properties.slide={set:function(B){var A=this.retrieve("slide");if(A){A.cancel();}return this.eliminate("slide").store("slide:options",$extend({link:"cancel"},B));
+},get:function(A){if(A||!this.retrieve("slide")){if(A||!this.retrieve("slide:options")){this.set("slide",A);}this.store("slide",new Fx.Slide(this,this.retrieve("slide:options")));
+}return this.retrieve("slide");}};Element.implement({slide:function(D,E){D=D||"toggle";var B=this.get("slide"),A;switch(D){case"hide":B.hide(E);break;case"show":B.show(E);
+break;case"toggle":var C=this.retrieve("slide:flag",B.open);B[(C)?"slideOut":"slideIn"](E);this.store("slide:flag",!C);A=true;break;default:B.start(D,E);
+}if(!A){this.eliminate("slide:flag");}return this;}});Fx.Scroll=new Class({Extends:Fx,options:{offset:{x:0,y:0},wheelStops:true},initialize:function(B,A){this.element=this.subject=$(B);
+this.parent(A);var D=this.cancel.bind(this,false);if($type(this.element)!="element"){this.element=$(this.element.getDocument().body);}var C=this.element;
+if(this.options.wheelStops){this.addEvent("start",function(){C.addEvent("mousewheel",D);},true);this.addEvent("complete",function(){C.removeEvent("mousewheel",D);
+},true);}},set:function(){var A=Array.flatten(arguments);this.element.scrollTo(A[0],A[1]);},compute:function(E,D,C){var B=[];var A=2;A.times(function(F){B.push(Fx.compute(E[F],D[F],C));
+});return B;},start:function(C,H){if(!this.check(arguments.callee,C,H)){return this;}var E=this.element.getSize(),F=this.element.getScrollSize();var B=this.element.getScroll(),D={x:C,y:H};
+for(var G in D){var A=F[G]-E[G];if($chk(D[G])){D[G]=($type(D[G])=="number")?D[G].limit(0,A):A;}else{D[G]=B[G];}D[G]+=this.options.offset[G];}return this.parent([B.x,B.y],[D.x,D.y]);
+},toTop:function(){return this.start(false,0);},toLeft:function(){return this.start(0,false);},toRight:function(){return this.start("right",false);},toBottom:function(){return this.start(false,"bottom");
+},toElement:function(B){var A=$(B).getPosition(this.element);return this.start(A.x,A.y);}});Fx.Elements=new Class({Extends:Fx.CSS,initialize:function(B,A){this.elements=this.subject=$$(B);
+this.parent(A);},compute:function(G,H,I){var C={};for(var D in G){var A=G[D],E=H[D],F=C[D]={};for(var B in A){F[B]=this.parent(A[B],E[B],I);}}return C;
+},set:function(B){for(var C in B){var A=B[C];for(var D in A){this.render(this.elements[C],D,A[D],this.options.unit);}}return this;},start:function(C){if(!this.check(arguments.callee,C)){return this;
+}var H={},I={};for(var D in C){var F=C[D],A=H[D]={},G=I[D]={};for(var B in F){var E=this.prepare(this.elements[D],B,F[B]);A[B]=E.from;G[B]=E.to;}}return this.parent(H,I);
+}});var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,modifiers:{x:"left",y:"top"}},initialize:function(){var B=Array.link(arguments,{options:Object.type,element:$defined});
+this.element=$(B.element);this.document=this.element.getDocument();this.setOptions(B.options||{});var A=$type(this.options.handle);this.handles=(A=="array"||A=="collection")?$$(this.options.handle):$(this.options.handle)||this.element;
+this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection=(Browser.Engine.trident)?"selectstart":"mousedown";this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:$lambda(false)};
+this.attach();},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this;},detach:function(){this.handles.removeEvent("mousedown",this.bound.start);
+return this;},start:function(C){if(this.options.preventDefault){C.preventDefault();}this.fireEvent("beforeStart",this.element);this.mouse.start=C.page;
+var A=this.options.limit;this.limit={x:[],y:[]};for(var D in this.options.modifiers){if(!this.options.modifiers[D]){continue;}if(this.options.style){this.value.now[D]=this.element.getStyle(this.options.modifiers[D]).toInt();
+}else{this.value.now[D]=this.element[this.options.modifiers[D]];}if(this.options.invert){this.value.now[D]*=-1;}this.mouse.pos[D]=C.page[D]-this.value.now[D];
+if(A&&A[D]){for(var B=2;B--;B){if($chk(A[D][B])){this.limit[D][B]=$lambda(A[D][B])();}}}}if($type(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid};
+}this.document.addEvents({mousemove:this.bound.check,mouseup:this.bound.cancel});this.document.addEvent(this.selection,this.bound.eventStop);},check:function(A){if(this.options.preventDefault){A.preventDefault();
+}var B=Math.round(Math.sqrt(Math.pow(A.page.x-this.mouse.start.x,2)+Math.pow(A.page.y-this.mouse.start.y,2)));if(B>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop});
+this.fireEvent("start",this.element).fireEvent("snap",this.element);}},drag:function(A){if(this.options.preventDefault){A.preventDefault();}this.mouse.now=A.page;
+for(var B in this.options.modifiers){if(!this.options.modifiers[B]){continue;}this.value.now[B]=this.mouse.now[B]-this.mouse.pos[B];if(this.options.invert){this.value.now[B]*=-1;
+}if(this.options.limit&&this.limit[B]){if($chk(this.limit[B][1])&&(this.value.now[B]>this.limit[B][1])){this.value.now[B]=this.limit[B][1];}else{if($chk(this.limit[B][0])&&(this.value.now[B]<this.limit[B][0])){this.value.now[B]=this.limit[B][0];
+}}}if(this.options.grid[B]){this.value.now[B]-=(this.value.now[B]%this.options.grid[B]);}if(this.options.style){this.element.setStyle(this.options.modifiers[B],this.value.now[B]+this.options.unit);
+}else{this.element[this.options.modifiers[B]]=this.value.now[B];}}this.fireEvent("drag",this.element);},cancel:function(A){this.document.removeEvent("mousemove",this.bound.check);
+this.document.removeEvent("mouseup",this.bound.cancel);if(A){this.document.removeEvent(this.selection,this.bound.eventStop);this.fireEvent("cancel",this.element);
+}},stop:function(A){this.document.removeEvent(this.selection,this.bound.eventStop);this.document.removeEvent("mousemove",this.bound.drag);this.document.removeEvent("mouseup",this.bound.stop);
+if(A){this.fireEvent("complete",this.element);}}});Element.implement({makeResizable:function(A){return new Drag(this,$merge({modifiers:{x:"width",y:"height"}},A));
+}});Drag.Move=new Class({Extends:Drag,options:{droppables:[],container:false},initialize:function(C,B){this.parent(C,B);this.droppables=$$(this.options.droppables);
+this.container=$(this.options.container);if(this.container&&$type(this.container)!="element"){this.container=$(this.container.getDocument().body);}C=this.element;
+var D=C.getStyle("position");var A=(D!="static")?D:"absolute";if(C.getStyle("left")=="auto"||C.getStyle("top")=="auto"){C.position(C.getPosition(C.offsetParent));
+}C.setStyle("position",A);this.addEvent("start",function(){this.checkDroppables();},true);},start:function(B){if(this.container){var D=this.element,J=this.container,E=J.getCoordinates(D.offsetParent),F={},A={};
+["top","right","bottom","left"].each(function(K){F[K]=J.getStyle("padding-"+K).toInt();A[K]=D.getStyle("margin-"+K).toInt();},this);var C=D.offsetWidth+A.left+A.right,I=D.offsetHeight+A.top+A.bottom;
+var H=[E.left+F.left,E.right-F.right-C];var G=[E.top+F.top,E.bottom-F.bottom-I];this.options.limit={x:H,y:G};}this.parent(B);},checkAgainst:function(B){B=B.getCoordinates();
+var A=this.mouse.now;return(A.x>B.left&&A.x<B.right&&A.y<B.bottom&&A.y>B.top);},checkDroppables:function(){var A=this.droppables.filter(this.checkAgainst,this).getLast();
+if(this.overed!=A){if(this.overed){this.fireEvent("leave",[this.element,this.overed]);}if(A){this.overed=A;this.fireEvent("enter",[this.element,A]);}else{this.overed=null;
+}}},drag:function(A){this.parent(A);if(this.droppables.length){this.checkDroppables();}},stop:function(A){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed]);
+this.overed=null;return this.parent(A);}});Element.implement({makeDraggable:function(A){return new Drag.Move(this,A);}});Hash.Cookie=new Class({Extends:Cookie,options:{autoSave:true},initialize:function(B,A){this.parent(B,A);
+this.load();},save:function(){var A=JSON.encode(this.hash);if(!A||A.length>4096){return false;}if(A=="{}"){this.dispose();}else{this.write(A);}return true;
+},load:function(){this.hash=new Hash(JSON.decode(this.read(),true));return this;}});Hash.Cookie.implement((function(){var A={};Hash.each(Hash.prototype,function(C,B){A[B]=function(){var D=C.apply(this.hash,arguments);
+if(this.options.autoSave){this.save();}return D;};});return A;})());var Color=new Native({initialize:function(B,C){if(arguments.length>=3){C="rgb";B=Array.slice(arguments,0,3);
+}else{if(typeof B=="string"){if(B.match(/rgb/)){B=B.rgbToHex().hexToRgb(true);}else{if(B.match(/hsb/)){B=B.hsbToRgb();}else{B=B.hexToRgb(true);}}}}C=C||"rgb";
+switch(C){case"hsb":var A=B;B=B.hsbToRgb();B.hsb=A;break;case"hex":B=B.hexToRgb(true);break;}B.rgb=B.slice(0,3);B.hsb=B.hsb||B.rgbToHsb();B.hex=B.rgbToHex();
+return $extend(B,this);}});Color.implement({mix:function(){var A=Array.slice(arguments);var C=($type(A.getLast())=="number")?A.pop():50;var B=this.slice();
+A.each(function(D){D=new Color(D);for(var E=0;E<3;E++){B[E]=Math.round((B[E]/100*(100-C))+(D[E]/100*C));}});return new Color(B,"rgb");},invert:function(){return new Color(this.map(function(A){return 255-A;
+}));},setHue:function(A){return new Color([A,this.hsb[1],this.hsb[2]],"hsb");},setSaturation:function(A){return new Color([this.hsb[0],A,this.hsb[2]],"hsb");
+},setBrightness:function(A){return new Color([this.hsb[0],this.hsb[1],A],"hsb");}});function $RGB(C,B,A){return new Color([C,B,A],"rgb");}function $HSB(C,B,A){return new Color([C,B,A],"hsb");
+}function $HEX(A){return new Color(A,"hex");}Array.implement({rgbToHsb:function(){var B=this[0],C=this[1],J=this[2];var G,F,H;var I=Math.max(B,C,J),E=Math.min(B,C,J);
+var K=I-E;H=I/255;F=(I!=0)?K/I:0;if(F==0){G=0;}else{var D=(I-B)/K;var A=(I-C)/K;var L=(I-J)/K;if(B==I){G=L-A;}else{if(C==I){G=2+D-L;}else{G=4+A-D;}}G/=6;
+if(G<0){G++;}}return[Math.round(G*360),Math.round(F*100),Math.round(H*100)];},hsbToRgb:function(){var C=Math.round(this[2]/100*255);if(this[1]==0){return[C,C,C];
+}else{var A=this[0]%360;var E=A%60;var F=Math.round((this[2]*(100-this[1]))/10000*255);var D=Math.round((this[2]*(6000-this[1]*E))/600000*255);var B=Math.round((this[2]*(6000-this[1]*(60-E)))/600000*255);
+switch(Math.floor(A/60)){case 0:return[C,B,F];case 1:return[D,C,F];case 2:return[F,C,B];case 3:return[F,D,C];case 4:return[B,F,C];case 5:return[C,F,D];
+}}return false;}});String.implement({rgbToHsb:function(){var A=this.match(/\d{1,3}/g);return(A)?hsb.rgbToHsb():null;},hsbToRgb:function(){var A=this.match(/\d{1,3}/g);
+return(A)?A.hsbToRgb():null;}});var Group=new Class({initialize:function(){this.instances=Array.flatten(arguments);this.events={};this.checker={};},addEvent:function(B,A){this.checker[B]=this.checker[B]||{};
+this.events[B]=this.events[B]||[];if(this.events[B].contains(A)){return false;}else{this.events[B].push(A);}this.instances.each(function(C,D){C.addEvent(B,this.check.bind(this,[B,C,D]));
+},this);return this;},check:function(C,A,B){this.checker[C][B]=true;var D=this.instances.every(function(F,E){return this.checker[C][E]||false;},this);if(!D){return ;
+}this.checker[C]={};this.events[C].each(function(E){E.call(this,this.instances,A);},this);}});var Asset=new Hash({javascript:function(F,D){D=$extend({onload:$empty,document:document,check:$lambda(true)},D);
+var B=new Element("script",{src:F,type:"text/javascript"});var E=D.onload.bind(B),A=D.check,G=D.document;delete D.onload;delete D.check;delete D.document;
+B.addEvents({load:E,readystatechange:function(){if(["loaded","complete"].contains(this.readyState)){E();}}}).setProperties(D);if(Browser.Engine.webkit419){var C=(function(){if(!$try(A)){return ;
+}$clear(C);E();}).periodical(50);}return B.inject(G.head);},css:function(B,A){return new Element("link",$merge({rel:"stylesheet",media:"screen",type:"text/css",href:B},A)).inject(document.head);
+},image:function(C,B){B=$merge({onload:$empty,onabort:$empty,onerror:$empty},B);var D=new Image();var A=$(D)||new Element("img");["load","abort","error"].each(function(E){var F="on"+E;
+var G=B[F];delete B[F];D[F]=function(){if(!D){return ;}if(!A.parentNode){A.width=D.width;A.height=D.height;}D=D.onload=D.onabort=D.onerror=null;G.delay(1,A,A);
+A.fireEvent(E,A,1);};});D.src=A.src=C;if(D&&D.complete){D.onload.delay(1);}return A.setProperties(B);},images:function(D,C){C=$merge({onComplete:$empty,onProgress:$empty},C);
+if(!D.push){D=[D];}var A=[];var B=0;D.each(function(F){var E=new Asset.image(F,{onload:function(){C.onProgress.call(this,B,D.indexOf(F));B++;if(B==D.length){C.onComplete();
+}}});A.push(E);});return new Elements(A);}});var Sortables=new Class({Implements:[Events,Options],options:{snap:4,opacity:1,clone:false,revert:false,handle:false,constrain:false},initialize:function(A,B){this.setOptions(B);
+this.elements=[];this.lists=[];this.idle=true;this.addLists($$($(A)||A));if(!this.options.clone){this.options.revert=false;}if(this.options.revert){this.effect=new Fx.Morph(null,$merge({duration:250,link:"cancel"},this.options.revert));
+}},attach:function(){this.addLists(this.lists);return this;},detach:function(){this.lists=this.removeLists(this.lists);return this;},addItems:function(){Array.flatten(arguments).each(function(A){this.elements.push(A);
+var B=A.retrieve("sortables:start",this.start.bindWithEvent(this,A));(this.options.handle?A.getElement(this.options.handle)||A:A).addEvent("mousedown",B);
+},this);return this;},addLists:function(){Array.flatten(arguments).each(function(A){this.lists.push(A);this.addItems(A.getChildren());},this);return this;
+},removeItems:function(){var A=[];Array.flatten(arguments).each(function(B){A.push(B);this.elements.erase(B);var C=B.retrieve("sortables:start");(this.options.handle?B.getElement(this.options.handle)||B:B).removeEvent("mousedown",C);
+},this);return $$(A);},removeLists:function(){var A=[];Array.flatten(arguments).each(function(B){A.push(B);this.lists.erase(B);this.removeItems(B.getChildren());
+},this);return $$(A);},getClone:function(B,A){if(!this.options.clone){return new Element("div").inject(document.body);}if($type(this.options.clone)=="function"){return this.options.clone.call(this,B,A,this.list);
+}return A.clone(true).setStyles({margin:"0px",position:"absolute",visibility:"hidden",width:A.getStyle("width")}).inject(this.list).position(A.getPosition(A.getOffsetParent()));
+},getDroppables:function(){var A=this.list.getChildren();if(!this.options.constrain){A=this.lists.concat(A).erase(this.list);}return A.erase(this.clone).erase(this.element);
+},insert:function(C,B){var A="inside";if(this.lists.contains(B)){this.list=B;this.drag.droppables=this.getDroppables();}else{A=this.element.getAllPrevious().contains(B)?"before":"after";
+}this.element.inject(B,A);this.fireEvent("sort",[this.element,this.clone]);},start:function(B,A){if(!this.idle){return ;}this.idle=false;this.element=A;
+this.opacity=A.get("opacity");this.list=A.getParent();this.clone=this.getClone(B,A);this.drag=new Drag.Move(this.clone,{snap:this.options.snap,container:this.options.constrain&&this.element.getParent(),droppables:this.getDroppables(),onSnap:function(){B.stop();
+this.clone.setStyle("visibility","visible");this.element.set("opacity",this.options.opacity||0);this.fireEvent("start",[this.element,this.clone]);}.bind(this),onEnter:this.insert.bind(this),onCancel:this.reset.bind(this),onComplete:this.end.bind(this)});
+this.clone.inject(this.element,"before");this.drag.start(B);},end:function(){this.drag.detach();this.element.set("opacity",this.opacity);if(this.effect){var A=this.element.getStyles("width","height");
+var B=this.clone.computePosition(this.element.getPosition(this.clone.offsetParent));this.effect.element=this.clone;this.effect.start({top:B.top,left:B.left,width:A.width,height:A.height,opacity:0.25}).chain(this.reset.bind(this));
+}else{this.reset();}},reset:function(){this.idle=true;this.clone.destroy();this.fireEvent("complete",this.element);},serialize:function(){var C=Array.link(arguments,{modifier:Function.type,index:$defined});
+var B=this.lists.map(function(D){return D.getChildren().map(C.modifier||function(E){return E.get("id");},this);},this);var A=C.index;if(this.lists.length==1){A=0;
+}return $chk(A)&&A>=0&&A<this.lists.length?B[A]:B;}});var Tips=new Class({Implements:[Events,Options],options:{onShow:function(A){A.setStyle("visibility","visible");
+},onHide:function(A){A.setStyle("visibility","hidden");},showDelay:100,hideDelay:100,className:null,offsets:{x:16,y:16},fixed:false},initialize:function(){var C=Array.link(arguments,{options:Object.type,elements:$defined});
+this.setOptions(C.options||null);this.tip=new Element("div").inject(document.body);if(this.options.className){this.tip.addClass(this.options.className);
+}var B=new Element("div",{"class":"tip-top"}).inject(this.tip);this.container=new Element("div",{"class":"tip"}).inject(this.tip);var A=new Element("div",{"class":"tip-bottom"}).inject(this.tip);
+this.tip.setStyles({position:"absolute",top:0,left:0,visibility:"hidden"});if(C.elements){this.attach(C.elements);}},attach:function(A){$$(A).each(function(D){var G=D.retrieve("tip:title",D.get("title"));
+var F=D.retrieve("tip:text",D.get("rel")||D.get("href"));var E=D.retrieve("tip:enter",this.elementEnter.bindWithEvent(this,D));var C=D.retrieve("tip:leave",this.elementLeave.bindWithEvent(this,D));
+D.addEvents({mouseenter:E,mouseleave:C});if(!this.options.fixed){var B=D.retrieve("tip:move",this.elementMove.bindWithEvent(this,D));D.addEvent("mousemove",B);
+}D.store("tip:native",D.get("title"));D.erase("title");},this);return this;},detach:function(A){$$(A).each(function(C){C.removeEvent("mouseenter",C.retrieve("tip:enter")||$empty);
+C.removeEvent("mouseleave",C.retrieve("tip:leave")||$empty);C.removeEvent("mousemove",C.retrieve("tip:move")||$empty);C.eliminate("tip:enter").eliminate("tip:leave").eliminate("tip:move");
+var B=C.retrieve("tip:native");if(B){C.set("title",B);}});return this;},elementEnter:function(B,A){$A(this.container.childNodes).each(Element.dispose);
+var D=A.retrieve("tip:title");if(D){this.titleElement=new Element("div",{"class":"tip-title"}).inject(this.container);this.fill(this.titleElement,D);}var C=A.retrieve("tip:text");
+if(C){this.textElement=new Element("div",{"class":"tip-text"}).inject(this.container);this.fill(this.textElement,C);}this.timer=$clear(this.timer);this.timer=this.show.delay(this.options.showDelay,this);
+this.position((!this.options.fixed)?B:{page:A.getPosition()});},elementLeave:function(A){$clear(this.timer);this.timer=this.hide.delay(this.options.hideDelay,this);
+},elementMove:function(A){this.position(A);},position:function(D){var B=window.getSize(),A=window.getScroll();var E={x:this.tip.offsetWidth,y:this.tip.offsetHeight};
+var C={x:"left",y:"top"};for(var F in C){var G=D.page[F]+this.options.offsets[F];if((G+E[F]-A[F])>B[F]){G=D.page[F]-this.options.offsets[F]-E[F];}this.tip.setStyle(C[F],G);
+}},fill:function(A,B){(typeof B=="string")?A.set("html",B):A.adopt(B);},show:function(){this.fireEvent("show",this.tip);},hide:function(){this.fireEvent("hide",this.tip);
+}});var SmoothScroll=new Class({Extends:Fx.Scroll,initialize:function(B,C){C=C||document;var E=C.getDocument(),D=C.getWindow();this.parent(E,B);this.links=(this.options.links)?$$(this.options.links):$$(E.links);
+var A=D.location.href.match(/^[^#]*/)[0]+"#";this.links.each(function(G){if(G.href.indexOf(A)!=0){return ;}var F=G.href.substr(A.length);if(F&&$(F)){this.useLink(G,F);
+}},this);if(!Browser.Engine.webkit419){this.addEvent("complete",function(){D.location.hash=this.anchor;},true);}},useLink:function(B,A){B.addEvent("click",function(C){this.anchor=A;
+this.toElement(A);C.stop();}.bind(this));}});var Slider=new Class({Implements:[Events,Options],options:{onTick:function(A){if(this.options.snap){A=this.toPosition(this.step);
+}this.knob.setStyle(this.property,A);},snap:false,offset:0,range:false,wheel:false,steps:100,mode:"horizontal"},initialize:function(E,A,D){this.setOptions(D);
+this.element=$(E);this.knob=$(A);this.previousChange=this.previousEnd=this.step=-1;this.element.addEvent("mousedown",this.clickedElement.bind(this));if(this.options.wheel){this.element.addEvent("mousewheel",this.scrolledElement.bindWithEvent(this));
+}var F,B={},C={x:false,y:false};switch(this.options.mode){case"vertical":this.axis="y";this.property="top";F="offsetHeight";break;case"horizontal":this.axis="x";
+this.property="left";F="offsetWidth";}this.half=this.knob[F]/2;this.full=this.element[F]-this.knob[F]+(this.options.offset*2);this.min=$chk(this.options.range[0])?this.options.range[0]:0;
+this.max=$chk(this.options.range[1])?this.options.range[1]:this.options.steps;this.range=this.max-this.min;this.steps=this.options.steps||this.full;this.stepSize=Math.abs(this.range)/this.steps;
+this.stepWidth=this.stepSize*this.full/Math.abs(this.range);this.knob.setStyle("position","relative").setStyle(this.property,-this.options.offset);C[this.axis]=this.property;
+B[this.axis]=[-this.options.offset,this.full-this.options.offset];this.drag=new Drag(this.knob,{snap:0,limit:B,modifiers:C,onDrag:this.draggedKnob.bind(this),onStart:this.draggedKnob.bind(this),onComplete:function(){this.draggedKnob();
+this.end();}.bind(this)});if(this.options.snap){this.drag.options.grid=Math.ceil(this.stepWidth);this.drag.options.limit[this.axis][1]=this.full;}},set:function(A){if(!((this.range>0)^(A<this.min))){A=this.min;
+}if(!((this.range>0)^(A>this.max))){A=this.max;}this.step=Math.round(A);this.checkStep();this.end();this.fireEvent("tick",this.toPosition(this.step));return this;
+},clickedElement:function(C){var B=this.range<0?-1:1;var A=C.page[this.axis]-this.element.getPosition()[this.axis]-this.half;A=A.limit(-this.options.offset,this.full-this.options.offset);
+this.step=Math.round(this.min+B*this.toStep(A));this.checkStep();this.end();this.fireEvent("tick",A);},scrolledElement:function(A){var B=(this.options.mode=="horizontal")?(A.wheel<0):(A.wheel>0);
+this.set(B?this.step-this.stepSize:this.step+this.stepSize);A.stop();},draggedKnob:function(){var B=this.range<0?-1:1;var A=this.drag.value.now[this.axis];
+A=A.limit(-this.options.offset,this.full-this.options.offset);this.step=Math.round(this.min+B*this.toStep(A));this.checkStep();},checkStep:function(){if(this.previousChange!=this.step){this.previousChange=this.step;
+this.fireEvent("change",this.step);}},end:function(){if(this.previousEnd!==this.step){this.previousEnd=this.step;this.fireEvent("complete",this.step+"");
+}},toStep:function(A){var B=(A+this.options.offset)*this.stepSize/this.full*this.steps;return this.options.steps?Math.round(B-=B%this.stepSize):B;},toPosition:function(A){return(this.full*Math.abs(this.min-A))/(this.steps*this.stepSize)-this.options.offset;
+}});var Scroller=new Class({Implements:[Events,Options],options:{area:20,velocity:1,onChange:function(A,B){this.element.scrollTo(A,B);}},initialize:function(B,A){this.setOptions(A);
+this.element=$(B);this.listener=($type(this.element)!="element")?$(this.element.getDocument().body):this.element;this.timer=null;this.coord=this.getCoords.bind(this);
+},start:function(){this.listener.addEvent("mousemove",this.coord);},stop:function(){this.listener.removeEvent("mousemove",this.coord);this.timer=$clear(this.timer);
+},getCoords:function(A){this.page=(this.listener.get("tag")=="body")?A.client:A.page;if(!this.timer){this.timer=this.scroll.periodical(50,this);}},scroll:function(){var B=this.element.getSize(),A=this.element.getScroll(),E=this.element.getPosition(),D={x:0,y:0};
+for(var C in this.page){if(this.page[C]<(this.options.area+E[C])&&A[C]!=0){D[C]=(this.page[C]-this.options.area-E[C])*this.options.velocity;}else{if(this.page[C]+this.options.area>(B[C]+E[C])&&B[C]+B[C]!=A[C]){D[C]=(this.page[C]-B[C]+this.options.area-E[C])*this.options.velocity;
+}}}if(D.y||D.x){this.fireEvent("change",[A.x+D.x,A.y+D.y]);}}});var Accordion=new Class({Extends:Fx.Elements,options:{display:0,show:false,height:true,width:false,opacity:true,fixedHeight:false,fixedWidth:false,wait:false,alwaysHide:false},initialize:function(){var C=Array.link(arguments,{container:Element.type,options:Object.type,togglers:$defined,elements:$defined});
+this.parent(C.elements,C.options);this.togglers=$$(C.togglers);this.container=$(C.container);this.previous=-1;if(this.options.alwaysHide){this.options.wait=true;
+}if($chk(this.options.show)){this.options.display=false;this.previous=this.options.show;}if(this.options.start){this.options.display=false;this.options.show=false;
+}this.effects={};if(this.options.opacity){this.effects.opacity="fullOpacity";}if(this.options.width){this.effects.width=this.options.fixedWidth?"fullWidth":"offsetWidth";
+}if(this.options.height){this.effects.height=this.options.fixedHeight?"fullHeight":"scrollHeight";}for(var B=0,A=this.togglers.length;B<A;B++){this.addSection(this.togglers[B],this.elements[B]);
+}this.elements.each(function(E,D){if(this.options.show===D){this.fireEvent("active",[this.togglers[D],E]);}else{for(var F in this.effects){E.setStyle(F,0);
+}}},this);if($chk(this.options.display)){this.display(this.options.display);}},addSection:function(E,C,G){E=$(E);C=$(C);var F=this.togglers.contains(E);
+var B=this.togglers.length;this.togglers.include(E);this.elements.include(C);if(B&&(!F||G)){G=$pick(G,B-1);E.inject(this.togglers[G],"before");C.inject(E,"after");
+}else{if(this.container&&!F){E.inject(this.container);C.inject(this.container);}}var A=this.togglers.indexOf(E);E.addEvent("click",this.display.bind(this,A));
+if(this.options.height){C.setStyles({"padding-top":0,"border-top":"none","padding-bottom":0,"border-bottom":"none"});}if(this.options.width){C.setStyles({"padding-left":0,"border-left":"none","padding-right":0,"border-right":"none"});
+}C.fullOpacity=1;if(this.options.fixedWidth){C.fullWidth=this.options.fixedWidth;}if(this.options.fixedHeight){C.fullHeight=this.options.fixedHeight;}C.setStyle("overflow","hidden");
+if(!F){for(var D in this.effects){C.setStyle(D,0);}}return this;},display:function(A){A=($type(A)=="element")?this.elements.indexOf(A):A;if((this.timer&&this.options.wait)||(A===this.previous&&!this.options.alwaysHide)){return this;
+}this.previous=A;var B={};this.elements.each(function(E,D){B[D]={};var C=(D!=A)||(this.options.alwaysHide&&(E.offsetHeight>0));this.fireEvent(C?"background":"active",[this.togglers[D],E]);
+for(var F in this.effects){B[D][F]=C?0:E[this.effects[F]];}},this);return this.start(B);}});
\ No newline at end of file
diff --git a/static/mochaui.html b/static/mochaui.html
new file mode 100644 (file)
index 0000000..8b919cb
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <title>QuakeNet Web IRC</title>
+  <link rel="stylesheet" href="css/colours.css" type="text/css">
+  <link rel="stylesheet" href="css/mochaui/layout.css" type="text/css">
+  <link rel="stylesheet" href="css/mochaui/ui.css" type="text/css">
+  <link rel="stylesheet" href="css/mochaui/content.css" type="text/css">
+  <!--[if IE]>
+    <script type="text/javascript" src="js/excanvas-compressed.js"></script>           
+       <![endif]-->
+  <script type="text/javascript" src="js/mootools-1.2-core.js"></script>
+  <script type="text/javascript" src="js/mootools-1.2-more.js"></script>
+  <script type="text/javascript" src="js/mocha.js"></script>
+  <script type="text/javascript" src="js/qwebirc.js"></script>
+  <script type="text/javascript" src="js/mochaui.js"></script>
+  <script type="text/javascript">
+    new QWebIRCInterface("ircui", QMochaUI);
+  </script>
+</head>
+<body scroll="no">
+  <div id="desktop">
+    <div id="desktopHeader"></div>
+    <div id="dockWrapper">
+       <div id="dock">
+               <div id="dockPlacement"></div>
+               <div id="dockAutoHide"></div>
+               <div id="dockSort">
+          <div id="dockClear" class="clear"></div>
+        </div>
+       </div>
+    </div>
+    <div id="pageWrapper"></div>
+    <div id="desktopFooterWrapper"></div>
+  </div>
+  <div id="ircui"></div>
+</body>
+</html>
diff --git a/static/mochauidebug.html b/static/mochauidebug.html
new file mode 100644 (file)
index 0000000..d37f1d0
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <title>QuakeNet Web IRC</title>
+  <link rel="stylesheet" href="css/colours.css" type="text/css">
+  <link rel="stylesheet" href="css/mochaui/layout.css" type="text/css">
+  <link rel="stylesheet" href="css/mochaui/ui.css" type="text/css">
+  <link rel="stylesheet" href="css/mochaui/content.css" type="text/css">
+  <!--[if IE]>
+    <script type="text/javascript" src="js/excanvas-compressed.js"></script>           
+       <![endif]-->
+  <script type="text/javascript" src="js/mootools-1.2-core.js"></script>
+  <script type="text/javascript" src="js/mootools-1.2-more.js"></script>
+  <script type="text/javascript" src="js/mocha.js"></script>
+  <script type="text/javascript" src="js/debug/version.js"></script>
+  <script type="text/javascript" src="js/debug/jslib.js"></script>
+  <script type="text/javascript" src="js/debug/irc/ircconnection.js"></script>
+  <script type="text/javascript" src="js/debug/irc/irclib.js"></script>
+  <script type="text/javascript" src="js/debug/irc/baseircclient.js"></script>
+  <script type="text/javascript" src="js/debug/irc/irctracker.js"></script>
+  <script type="text/javascript" src="js/debug/irc/commandparser.js"></script>
+  <script type="text/javascript" src="js/debug/irc/ircclient.js"></script>
+  <script type="text/javascript" src="js/debug/ui/baseui.js"></script>
+  <script type="text/javascript" src="js/debug/ui/baseuiwindow.js"></script>
+  <script type="text/javascript" src="js/debug/ui/colour.js"></script>
+  <script type="text/javascript" src="js/debug/ui/theme.js"></script>
+  <script type="text/javascript" src="js/debug/ui/mochaui.js"></script>
+  <script type="text/javascript" src="js/debug/qwebircinterface.js"></script>
+  <script type="text/javascript">
+    new QWebIRCInterface("ircui", QMochaUI);
+  </script>
+</head>
+<body scroll="no">
+  <div id="desktop">
+    <div id="desktopHeader"></div>
+    <div id="dockWrapper">
+       <div id="dock">
+               <div id="dockPlacement"></div>
+               <div id="dockAutoHide"></div>
+               <div id="dockSort">
+          <div id="dockClear" class="clear"></div>
+        </div>
+       </div>
+    </div>
+    <div id="pageWrapper"></div>
+    <div id="desktopFooterWrapper"></div>
+  </div>
+  <div id="ircui"></div>
+</body>
+</html>
index 05d8fe7f55e864e7b73b147a16adb756b4b66fa1..5c50d605b59233d2c4ef874cf2460f0afa3f2c3d 100644 (file)
@@ -37,7 +37,6 @@ class QWebIRCServiceMaker(object):
   tapname = "qwebirc"
   description = "QuakeNet web-based IRC client"
   options = Options
-
   
   def makeService(self, config):
     if config['logfile']:
@@ -45,7 +44,6 @@ class QWebIRCServiceMaker(object):
     else:
       site = RootSite(config['staticpath'])
     
-    
     site.displayTracebacks = not config["notracebacks"]
     if config['https']:
       from twisted.internet.ssl import DefaultOpenSSLContextFactory