]> gitweb.factorcode.org Git - factor.git/commitdiff
fjsc: change to a furnace based responder
authorchris.double <chris.double@double.co.nz>
Mon, 11 Dec 2006 12:37:27 +0000 (12:37 +0000)
committerchris.double <chris.double@double.co.nz>
Mon, 11 Dec 2006 12:37:27 +0000 (12:37 +0000)
14 files changed:
apps/fjsc-responder/fjsc-responder.factor [deleted file]
apps/fjsc-responder/load.factor [deleted file]
apps/fjsc-responder/resources/bootstrap.js [deleted file]
apps/fjsc-responder/resources/yahoo/connection.js [deleted file]
apps/fjsc-responder/resources/yahoo/event.js [deleted file]
apps/fjsc-responder/resources/yahoo/yahoo.js [deleted file]
apps/furnace-fjsc/furnace-fjsc.factor [new file with mode: 0644]
apps/furnace-fjsc/load.factor [new file with mode: 0644]
apps/furnace-fjsc/repl.fhtml [new file with mode: 0644]
apps/furnace-fjsc/resources/bootstrap.js [new file with mode: 0644]
apps/furnace-fjsc/resources/yahoo/connection.js [new file with mode: 0644]
apps/furnace-fjsc/resources/yahoo/event.js [new file with mode: 0644]
apps/furnace-fjsc/resources/yahoo/yahoo.js [new file with mode: 0644]
libs/fjsc/fjsc.factor

diff --git a/apps/fjsc-responder/fjsc-responder.factor b/apps/fjsc-responder/fjsc-responder.factor
deleted file mode 100644 (file)
index 32844b8..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-! Copyright (C) 2006 Chris Double. All Rights Reserved.
-! See http://factorcode.org/license.txt for BSD license.
-!
-IN: fjsc-responder
-USING: kernel lazy-lists parser-combinators fjsc cont-responder html io namespaces file-responder httpd hashtables ;
-
-USE: prettyprint
-
-: fjsc-eval-page ( -- )
-  [ "response" get . ] string-out log-message
-  "code" "response" get hash dup log-message
-  serving-text
-  'expression' parse car 
-  parse-result-parsed compile write flush ;
-
-: fjsc-page ( -- )
-  [
-    <html>
-      <head> 
-        <script "text/javascript" =type "/responder/fjsc-resources/yahoo/yahoo.js" =src script> </script>
-        <script "text/javascript" =type "/responder/fjsc-resources/yahoo/event.js" =src script> </script>
-        <script "text/javascript" =type "/responder/fjsc-resources/yahoo/connection.js" =src script> </script>
-        <script "text/javascript" =type "/responder/fjsc-resources/bootstrap.js" =src script> </script>
-      </head>
-      <body>   
-       <form "toeval" =id "fjsc_eval(document.getElementById(\"toeval\"));return false;" =onsubmit "post" =method form>
-         <textarea "code" =name "code" =id textarea>
-         </textarea>
-         <input "submit" =type input/>
-       </form>
-       <div "compiled" =id div>
-       </div>
-       <div "stack" =id div>
-       </div>
-      </body>     
-    </html>
-  ] show ;
-  
-
-"fjsc" [ fjsc-page ] install-cont-responder
-"fjsceval" [ fjsc-eval-page ] add-simple-responder
-"fjsc-resources" [
-  [
-    "apps/fjsc-responder/resources/" resource-path "doc-root" set
-    file-responder
-  ] with-scope
-] add-simple-responder
-
-
diff --git a/apps/fjsc-responder/load.factor b/apps/fjsc-responder/load.factor
deleted file mode 100644 (file)
index 83b2878..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-! Copyright (C) 2006 Chris Double. All Rights Reserved.
-! See http://factorcode.org/license.txt for BSD license.
-!
-REQUIRES: libs/httpd libs/fjsc ;
-
-PROVIDE: apps/fjsc-responder 
-{ 
-  +files+ { 
-  "fjsc-responder.factor"
-  } 
-} {
-  +tests+ { 
-  }
-} { 
-  +help+ 
-  { 
-  } 
-} ;
diff --git a/apps/fjsc-responder/resources/bootstrap.js b/apps/fjsc-responder/resources/bootstrap.js
deleted file mode 100644 (file)
index 3885606..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-function fjsc_eval(form) {
-   var callback = {
-      success: function(o) {
-        var v = o.responseText;
-        eval(v)
-        display_datastack();
-        document.getElementById('compiled').innerHTML="<pre>" + v + "</pre>";
-        document.getElementById('code').value="";
-
-      }
-   };
-   YAHOO.util.Connect.setForm(form);
-   YAHOO.util.Connect.asyncRequest('POST', "/responder/fjsceval/", callback);
-}
-
-var data_stack = [ ] 
-
-function fjsc_dup() {
-   var v = data_stack.pop();
-   data_stack.push(v);
-   data_stack.push(v);
-}
-
-function fjsc_drop() {
-   data_stack.pop();
-}
-
-function fjsc_alert() {
-   alert(data_stack.pop())
-}
-
-function display_datastack() {
-   var html=[];
-   html.push("<table border='1'>")
-   for(var i = 0; i < data_stack.length; ++i) {
-      html.push("<tr><td>")
-      html.push(data_stack[i])
-      html.push("</td></tr>")
-   }
-   html.push("</table>")
-   document.getElementById('stack').innerHTML=html.join("");
-}
diff --git a/apps/fjsc-responder/resources/yahoo/connection.js b/apps/fjsc-responder/resources/yahoo/connection.js
deleted file mode 100644 (file)
index 098a3ab..0000000
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
-Copyright (c) 2006, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.net/yui/license.txt
-*/
-
-/**
- * The Connection Manager provides a simplified interface to the XMLHttpRequest
- * object.  It handles cross-browser instantiantion of XMLHttpRequest, negotiates the
- * interactive states and server response, returning the results to a pre-defined
- * callback you create.
- * @ class
- */
-YAHOO.util.Connect =
-{
-  /**
-   * Array of MSFT ActiveX ids for XMLHttpRequest.
-   * @private
-   * @type array
-   */
-       _msxml_progid:[
-               'MSXML2.XMLHTTP.5.0',
-               'MSXML2.XMLHTTP.4.0',
-               'MSXML2.XMLHTTP.3.0',
-               'MSXML2.XMLHTTP',
-               'Microsoft.XMLHTTP'
-               ],
-
-  /**
-   * Array of HTTP header(s)
-   * @private
-   * @type array
-   */
-       _http_header:{},
-
-  /**
-   * Determines if HTTP headers are set.
-   * @private
-   * @type boolean
-   */
-       _has_http_headers:false,
-
- /**
-  * Property modified by setForm() to determine if the data
-  * should be submitted as an HTML form.
-  * @private
-  * @type boolean
-  */
-       _isFormSubmit:false,
-
- /**
-  * Property modified by setForm() to set the HTML form data
-  * for each transaction.
-  * @private
-  * @type string
-  */
-       _sFormData:null,
-
- /**
-  * Collection of polling references to the polling mechanism in handleReadyState.
-  * @private
-  * @type string
-  */
-       _poll:[],
-
-  /**
-   * The polling frequency, in milliseconds, for HandleReadyState.
-   * when attempting to determine a transaction's XHR  readyState.
-   * The default is 50 milliseconds.
-   * @private
-   * @type int
-   */
-       _polling_interval:50,
-
-  /**
-   * A transaction counter that increments the transaction id for each transaction.
-   * @private
-   * @type int
-   */
-       _transaction_id:0,
-
-  /**
-   * Member to add an ActiveX id to the existing xml_progid array.
-   * In the event(unlikely) a new ActiveX id is introduced, it can be added
-   * without internal code modifications.
-   * @public
-   * @param string id The ActiveX id to be added to initialize the XHR object.
-   * @return void
-   */
-       setProgId:function(id)
-       {
-               this.msxml_progid.unshift(id);
-       },
-
-  /**
-   * Member to modify the default polling interval.
-   * @public
-   * @param {int} i The polling interval in milliseconds.
-   * @return void
-   */
-       setPollingInterval:function(i)
-       {
-               if(typeof i == 'number' && isFinite(i)){
-                       this._polling_interval = i;
-               }
-       },
-
-  /**
-   * Instantiates a XMLHttpRequest object and returns an object with two properties:
-   * the XMLHttpRequest instance and the transaction id.
-   * @private
-   * @param {int} transactionId Property containing the transaction id for this transaction.
-   * @return connection object
-   */
-       createXhrObject:function(transactionId)
-       {
-               var obj,http;
-               try
-               {
-                       // Instantiates XMLHttpRequest in non-IE browsers and assigns to http.
-                       http = new XMLHttpRequest();
-                       //  Object literal with http and tId properties
-                       obj = { conn:http, tId:transactionId };
-               }
-               catch(e)
-               {
-                       for(var i=0; i<this._msxml_progid.length; ++i){
-                               try
-                               {
-                                       // Instantiates XMLHttpRequest for IE and assign to http.
-                                       http = new ActiveXObject(this._msxml_progid[i]);
-                                       if(http){
-                                       //  Object literal with http and tId properties
-                                               obj = { conn:http, tId:transactionId };
-                                               break;
-                                       }
-                               }
-                               catch(e){}
-                       }
-               }
-               finally
-               {
-                       return obj;
-               }
-       },
-
-  /**
-   * This method is called by asyncRequest to create a
-   * valid connection object for the transaction.  It also passes a
-   * transaction id and increments the transaction id counter.
-   * @private
-   * @return object
-   */
-       getConnectionObject:function()
-       {
-               var o;
-               var tId = this._transaction_id;
-
-               try
-               {
-                       o = this.createXhrObject(tId);
-                       if(o){
-                               this._transaction_id++;
-                       }
-               }
-               catch(e){}
-               finally
-               {
-                       return o;
-               }
-       },
-
-  /**
-   * Method for initiating an asynchronous request via the XHR object.
-   * @public
-   * @param {string} method HTTP transaction method
-   * @param {string} uri Fully qualified path of resource
-   * @param callback User-defined callback function or object
-   * @param {string} postData POST body
-   * @return {object} Returns the connection object
-   */
-       asyncRequest:function(method, uri, callback, postData)
-       {
-               var o = this.getConnectionObject();
-
-               if(!o){
-                       return null;
-               }
-               else{
-                       if(this._isFormSubmit){
-                               //If the specified HTTP method is GET, setForm() will return an
-                               //encoded string that is concatenated to the uri to
-                               //create a querystring.
-                               if(method == 'GET'){
-                                       uri += "?" +  this._sFormData;
-                               }
-                               else if(method == 'POST'){
-                                       postData =  this._sFormData;
-                               }
-                               this._sFormData = '';
-                               this._isFormSubmit = false;
-                       }
-
-                       o.conn.open(method, uri, true);
-
-                       if(postData){
-                               this.initHeader('Content-Type','application/x-www-form-urlencoded');
-                       }
-
-                       //Verify whether the transaction has any user-defined HTTP headers
-                       //and set them.
-                       if(this._has_http_headers){
-                               this.setHeader(o);
-                       }
-
-                       this.handleReadyState(o, callback);
-                       postData?o.conn.send(postData):o.conn.send(null);
-
-                       return o;
-               }
-       },
-
-  /**
-   * This method serves as a timer that polls the XHR object's readyState
-   * property during a transaction, instead of binding a callback to the
-   * onreadystatechange event.  Upon readyState 4, handleTransactionResponse
-   * will process the response, and the timer will be cleared.
-   *
-   * @private
-   * @param {object} o The connection object
-   * @param callback User-defined callback object
-   * @return void
-   */
-       handleReadyState:function(o, callback)
-       {
-               var oConn = this;
-               try
-               {
-                       this._poll[o.tId] = window.setInterval(
-                               function(){
-                                       if(o.conn && o.conn.readyState == 4){
-                                               window.clearInterval(oConn._poll[o.tId]);
-                                               oConn._poll.splice(o.tId);
-                                               oConn.handleTransactionResponse(o, callback);
-                                       }
-                               }
-                       ,this._polling_interval);
-               }
-               catch(e)
-               {
-                       window.clearInterval(oConn._poll[o.tId]);
-                       oConn._poll.splice(o.tId);
-                       oConn.handleTransactionResponse(o, callback);
-               }
-       },
-
-  /**
-   * This method attempts to interpret the server response and
-   * determine whether the transaction was successful, or if an error or
-   * exception was encountered.
-   *
-   * @private
-   * @param {object} o The connection object
-   * @param {function} callback - User-defined callback object
-   * @return void
-   */
-       handleTransactionResponse:function(o, callback)
-       {
-               // If no valid callback is provided, then do not process any callback handling.
-               if(!callback){
-                       this.releaseObject(o);
-                       return;
-               }
-
-               var httpStatus;
-               var responseObject;
-
-               try
-               {
-                       httpStatus = o.conn.status;
-               }
-               catch(e){
-                       // 13030 is the custom code to indicate the condition -- in Mozilla/FF --
-                       // when the o object's status and statusText properties are
-                       // unavailable, and a query attempt throws an exception.
-                       httpStatus = 13030;
-               }
-
-               if(httpStatus >= 200 && httpStatus < 300){
-                       responseObject = this.createResponseObject(o, callback.argument);
-                       if(callback.success){
-                               if(!callback.scope){
-                                       callback.success(responseObject);
-                               }
-                               else{
-                                       // If a scope property is defined, the callback will be fired from
-                                       // the context of the object.
-                                       callback.success.apply(callback.scope, [responseObject]);
-                               }
-                       }
-               }
-               else{
-                       switch(httpStatus){
-                               // The following case labels are wininet.dll error codes that may be encountered.
-                               // Server timeout
-                               case 12002:
-                               // 12029 to 12031 correspond to dropped connections.
-                               case 12029:
-                               case 12030:
-                               case 12031:
-                               // Connection closed by server.
-                               case 12152:
-                               // See above comments for variable status.
-                               case 13030:
-                                       responseObject = this.createExceptionObject(o, callback.argument);
-                                       if(callback.failure){
-                                               if(!callback.scope){
-                                                       callback.failure(responseObject);
-                                               }
-                                               else{
-                                                       callback.failure.apply(callback.scope,[responseObject]);
-                                               }
-                                       }
-                                       break;
-                               default:
-                                       responseObject = this.createResponseObject(o, callback.argument);
-                                       if(callback.failure){
-                                               if(!callback.scope){
-                                                       callback.failure(responseObject);
-                                               }
-                                               else{
-                                                       callback.failure.apply(callback.scope,[responseObject]);
-                                               }
-                                       }
-                       }
-               }
-
-               this.releaseObject(o);
-       },
-
-  /**
-   * This method evaluates the server response, creates and returns the results via
-   * its properties.  Success and failure cases will differ in the response
-   * object's property values.
-   * @private
-   * @param {object} o The connection object
-   * @param {} callbackArg User-defined argument or arguments to be passed to the callback
-   * @return object
-   */
-       createResponseObject:function(o, callbackArg)
-       {
-               var obj = {};
-               var headerObj = {};
-
-               try
-               {
-                       var headerStr = o.conn.getAllResponseHeaders();
-                       var header = headerStr.split("\n");
-                       for(var i=0; i < header.length; i++){
-                               var delimitPos = header[i].indexOf(':');
-                               if(delimitPos != -1){
-                                       headerObj[header[i].substring(0,delimitPos)] = header[i].substring(delimitPos+1);
-                               }
-                       }
-
-                       obj.tId = o.tId;
-                       obj.status = o.conn.status;
-                       obj.statusText = o.conn.statusText;
-                       obj.getResponseHeader = headerObj;
-                       obj.getAllResponseHeaders = headerStr;
-                       obj.responseText = o.conn.responseText;
-                       obj.responseXML = o.conn.responseXML;
-                       if(typeof callbackArg !== undefined){
-                               obj.argument = callbackArg;
-                       }
-               }
-               catch(e){}
-               finally
-               {
-                       return obj;
-               }
-       },
-
-  /**
-   * If a transaction cannot be completed due to dropped or closed connections,
-   * there may be not be enough information to build a full response object.
-   * The failure callback will be fired and this specific condition can be identified
-   * by a status property value of 0.
-   * @private
-   * @param {int} tId Transaction Id
-   * @param callbackArg The user-defined arguments
-   * @return object
-   */
-       createExceptionObject:function(tId, callbackArg)
-       {
-               var COMM_CODE = 0;
-               var COMM_ERROR = 'communication failure';
-
-               var obj = {};
-
-               obj.tId = tId;
-               obj.status = COMM_CODE;
-               obj.statusText = COMM_ERROR;
-               if(callbackArg){
-                       obj.argument = callbackArg;
-               }
-
-               return obj;
-       },
-
-  /**
-   * Public method that stores the custom HTTP headers for each transaction.
-   * @public
-   * @param {string} label The HTTP header label
-   * @param {string} value The HTTP header value
-   * @return void
-   */
-       initHeader:function(label,value)
-       {
-               if(this._http_header[label] === undefined){
-                       this._http_header[label] = value;
-               }
-               else{
-                       this._http_header[label] =  value + "," + this._http_header[label];
-               }
-
-               this._has_http_headers = true;
-       },
-
-  /**
-   * Accessor that sets the HTTP headers for each transaction.
-   * @private
-   * @param {object} o The connection object for the transaction.
-   * @return void
-   */
-       setHeader:function(o)
-       {
-               for(var prop in this._http_header){
-                       o.conn.setRequestHeader(prop, this._http_header[prop]);
-               }
-               delete this._http_header;
-
-               this._http_header = {};
-               this._has_http_headers = false;
-       },
-
-  /**
-   * This method assembles the form label and value pairs and
-   * constructs an encoded string.
-   * asyncRequest() will automatically initialize the
-   * transaction with a HTTP header Content-Type of
-   * application/x-www-form-urlencoded.
-   * @public
-   * @param {string || object} form id or name attribute, or form object.
-   * @return void
-   */
-       setForm:function(formId)
-       {
-               this._sFormData = '';
-               if(typeof formId == 'string'){
-                       // Determine if the argument is a form id or a form name.
-                       // Note form name usage is deprecated by supported
-                       // here for legacy reasons.
-                       var oForm = (document.getElementById(formId) || document.forms[formId] );
-               }
-               else if(typeof formId == 'object'){
-                       var oForm = formId;
-               }
-               else{
-                       return;
-               }
-               var oElement, oName, oValue, oDisabled;
-               var hasSubmit = false;
-
-               // Iterate over the form elements collection to construct the
-               // label-value pairs.
-               for (var i=0; i<oForm.elements.length; i++){
-                       oDisabled = oForm.elements[i].disabled;
-                       // If the name attribute is not populated, the form field's
-                       // value will not be submitted.
-                       if(oForm.elements[i].name != ""){
-                               oElement = oForm.elements[i];
-                               oName = oForm.elements[i].name;
-                               oValue = oForm.elements[i].value;
-                       }
-
-                       // Do not submit fields that are disabled.
-                       if(!oDisabled)
-                       {
-                               switch (oElement.type)
-                               {
-                                       case 'select-one':
-                                       case 'select-multiple':
-                                               for(var j=0; j<oElement.options.length; j++){
-                                                       if(oElement.options[j].selected){
-                                                               this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oElement.options[j].value || oElement.options[j].text) + '&';
-                                                       }
-                                               }
-                                               break;
-                                       case 'radio':
-                                       case 'checkbox':
-                                               if(oElement.checked){
-                                                       this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
-                                               }
-                                               break;
-                                       case 'file':
-                                       //      this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
-                                       // stub case as XMLHttpRequest will only send the file path as a string.
-                                       case undefined:
-                                       // stub case for fieldset element which returns undefined.
-                                       case 'reset':
-                                       // stub case for input type reset button.
-                                       case 'button':
-                                       // stub case for input type button elements.
-                                               break;
-                                       case 'submit':
-                                               if(hasSubmit == false){
-                                                       this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
-                                                       hasSubmit = true;
-                                               }
-                                               break;
-                                       default:
-                                               this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
-                                               break;
-                               }
-                       }
-               }
-
-               this._isFormSubmit = true;
-               this._sFormData = this._sFormData.substr(0, this._sFormData.length - 1);
-       },
-
-  /**
-   * Public method to terminate a transaction, if it has not reached readyState 4.
-   * @public
-   * @param {object} o The connection object returned by asyncRequest.
-   * @return void
-   */
-       abort:function(o)
-       {
-               if(this.isCallInProgress(o)){
-                       window.clearInterval(this._poll[o.tId]);
-                       this._poll.splice(o.tId);
-                       o.conn.abort();
-                       this.releaseObject(o);
-
-                       return true;
-               }
-               else{
-                       return false;
-               }
-       },
-
-  /**
-   * Public method to check if the transaction is still being processed.
-   * @public
-   * @param {object} o The connection object returned by asyncRequest
-   * @return boolean
-   */
-       isCallInProgress:function(o)
-       {
-               // if the XHR object assigned to the transaction has not been dereferenced,
-               // then check its readyState status.  Otherwise, return false.
-               if(o.conn){
-                       return o.conn.readyState != 4 && o.conn.readyState != 0;
-               }
-               else{
-                       //The XHR object has been destroyed.
-                       return false;
-               }
-       },
-
-  /**
-   * Dereference the XHR instance and the connection object after the transaction is completed.
-   * @private
-   * @param {object} o The connection object
-   * @return void
-   */
-       releaseObject:function(o)
-       {
-               //dereference the XHR instance.
-               o.conn = null;
-               //dereference the connection object.
-               o = null;
-       }
-};
diff --git a/apps/fjsc-responder/resources/yahoo/event.js b/apps/fjsc-responder/resources/yahoo/event.js
deleted file mode 100644 (file)
index cc2a087..0000000
+++ /dev/null
@@ -1,1096 +0,0 @@
-/*                                                                                                                                                      \r
-Copyright (c) 2006, Yahoo! Inc. All rights reserved.                                                                                                    \r
-Code licensed under the BSD License:                                                                                                                    \r
-http://developer.yahoo.net/yui/license.txt                                                                                                              \r
-version: 0.10.0                                                                                                                                         \r
-*/ \r
-\r
-/**\r
- * The CustomEvent class lets you define events for your application\r
- * that can be subscribed to by one or more independent component.\r
- *\r
- * @param {String} type The type of event, which is passed to the callback\r
- *                 when the event fires\r
- * @param {Object} oScope The context the event will fire from.  "this" will\r
- *                 refer to this object in the callback.  Default value: \r
- *                 the window object.  The listener can override this.\r
- * @constructor\r
- */\r
-YAHOO.util.CustomEvent = function(type, oScope) {\r
-    /**\r
-     * The type of event, returned to subscribers when the event fires\r
-     * @type string\r
-     */\r
-    this.type = type;\r
-\r
-    /**\r
-     * The scope the the event will fire from by default.  Defaults to the window \r
-     * obj\r
-     * @type object\r
-     */\r
-    this.scope = oScope || window;\r
-\r
-    /**\r
-     * The subscribers to this event\r
-     * @type Subscriber[]\r
-     */\r
-    this.subscribers = [];\r
-\r
-    // Register with the event utility for automatic cleanup.  Made optional\r
-    // so that CustomEvent can be used independently of pe.event\r
-    if (YAHOO.util.Event) { \r
-        YAHOO.util.Event.regCE(this);\r
-    }\r
-};\r
-\r
-YAHOO.util.CustomEvent.prototype = {\r
-    /**\r
-     * Subscribes the caller to this event\r
-     * @param {Function} fn       The function to execute\r
-     * @param {Object}   obj      An object to be passed along when the event fires\r
-     * @param {boolean}  bOverride If true, the obj passed in becomes the execution\r
-     *                            scope of the listener\r
-     */\r
-    subscribe: function(fn, obj, bOverride) {\r
-        this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, bOverride) );\r
-    },\r
-\r
-    /**\r
-     * Unsubscribes the caller from this event\r
-     * @param {Function} fn  The function to execute\r
-     * @param {Object}   obj An object to be passed along when the event fires\r
-     * @return {boolean} True if the subscriber was found and detached.\r
-     */\r
-    unsubscribe: function(fn, obj) {\r
-        var found = false;\r
-        for (var i=0, len=this.subscribers.length; i<len; ++i) {\r
-            var s = this.subscribers[i];\r
-            if (s && s.contains(fn, obj)) {\r
-                this._delete(i);\r
-                found = true;\r
-            }\r
-        }\r
-\r
-        return found;\r
-    },\r
-\r
-    /**\r
-     * Notifies the subscribers.  The callback functions will be executed\r
-     * from the scope specified when the event was created, and with the following\r
-     * parameters:\r
-     *   <pre>\r
-     *   - The type of event\r
-     *   - All of the arguments fire() was executed with as an array\r
-     *   - The custom object (if any) that was passed into the subscribe() method\r
-     *   </pre>\r
-     *   \r
-     * @param {Array} an arbitrary set of parameters to pass to the handler\r
-     */\r
-    fire: function() {\r
-        for (var i=0, len=this.subscribers.length; i<len; ++i) {\r
-            var s = this.subscribers[i];\r
-            if (s) {\r
-                var scope = (s.override) ? s.obj : this.scope;\r
-                s.fn.call(scope, this.type, arguments, s.obj);\r
-            }\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Removes all listeners\r
-     */\r
-    unsubscribeAll: function() {\r
-        for (var i=0, len=this.subscribers.length; i<len; ++i) {\r
-            this._delete(i);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * @private\r
-     */\r
-    _delete: function(index) {\r
-        var s = this.subscribers[index];\r
-        if (s) {\r
-            delete s.fn;\r
-            delete s.obj;\r
-        }\r
-\r
-        delete this.subscribers[index];\r
-    }\r
-};\r
-\r
-/////////////////////////////////////////////////////////////////////\r
-\r
-/**\r
- * @class Stores the subscriber information to be used when the event fires.\r
- * @param {Function} fn       The function to execute\r
- * @param {Object}   obj      An object to be passed along when the event fires\r
- * @param {boolean}  bOverride If true, the obj passed in becomes the execution\r
- *                            scope of the listener\r
- * @constructor\r
- */\r
-YAHOO.util.Subscriber = function(fn, obj, bOverride) {\r
-    /**\r
-     * The callback that will be execute when the event fires\r
-     * @type function\r
-     */\r
-    this.fn = fn;\r
-\r
-    /**\r
-     * An optional custom object that will passed to the callback when\r
-     * the event fires\r
-     * @type object\r
-     */\r
-    this.obj = obj || null;\r
-\r
-    /**\r
-     * The default execution scope for the event listener is defined when the\r
-     * event is created (usually the object which contains the event).\r
-     * By setting override to true, the execution scope becomes the custom\r
-     * object passed in by the subscriber\r
-     * @type boolean\r
-     */\r
-    this.override = (bOverride);\r
-};\r
-\r
-/**\r
- * Returns true if the fn and obj match this objects properties.\r
- * Used by the unsubscribe method to match the right subscriber.\r
- *\r
- * @param {Function} fn the function to execute\r
- * @param {Object} obj an object to be passed along when the event fires\r
- * @return {boolean} true if the supplied arguments match this \r
- *                   subscriber's signature.\r
- */\r
-YAHOO.util.Subscriber.prototype.contains = function(fn, obj) {\r
-    return (this.fn == fn && this.obj == obj);\r
-};\r
-\r
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */\r
-\r
-// Only load this library once.  If it is loaded a second time, existing\r
-// events cannot be detached.\r
-if (!YAHOO.util.Event) {\r
-\r
-/**\r
- * @class\r
- * The event utility provides functions to add and remove event listeners,\r
- * event cleansing.  It also tries to automatically remove listeners it\r
- * registers during the unload event.\r
- * @constructor\r
- */\r
-    YAHOO.util.Event = function() {\r
-\r
-        /**\r
-         * True after the onload event has fired\r
-         * @type boolean\r
-         * @private\r
-         */\r
-        var loadComplete =  false;\r
-\r
-        /**\r
-         * Cache of wrapped listeners\r
-         * @type array\r
-         * @private\r
-         */\r
-        var listeners = [];\r
-\r
-        /**\r
-         * Listeners that will be attached during the onload event\r
-         * @type array\r
-         * @private\r
-         */\r
-        var delayedListeners = [];\r
-\r
-        /**\r
-         * User-defined unload function that will be fired before all events\r
-         * are detached\r
-         * @type array\r
-         * @private\r
-         */\r
-        var unloadListeners = [];\r
-\r
-        /**\r
-         * Cache of the custom events that have been defined.  Used for\r
-         * automatic cleanup\r
-         * @type array\r
-         * @private\r
-         */\r
-        var customEvents = [];\r
-\r
-        /**\r
-         * Cache of DOM0 event handlers to work around issues with DOM2 events\r
-         * in Safari\r
-         * @private\r
-         */\r
-        var legacyEvents = [];\r
-\r
-        /**\r
-         * Listener stack for DOM0 events\r
-         * @private\r
-         */\r
-        var legacyHandlers = [];\r
-\r
-        /**\r
-         * The number of times to poll after window.onload.  This number is\r
-         * increased if additional late-bound handlers are requested after\r
-         * the page load.\r
-         * @private\r
-         */\r
-        var retryCount = 0;\r
-\r
-        /**\r
-         * onAvailable listeners\r
-         * @private\r
-         */\r
-        var onAvailStack = [];\r
-\r
-        /**\r
-         * Lookup table for legacy events\r
-         * @private\r
-         */\r
-        var legacyMap = [];\r
-\r
-        /**\r
-         * Counter for auto id generation\r
-         * @private\r
-         */\r
-        var counter = 0;\r
-\r
-        return { // PREPROCESS\r
-\r
-            /**\r
-             * The number of times we should look for elements that are not\r
-             * in the DOM at the time the event is requested after the document\r
-             * has been loaded.  The default is 200@50 ms, so it will poll\r
-             * for 10 seconds or until all outstanding handlers are bound\r
-             * (whichever comes first).\r
-             * @type int\r
-             */\r
-            POLL_RETRYS: 200,\r
-\r
-            /**\r
-             * The poll interval in milliseconds\r
-             * @type int\r
-             */\r
-            POLL_INTERVAL: 50,\r
-\r
-            /**\r
-             * Element to bind, int constant\r
-             * @type int\r
-             */\r
-            EL: 0,\r
-\r
-            /**\r
-             * Type of event, int constant\r
-             * @type int\r
-             */\r
-            TYPE: 1,\r
-\r
-            /**\r
-             * Function to execute, int constant\r
-             * @type int\r
-             */\r
-            FN: 2,\r
-\r
-            /**\r
-             * Function wrapped for scope correction and cleanup, int constant\r
-             * @type int\r
-             */\r
-            WFN: 3,\r
-\r
-            /**\r
-             * Object passed in by the user that will be returned as a \r
-             * parameter to the callback, int constant\r
-             * @type int\r
-             */\r
-            SCOPE: 3,\r
-\r
-            /**\r
-             * Adjusted scope, either the element we are registering the event\r
-             * on or the custom object passed in by the listener, int constant\r
-             * @type int\r
-             */\r
-            ADJ_SCOPE: 4,\r
-\r
-            /**\r
-             * Safari detection is necessary to work around the preventDefault\r
-             * bug that makes it so you can't cancel a href click from the \r
-             * handler.  There is not a capabilities check we can use here.\r
-             * @private\r
-             */\r
-            isSafari: (/Safari|Konqueror|KHTML/gi).test(navigator.userAgent),\r
-\r
-            /**\r
-             * IE detection needed to properly calculate pageX and pageY.  \r
-             * capabilities checking didn't seem to work because another \r
-             * browser that does not provide the properties have the values \r
-             * calculated in a different manner than IE.\r
-             * @private\r
-             */\r
-            isIE: (!this.isSafari && !navigator.userAgent.match(/opera/gi) && \r
-                    navigator.userAgent.match(/msie/gi)),\r
-\r
-            /**\r
-             * @private\r
-             */\r
-            addDelayedListener: function(el, sType, fn, oScope, bOverride) {\r
-                delayedListeners[delayedListeners.length] =\r
-                    [el, sType, fn, oScope, bOverride];\r
-\r
-                // If this happens after the inital page load, we need to\r
-                // reset the poll counter so that we continue to search for\r
-                // the element for a fixed period of time.\r
-                if (loadComplete) {\r
-                    retryCount = this.POLL_RETRYS;\r
-                    this.startTimeout(0);\r
-                    // this._tryPreloadAttach();\r
-                }\r
-            },\r
-\r
-            /**\r
-             * @private\r
-             */\r
-            startTimeout: function(interval) {\r
-                var i = (interval || interval === 0) ? interval : this.POLL_INTERVAL;\r
-                var self = this;\r
-                var callback = function() { self._tryPreloadAttach(); };\r
-                this.timeout = setTimeout(callback, i);\r
-            },\r
-\r
-            /**\r
-             * Executes the supplied callback when the item with the supplied\r
-             * id is found.  This is meant to be used to execute behavior as\r
-             * soon as possible as the page loads.  If you use this after the\r
-             * initial page load it will poll for a fixed time for the element.\r
-             * The number of times it will poll and the frequency are\r
-             * configurable.  By default it will poll for 10 seconds.\r
-             * @param {string} p_id the id of the element to look for.\r
-             * @param {function} p_fn what to execute when the element is found.\r
-             * @param {object} p_obj an optional object to be passed back as\r
-             * a parameter to p_fn.\r
-             * @param {boolean} p_override If set to true, p_fn will execute\r
-             * in the scope of p_obj\r
-             *\r
-             */\r
-            onAvailable: function(p_id, p_fn, p_obj, p_override) {\r
-                onAvailStack.push( { id:       p_id, \r
-                                     fn:       p_fn, \r
-                                     obj:      p_obj, \r
-                                     override: p_override } );\r
-\r
-                retryCount = this.POLL_RETRYS;\r
-                this.startTimeout(0);\r
-                // this._tryPreloadAttach();\r
-            },\r
-\r
-            /**\r
-             * Appends an event handler\r
-             *\r
-             * @param {Object}   el        The html element to assign the \r
-             *                             event to\r
-             * @param {String}   sType     The type of event to append\r
-             * @param {Function} fn        The method the event invokes\r
-             * @param {Object}   oScope    An arbitrary object that will be \r
-             *                             passed as a parameter to the handler\r
-             * @param {boolean}  bOverride If true, the obj passed in becomes\r
-             *                             the execution scope of the listener\r
-             * @return {boolean} True if the action was successful or defered,\r
-             *                        false if one or more of the elements \r
-             *                        could not have the event bound to it.\r
-             */\r
-            addListener: function(el, sType, fn, oScope, bOverride) {\r
-\r
-                if (!fn || !fn.call) {\r
-                    return false;\r
-                }\r
-\r
-                // The el argument can be an array of elements or element ids.\r
-                if ( this._isValidCollection(el)) {\r
-                    var ok = true;\r
-                    for (var i=0,len=el.length; i<len; ++i) {\r
-                        ok = ( this.on(el[i], \r
-                                       sType, \r
-                                       fn, \r
-                                       oScope, \r
-                                       bOverride) && ok );\r
-                    }\r
-                    return ok;\r
-\r
-                } else if (typeof el == "string") {\r
-                    var oEl = this.getEl(el);\r
-                    // If the el argument is a string, we assume it is \r
-                    // actually the id of the element.  If the page is loaded\r
-                    // we convert el to the actual element, otherwise we \r
-                    // defer attaching the event until onload event fires\r
-\r
-                    // check to see if we need to delay hooking up the event \r
-                    // until after the page loads.\r
-                    if (loadComplete && oEl) {\r
-                        el = oEl;\r
-                    } else {\r
-                        // defer adding the event until onload fires\r
-                        this.addDelayedListener(el, \r
-                                                sType, \r
-                                                fn, \r
-                                                oScope, \r
-                                                bOverride);\r
-\r
-                        return true;\r
-                    }\r
-                }\r
-\r
-                // Element should be an html element or an array if we get \r
-                // here.\r
-                if (!el) {\r
-                    return false;\r
-                }\r
-\r
-                // we need to make sure we fire registered unload events \r
-                // prior to automatically unhooking them.  So we hang on to \r
-                // these instead of attaching them to the window and fire the\r
-                // handles explicitly during our one unload event.\r
-                if ("unload" == sType && oScope !== this) {\r
-                    unloadListeners[unloadListeners.length] =\r
-                            [el, sType, fn, oScope, bOverride];\r
-                    return true;\r
-                }\r
-\r
-\r
-                // if the user chooses to override the scope, we use the custom\r
-                // object passed in, otherwise the executing scope will be the\r
-                // HTML element that the event is registered on\r
-                var scope = (bOverride) ? oScope : el;\r
-\r
-                // wrap the function so we can return the oScope object when\r
-                // the event fires;\r
-                var wrappedFn = function(e) {\r
-                        return fn.call(scope, YAHOO.util.Event.getEvent(e), \r
-                                oScope);\r
-                    };\r
-\r
-                var li = [el, sType, fn, wrappedFn, scope];\r
-                var index = listeners.length;\r
-                // cache the listener so we can try to automatically unload\r
-                listeners[index] = li;\r
-\r
-                if (this.useLegacyEvent(el, sType)) {\r
-                    var legacyIndex = this.getLegacyIndex(el, sType);\r
-                    if (legacyIndex == -1) {\r
-\r
-                        legacyIndex = legacyEvents.length;\r
-                        legacyMap[el.id + sType] = legacyIndex;\r
-\r
-                        // cache the signature for the DOM0 event, and \r
-                        // include the existing handler for the event, if any\r
-                        legacyEvents[legacyIndex] = \r
-                            [el, sType, el["on" + sType]];\r
-                        legacyHandlers[legacyIndex] = [];\r
-\r
-                        el["on" + sType] = \r
-                            function(e) {\r
-                                YAHOO.util.Event.fireLegacyEvent(\r
-                                    YAHOO.util.Event.getEvent(e), legacyIndex);\r
-                            };\r
-                    }\r
-\r
-                    // add a reference to the wrapped listener to our custom\r
-                    // stack of events\r
-                    legacyHandlers[legacyIndex].push(index);\r
-\r
-                // DOM2 Event model\r
-                } else if (el.addEventListener) {\r
-                    el.addEventListener(sType, wrappedFn, false);\r
-                // Internet Explorer abstraction\r
-                } else if (el.attachEvent) {\r
-                    el.attachEvent("on" + sType, wrappedFn);\r
-                }\r
-\r
-                return true;\r
-                \r
-            },\r
-\r
-            /**\r
-             * Shorthand for YAHOO.util.Event.addListener\r
-             * @type function\r
-             */\r
-            // on: this.addListener,\r
-\r
-            /**\r
-             * When using legacy events, the handler is routed to this object\r
-             * so we can fire our custom listener stack.\r
-             * @private\r
-             */\r
-            fireLegacyEvent: function(e, legacyIndex) {\r
-                var ok = true;\r
-\r
-                var le = legacyHandlers[legacyIndex];\r
-                for (var i=0,len=le.length; i<len; ++i) {\r
-                    var index = le[i];\r
-                    if (index) {\r
-                        var li = listeners[index];\r
-                        if ( li && li[this.WFN] ) {\r
-                            var scope = li[this.ADJ_SCOPE];\r
-                            var ret = li[this.WFN].call(scope, e);\r
-                            ok = (ok && ret);\r
-                        } else {\r
-                            // This listener was removed, so delete it from\r
-                            // the array\r
-                            delete le[i];\r
-                        }\r
-                    }\r
-                }\r
-\r
-                return ok;\r
-            },\r
-\r
-            /**\r
-             * Returns the legacy event index that matches the supplied \r
-             * signature\r
-             * @private\r
-             */\r
-            getLegacyIndex: function(el, sType) {\r
-                /*\r
-                for (var i=0,len=legacyEvents.length; i<len; ++i) {\r
-                    var le = legacyEvents[i];\r
-                    if (le && le[0] === el && le[1] === sType) {\r
-                        return i;\r
-                    }\r
-                }\r
-                return -1;\r
-                */\r
-\r
-                var key = this.generateId(el) + sType;\r
-                if (typeof legacyMap[key] == "undefined") { \r
-                    return -1;\r
-                } else {\r
-                    return legacyMap[key];\r
-                }\r
-\r
-            },\r
-\r
-            /**\r
-             * Logic that determines when we should automatically use legacy\r
-             * events instead of DOM2 events.\r
-             * @private\r
-             */\r
-            useLegacyEvent: function(el, sType) {\r
-\r
-                if (!el.addEventListener && !el.attachEvent) {\r
-                    return true;\r
-                } else if (this.isSafari) {\r
-                    if ("click" == sType || "dblclick" == sType) {\r
-                        return true;\r
-                    }\r
-                }\r
-\r
-                return false;\r
-            },\r
-                    \r
-            /**\r
-             * Removes an event handler\r
-             *\r
-             * @param {Object} el the html element or the id of the element to \r
-             * assign the event to.\r
-             * @param {String} sType the type of event to remove\r
-             * @param {Function} fn the method the event invokes\r
-             * @return {boolean} true if the unbind was successful, false \r
-             * otherwise\r
-             */\r
-            removeListener: function(el, sType, fn, index) {\r
-\r
-                if (!fn || !fn.call) {\r
-                    return false;\r
-                }\r
-\r
-                // The el argument can be a string\r
-                if (typeof el == "string") {\r
-                    el = this.getEl(el);\r
-                // The el argument can be an array of elements or element ids.\r
-                } else if ( this._isValidCollection(el)) {\r
-                    var ok = true;\r
-                    for (var i=0,len=el.length; i<len; ++i) {\r
-                        ok = ( this.removeListener(el[i], sType, fn) && ok );\r
-                    }\r
-                    return ok;\r
-                }\r
-\r
-                if ("unload" == sType) {\r
-\r
-                    for (i=0, len=unloadListeners.length; i<len; i++) {\r
-                        var li = unloadListeners[i];\r
-                        if (li && \r
-                            li[0] == el && \r
-                            li[1] == sType && \r
-                            li[2] == fn) {\r
-                                delete unloadListeners[i];\r
-                                return true;\r
-                        }\r
-                    }\r
-\r
-                    return false;\r
-                }\r
-\r
-                var cacheItem = null;\r
-  \r
-                if ("undefined" == typeof index) {\r
-                    index = this._getCacheIndex(el, sType, fn);\r
-                }\r
-\r
-                if (index >= 0) {\r
-                    cacheItem = listeners[index];\r
-                }\r
-\r
-                if (!el || !cacheItem) {\r
-                    return false;\r
-                }\r
-\r
-\r
-                if (el.removeEventListener) {\r
-                    el.removeEventListener(sType, cacheItem[this.WFN], false);\r
-                } else if (el.detachEvent) {\r
-                    el.detachEvent("on" + sType, cacheItem[this.WFN]);\r
-                }\r
-\r
-                // removed the wrapped handler\r
-                delete listeners[index][this.WFN];\r
-                delete listeners[index][this.FN];\r
-                delete listeners[index];\r
-\r
-                return true;\r
-\r
-            },\r
-\r
-            /**\r
-             * Returns the event's target element\r
-             * @param {Event} ev the event\r
-             * @param {boolean} resolveTextNode when set to true the target's\r
-             *                  parent will be returned if the target is a \r
-             *                  text node\r
-             * @return {HTMLElement} the event's target\r
-             */\r
-            getTarget: function(ev, resolveTextNode) {\r
-                var t = ev.target || ev.srcElement;\r
-\r
-                if (resolveTextNode && t && "#text" == t.nodeName) {\r
-                    return t.parentNode;\r
-                } else {\r
-                    return t;\r
-                }\r
-            },\r
-\r
-            /**\r
-             * Returns the event's pageX\r
-             * @param {Event} ev the event\r
-             * @return {int} the event's pageX\r
-             */\r
-            getPageX: function(ev) {\r
-                var x = ev.pageX;\r
-                if (!x && 0 !== x) {\r
-                    x = ev.clientX || 0;\r
-\r
-                    if ( this.isIE ) {\r
-                        x += this._getScrollLeft();\r
-                    }\r
-                }\r
-\r
-                return x;\r
-            },\r
-\r
-            /**\r
-             * Returns the event's pageY\r
-             * @param {Event} ev the event\r
-             * @return {int} the event's pageY\r
-             */\r
-            getPageY: function(ev) {\r
-                var y = ev.pageY;\r
-                if (!y && 0 !== y) {\r
-                    y = ev.clientY || 0;\r
-\r
-                    if ( this.isIE ) {\r
-                        y += this._getScrollTop();\r
-                    }\r
-                }\r
-\r
-                return y;\r
-            },\r
-\r
-            /**\r
-             * Returns the pageX and pageY properties as an indexed array.\r
-             * @type int[]\r
-             */\r
-            getXY: function(ev) {\r
-                return [this.getPageX(ev), this.getPageY(ev)];\r
-            },\r
-\r
-            /**\r
-             * Returns the event's related target \r
-             * @param {Event} ev the event\r
-             * @return {HTMLElement} the event's relatedTarget\r
-             */\r
-            getRelatedTarget: function(ev) {\r
-                var t = ev.relatedTarget;\r
-                if (!t) {\r
-                    if (ev.type == "mouseout") {\r
-                        t = ev.toElement;\r
-                    } else if (ev.type == "mouseover") {\r
-                        t = ev.fromElement;\r
-                    }\r
-                }\r
-\r
-                return t;\r
-            },\r
-\r
-            /**\r
-             * Returns the time of the event.  If the time is not included, the\r
-             * event is modified using the current time.\r
-             * @param {Event} ev the event\r
-             * @return {Date} the time of the event\r
-             */\r
-            getTime: function(ev) {\r
-                if (!ev.time) {\r
-                    var t = new Date().getTime();\r
-                    try {\r
-                        ev.time = t;\r
-                    } catch(e) { \r
-                        // can't set the time property  \r
-                        return t;\r
-                    }\r
-                }\r
-\r
-                return ev.time;\r
-            },\r
-\r
-            /**\r
-             * Convenience method for stopPropagation + preventDefault\r
-             * @param {Event} ev the event\r
-             */\r
-            stopEvent: function(ev) {\r
-                this.stopPropagation(ev);\r
-                this.preventDefault(ev);\r
-            },\r
-\r
-            /**\r
-             * Stops event propagation\r
-             * @param {Event} ev the event\r
-             */\r
-            stopPropagation: function(ev) {\r
-                if (ev.stopPropagation) {\r
-                    ev.stopPropagation();\r
-                } else {\r
-                    ev.cancelBubble = true;\r
-                }\r
-            },\r
-\r
-            /**\r
-             * Prevents the default behavior of the event\r
-             * @param {Event} ev the event\r
-             */\r
-            preventDefault: function(ev) {\r
-                if (ev.preventDefault) {\r
-                    ev.preventDefault();\r
-                } else {\r
-                    ev.returnValue = false;\r
-                }\r
-            },\r
-             \r
-            /**\r
-             * Finds the event in the window object, the caller's arguments, or\r
-             * in the arguments of another method in the callstack.  This is\r
-             * executed automatically for events registered through the event\r
-             * manager, so the implementer should not normally need to execute\r
-             * this function at all.\r
-             * @param {Event} the event parameter from the handler\r
-             * @return {Event} the event \r
-             */\r
-            getEvent: function(e) {\r
-                var ev = e || window.event;\r
-\r
-                if (!ev) {\r
-                    var c = this.getEvent.caller;\r
-                    while (c) {\r
-                        ev = c.arguments[0];\r
-                        if (ev && Event == ev.constructor) {\r
-                            break;\r
-                        }\r
-                        c = c.caller;\r
-                    }\r
-                }\r
-\r
-                return ev;\r
-            },\r
-\r
-            /**\r
-             * Returns the charcode for an event\r
-             * @param {Event} ev the event\r
-             * @return {int} the event's charCode\r
-             */\r
-            getCharCode: function(ev) {\r
-                return ev.charCode || ((ev.type == "keypress") ? ev.keyCode : 0);\r
-            },\r
-\r
-            /**\r
-             * @private\r
-             * Locating the saved event handler data by function ref\r
-             */\r
-            _getCacheIndex: function(el, sType, fn) {\r
-                for (var i=0,len=listeners.length; i<len; ++i) {\r
-                    var li = listeners[i];\r
-                    if ( li                 && \r
-                         li[this.FN] == fn  && \r
-                         li[this.EL] == el  && \r
-                         li[this.TYPE] == sType ) {\r
-                        return i;\r
-                    }\r
-                }\r
-\r
-                return -1;\r
-            },\r
-\r
-            /**\r
-             * Generates an unique ID for the element if it does not already \r
-             * have one.\r
-             * @param el the element\r
-             * @return {string} the id of the element\r
-             */\r
-            generateId: function(el) {\r
-                var id = el.id;\r
-\r
-                if (!id) {\r
-                    id = "yuievtautoid-" + (counter++);\r
-                    el.id = id;\r
-                }\r
-\r
-                return id;\r
-            },\r
-\r
-            /**\r
-             * We want to be able to use getElementsByTagName as a collection\r
-             * to attach a group of events to.  Unfortunately, different \r
-             * browsers return different types of collections.  This function\r
-             * tests to determine if the object is array-like.  It will also \r
-             * fail if the object is an array, but is empty.\r
-             * @param o the object to test\r
-             * @return {boolean} true if the object is array-like and populated\r
-             * @private\r
-             */\r
-            _isValidCollection: function(o) {\r
-\r
-                return ( o                    && // o is something\r
-                         o.length             && // o is indexed\r
-                         typeof o != "string" && // o is not a string\r
-                         !o.tagName           && // o is not an HTML element\r
-                         !o.alert             && // o is not a window\r
-                         typeof o[0] != "undefined" );\r
-\r
-            },\r
-\r
-            /**\r
-             * @private\r
-             * DOM element cache\r
-             */\r
-            elCache: {},\r
-\r
-            /**\r
-             * We cache elements bound by id because when the unload event \r
-             * fires, we can no longer use document.getElementById\r
-             * @private\r
-             */\r
-            getEl: function(id) {\r
-                return document.getElementById(id);\r
-            },\r
-\r
-            /**\r
-             * Clears the element cache\r
-             * @deprecated\r
-             * @private\r
-             */\r
-            clearCache: function() { },\r
-\r
-            /**\r
-             * Called by CustomEvent instances to provide a handle to the \r
-             * event * that can be removed later on.  Should be package \r
-             * protected.\r
-             * @private\r
-             */\r
-            regCE: function(ce) {\r
-                customEvents.push(ce);\r
-            },\r
-\r
-            /**\r
-             * @private\r
-             * hook up any deferred listeners\r
-             */\r
-            _load: function(e) {\r
-                loadComplete = true;\r
-            },\r
-\r
-            /**\r
-             * Polling function that runs before the onload event fires, \r
-             * attempting * to attach to DOM Nodes as soon as they are \r
-             * available\r
-             * @private\r
-             */\r
-            _tryPreloadAttach: function() {\r
-\r
-                if (this.locked) {\r
-                    return false;\r
-                }\r
-\r
-                this.locked = true;\r
-\r
-\r
-                // keep trying until after the page is loaded.  We need to \r
-                // check the page load state prior to trying to bind the \r
-                // elements so that we can be certain all elements have been \r
-                // tested appropriately\r
-                var tryAgain = !loadComplete;\r
-                if (!tryAgain) {\r
-                    tryAgain = (retryCount > 0);\r
-                }\r
-\r
-                // Delayed listeners\r
-                var stillDelayed = [];\r
-\r
-                for (var i=0,len=delayedListeners.length; i<len; ++i) {\r
-                    var d = delayedListeners[i];\r
-                    // There may be a race condition here, so we need to \r
-                    // verify the array element is usable.\r
-                    if (d) {\r
-\r
-                        // el will be null if document.getElementById did not\r
-                        // work\r
-                        var el = this.getEl(d[this.EL]);\r
-\r
-                        if (el) {\r
-                            this.on(el, d[this.TYPE], d[this.FN], \r
-                                    d[this.SCOPE], d[this.ADJ_SCOPE]);\r
-                            delete delayedListeners[i];\r
-                        } else {\r
-                            stillDelayed.push(d);\r
-                        }\r
-                    }\r
-                }\r
-\r
-                delayedListeners = stillDelayed;\r
-\r
-                // onAvailable\r
-                notAvail = [];\r
-                for (i=0,len=onAvailStack.length; i<len ; ++i) {\r
-                    var item = onAvailStack[i];\r
-                    if (item) {\r
-                        el = this.getEl(item.id);\r
-\r
-                        if (el) {\r
-                            var scope = (item.override) ? item.obj : el;\r
-                            item.fn.call(scope, item.obj);\r
-                            delete onAvailStack[i];\r
-                        } else {\r
-                            notAvail.push(item);\r
-                        }\r
-                    }\r
-                }\r
-\r
-                retryCount = (stillDelayed.length === 0 && \r
-                                    notAvail.length === 0) ? 0 : retryCount - 1;\r
-\r
-                if (tryAgain) {\r
-                    this.startTimeout();\r
-                }\r
-\r
-                this.locked = false;\r
-\r
-            },\r
-\r
-            /**\r
-             * Removes all listeners registered by pe.event.  Called \r
-             * automatically during the unload event.\r
-             * @private\r
-             */\r
-            _unload: function(e, me) {\r
-                for (var i=0,len=unloadListeners.length; i<len; ++i) {\r
-                    var l = unloadListeners[i];\r
-                    if (l) {\r
-                        var scope = (l[this.ADJ_SCOPE]) ? l[this.SCOPE]: window;\r
-                        l[this.FN].call(scope, this.getEvent(e), l[this.SCOPE] );\r
-                    }\r
-                }\r
-\r
-                if (listeners && listeners.length > 0) {\r
-                    for (i=0,len=listeners.length; i<len ; ++i) {\r
-                        l = listeners[i];\r
-                        if (l) {\r
-                            this.removeListener(l[this.EL], l[this.TYPE], \r
-                                    l[this.FN], i);\r
-                        }\r
-                    }\r
-\r
-                    this.clearCache();\r
-                }\r
-\r
-                for (i=0,len=customEvents.length; i<len; ++i) {\r
-                    customEvents[i].unsubscribeAll();\r
-                    delete customEvents[i];\r
-                }\r
-\r
-                for (i=0,len=legacyEvents.length; i<len; ++i) {\r
-                    // dereference the element\r
-                    delete legacyEvents[i][0];\r
-                    // delete the array item\r
-                    delete legacyEvents[i];\r
-                }\r
-            },\r
-\r
-            /**\r
-             * Returns scrollLeft\r
-             * @private\r
-             */\r
-            _getScrollLeft: function() {\r
-                return this._getScroll()[1];\r
-            },\r
-\r
-            /**\r
-             * Returns scrollTop\r
-             * @private\r
-             */\r
-            _getScrollTop: function() {\r
-                return this._getScroll()[0];\r
-            },\r
-\r
-            /**\r
-             * Returns the scrollTop and scrollLeft.  Used to calculate the \r
-             * pageX and pageY in Internet Explorer\r
-             * @private\r
-             */\r
-            _getScroll: function() {\r
-                var dd = document.documentElement; db = document.body;\r
-                if (dd && dd.scrollTop) {\r
-                    return [dd.scrollTop, dd.scrollLeft];\r
-                } else if (db) {\r
-                    return [db.scrollTop, db.scrollLeft];\r
-                } else {\r
-                    return [0, 0];\r
-                }\r
-            }\r
-        };\r
-    } ();\r
-\r
-    /**\r
-     * @private\r
-     */\r
-    YAHOO.util.Event.on = YAHOO.util.Event.addListener;\r
-\r
-    if (document && document.body) {\r
-        YAHOO.util.Event._load();\r
-    } else {\r
-        YAHOO.util.Event.on(window, "load", YAHOO.util.Event._load, \r
-                YAHOO.util.Event, true);\r
-    }\r
-\r
-    YAHOO.util.Event.on(window, "unload", YAHOO.util.Event._unload, \r
-                YAHOO.util.Event, true);\r
-\r
-    YAHOO.util.Event._tryPreloadAttach();\r
-\r
-}\r
-\r
diff --git a/apps/fjsc-responder/resources/yahoo/yahoo.js b/apps/fjsc-responder/resources/yahoo/yahoo.js
deleted file mode 100644 (file)
index 55cdc78..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*                                                                                                                                                      \r
-Copyright (c) 2006, Yahoo! Inc. All rights reserved.                                                                                                    \r
-Code licensed under the BSD License:                                                                                                                    \r
-http://developer.yahoo.net/yui/license.txt                                                                                                              \r
-version: 0.10.0                                                                                                                                         \r
-*/ \r
-\r
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */\r
-\r
-/**\r
- * The Yahoo global namespace\r
- * @constructor\r
- */\r
-var YAHOO = window.YAHOO || {};\r
-\r
-/**\r
- * Returns the namespace specified and creates it if it doesn't exist\r
- *\r
- * YAHOO.namespace("property.package");\r
- * YAHOO.namespace("YAHOO.property.package");\r
- *\r
- * Either of the above would create YAHOO.property, then\r
- * YAHOO.property.package\r
- *\r
- * @param  {String} sNameSpace String representation of the desired \r
- *                             namespace\r
- * @return {Object}            A reference to the namespace object\r
- */\r
-YAHOO.namespace = function( sNameSpace ) {\r
-\r
-    if (!sNameSpace || !sNameSpace.length) {\r
-        return null;\r
-    }\r
-\r
-    var levels = sNameSpace.split(".");\r
-\r
-    var currentNS = YAHOO;\r
-\r
-    // YAHOO is implied, so it is ignored if it is included\r
-    for (var i=(levels[0] == "YAHOO") ? 1 : 0; i<levels.length; ++i) {\r
-        currentNS[levels[i]] = currentNS[levels[i]] || {};\r
-        currentNS = currentNS[levels[i]];\r
-    }\r
-\r
-    return currentNS;\r
-};\r
-\r
-/**\r
- * Global log method.\r
- */\r
-YAHOO.log = function(sMsg,sCategory) {\r
-    if(YAHOO.widget.Logger) {\r
-        YAHOO.widget.Logger.log(null, sMsg, sCategory);\r
-    } else {\r
-        return false;\r
-    }\r
-};\r
-\r
-YAHOO.namespace("util");\r
-YAHOO.namespace("widget");\r
-YAHOO.namespace("example");\r
diff --git a/apps/furnace-fjsc/furnace-fjsc.factor b/apps/furnace-fjsc/furnace-fjsc.factor
new file mode 100644 (file)
index 0000000..4cd5ad6
--- /dev/null
@@ -0,0 +1,78 @@
+! Copyright (C) 2006 Chris Double. All Rights Reserved.
+! See http://factorcode.org/license.txt for BSD license.
+!
+IN: furnace:fjsc
+USING: kernel html furnace xml io httpd sequences 
+       namespaces file-responder parser-combinators lazy-lists
+       fjsc  ;
+
+: script ( path -- )
+  #! given a path to a javascript file, output the 
+  #! script tag that references it.
+  <script "text/javascript" =type =src script> </script> ;
+
+: fjsc-page ( scripts title quot -- )
+  #! Display a web page importing the given script
+  #! tags and using the title. The body of the page
+  #! is generated by calling the quotation.
+  -rot xhtml-preamble
+  chars>entities
+  <html " xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"" write-html html>
+    <head>
+      <title> write </title>
+      [ script ] each
+    </head>
+    <body>
+     call
+    </body>
+  </html> ;
+  
+: fjsc-render ( template title -- )
+  #! Render the fjsc page importing the required
+  #! scripts.
+  serving-html {
+    "/responder/fjsc-resources/yahoo/yahoo.js"
+    "/responder/fjsc-resources/yahoo/event.js"
+    "/responder/fjsc-resources/yahoo/connection.js"
+    "/responder/fjsc-resources/bootstrap.js"
+  } swap [
+    [
+      f swap render-template
+    ] fjsc-page
+  ] with-html-stream ;
+
+: compile ( code -- )
+  #! Compile the facor code as a string, outputting the http
+  #! response containing the javascript.
+  serving-text
+  'expression' parse car parse-result-parsed fjsc-compile 
+   write flush ;
+
+! The 'compile' action results in an URL that looks like
+! 'responder/fjsc/compile'. It takes one query or post 
+! parameter called 'code'. It calls the 'compile' word
+! passing the parameter to it on the stack.
+\ compile { 
+  { "code" v-required } 
+} define-action
+
+: repl ( -- )
+  #! The main 'repl' page.
+  f "repl" "Factor to Javascript REPL" fjsc-render ;
+
+! An action called 'repl' 
+\ repl { } define-action
+
+! Create the web app, providing access 
+! under '/responder/fjsc' which calls the
+! 'repl' action.
+"fjsc" "repl" "apps/furnace-fjsc" web-app
+
+! An URL to the javascript resource files used by
+! the 'fjsc' responder.
+"fjsc-resources" [
+ [
+   "apps/furnace-fjsc/resources/" resource-path "doc-root" set
+   file-responder
+ ] with-scope
+] add-simple-responder
diff --git a/apps/furnace-fjsc/load.factor b/apps/furnace-fjsc/load.factor
new file mode 100644 (file)
index 0000000..f7b8a94
--- /dev/null
@@ -0,0 +1,18 @@
+! Copyright (C) 2006 Chris Double. All Rights Reserved.
+! See http://factorcode.org/license.txt for BSD license.
+!
+REQUIRES: libs/furnace libs/fjsc ;
+
+PROVIDE: apps/furnace-fjsc 
+{ 
+  +files+ { 
+  "furnace-fjsc.factor"
+  } 
+} {
+  +tests+ { 
+  }
+} { 
+  +help+ 
+  { 
+  } 
+} ;
diff --git a/apps/furnace-fjsc/repl.fhtml b/apps/furnace-fjsc/repl.fhtml
new file mode 100644 (file)
index 0000000..1c28ef8
--- /dev/null
@@ -0,0 +1,9 @@
+<form id="toeval" onsubmit="fjsc_eval(document.getElementById('toeval'));return false;" method="post">
+  <textarea name="code" id="code">
+  </textarea>
+  <input type="submit"/>
+</form>
+<div id="compiled">
+</div>
+<div id="stack">
+</div>
\ No newline at end of file
diff --git a/apps/furnace-fjsc/resources/bootstrap.js b/apps/furnace-fjsc/resources/bootstrap.js
new file mode 100644 (file)
index 0000000..25a784c
--- /dev/null
@@ -0,0 +1,42 @@
+function fjsc_eval(form) {
+   var callback = {
+      success: function(o) {
+        var v = o.responseText;
+        eval(v)
+        display_datastack();
+        document.getElementById('compiled').innerHTML="<pre>" + v + "</pre>";
+        document.getElementById('code').value="";
+
+      }
+   };
+   YAHOO.util.Connect.setForm(form);
+   YAHOO.util.Connect.asyncRequest('POST', "/responder/fjsc/compile", callback);
+}
+
+var data_stack = [ ] 
+
+function fjsc_dup() {
+   var v = data_stack.pop();
+   data_stack.push(v);
+   data_stack.push(v);
+}
+
+function fjsc_drop() {
+   data_stack.pop();
+}
+
+function fjsc_alert() {
+   alert(data_stack.pop())
+}
+
+function display_datastack() {
+   var html=[];
+   html.push("<table border='1'>")
+   for(var i = 0; i < data_stack.length; ++i) {
+      html.push("<tr><td>")
+      html.push(data_stack[i])
+      html.push("</td></tr>")
+   }
+   html.push("</table>")
+   document.getElementById('stack').innerHTML=html.join("");
+}
diff --git a/apps/furnace-fjsc/resources/yahoo/connection.js b/apps/furnace-fjsc/resources/yahoo/connection.js
new file mode 100644 (file)
index 0000000..098a3ab
--- /dev/null
@@ -0,0 +1,586 @@
+/*
+Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+*/
+
+/**
+ * The Connection Manager provides a simplified interface to the XMLHttpRequest
+ * object.  It handles cross-browser instantiantion of XMLHttpRequest, negotiates the
+ * interactive states and server response, returning the results to a pre-defined
+ * callback you create.
+ * @ class
+ */
+YAHOO.util.Connect =
+{
+  /**
+   * Array of MSFT ActiveX ids for XMLHttpRequest.
+   * @private
+   * @type array
+   */
+       _msxml_progid:[
+               'MSXML2.XMLHTTP.5.0',
+               'MSXML2.XMLHTTP.4.0',
+               'MSXML2.XMLHTTP.3.0',
+               'MSXML2.XMLHTTP',
+               'Microsoft.XMLHTTP'
+               ],
+
+  /**
+   * Array of HTTP header(s)
+   * @private
+   * @type array
+   */
+       _http_header:{},
+
+  /**
+   * Determines if HTTP headers are set.
+   * @private
+   * @type boolean
+   */
+       _has_http_headers:false,
+
+ /**
+  * Property modified by setForm() to determine if the data
+  * should be submitted as an HTML form.
+  * @private
+  * @type boolean
+  */
+       _isFormSubmit:false,
+
+ /**
+  * Property modified by setForm() to set the HTML form data
+  * for each transaction.
+  * @private
+  * @type string
+  */
+       _sFormData:null,
+
+ /**
+  * Collection of polling references to the polling mechanism in handleReadyState.
+  * @private
+  * @type string
+  */
+       _poll:[],
+
+  /**
+   * The polling frequency, in milliseconds, for HandleReadyState.
+   * when attempting to determine a transaction's XHR  readyState.
+   * The default is 50 milliseconds.
+   * @private
+   * @type int
+   */
+       _polling_interval:50,
+
+  /**
+   * A transaction counter that increments the transaction id for each transaction.
+   * @private
+   * @type int
+   */
+       _transaction_id:0,
+
+  /**
+   * Member to add an ActiveX id to the existing xml_progid array.
+   * In the event(unlikely) a new ActiveX id is introduced, it can be added
+   * without internal code modifications.
+   * @public
+   * @param string id The ActiveX id to be added to initialize the XHR object.
+   * @return void
+   */
+       setProgId:function(id)
+       {
+               this.msxml_progid.unshift(id);
+       },
+
+  /**
+   * Member to modify the default polling interval.
+   * @public
+   * @param {int} i The polling interval in milliseconds.
+   * @return void
+   */
+       setPollingInterval:function(i)
+       {
+               if(typeof i == 'number' && isFinite(i)){
+                       this._polling_interval = i;
+               }
+       },
+
+  /**
+   * Instantiates a XMLHttpRequest object and returns an object with two properties:
+   * the XMLHttpRequest instance and the transaction id.
+   * @private
+   * @param {int} transactionId Property containing the transaction id for this transaction.
+   * @return connection object
+   */
+       createXhrObject:function(transactionId)
+       {
+               var obj,http;
+               try
+               {
+                       // Instantiates XMLHttpRequest in non-IE browsers and assigns to http.
+                       http = new XMLHttpRequest();
+                       //  Object literal with http and tId properties
+                       obj = { conn:http, tId:transactionId };
+               }
+               catch(e)
+               {
+                       for(var i=0; i<this._msxml_progid.length; ++i){
+                               try
+                               {
+                                       // Instantiates XMLHttpRequest for IE and assign to http.
+                                       http = new ActiveXObject(this._msxml_progid[i]);
+                                       if(http){
+                                       //  Object literal with http and tId properties
+                                               obj = { conn:http, tId:transactionId };
+                                               break;
+                                       }
+                               }
+                               catch(e){}
+                       }
+               }
+               finally
+               {
+                       return obj;
+               }
+       },
+
+  /**
+   * This method is called by asyncRequest to create a
+   * valid connection object for the transaction.  It also passes a
+   * transaction id and increments the transaction id counter.
+   * @private
+   * @return object
+   */
+       getConnectionObject:function()
+       {
+               var o;
+               var tId = this._transaction_id;
+
+               try
+               {
+                       o = this.createXhrObject(tId);
+                       if(o){
+                               this._transaction_id++;
+                       }
+               }
+               catch(e){}
+               finally
+               {
+                       return o;
+               }
+       },
+
+  /**
+   * Method for initiating an asynchronous request via the XHR object.
+   * @public
+   * @param {string} method HTTP transaction method
+   * @param {string} uri Fully qualified path of resource
+   * @param callback User-defined callback function or object
+   * @param {string} postData POST body
+   * @return {object} Returns the connection object
+   */
+       asyncRequest:function(method, uri, callback, postData)
+       {
+               var o = this.getConnectionObject();
+
+               if(!o){
+                       return null;
+               }
+               else{
+                       if(this._isFormSubmit){
+                               //If the specified HTTP method is GET, setForm() will return an
+                               //encoded string that is concatenated to the uri to
+                               //create a querystring.
+                               if(method == 'GET'){
+                                       uri += "?" +  this._sFormData;
+                               }
+                               else if(method == 'POST'){
+                                       postData =  this._sFormData;
+                               }
+                               this._sFormData = '';
+                               this._isFormSubmit = false;
+                       }
+
+                       o.conn.open(method, uri, true);
+
+                       if(postData){
+                               this.initHeader('Content-Type','application/x-www-form-urlencoded');
+                       }
+
+                       //Verify whether the transaction has any user-defined HTTP headers
+                       //and set them.
+                       if(this._has_http_headers){
+                               this.setHeader(o);
+                       }
+
+                       this.handleReadyState(o, callback);
+                       postData?o.conn.send(postData):o.conn.send(null);
+
+                       return o;
+               }
+       },
+
+  /**
+   * This method serves as a timer that polls the XHR object's readyState
+   * property during a transaction, instead of binding a callback to the
+   * onreadystatechange event.  Upon readyState 4, handleTransactionResponse
+   * will process the response, and the timer will be cleared.
+   *
+   * @private
+   * @param {object} o The connection object
+   * @param callback User-defined callback object
+   * @return void
+   */
+       handleReadyState:function(o, callback)
+       {
+               var oConn = this;
+               try
+               {
+                       this._poll[o.tId] = window.setInterval(
+                               function(){
+                                       if(o.conn && o.conn.readyState == 4){
+                                               window.clearInterval(oConn._poll[o.tId]);
+                                               oConn._poll.splice(o.tId);
+                                               oConn.handleTransactionResponse(o, callback);
+                                       }
+                               }
+                       ,this._polling_interval);
+               }
+               catch(e)
+               {
+                       window.clearInterval(oConn._poll[o.tId]);
+                       oConn._poll.splice(o.tId);
+                       oConn.handleTransactionResponse(o, callback);
+               }
+       },
+
+  /**
+   * This method attempts to interpret the server response and
+   * determine whether the transaction was successful, or if an error or
+   * exception was encountered.
+   *
+   * @private
+   * @param {object} o The connection object
+   * @param {function} callback - User-defined callback object
+   * @return void
+   */
+       handleTransactionResponse:function(o, callback)
+       {
+               // If no valid callback is provided, then do not process any callback handling.
+               if(!callback){
+                       this.releaseObject(o);
+                       return;
+               }
+
+               var httpStatus;
+               var responseObject;
+
+               try
+               {
+                       httpStatus = o.conn.status;
+               }
+               catch(e){
+                       // 13030 is the custom code to indicate the condition -- in Mozilla/FF --
+                       // when the o object's status and statusText properties are
+                       // unavailable, and a query attempt throws an exception.
+                       httpStatus = 13030;
+               }
+
+               if(httpStatus >= 200 && httpStatus < 300){
+                       responseObject = this.createResponseObject(o, callback.argument);
+                       if(callback.success){
+                               if(!callback.scope){
+                                       callback.success(responseObject);
+                               }
+                               else{
+                                       // If a scope property is defined, the callback will be fired from
+                                       // the context of the object.
+                                       callback.success.apply(callback.scope, [responseObject]);
+                               }
+                       }
+               }
+               else{
+                       switch(httpStatus){
+                               // The following case labels are wininet.dll error codes that may be encountered.
+                               // Server timeout
+                               case 12002:
+                               // 12029 to 12031 correspond to dropped connections.
+                               case 12029:
+                               case 12030:
+                               case 12031:
+                               // Connection closed by server.
+                               case 12152:
+                               // See above comments for variable status.
+                               case 13030:
+                                       responseObject = this.createExceptionObject(o, callback.argument);
+                                       if(callback.failure){
+                                               if(!callback.scope){
+                                                       callback.failure(responseObject);
+                                               }
+                                               else{
+                                                       callback.failure.apply(callback.scope,[responseObject]);
+                                               }
+                                       }
+                                       break;
+                               default:
+                                       responseObject = this.createResponseObject(o, callback.argument);
+                                       if(callback.failure){
+                                               if(!callback.scope){
+                                                       callback.failure(responseObject);
+                                               }
+                                               else{
+                                                       callback.failure.apply(callback.scope,[responseObject]);
+                                               }
+                                       }
+                       }
+               }
+
+               this.releaseObject(o);
+       },
+
+  /**
+   * This method evaluates the server response, creates and returns the results via
+   * its properties.  Success and failure cases will differ in the response
+   * object's property values.
+   * @private
+   * @param {object} o The connection object
+   * @param {} callbackArg User-defined argument or arguments to be passed to the callback
+   * @return object
+   */
+       createResponseObject:function(o, callbackArg)
+       {
+               var obj = {};
+               var headerObj = {};
+
+               try
+               {
+                       var headerStr = o.conn.getAllResponseHeaders();
+                       var header = headerStr.split("\n");
+                       for(var i=0; i < header.length; i++){
+                               var delimitPos = header[i].indexOf(':');
+                               if(delimitPos != -1){
+                                       headerObj[header[i].substring(0,delimitPos)] = header[i].substring(delimitPos+1);
+                               }
+                       }
+
+                       obj.tId = o.tId;
+                       obj.status = o.conn.status;
+                       obj.statusText = o.conn.statusText;
+                       obj.getResponseHeader = headerObj;
+                       obj.getAllResponseHeaders = headerStr;
+                       obj.responseText = o.conn.responseText;
+                       obj.responseXML = o.conn.responseXML;
+                       if(typeof callbackArg !== undefined){
+                               obj.argument = callbackArg;
+                       }
+               }
+               catch(e){}
+               finally
+               {
+                       return obj;
+               }
+       },
+
+  /**
+   * If a transaction cannot be completed due to dropped or closed connections,
+   * there may be not be enough information to build a full response object.
+   * The failure callback will be fired and this specific condition can be identified
+   * by a status property value of 0.
+   * @private
+   * @param {int} tId Transaction Id
+   * @param callbackArg The user-defined arguments
+   * @return object
+   */
+       createExceptionObject:function(tId, callbackArg)
+       {
+               var COMM_CODE = 0;
+               var COMM_ERROR = 'communication failure';
+
+               var obj = {};
+
+               obj.tId = tId;
+               obj.status = COMM_CODE;
+               obj.statusText = COMM_ERROR;
+               if(callbackArg){
+                       obj.argument = callbackArg;
+               }
+
+               return obj;
+       },
+
+  /**
+   * Public method that stores the custom HTTP headers for each transaction.
+   * @public
+   * @param {string} label The HTTP header label
+   * @param {string} value The HTTP header value
+   * @return void
+   */
+       initHeader:function(label,value)
+       {
+               if(this._http_header[label] === undefined){
+                       this._http_header[label] = value;
+               }
+               else{
+                       this._http_header[label] =  value + "," + this._http_header[label];
+               }
+
+               this._has_http_headers = true;
+       },
+
+  /**
+   * Accessor that sets the HTTP headers for each transaction.
+   * @private
+   * @param {object} o The connection object for the transaction.
+   * @return void
+   */
+       setHeader:function(o)
+       {
+               for(var prop in this._http_header){
+                       o.conn.setRequestHeader(prop, this._http_header[prop]);
+               }
+               delete this._http_header;
+
+               this._http_header = {};
+               this._has_http_headers = false;
+       },
+
+  /**
+   * This method assembles the form label and value pairs and
+   * constructs an encoded string.
+   * asyncRequest() will automatically initialize the
+   * transaction with a HTTP header Content-Type of
+   * application/x-www-form-urlencoded.
+   * @public
+   * @param {string || object} form id or name attribute, or form object.
+   * @return void
+   */
+       setForm:function(formId)
+       {
+               this._sFormData = '';
+               if(typeof formId == 'string'){
+                       // Determine if the argument is a form id or a form name.
+                       // Note form name usage is deprecated by supported
+                       // here for legacy reasons.
+                       var oForm = (document.getElementById(formId) || document.forms[formId] );
+               }
+               else if(typeof formId == 'object'){
+                       var oForm = formId;
+               }
+               else{
+                       return;
+               }
+               var oElement, oName, oValue, oDisabled;
+               var hasSubmit = false;
+
+               // Iterate over the form elements collection to construct the
+               // label-value pairs.
+               for (var i=0; i<oForm.elements.length; i++){
+                       oDisabled = oForm.elements[i].disabled;
+                       // If the name attribute is not populated, the form field's
+                       // value will not be submitted.
+                       if(oForm.elements[i].name != ""){
+                               oElement = oForm.elements[i];
+                               oName = oForm.elements[i].name;
+                               oValue = oForm.elements[i].value;
+                       }
+
+                       // Do not submit fields that are disabled.
+                       if(!oDisabled)
+                       {
+                               switch (oElement.type)
+                               {
+                                       case 'select-one':
+                                       case 'select-multiple':
+                                               for(var j=0; j<oElement.options.length; j++){
+                                                       if(oElement.options[j].selected){
+                                                               this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oElement.options[j].value || oElement.options[j].text) + '&';
+                                                       }
+                                               }
+                                               break;
+                                       case 'radio':
+                                       case 'checkbox':
+                                               if(oElement.checked){
+                                                       this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
+                                               }
+                                               break;
+                                       case 'file':
+                                       //      this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
+                                       // stub case as XMLHttpRequest will only send the file path as a string.
+                                       case undefined:
+                                       // stub case for fieldset element which returns undefined.
+                                       case 'reset':
+                                       // stub case for input type reset button.
+                                       case 'button':
+                                       // stub case for input type button elements.
+                                               break;
+                                       case 'submit':
+                                               if(hasSubmit == false){
+                                                       this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
+                                                       hasSubmit = true;
+                                               }
+                                               break;
+                                       default:
+                                               this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
+                                               break;
+                               }
+                       }
+               }
+
+               this._isFormSubmit = true;
+               this._sFormData = this._sFormData.substr(0, this._sFormData.length - 1);
+       },
+
+  /**
+   * Public method to terminate a transaction, if it has not reached readyState 4.
+   * @public
+   * @param {object} o The connection object returned by asyncRequest.
+   * @return void
+   */
+       abort:function(o)
+       {
+               if(this.isCallInProgress(o)){
+                       window.clearInterval(this._poll[o.tId]);
+                       this._poll.splice(o.tId);
+                       o.conn.abort();
+                       this.releaseObject(o);
+
+                       return true;
+               }
+               else{
+                       return false;
+               }
+       },
+
+  /**
+   * Public method to check if the transaction is still being processed.
+   * @public
+   * @param {object} o The connection object returned by asyncRequest
+   * @return boolean
+   */
+       isCallInProgress:function(o)
+       {
+               // if the XHR object assigned to the transaction has not been dereferenced,
+               // then check its readyState status.  Otherwise, return false.
+               if(o.conn){
+                       return o.conn.readyState != 4 && o.conn.readyState != 0;
+               }
+               else{
+                       //The XHR object has been destroyed.
+                       return false;
+               }
+       },
+
+  /**
+   * Dereference the XHR instance and the connection object after the transaction is completed.
+   * @private
+   * @param {object} o The connection object
+   * @return void
+   */
+       releaseObject:function(o)
+       {
+               //dereference the XHR instance.
+               o.conn = null;
+               //dereference the connection object.
+               o = null;
+       }
+};
diff --git a/apps/furnace-fjsc/resources/yahoo/event.js b/apps/furnace-fjsc/resources/yahoo/event.js
new file mode 100644 (file)
index 0000000..cc2a087
--- /dev/null
@@ -0,0 +1,1096 @@
+/*                                                                                                                                                      \r
+Copyright (c) 2006, Yahoo! Inc. All rights reserved.                                                                                                    \r
+Code licensed under the BSD License:                                                                                                                    \r
+http://developer.yahoo.net/yui/license.txt                                                                                                              \r
+version: 0.10.0                                                                                                                                         \r
+*/ \r
+\r
+/**\r
+ * The CustomEvent class lets you define events for your application\r
+ * that can be subscribed to by one or more independent component.\r
+ *\r
+ * @param {String} type The type of event, which is passed to the callback\r
+ *                 when the event fires\r
+ * @param {Object} oScope The context the event will fire from.  "this" will\r
+ *                 refer to this object in the callback.  Default value: \r
+ *                 the window object.  The listener can override this.\r
+ * @constructor\r
+ */\r
+YAHOO.util.CustomEvent = function(type, oScope) {\r
+    /**\r
+     * The type of event, returned to subscribers when the event fires\r
+     * @type string\r
+     */\r
+    this.type = type;\r
+\r
+    /**\r
+     * The scope the the event will fire from by default.  Defaults to the window \r
+     * obj\r
+     * @type object\r
+     */\r
+    this.scope = oScope || window;\r
+\r
+    /**\r
+     * The subscribers to this event\r
+     * @type Subscriber[]\r
+     */\r
+    this.subscribers = [];\r
+\r
+    // Register with the event utility for automatic cleanup.  Made optional\r
+    // so that CustomEvent can be used independently of pe.event\r
+    if (YAHOO.util.Event) { \r
+        YAHOO.util.Event.regCE(this);\r
+    }\r
+};\r
+\r
+YAHOO.util.CustomEvent.prototype = {\r
+    /**\r
+     * Subscribes the caller to this event\r
+     * @param {Function} fn       The function to execute\r
+     * @param {Object}   obj      An object to be passed along when the event fires\r
+     * @param {boolean}  bOverride If true, the obj passed in becomes the execution\r
+     *                            scope of the listener\r
+     */\r
+    subscribe: function(fn, obj, bOverride) {\r
+        this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, bOverride) );\r
+    },\r
+\r
+    /**\r
+     * Unsubscribes the caller from this event\r
+     * @param {Function} fn  The function to execute\r
+     * @param {Object}   obj An object to be passed along when the event fires\r
+     * @return {boolean} True if the subscriber was found and detached.\r
+     */\r
+    unsubscribe: function(fn, obj) {\r
+        var found = false;\r
+        for (var i=0, len=this.subscribers.length; i<len; ++i) {\r
+            var s = this.subscribers[i];\r
+            if (s && s.contains(fn, obj)) {\r
+                this._delete(i);\r
+                found = true;\r
+            }\r
+        }\r
+\r
+        return found;\r
+    },\r
+\r
+    /**\r
+     * Notifies the subscribers.  The callback functions will be executed\r
+     * from the scope specified when the event was created, and with the following\r
+     * parameters:\r
+     *   <pre>\r
+     *   - The type of event\r
+     *   - All of the arguments fire() was executed with as an array\r
+     *   - The custom object (if any) that was passed into the subscribe() method\r
+     *   </pre>\r
+     *   \r
+     * @param {Array} an arbitrary set of parameters to pass to the handler\r
+     */\r
+    fire: function() {\r
+        for (var i=0, len=this.subscribers.length; i<len; ++i) {\r
+            var s = this.subscribers[i];\r
+            if (s) {\r
+                var scope = (s.override) ? s.obj : this.scope;\r
+                s.fn.call(scope, this.type, arguments, s.obj);\r
+            }\r
+        }\r
+    },\r
+\r
+    /**\r
+     * Removes all listeners\r
+     */\r
+    unsubscribeAll: function() {\r
+        for (var i=0, len=this.subscribers.length; i<len; ++i) {\r
+            this._delete(i);\r
+        }\r
+    },\r
+\r
+    /**\r
+     * @private\r
+     */\r
+    _delete: function(index) {\r
+        var s = this.subscribers[index];\r
+        if (s) {\r
+            delete s.fn;\r
+            delete s.obj;\r
+        }\r
+\r
+        delete this.subscribers[index];\r
+    }\r
+};\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+/**\r
+ * @class Stores the subscriber information to be used when the event fires.\r
+ * @param {Function} fn       The function to execute\r
+ * @param {Object}   obj      An object to be passed along when the event fires\r
+ * @param {boolean}  bOverride If true, the obj passed in becomes the execution\r
+ *                            scope of the listener\r
+ * @constructor\r
+ */\r
+YAHOO.util.Subscriber = function(fn, obj, bOverride) {\r
+    /**\r
+     * The callback that will be execute when the event fires\r
+     * @type function\r
+     */\r
+    this.fn = fn;\r
+\r
+    /**\r
+     * An optional custom object that will passed to the callback when\r
+     * the event fires\r
+     * @type object\r
+     */\r
+    this.obj = obj || null;\r
+\r
+    /**\r
+     * The default execution scope for the event listener is defined when the\r
+     * event is created (usually the object which contains the event).\r
+     * By setting override to true, the execution scope becomes the custom\r
+     * object passed in by the subscriber\r
+     * @type boolean\r
+     */\r
+    this.override = (bOverride);\r
+};\r
+\r
+/**\r
+ * Returns true if the fn and obj match this objects properties.\r
+ * Used by the unsubscribe method to match the right subscriber.\r
+ *\r
+ * @param {Function} fn the function to execute\r
+ * @param {Object} obj an object to be passed along when the event fires\r
+ * @return {boolean} true if the supplied arguments match this \r
+ *                   subscriber's signature.\r
+ */\r
+YAHOO.util.Subscriber.prototype.contains = function(fn, obj) {\r
+    return (this.fn == fn && this.obj == obj);\r
+};\r
+\r
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */\r
+\r
+// Only load this library once.  If it is loaded a second time, existing\r
+// events cannot be detached.\r
+if (!YAHOO.util.Event) {\r
+\r
+/**\r
+ * @class\r
+ * The event utility provides functions to add and remove event listeners,\r
+ * event cleansing.  It also tries to automatically remove listeners it\r
+ * registers during the unload event.\r
+ * @constructor\r
+ */\r
+    YAHOO.util.Event = function() {\r
+\r
+        /**\r
+         * True after the onload event has fired\r
+         * @type boolean\r
+         * @private\r
+         */\r
+        var loadComplete =  false;\r
+\r
+        /**\r
+         * Cache of wrapped listeners\r
+         * @type array\r
+         * @private\r
+         */\r
+        var listeners = [];\r
+\r
+        /**\r
+         * Listeners that will be attached during the onload event\r
+         * @type array\r
+         * @private\r
+         */\r
+        var delayedListeners = [];\r
+\r
+        /**\r
+         * User-defined unload function that will be fired before all events\r
+         * are detached\r
+         * @type array\r
+         * @private\r
+         */\r
+        var unloadListeners = [];\r
+\r
+        /**\r
+         * Cache of the custom events that have been defined.  Used for\r
+         * automatic cleanup\r
+         * @type array\r
+         * @private\r
+         */\r
+        var customEvents = [];\r
+\r
+        /**\r
+         * Cache of DOM0 event handlers to work around issues with DOM2 events\r
+         * in Safari\r
+         * @private\r
+         */\r
+        var legacyEvents = [];\r
+\r
+        /**\r
+         * Listener stack for DOM0 events\r
+         * @private\r
+         */\r
+        var legacyHandlers = [];\r
+\r
+        /**\r
+         * The number of times to poll after window.onload.  This number is\r
+         * increased if additional late-bound handlers are requested after\r
+         * the page load.\r
+         * @private\r
+         */\r
+        var retryCount = 0;\r
+\r
+        /**\r
+         * onAvailable listeners\r
+         * @private\r
+         */\r
+        var onAvailStack = [];\r
+\r
+        /**\r
+         * Lookup table for legacy events\r
+         * @private\r
+         */\r
+        var legacyMap = [];\r
+\r
+        /**\r
+         * Counter for auto id generation\r
+         * @private\r
+         */\r
+        var counter = 0;\r
+\r
+        return { // PREPROCESS\r
+\r
+            /**\r
+             * The number of times we should look for elements that are not\r
+             * in the DOM at the time the event is requested after the document\r
+             * has been loaded.  The default is 200@50 ms, so it will poll\r
+             * for 10 seconds or until all outstanding handlers are bound\r
+             * (whichever comes first).\r
+             * @type int\r
+             */\r
+            POLL_RETRYS: 200,\r
+\r
+            /**\r
+             * The poll interval in milliseconds\r
+             * @type int\r
+             */\r
+            POLL_INTERVAL: 50,\r
+\r
+            /**\r
+             * Element to bind, int constant\r
+             * @type int\r
+             */\r
+            EL: 0,\r
+\r
+            /**\r
+             * Type of event, int constant\r
+             * @type int\r
+             */\r
+            TYPE: 1,\r
+\r
+            /**\r
+             * Function to execute, int constant\r
+             * @type int\r
+             */\r
+            FN: 2,\r
+\r
+            /**\r
+             * Function wrapped for scope correction and cleanup, int constant\r
+             * @type int\r
+             */\r
+            WFN: 3,\r
+\r
+            /**\r
+             * Object passed in by the user that will be returned as a \r
+             * parameter to the callback, int constant\r
+             * @type int\r
+             */\r
+            SCOPE: 3,\r
+\r
+            /**\r
+             * Adjusted scope, either the element we are registering the event\r
+             * on or the custom object passed in by the listener, int constant\r
+             * @type int\r
+             */\r
+            ADJ_SCOPE: 4,\r
+\r
+            /**\r
+             * Safari detection is necessary to work around the preventDefault\r
+             * bug that makes it so you can't cancel a href click from the \r
+             * handler.  There is not a capabilities check we can use here.\r
+             * @private\r
+             */\r
+            isSafari: (/Safari|Konqueror|KHTML/gi).test(navigator.userAgent),\r
+\r
+            /**\r
+             * IE detection needed to properly calculate pageX and pageY.  \r
+             * capabilities checking didn't seem to work because another \r
+             * browser that does not provide the properties have the values \r
+             * calculated in a different manner than IE.\r
+             * @private\r
+             */\r
+            isIE: (!this.isSafari && !navigator.userAgent.match(/opera/gi) && \r
+                    navigator.userAgent.match(/msie/gi)),\r
+\r
+            /**\r
+             * @private\r
+             */\r
+            addDelayedListener: function(el, sType, fn, oScope, bOverride) {\r
+                delayedListeners[delayedListeners.length] =\r
+                    [el, sType, fn, oScope, bOverride];\r
+\r
+                // If this happens after the inital page load, we need to\r
+                // reset the poll counter so that we continue to search for\r
+                // the element for a fixed period of time.\r
+                if (loadComplete) {\r
+                    retryCount = this.POLL_RETRYS;\r
+                    this.startTimeout(0);\r
+                    // this._tryPreloadAttach();\r
+                }\r
+            },\r
+\r
+            /**\r
+             * @private\r
+             */\r
+            startTimeout: function(interval) {\r
+                var i = (interval || interval === 0) ? interval : this.POLL_INTERVAL;\r
+                var self = this;\r
+                var callback = function() { self._tryPreloadAttach(); };\r
+                this.timeout = setTimeout(callback, i);\r
+            },\r
+\r
+            /**\r
+             * Executes the supplied callback when the item with the supplied\r
+             * id is found.  This is meant to be used to execute behavior as\r
+             * soon as possible as the page loads.  If you use this after the\r
+             * initial page load it will poll for a fixed time for the element.\r
+             * The number of times it will poll and the frequency are\r
+             * configurable.  By default it will poll for 10 seconds.\r
+             * @param {string} p_id the id of the element to look for.\r
+             * @param {function} p_fn what to execute when the element is found.\r
+             * @param {object} p_obj an optional object to be passed back as\r
+             * a parameter to p_fn.\r
+             * @param {boolean} p_override If set to true, p_fn will execute\r
+             * in the scope of p_obj\r
+             *\r
+             */\r
+            onAvailable: function(p_id, p_fn, p_obj, p_override) {\r
+                onAvailStack.push( { id:       p_id, \r
+                                     fn:       p_fn, \r
+                                     obj:      p_obj, \r
+                                     override: p_override } );\r
+\r
+                retryCount = this.POLL_RETRYS;\r
+                this.startTimeout(0);\r
+                // this._tryPreloadAttach();\r
+            },\r
+\r
+            /**\r
+             * Appends an event handler\r
+             *\r
+             * @param {Object}   el        The html element to assign the \r
+             *                             event to\r
+             * @param {String}   sType     The type of event to append\r
+             * @param {Function} fn        The method the event invokes\r
+             * @param {Object}   oScope    An arbitrary object that will be \r
+             *                             passed as a parameter to the handler\r
+             * @param {boolean}  bOverride If true, the obj passed in becomes\r
+             *                             the execution scope of the listener\r
+             * @return {boolean} True if the action was successful or defered,\r
+             *                        false if one or more of the elements \r
+             *                        could not have the event bound to it.\r
+             */\r
+            addListener: function(el, sType, fn, oScope, bOverride) {\r
+\r
+                if (!fn || !fn.call) {\r
+                    return false;\r
+                }\r
+\r
+                // The el argument can be an array of elements or element ids.\r
+                if ( this._isValidCollection(el)) {\r
+                    var ok = true;\r
+                    for (var i=0,len=el.length; i<len; ++i) {\r
+                        ok = ( this.on(el[i], \r
+                                       sType, \r
+                                       fn, \r
+                                       oScope, \r
+                                       bOverride) && ok );\r
+                    }\r
+                    return ok;\r
+\r
+                } else if (typeof el == "string") {\r
+                    var oEl = this.getEl(el);\r
+                    // If the el argument is a string, we assume it is \r
+                    // actually the id of the element.  If the page is loaded\r
+                    // we convert el to the actual element, otherwise we \r
+                    // defer attaching the event until onload event fires\r
+\r
+                    // check to see if we need to delay hooking up the event \r
+                    // until after the page loads.\r
+                    if (loadComplete && oEl) {\r
+                        el = oEl;\r
+                    } else {\r
+                        // defer adding the event until onload fires\r
+                        this.addDelayedListener(el, \r
+                                                sType, \r
+                                                fn, \r
+                                                oScope, \r
+                                                bOverride);\r
+\r
+                        return true;\r
+                    }\r
+                }\r
+\r
+                // Element should be an html element or an array if we get \r
+                // here.\r
+                if (!el) {\r
+                    return false;\r
+                }\r
+\r
+                // we need to make sure we fire registered unload events \r
+                // prior to automatically unhooking them.  So we hang on to \r
+                // these instead of attaching them to the window and fire the\r
+                // handles explicitly during our one unload event.\r
+                if ("unload" == sType && oScope !== this) {\r
+                    unloadListeners[unloadListeners.length] =\r
+                            [el, sType, fn, oScope, bOverride];\r
+                    return true;\r
+                }\r
+\r
+\r
+                // if the user chooses to override the scope, we use the custom\r
+                // object passed in, otherwise the executing scope will be the\r
+                // HTML element that the event is registered on\r
+                var scope = (bOverride) ? oScope : el;\r
+\r
+                // wrap the function so we can return the oScope object when\r
+                // the event fires;\r
+                var wrappedFn = function(e) {\r
+                        return fn.call(scope, YAHOO.util.Event.getEvent(e), \r
+                                oScope);\r
+                    };\r
+\r
+                var li = [el, sType, fn, wrappedFn, scope];\r
+                var index = listeners.length;\r
+                // cache the listener so we can try to automatically unload\r
+                listeners[index] = li;\r
+\r
+                if (this.useLegacyEvent(el, sType)) {\r
+                    var legacyIndex = this.getLegacyIndex(el, sType);\r
+                    if (legacyIndex == -1) {\r
+\r
+                        legacyIndex = legacyEvents.length;\r
+                        legacyMap[el.id + sType] = legacyIndex;\r
+\r
+                        // cache the signature for the DOM0 event, and \r
+                        // include the existing handler for the event, if any\r
+                        legacyEvents[legacyIndex] = \r
+                            [el, sType, el["on" + sType]];\r
+                        legacyHandlers[legacyIndex] = [];\r
+\r
+                        el["on" + sType] = \r
+                            function(e) {\r
+                                YAHOO.util.Event.fireLegacyEvent(\r
+                                    YAHOO.util.Event.getEvent(e), legacyIndex);\r
+                            };\r
+                    }\r
+\r
+                    // add a reference to the wrapped listener to our custom\r
+                    // stack of events\r
+                    legacyHandlers[legacyIndex].push(index);\r
+\r
+                // DOM2 Event model\r
+                } else if (el.addEventListener) {\r
+                    el.addEventListener(sType, wrappedFn, false);\r
+                // Internet Explorer abstraction\r
+                } else if (el.attachEvent) {\r
+                    el.attachEvent("on" + sType, wrappedFn);\r
+                }\r
+\r
+                return true;\r
+                \r
+            },\r
+\r
+            /**\r
+             * Shorthand for YAHOO.util.Event.addListener\r
+             * @type function\r
+             */\r
+            // on: this.addListener,\r
+\r
+            /**\r
+             * When using legacy events, the handler is routed to this object\r
+             * so we can fire our custom listener stack.\r
+             * @private\r
+             */\r
+            fireLegacyEvent: function(e, legacyIndex) {\r
+                var ok = true;\r
+\r
+                var le = legacyHandlers[legacyIndex];\r
+                for (var i=0,len=le.length; i<len; ++i) {\r
+                    var index = le[i];\r
+                    if (index) {\r
+                        var li = listeners[index];\r
+                        if ( li && li[this.WFN] ) {\r
+                            var scope = li[this.ADJ_SCOPE];\r
+                            var ret = li[this.WFN].call(scope, e);\r
+                            ok = (ok && ret);\r
+                        } else {\r
+                            // This listener was removed, so delete it from\r
+                            // the array\r
+                            delete le[i];\r
+                        }\r
+                    }\r
+                }\r
+\r
+                return ok;\r
+            },\r
+\r
+            /**\r
+             * Returns the legacy event index that matches the supplied \r
+             * signature\r
+             * @private\r
+             */\r
+            getLegacyIndex: function(el, sType) {\r
+                /*\r
+                for (var i=0,len=legacyEvents.length; i<len; ++i) {\r
+                    var le = legacyEvents[i];\r
+                    if (le && le[0] === el && le[1] === sType) {\r
+                        return i;\r
+                    }\r
+                }\r
+                return -1;\r
+                */\r
+\r
+                var key = this.generateId(el) + sType;\r
+                if (typeof legacyMap[key] == "undefined") { \r
+                    return -1;\r
+                } else {\r
+                    return legacyMap[key];\r
+                }\r
+\r
+            },\r
+\r
+            /**\r
+             * Logic that determines when we should automatically use legacy\r
+             * events instead of DOM2 events.\r
+             * @private\r
+             */\r
+            useLegacyEvent: function(el, sType) {\r
+\r
+                if (!el.addEventListener && !el.attachEvent) {\r
+                    return true;\r
+                } else if (this.isSafari) {\r
+                    if ("click" == sType || "dblclick" == sType) {\r
+                        return true;\r
+                    }\r
+                }\r
+\r
+                return false;\r
+            },\r
+                    \r
+            /**\r
+             * Removes an event handler\r
+             *\r
+             * @param {Object} el the html element or the id of the element to \r
+             * assign the event to.\r
+             * @param {String} sType the type of event to remove\r
+             * @param {Function} fn the method the event invokes\r
+             * @return {boolean} true if the unbind was successful, false \r
+             * otherwise\r
+             */\r
+            removeListener: function(el, sType, fn, index) {\r
+\r
+                if (!fn || !fn.call) {\r
+                    return false;\r
+                }\r
+\r
+                // The el argument can be a string\r
+                if (typeof el == "string") {\r
+                    el = this.getEl(el);\r
+                // The el argument can be an array of elements or element ids.\r
+                } else if ( this._isValidCollection(el)) {\r
+                    var ok = true;\r
+                    for (var i=0,len=el.length; i<len; ++i) {\r
+                        ok = ( this.removeListener(el[i], sType, fn) && ok );\r
+                    }\r
+                    return ok;\r
+                }\r
+\r
+                if ("unload" == sType) {\r
+\r
+                    for (i=0, len=unloadListeners.length; i<len; i++) {\r
+                        var li = unloadListeners[i];\r
+                        if (li && \r
+                            li[0] == el && \r
+                            li[1] == sType && \r
+                            li[2] == fn) {\r
+                                delete unloadListeners[i];\r
+                                return true;\r
+                        }\r
+                    }\r
+\r
+                    return false;\r
+                }\r
+\r
+                var cacheItem = null;\r
+  \r
+                if ("undefined" == typeof index) {\r
+                    index = this._getCacheIndex(el, sType, fn);\r
+                }\r
+\r
+                if (index >= 0) {\r
+                    cacheItem = listeners[index];\r
+                }\r
+\r
+                if (!el || !cacheItem) {\r
+                    return false;\r
+                }\r
+\r
+\r
+                if (el.removeEventListener) {\r
+                    el.removeEventListener(sType, cacheItem[this.WFN], false);\r
+                } else if (el.detachEvent) {\r
+                    el.detachEvent("on" + sType, cacheItem[this.WFN]);\r
+                }\r
+\r
+                // removed the wrapped handler\r
+                delete listeners[index][this.WFN];\r
+                delete listeners[index][this.FN];\r
+                delete listeners[index];\r
+\r
+                return true;\r
+\r
+            },\r
+\r
+            /**\r
+             * Returns the event's target element\r
+             * @param {Event} ev the event\r
+             * @param {boolean} resolveTextNode when set to true the target's\r
+             *                  parent will be returned if the target is a \r
+             *                  text node\r
+             * @return {HTMLElement} the event's target\r
+             */\r
+            getTarget: function(ev, resolveTextNode) {\r
+                var t = ev.target || ev.srcElement;\r
+\r
+                if (resolveTextNode && t && "#text" == t.nodeName) {\r
+                    return t.parentNode;\r
+                } else {\r
+                    return t;\r
+                }\r
+            },\r
+\r
+            /**\r
+             * Returns the event's pageX\r
+             * @param {Event} ev the event\r
+             * @return {int} the event's pageX\r
+             */\r
+            getPageX: function(ev) {\r
+                var x = ev.pageX;\r
+                if (!x && 0 !== x) {\r
+                    x = ev.clientX || 0;\r
+\r
+                    if ( this.isIE ) {\r
+                        x += this._getScrollLeft();\r
+                    }\r
+                }\r
+\r
+                return x;\r
+            },\r
+\r
+            /**\r
+             * Returns the event's pageY\r
+             * @param {Event} ev the event\r
+             * @return {int} the event's pageY\r
+             */\r
+            getPageY: function(ev) {\r
+                var y = ev.pageY;\r
+                if (!y && 0 !== y) {\r
+                    y = ev.clientY || 0;\r
+\r
+                    if ( this.isIE ) {\r
+                        y += this._getScrollTop();\r
+                    }\r
+                }\r
+\r
+                return y;\r
+            },\r
+\r
+            /**\r
+             * Returns the pageX and pageY properties as an indexed array.\r
+             * @type int[]\r
+             */\r
+            getXY: function(ev) {\r
+                return [this.getPageX(ev), this.getPageY(ev)];\r
+            },\r
+\r
+            /**\r
+             * Returns the event's related target \r
+             * @param {Event} ev the event\r
+             * @return {HTMLElement} the event's relatedTarget\r
+             */\r
+            getRelatedTarget: function(ev) {\r
+                var t = ev.relatedTarget;\r
+                if (!t) {\r
+                    if (ev.type == "mouseout") {\r
+                        t = ev.toElement;\r
+                    } else if (ev.type == "mouseover") {\r
+                        t = ev.fromElement;\r
+                    }\r
+                }\r
+\r
+                return t;\r
+            },\r
+\r
+            /**\r
+             * Returns the time of the event.  If the time is not included, the\r
+             * event is modified using the current time.\r
+             * @param {Event} ev the event\r
+             * @return {Date} the time of the event\r
+             */\r
+            getTime: function(ev) {\r
+                if (!ev.time) {\r
+                    var t = new Date().getTime();\r
+                    try {\r
+                        ev.time = t;\r
+                    } catch(e) { \r
+                        // can't set the time property  \r
+                        return t;\r
+                    }\r
+                }\r
+\r
+                return ev.time;\r
+            },\r
+\r
+            /**\r
+             * Convenience method for stopPropagation + preventDefault\r
+             * @param {Event} ev the event\r
+             */\r
+            stopEvent: function(ev) {\r
+                this.stopPropagation(ev);\r
+                this.preventDefault(ev);\r
+            },\r
+\r
+            /**\r
+             * Stops event propagation\r
+             * @param {Event} ev the event\r
+             */\r
+            stopPropagation: function(ev) {\r
+                if (ev.stopPropagation) {\r
+                    ev.stopPropagation();\r
+                } else {\r
+                    ev.cancelBubble = true;\r
+                }\r
+            },\r
+\r
+            /**\r
+             * Prevents the default behavior of the event\r
+             * @param {Event} ev the event\r
+             */\r
+            preventDefault: function(ev) {\r
+                if (ev.preventDefault) {\r
+                    ev.preventDefault();\r
+                } else {\r
+                    ev.returnValue = false;\r
+                }\r
+            },\r
+             \r
+            /**\r
+             * Finds the event in the window object, the caller's arguments, or\r
+             * in the arguments of another method in the callstack.  This is\r
+             * executed automatically for events registered through the event\r
+             * manager, so the implementer should not normally need to execute\r
+             * this function at all.\r
+             * @param {Event} the event parameter from the handler\r
+             * @return {Event} the event \r
+             */\r
+            getEvent: function(e) {\r
+                var ev = e || window.event;\r
+\r
+                if (!ev) {\r
+                    var c = this.getEvent.caller;\r
+                    while (c) {\r
+                        ev = c.arguments[0];\r
+                        if (ev && Event == ev.constructor) {\r
+                            break;\r
+                        }\r
+                        c = c.caller;\r
+                    }\r
+                }\r
+\r
+                return ev;\r
+            },\r
+\r
+            /**\r
+             * Returns the charcode for an event\r
+             * @param {Event} ev the event\r
+             * @return {int} the event's charCode\r
+             */\r
+            getCharCode: function(ev) {\r
+                return ev.charCode || ((ev.type == "keypress") ? ev.keyCode : 0);\r
+            },\r
+\r
+            /**\r
+             * @private\r
+             * Locating the saved event handler data by function ref\r
+             */\r
+            _getCacheIndex: function(el, sType, fn) {\r
+                for (var i=0,len=listeners.length; i<len; ++i) {\r
+                    var li = listeners[i];\r
+                    if ( li                 && \r
+                         li[this.FN] == fn  && \r
+                         li[this.EL] == el  && \r
+                         li[this.TYPE] == sType ) {\r
+                        return i;\r
+                    }\r
+                }\r
+\r
+                return -1;\r
+            },\r
+\r
+            /**\r
+             * Generates an unique ID for the element if it does not already \r
+             * have one.\r
+             * @param el the element\r
+             * @return {string} the id of the element\r
+             */\r
+            generateId: function(el) {\r
+                var id = el.id;\r
+\r
+                if (!id) {\r
+                    id = "yuievtautoid-" + (counter++);\r
+                    el.id = id;\r
+                }\r
+\r
+                return id;\r
+            },\r
+\r
+            /**\r
+             * We want to be able to use getElementsByTagName as a collection\r
+             * to attach a group of events to.  Unfortunately, different \r
+             * browsers return different types of collections.  This function\r
+             * tests to determine if the object is array-like.  It will also \r
+             * fail if the object is an array, but is empty.\r
+             * @param o the object to test\r
+             * @return {boolean} true if the object is array-like and populated\r
+             * @private\r
+             */\r
+            _isValidCollection: function(o) {\r
+\r
+                return ( o                    && // o is something\r
+                         o.length             && // o is indexed\r
+                         typeof o != "string" && // o is not a string\r
+                         !o.tagName           && // o is not an HTML element\r
+                         !o.alert             && // o is not a window\r
+                         typeof o[0] != "undefined" );\r
+\r
+            },\r
+\r
+            /**\r
+             * @private\r
+             * DOM element cache\r
+             */\r
+            elCache: {},\r
+\r
+            /**\r
+             * We cache elements bound by id because when the unload event \r
+             * fires, we can no longer use document.getElementById\r
+             * @private\r
+             */\r
+            getEl: function(id) {\r
+                return document.getElementById(id);\r
+            },\r
+\r
+            /**\r
+             * Clears the element cache\r
+             * @deprecated\r
+             * @private\r
+             */\r
+            clearCache: function() { },\r
+\r
+            /**\r
+             * Called by CustomEvent instances to provide a handle to the \r
+             * event * that can be removed later on.  Should be package \r
+             * protected.\r
+             * @private\r
+             */\r
+            regCE: function(ce) {\r
+                customEvents.push(ce);\r
+            },\r
+\r
+            /**\r
+             * @private\r
+             * hook up any deferred listeners\r
+             */\r
+            _load: function(e) {\r
+                loadComplete = true;\r
+            },\r
+\r
+            /**\r
+             * Polling function that runs before the onload event fires, \r
+             * attempting * to attach to DOM Nodes as soon as they are \r
+             * available\r
+             * @private\r
+             */\r
+            _tryPreloadAttach: function() {\r
+\r
+                if (this.locked) {\r
+                    return false;\r
+                }\r
+\r
+                this.locked = true;\r
+\r
+\r
+                // keep trying until after the page is loaded.  We need to \r
+                // check the page load state prior to trying to bind the \r
+                // elements so that we can be certain all elements have been \r
+                // tested appropriately\r
+                var tryAgain = !loadComplete;\r
+                if (!tryAgain) {\r
+                    tryAgain = (retryCount > 0);\r
+                }\r
+\r
+                // Delayed listeners\r
+                var stillDelayed = [];\r
+\r
+                for (var i=0,len=delayedListeners.length; i<len; ++i) {\r
+                    var d = delayedListeners[i];\r
+                    // There may be a race condition here, so we need to \r
+                    // verify the array element is usable.\r
+                    if (d) {\r
+\r
+                        // el will be null if document.getElementById did not\r
+                        // work\r
+                        var el = this.getEl(d[this.EL]);\r
+\r
+                        if (el) {\r
+                            this.on(el, d[this.TYPE], d[this.FN], \r
+                                    d[this.SCOPE], d[this.ADJ_SCOPE]);\r
+                            delete delayedListeners[i];\r
+                        } else {\r
+                            stillDelayed.push(d);\r
+                        }\r
+                    }\r
+                }\r
+\r
+                delayedListeners = stillDelayed;\r
+\r
+                // onAvailable\r
+                notAvail = [];\r
+                for (i=0,len=onAvailStack.length; i<len ; ++i) {\r
+                    var item = onAvailStack[i];\r
+                    if (item) {\r
+                        el = this.getEl(item.id);\r
+\r
+                        if (el) {\r
+                            var scope = (item.override) ? item.obj : el;\r
+                            item.fn.call(scope, item.obj);\r
+                            delete onAvailStack[i];\r
+                        } else {\r
+                            notAvail.push(item);\r
+                        }\r
+                    }\r
+                }\r
+\r
+                retryCount = (stillDelayed.length === 0 && \r
+                                    notAvail.length === 0) ? 0 : retryCount - 1;\r
+\r
+                if (tryAgain) {\r
+                    this.startTimeout();\r
+                }\r
+\r
+                this.locked = false;\r
+\r
+            },\r
+\r
+            /**\r
+             * Removes all listeners registered by pe.event.  Called \r
+             * automatically during the unload event.\r
+             * @private\r
+             */\r
+            _unload: function(e, me) {\r
+                for (var i=0,len=unloadListeners.length; i<len; ++i) {\r
+                    var l = unloadListeners[i];\r
+                    if (l) {\r
+                        var scope = (l[this.ADJ_SCOPE]) ? l[this.SCOPE]: window;\r
+                        l[this.FN].call(scope, this.getEvent(e), l[this.SCOPE] );\r
+                    }\r
+                }\r
+\r
+                if (listeners && listeners.length > 0) {\r
+                    for (i=0,len=listeners.length; i<len ; ++i) {\r
+                        l = listeners[i];\r
+                        if (l) {\r
+                            this.removeListener(l[this.EL], l[this.TYPE], \r
+                                    l[this.FN], i);\r
+                        }\r
+                    }\r
+\r
+                    this.clearCache();\r
+                }\r
+\r
+                for (i=0,len=customEvents.length; i<len; ++i) {\r
+                    customEvents[i].unsubscribeAll();\r
+                    delete customEvents[i];\r
+                }\r
+\r
+                for (i=0,len=legacyEvents.length; i<len; ++i) {\r
+                    // dereference the element\r
+                    delete legacyEvents[i][0];\r
+                    // delete the array item\r
+                    delete legacyEvents[i];\r
+                }\r
+            },\r
+\r
+            /**\r
+             * Returns scrollLeft\r
+             * @private\r
+             */\r
+            _getScrollLeft: function() {\r
+                return this._getScroll()[1];\r
+            },\r
+\r
+            /**\r
+             * Returns scrollTop\r
+             * @private\r
+             */\r
+            _getScrollTop: function() {\r
+                return this._getScroll()[0];\r
+            },\r
+\r
+            /**\r
+             * Returns the scrollTop and scrollLeft.  Used to calculate the \r
+             * pageX and pageY in Internet Explorer\r
+             * @private\r
+             */\r
+            _getScroll: function() {\r
+                var dd = document.documentElement; db = document.body;\r
+                if (dd && dd.scrollTop) {\r
+                    return [dd.scrollTop, dd.scrollLeft];\r
+                } else if (db) {\r
+                    return [db.scrollTop, db.scrollLeft];\r
+                } else {\r
+                    return [0, 0];\r
+                }\r
+            }\r
+        };\r
+    } ();\r
+\r
+    /**\r
+     * @private\r
+     */\r
+    YAHOO.util.Event.on = YAHOO.util.Event.addListener;\r
+\r
+    if (document && document.body) {\r
+        YAHOO.util.Event._load();\r
+    } else {\r
+        YAHOO.util.Event.on(window, "load", YAHOO.util.Event._load, \r
+                YAHOO.util.Event, true);\r
+    }\r
+\r
+    YAHOO.util.Event.on(window, "unload", YAHOO.util.Event._unload, \r
+                YAHOO.util.Event, true);\r
+\r
+    YAHOO.util.Event._tryPreloadAttach();\r
+\r
+}\r
+\r
diff --git a/apps/furnace-fjsc/resources/yahoo/yahoo.js b/apps/furnace-fjsc/resources/yahoo/yahoo.js
new file mode 100644 (file)
index 0000000..55cdc78
--- /dev/null
@@ -0,0 +1,61 @@
+/*                                                                                                                                                      \r
+Copyright (c) 2006, Yahoo! Inc. All rights reserved.                                                                                                    \r
+Code licensed under the BSD License:                                                                                                                    \r
+http://developer.yahoo.net/yui/license.txt                                                                                                              \r
+version: 0.10.0                                                                                                                                         \r
+*/ \r
+\r
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */\r
+\r
+/**\r
+ * The Yahoo global namespace\r
+ * @constructor\r
+ */\r
+var YAHOO = window.YAHOO || {};\r
+\r
+/**\r
+ * Returns the namespace specified and creates it if it doesn't exist\r
+ *\r
+ * YAHOO.namespace("property.package");\r
+ * YAHOO.namespace("YAHOO.property.package");\r
+ *\r
+ * Either of the above would create YAHOO.property, then\r
+ * YAHOO.property.package\r
+ *\r
+ * @param  {String} sNameSpace String representation of the desired \r
+ *                             namespace\r
+ * @return {Object}            A reference to the namespace object\r
+ */\r
+YAHOO.namespace = function( sNameSpace ) {\r
+\r
+    if (!sNameSpace || !sNameSpace.length) {\r
+        return null;\r
+    }\r
+\r
+    var levels = sNameSpace.split(".");\r
+\r
+    var currentNS = YAHOO;\r
+\r
+    // YAHOO is implied, so it is ignored if it is included\r
+    for (var i=(levels[0] == "YAHOO") ? 1 : 0; i<levels.length; ++i) {\r
+        currentNS[levels[i]] = currentNS[levels[i]] || {};\r
+        currentNS = currentNS[levels[i]];\r
+    }\r
+\r
+    return currentNS;\r
+};\r
+\r
+/**\r
+ * Global log method.\r
+ */\r
+YAHOO.log = function(sMsg,sCategory) {\r
+    if(YAHOO.widget.Logger) {\r
+        YAHOO.widget.Logger.log(null, sMsg, sCategory);\r
+    } else {\r
+        return false;\r
+    }\r
+};\r
+\r
+YAHOO.namespace("util");\r
+YAHOO.namespace("widget");\r
+YAHOO.namespace("example");\r
index 527f54ed87262741d6bd26a63f24f3c52445137f..9868be1f552e8ea2fbc6cc00a2a2e183087bef5a 100644 (file)
@@ -59,7 +59,7 @@ M: ast-expression (compile)
     (compile) "; " ,
   ] each ;
 
-: compile ( ast -- string )
+: fjsc-compile ( ast -- string )
   [
     [ (compile) ] { } make [ write ] each
   ] string-out ;