[ Index ]
 

Code source de Seagull 0.6.1

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/js/html_ajax/ -> HTML_AJAX.js (source)

   1  // Compat.js
   2  /**
   3   * Compat functions
   4   * @category    HTML
   5   * @package    AJAX
   6   * @author    Joshua Eichorn <josh@bluga.net>
   7   * @copyright    2005 Joshua Eichorn
   8   * @license    http://www.opensource.org/licenses/lgpl-license.php  LGPL
   9   */
  10  /**
  11   *  Functions for compatibility with older browsers
  12   */
  13  if (!String.fromCharCode && !String.prototype.fromCharCode) {
  14      String.prototype.fromCharCode = function(code)
  15      {
  16          var h = code.toString(16);
  17          if (h.length == 1) {
  18              h = '0' + h;
  19          }
  20          return unescape('%' + h);
  21      }
  22  }
  23  if (!String.charCodeAt && !String.prototype.charCodeAt) {
  24      String.prototype.charCodeAt = function(index)
  25      {
  26          var c = this.charAt(index);
  27          for (i = 1; i < 256; i++) {
  28              if (String.fromCharCode(i) == c) {
  29                  return i;
  30              }
  31          } 
  32      }
  33  }
  34  // http://www.crockford.com/javascript/remedial.html
  35  if (!Array.splice && !Array.prototype.splice) {
  36      Array.prototype.splice = function(s, d)
  37      {
  38          var max = Math.max,
  39          min = Math.min,
  40          a = [], // The return value array
  41          e,  // element
  42          i = max(arguments.length - 2, 0),   // insert count
  43          k = 0,
  44          l = this.length,
  45          n,  // new length
  46          v,  // delta
  47          x;  // shift count
  48  
  49          s = s || 0;
  50          if (s < 0) {
  51              s += l;
  52          }
  53          s = max(min(s, l), 0);  // start point
  54          d = max(min(typeof d == 'number' ? d : l, l - s), 0);    // delete count
  55          v = i - d;
  56          n = l + v;
  57          while (k < d) {
  58              e = this[s + k];
  59              if (!e) {
  60                  a[k] = e;
  61              }
  62              k += 1;
  63          }
  64          x = l - s - d;
  65          if (v < 0) {
  66              k = s + i;
  67              while (x) {
  68                  this[k] = this[k - v];
  69                  k += 1;
  70                  x -= 1;
  71              }
  72              this.length = n;
  73          } else if (v > 0) {
  74              k = 1;
  75              while (x) {
  76                  this[n - k] = this[l - k];
  77                  k += 1;
  78                  x -= 1;
  79              }
  80          }
  81          for (k = 0; k < i; ++k) {
  82              this[s + k] = arguments[k + 2];
  83          }
  84          return a;
  85      }
  86  }
  87  if (!Array.push && !Array.prototype.push) {
  88      Array.prototype.push = function()
  89      {
  90          for (var i = 0, startLength = this.length; i < arguments.length; i++) {
  91              this[startLength + i] = arguments[i];
  92          }
  93          return this.length;
  94      }
  95  }
  96  if (!Array.pop && !Array.prototype.pop) {
  97      Array.prototype.pop = function()
  98      {
  99          return this.splice(this.length - 1, 1)[0];
 100      }
 101  }
 102  /*
 103      From IE7, version 0.9 (alpha) (2005-08-19)
 104      Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
 105  */
 106  if (!DOMParser.parseFromString && window.ActiveXObject)
 107  {
 108  function DOMParser() {/* empty constructor */};
 109  DOMParser.prototype = {
 110      parseFromString: function(str, contentType) {
 111          var xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
 112          xmlDocument.loadXML(str);
 113          return xmlDocument;
 114      }
 115  };
 116  
 117  function XMLSerializer() {/* empty constructor */};
 118  XMLSerializer.prototype = {
 119      serializeToString: function(root) {
 120          return root.xml || root.outerHTML;
 121      }
 122  };
 123  }
 124  // Main.js
 125  /**
 126   * JavaScript library for use with HTML_AJAX
 127   *
 128   * This library is free software; you can redistribute it and/or
 129   * modify it under the terms of the GNU Lesser General Public
 130   * License as published by the Free Software Foundation; either
 131   * version 2.1 of the License, or (at your option) any later version.
 132   *
 133   * This library is distributed in the hope that it will be useful,
 134   * but WITHOUT ANY WARRANTY; without even the implied warranty of
 135   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 136   * Lesser General Public License for more details.
 137   *
 138   * You should have received a copy of the GNU Lesser General Public
 139   * License along with this library; if not, write to:
 140   * Free Software Foundation, Inc.,
 141   * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 142   *
 143   * @category    HTML
 144   * @package    Ajax
 145   * @author    Joshua Eichorn <josh@bluga.net>
 146   * @author    Arpad Ray <arpad@php.net>
 147   * @author    David Coallier <davidc@php.net>
 148   * @author    Elizabeth Smith <auroraeosrose@gmail.com>
 149   * @copyright    2005 Joshua Eichorn, Arpad Ray, David Coallier, Elizabeth Smith
 150   * @license    http://www.opensource.org/licenses/lgpl-license.php  LGPL
 151   */
 152  
 153  /**
 154   * HTML_AJAX static methods, this is the main proxyless api, it also handles global error and event handling
 155   */
 156  var HTML_AJAX = {
 157      defaultServerUrl: false,
 158      defaultEncoding: 'JSON',
 159      queues: false,
 160      clientPools: {},
 161      // get an HttpClient, supply a name to use the pool of that name or the default if it isn't found
 162      httpClient: function(name) {
 163          if (name) {
 164              if (this.clientPools[name]) {
 165                  return this.clientPools[name].getClient();
 166              }
 167          }
 168          return this.clientPools['default'].getClient();
 169      },
 170      // Pushing the given request to queue specified by it, in default operation this will immediately make a request
 171      // request might be delayed or never happen depending on the queue setup
 172      // making a sync request to a non immediate queue will cause you problems so just don't do it
 173      makeRequest: function(request) {
 174          if (!HTML_AJAX.queues[request.queue]) {
 175              var e = new Error('Unknown Queue: '+request.queue);
 176              if (HTML_AJAX.onError) {
 177                  HTML_AJAX.onError(e);
 178                  return false;
 179              }
 180              else {
 181                  throw(e);
 182              }
 183          }
 184          else {
 185              var qn = request.queue;
 186              var q = HTML_AJAX.queues[qn];
 187  
 188              HTML_AJAX.queues[request.queue].addRequest(request);
 189              return HTML_AJAX.queues[request.queue].processRequest();
 190          }
 191      },
 192      // get a serializer object for a specific encoding
 193      serializerForEncoding: function(encoding) {
 194          for(var i in HTML_AJAX.contentTypeMap) {
 195              if (encoding == HTML_AJAX.contentTypeMap[i] || encoding == i) {
 196                  return eval("new HTML_AJAX_Serialize_"+i+";");
 197              }
 198          }
 199          return new HTML_AJAX_Serialize_Null();
 200      },
 201      fullcall: function(url,encoding,className,method,callback,args, options) {
 202          var serializer = HTML_AJAX.serializerForEncoding(encoding);
 203  
 204          var request = new HTML_AJAX_Request(serializer);
 205          if (callback) {
 206              request.isAsync = true;
 207          }
 208          request.requestUrl = url;
 209          request.className = className;
 210          request.methodName = method;
 211          request.callback = callback;
 212          request.args = args;
 213          if (options) {
 214              for(var i in options) {
 215                  request[i] = options[i];
 216              }
 217              if (options.grab) {
 218                  if (!request.args || !request.args.length) {
 219                      request.requestType = 'GET';
 220                  }
 221              }
 222          }
 223  
 224          return HTML_AJAX.makeRequest(request);
 225      },
 226      callPhpCallback: function(phpCallback, jsCallback, url) {
 227          var args = new Array();
 228          for (var i = 3; i < arguments.length; i++) {
 229              args.push(arguments[i]);
 230          }
 231          if (HTML_AJAX_Util.getType(phpCallback[0]) == 'object') {
 232              jsCallback(phpCallback[0][phpCallback[1]](args));
 233              return;
 234          }
 235          if (!url) {
 236              url = HTML_AJAX.defaultServerUrl;
 237          }
 238          HTML_AJAX.fullcall(url, HTML_AJAX.defaultEncoding,
 239              false, false, jsCallback, args, {phpCallback: phpCallback});
 240      },
 241      call: function(className,method,callback) {
 242          var args = new Array();
 243          for(var i = 3; i < arguments.length; i++) {
 244              args.push(arguments[i]);
 245          }
 246          return HTML_AJAX.fullcall(HTML_AJAX.defaultServerUrl,HTML_AJAX.defaultEncoding,className,method,callback,args);
 247      },
 248      grab: function(url,callback,options) {
 249          if (!options) {
 250              options = {grab:true};
 251          }
 252          else {
 253              options['grab'] = true;
 254          }
 255          return HTML_AJAX.fullcall(url,'Null',false,null,callback, '', options);
 256      },
 257      post: function(url,payload,callback,options) {
 258          var serializer = 'Null';
 259          if (HTML_AJAX_Util.getType(payload) == 'object') {
 260              serializer = 'Urlencoded';
 261          }
 262          return HTML_AJAX.fullcall(url,serializer,false,null,callback, payload, options);
 263      },
 264      replace: function(id) {
 265          var callback = function(result) {
 266              HTML_AJAX_Util.setInnerHTML(document.getElementById(id),result);
 267          }
 268          if (arguments.length == 2) {
 269              // grab replacement
 270              HTML_AJAX.grab(arguments[1],callback);
 271          }
 272          else {
 273              // call replacement
 274              var args = new Array();
 275              for(var i = 3; i < arguments.length; i++) {
 276                  args.push(arguments[i]);
 277              }
 278              HTML_AJAX.fullcall(HTML_AJAX.defaultServerUrl,HTML_AJAX.defaultEncoding,arguments[1],arguments[2],callback,args, {grab:true});
 279          }
 280      },
 281      append: function(id) {
 282          var callback = function(result) {
 283              HTML_AJAX_Util.setInnerHTML(document.getElementById(id),result,'append');
 284          }
 285          if (arguments.length == 2) {
 286              // grab replacement
 287              HTML_AJAX.grab(arguments[1],callback);
 288          }
 289          else {
 290              // call replacement
 291              var args = new Array();
 292              for(var i = 3; i < arguments.length; i++) {
 293                  args.push(arguments[i]);
 294              }
 295              HTML_AJAX.fullcall(HTML_AJAX.defaultServerUrl,HTML_AJAX.defaultEncoding,arguments[1],arguments[2],callback,args, {grab:true});
 296          }
 297      }, 
 298      // override to add top level loading notification (start)
 299      Open: function(request) {
 300      },
 301      // override to add top level loading notification (finish)
 302      Load: function(request) {
 303      },
 304      /*
 305      // A really basic error handler 
 306      onError: function(e) {
 307          msg = "";
 308          for(var i in e) {
 309              msg += i+':'+e[i]+"\n";
 310          }
 311          alert(msg);
 312      },
 313      */
 314      // Class postfix to content-type map
 315      contentTypeMap: {
 316          'JSON':            'application/json',
 317          'Null':            'text/plain',
 318          'Error':        'application/error',
 319          'PHP':            'application/php-serialized',
 320          'HA' :            'application/html_ajax_action',
 321          'Urlencoded':    'application/x-www-form-urlencoded'
 322      },
 323      // used internally to make queues work, override Load or onError to perform custom events when a request is complete
 324      // fires on success and error
 325      requestComplete: function(request,error) {
 326          for(var i in HTML_AJAX.queues) {
 327              if (HTML_AJAX.queues[i].requestComplete) {
 328                  HTML_AJAX.queues[i].requestComplete(request,error);
 329              }
 330          }
 331      },
 332      
 333      // turns a form into a urlencoded string
 334      formEncode: function(form, array_format) {
 335          form = HTML_AJAX_Util.getElement(form);
 336          var el, inpType, value, name;
 337          var out = (array_format) ? {} : '';
 338          var inputTags = form.getElementsByTagName('INPUT');
 339          var selectTags = form.getElementsByTagName('SELECT');
 340          var buttonTags = form.getElementsByTagName('BUTTON');
 341          var textareaTags = form.getElementsByTagName('TEXTAREA');
 342          var arrayRegex = /(.+)%5B%5D/;
 343  
 344          var validElement = function (element) {
 345              if (!element || !element.getAttribute) {
 346                  return false;
 347              }
 348              el = element;
 349              name = HTML_AJAX_Util.encodeUrl(el.getAttribute('name'));
 350              if (!name) {
 351                  // no element name so skip
 352                  return false;
 353              }
 354              if (element.disabled) {
 355                  return false;
 356              }
 357              
 358              if (!array_format) {
 359                  value = HTML_AJAX_Util.encodeUrl(el.value);
 360              } else {
 361                  value = el.value;
 362              }
 363              
 364              inpType = el.getAttribute('type');
 365              return true;
 366          }
 367          
 368          inputLoop:
 369          for (var i=0; i < inputTags.length; i++) {
 370              if (!validElement(inputTags[i])) {
 371                  continue;
 372              }
 373              if (inpType == 'checkbox' || inpType == 'radio') {
 374                  if (!el.checked) {
 375                      // unchecked radios/checkboxes don't get submitted
 376                      continue inputLoop;
 377                  }
 378                  var arr_var = arrayRegex.exec(name); 
 379                  if (array_format && arr_var) {
 380                      if (!out[arr_var[1]]) {
 381                          out[arr_var[1]] = new Array();
 382                      }
 383                      out[arr_var[1]].push(value);
 384                      continue inputLoop;
 385                  }
 386              }
 387              // add element to output array
 388              if (array_format) {
 389                  out[name] = value;
 390              } else {
 391                  out += name + '=' + value + '&';
 392              }
 393          } // end inputLoop
 394  
 395          selectLoop:
 396          for (var i=0; i<selectTags.length; i++) {
 397              if (!validElement(selectTags[i])) {
 398                  continue selectLoop;
 399              }
 400              var options = el.options;
 401              for (var z=0; z<options.length; z++){
 402                  var option=options[z];
 403                  if(option.selected){
 404                      if (array_format) {
 405                          if (el.type == 'select-one') {
 406                              out[name] = option.value;
 407                              //only one item can be selected
 408                              continue selectLoop;
 409                          } else {
 410                              if (!out[name]) {
 411                                  out[name] = new Array();
 412                              }
 413                              out[name].push(option.value);
 414                          }
 415                      } else {
 416                          out += name + '=' + option.value + '&';
 417                          if (el.type == 'select-one') {
 418                              continue selectLoop;
 419                          }
 420                      }
 421                  }
 422              }
 423          } // end selectLoop
 424  
 425          buttonLoop:
 426          for (var i=0; i<buttonTags.length; i++) {
 427              if (!validElement(buttonTags[i])) {
 428                  continue;
 429              }
 430              // add element to output array
 431              if (array_format) {
 432                  out[name] = value;
 433              } else {
 434                  out += name + '=' + value + '&';
 435              }
 436          } // end buttonLoop
 437  
 438          textareaLoop:
 439          for (var i=0; i<textareaTags.length; i++) {
 440              if (!validElement(textareaTags[i])) {
 441                  continue;
 442              }
 443              // add element to output array
 444              if (array_format) {
 445                  out[name] = value;
 446              } else {
 447                  out += name + '=' + value + '&';
 448              }
 449          } // end textareaLoop
 450          
 451          return out;
 452      },
 453      // submits a form through ajax. both arguments can be either DOM nodes or IDs, if the target is omitted then the form is set to be the target
 454      formSubmit: function (form, target, options)
 455      {
 456          form = HTML_AJAX_Util.getElement(form);
 457          if (!form) {
 458          // let the submit be processed normally
 459              return false;
 460          }
 461  
 462          var out = HTML_AJAX.formEncode(form);
 463          target = HTML_AJAX_Util.getElement(target);
 464          if (!target) {
 465              target = form;
 466          }
 467          var action = form.attributes['action'].value;
 468          var callback = function(result) {
 469              HTML_AJAX_Util.setInnerHTML(target,result);
 470          }
 471  
 472          var serializer = HTML_AJAX.serializerForEncoding('Null');
 473          var request = new HTML_AJAX_Request(serializer);
 474          request.isAsync = true;
 475          request.callback = callback;
 476  
 477          switch (form.getAttribute('method').toLowerCase()) {
 478          case 'post':
 479              var headers = {};
 480              headers['Content-Type'] = 'application/x-www-form-urlencoded';
 481              request.customHeaders = headers;
 482              request.requestType = 'POST';
 483              request.requestUrl = action;
 484              request.args = out;
 485              break;
 486          default:
 487              if (action.indexOf('?') == -1) {
 488                  out = '?' + out.substr(0, out.length - 1);
 489              }
 490              request.requestUrl = action+out;
 491              request.requestType = 'GET';
 492          }
 493  
 494          if(options) {
 495              for(var i in options) {
 496                  request[i] = options[i];
 497              }
 498          }
 499          HTML_AJAX.makeRequest(request);
 500          return true;
 501      }, // end formSubmit()
 502      makeFormAJAX: function(form,target,options) {
 503          form = HTML_AJAX_Util.getElement(form);
 504          var preSubmit = false;
 505          if(typeof form.onsubmit != 'undefined') {
 506              preSubmit = form.onsubmit;
 507              form.onsubmit = function() {};
 508          }
 509          form.HAOptions = options;
 510          var handler = function(e) {
 511              var form = HTML_AJAX_Util.eventTarget(e);
 512  
 513              var valid = true;
 514              if (preSubmit) {
 515                  valid = preSubmit();
 516              }
 517              if (valid) {
 518                  HTML_AJAX.formSubmit(form,target,form.HAOptions);
 519              }
 520              // cancel submission in IE
 521              e.returnValue = false;
 522              // cancel submission in FF
 523              if (e.preventDefault) {
 524                  e.preventDefault();
 525              }
 526          }
 527          HTML_AJAX_Util.registerEvent(form,'submit',handler);
 528      }
 529  }
 530  
 531  
 532  
 533  
 534  // small classes that I don't want to put in there own file
 535  
 536  function HTML_AJAX_Serialize_Null() {}
 537  HTML_AJAX_Serialize_Null.prototype = {
 538      contentType: 'text/plain; charset=utf-8',
 539      serialize: function(input) {
 540          return new String(input).valueOf();
 541      },
 542      
 543      unserialize: function(input) {
 544          return new String(input).valueOf();    
 545      }
 546  }
 547  
 548  function HTML_AJAX_Serialize_XML() {}
 549  HTML_AJAX_Serialize_XML.prototype = {
 550      contentType: 'application/xml; charset=utf-8',
 551      serialize: function(input) {
 552          var xml = '';
 553          if(typeof(input) == 'object' && input)
 554          {
 555              for (var i = 0;i<input.length;i++)
 556              {
 557                  xml += new XMLSerializer().serializeToString(input[i]);
 558              }
 559          }
 560          return xml;
 561      },
 562  
 563      unserialize: function(input) {
 564          return input;
 565      }
 566  }
 567  
 568  // serialization class for JSON, wrapper for JSON.stringify in json.js
 569  function HTML_AJAX_Serialize_JSON() {}
 570  HTML_AJAX_Serialize_JSON.prototype = {
 571      contentType: 'application/json; charset=utf-8',
 572      serialize: function(input) {
 573          return HTML_AJAX_JSON.stringify(input);
 574      },
 575      unserialize: function(input) {
 576          try {
 577              return eval('('+input+')');
 578          } catch(e) {
 579              // sometimes JSON encoded input isn't created properly, if eval of it fails we use the more forgiving but slower parser so will at least get something
 580              return HTML_AJAX_JSON.parse(input);
 581          }
 582      }
 583  }
 584  
 585  function HTML_AJAX_Serialize_Error() {}
 586  HTML_AJAX_Serialize_Error.prototype = {
 587      contentType: 'application/error; charset=utf-8',
 588      serialize: function(input) {
 589          var ser = new HTML_AJAX_Serialize_JSON();
 590          return ser.serialize(input);
 591      },
 592      unserialize: function(input) {
 593          var ser = new HTML_AJAX_Serialize_JSON();
 594          var data = new ser.unserialize(input);
 595  
 596          var e = new Error('PHP Error: '+data.errStr);
 597          for(var i in data) {
 598              e[i] = data[i];
 599          }
 600          throw e;
 601      }
 602  }
 603  
 604  // Processing Queues
 605  
 606  // simple queue, just processes the request immediately
 607  function HTML_AJAX_Queue_Immediate() {}
 608  HTML_AJAX_Queue_Immediate.prototype = {
 609      request: false,
 610      addRequest: function(request) {
 611          this.request = request;
 612      },
 613      processRequest: function() {
 614          var client = HTML_AJAX.httpClient();
 615          client.request = this.request;
 616          return client.makeRequest();
 617      }
 618  }
 619  
 620  
 621  
 622  // create a default queue, has to happen after the Queue class has been defined
 623  HTML_AJAX.queues = new Object();
 624  HTML_AJAX.queues['default'] = new HTML_AJAX_Queue_Immediate();
 625  
 626  // Queue.js
 627  /**
 628   * Various processing queues, use when you want to control how multiple requests are made
 629   * @category    HTML
 630   * @package    AJAX
 631   * @author    Joshua Eichorn <josh@bluga.net>
 632   * @copyright    2005 Joshua Eichorn
 633   * @license    http://www.opensource.org/licenses/lgpl-license.php  LGPL
 634   */
 635  
 636  // Single Buffer queue with interval
 637  // works by attempting to send a request every x miliseconds
 638  // if an item is currently in the queue when a new item is added it will be replaced
 639  // simple queue, just processes the request immediately
 640  // the first request starts the interval timer
 641  function HTML_AJAX_Queue_Interval_SingleBuffer(interval,singleOutstandingRequest) {
 642      this.interval = interval;
 643      if (singleOutstandingRequest) {
 644          this.singleOutstandingRequest = true;
 645      }
 646  }
 647  HTML_AJAX_Queue_Interval_SingleBuffer.prototype = {
 648      request: false,
 649      _intervalId: false,
 650      singleOutstandingRequest: false,
 651      client: false,
 652      addRequest: function(request) {
 653          this.request = request;
 654      },
 655      processRequest: function() {
 656          if (!this._intervalId) {
 657              this.runInterval();
 658              this.start();
 659          }
 660      }, 
 661      start: function() {
 662          var self = this;
 663          this._intervalId = setInterval(function() { self.runInterval() },this.interval);
 664      },
 665      stop: function() {
 666          clearInterval(this._intervalId);
 667      },
 668      runInterval: function() {
 669          if (this.request) {
 670              if (this.singleOutstandingRequest && this.client) {
 671                  this.client.abort();
 672              }
 673              this.client = HTML_AJAX.httpClient();
 674              this.client.request = this.request;
 675              this.request = false;
 676              this.client.makeRequest();
 677          }
 678      }
 679  }
 680  
 681  // Requests return in the same order they were called
 682  // this helps handle high latency situations
 683  function HTML_AJAX_Queue_Ordered() { }
 684  HTML_AJAX_Queue_Ordered.prototype = {
 685      request: false,
 686      order: 0,
 687      current: 0,
 688      callbacks: {},
 689      interned: {},
 690      addRequest: function(request) {
 691          request.order = this.order;
 692          this.request = request;
 693          this.callbacks[this.order] = this.request.callback;
 694          var self = this;
 695          this.request.callback = function(result) {
 696              self.processCallback(result,request.order);
 697          } 
 698      },
 699      processRequest: function() {
 700          var client = HTML_AJAX.httpClient();
 701          client.request = this.request;
 702          client.makeRequest();
 703          this.order++;
 704      },
 705      requestComplete: function(request,e) {
 706          // something when wrong with the request lets stop waiting for it
 707          if (e) {
 708              this.current++;
 709          }
 710      },
 711      processCallback: function(result,order) {
 712          if (order == this.current) {
 713              this.callbacks[order](result);
 714              this.current++;
 715          }
 716          else {
 717              this.interned[order] = result;
 718              if (this.interned[this.current]) {
 719                  this.callbacks[this.current](this.interned[this.current]);
 720                  this.current++;
 721              }
 722          }
 723      } 
 724  }
 725  
 726  // Make a single request at once, canceling and currently outstanding requests when a new one is made
 727  function HTML_AJAX_Queue_Single() {
 728  }
 729  HTML_AJAX_Queue_Single.prototype = {
 730      request: false,
 731      client: false,
 732      addRequest: function(request) {
 733          this.request = request;
 734      },
 735      processRequest: function() {
 736          if (this.request) {
 737              if (this.client) {
 738                  this.client.abort();
 739              }
 740              this.client = HTML_AJAX.httpClient();
 741              this.client.request = this.request;
 742              this.request = false;
 743              this.client.makeRequest();
 744          }
 745      }
 746  }
 747  
 748  /**
 749   * Priority queue
 750   *
 751   * @author     Arpad Ray <arpad@php.net>
 752   */
 753  function HTML_AJAX_Queue_Priority_Item(item, time) {
 754      this.item = item;
 755      this.time = time;
 756  }
 757  HTML_AJAX_Queue_Priority_Item.prototype = {
 758      compareTo: function (other) {
 759          var ret = this.item.compareTo(other.item);
 760          if (ret == 0) {
 761              ret = this.time - other.time;
 762          }
 763          return ret;
 764      }
 765  }
 766  
 767  function HTML_AJAX_Queue_Priority_Simple(interval) {
 768      this.interval = interval;   
 769      this.idleMax = 10;            // keep the interval going with an empty queue for 10 intervals
 770      this.requestTimeout = 5;      // retry uncompleted requests after 5 seconds
 771      this.checkRetryChance = 0.1;  // check for uncompleted requests to retry on 10% of intervals
 772      this._intervalId = 0;
 773      this._requests = [];
 774      this._removed = [];
 775      this._len = 0;
 776      this._removedLen = 0;
 777      this._idle = 0;
 778  }
 779  HTML_AJAX_Queue_Priority_Simple.prototype = {
 780      isEmpty: function () {
 781          return this._len == 0;
 782      },
 783      addRequest: function (request) {
 784          request = new HTML_AJAX_Queue_Priority_Item(request, new Date().getTime());
 785          ++this._len;
 786          if (this.isEmpty()) {
 787              this._requests[0] = request;
 788              return;
 789          }
 790          for (i = 0; i < this._len - 1; i++) {
 791              if (request.compareTo(this._requests[i]) < 0) {
 792                  this._requests.splice(i, 1, request, this._requests[i]);
 793                  return;
 794              }
 795          }
 796          this._requests.push(request);
 797      },
 798      peek: function () {
 799          return (this.isEmpty() ? false : this._requests[0]);
 800      },
 801      requestComplete: function (request) {
 802          for (i = 0; i < this._removedLen; i++) {
 803              if (this._removed[i].item == request) {
 804                  this._removed.splice(i, 1);
 805                  --this._removedLen;
 806                  out('removed from _removed');
 807                  return true;
 808              }
 809          }
 810          return false;
 811      },
 812      processRequest: function() {
 813          if (!this._intervalId) {
 814              this._runInterval();
 815              this._start();
 816          }
 817          this._idle = 0;
 818      },
 819      _runInterval: function() {
 820          if (Math.random() < this.checkRetryChance) {
 821              this._doRetries();
 822          }
 823          if (this.isEmpty()) {
 824              if (++this._idle > this.idleMax) {
 825                  this._stop();
 826              }
 827              return;
 828          }
 829          var client = HTML_AJAX.httpClient();
 830          if (!client) {
 831              return;
 832          }
 833          var request = this.peek();
 834          if (!request) {
 835              this._requests.splice(0, 1);
 836              return;
 837          }
 838          client.request = request.item;
 839          client.makeRequest();
 840          this._requests.splice(0, 1);
 841          --this._len;
 842          this._removed[this._removedLen++] = new HTML_AJAX_Queue_Priority_Item(request, new Date().getTime());
 843      },
 844      _doRetries: function () {
 845          for (i = 0; i < this._removedLen; i++) {
 846              if (this._removed[i].time + this._requestTimeout < new Date().getTime()) {
 847                  this.addRequest(request.item);
 848                  this._removed.splice(i, 1);
 849                  --this._removedLen;
 850                  return true;
 851              }
 852          }
 853      },
 854      _start: function() {
 855          var self = this;
 856          this._intervalId = setInterval(function() { self._runInterval() }, this.interval);
 857      },
 858      _stop: function() {
 859          clearInterval(this._intervalId);
 860          this._intervalId = 0;
 861      }
 862  };
 863  // clientPool.js
 864  HTML_AJAX_Client_Pool = function(maxClients, startingClients)
 865  {
 866      this.maxClients = maxClients;
 867      this._clients = [];
 868      this._len = 0;
 869      while (--startingClients > 0) {
 870          this.addClient();
 871      }
 872  }
 873  
 874  HTML_AJAX_Client_Pool.prototype = {
 875      isEmpty: function()
 876      {
 877          return this._len == 0;
 878      },
 879      addClient: function()
 880      {
 881          if (this.maxClients != 0 && this._len > this.maxClients) {
 882              return false;
 883          }
 884          var key = this._len++;
 885          this._clients[key] = new HTML_AJAX_HttpClient();
 886          return this._clients[key];
 887      },
 888      getClient: function ()
 889      {
 890          for (var i = 0; i < this._len; i++) {
 891              if (!this._clients[i].callInProgress() && this._clients[i].callbackComplete) {
 892                  return this._clients[i];
 893              }
 894          }
 895          var client = this.addClient();
 896          if (client) {
 897              return client;
 898          }
 899          return false;
 900      },
 901      removeClient: function (client)
 902      {
 903          for (var i = 0; i < this._len; i++) {
 904              if (!this._clients[i] == client) {
 905                  this._clients.splice(i, 1);
 906                  return true;
 907              }
 908          }
 909          return false;
 910      },
 911      clear: function ()
 912      {
 913          this._clients = [];
 914          this._len = 0;
 915      }
 916  };
 917  
 918  // create a default client pool with unlimited clients
 919  HTML_AJAX.clientPools['default'] = new HTML_AJAX_Client_Pool(0);
 920  // IframeXHR.js
 921  /**
 922   * XMLHttpRequest Iframe fallback
 923   *
 924   * http://lxr.mozilla.org/seamonkey/source/extensions/xmlextras/tests/ - should work with these
 925   *
 926   * @category    HTML
 927   * @package    AJAX
 928   * @author    Elizabeth Smith <auroraeosrose@gmail.com>
 929   * @copyright     2005 Elizabeth Smith
 930   * @license    http://www.opensource.org/licenses/lgpl-license.php  LGPL
 931   */
 932  HTML_AJAX_IframeXHR_instances = new Object();
 933  function HTML_AJAX_IframeXHR()
 934  {
 935      this._id = 'HAXHR_iframe_' + new Date().getTime();
 936      HTML_AJAX_IframeXHR_instances[this._id] = this;
 937  }
 938  HTML_AJAX_IframeXHR.prototype = {
 939  // Data not sent with text/xml Content-Type will only be available via the responseText property
 940  
 941      // properties available in safari/mozilla/IE xmlhttprequest object
 942      onreadystatechange: null, // Event handler for an event that fires at every state change
 943      readyState: 0, // Object status integer: 0 = uninitialized 1 = loading 2 = loaded 3 = interactive 4 = complete
 944      responseText: '', // String version of data returned from server process
 945      responseXML: null, // DOM-compatible document object of data returned from server process
 946      status: 0, // Numeric code returned by server, such as 404 for "Not Found" or 200 for "OK"
 947      statusText: '', // String message accompanying the status code
 948      iframe: true, // flag for iframe
 949  
 950      //these are private properties used internally to keep track of stuff
 951      _id: null, // iframe id, unique to object(hopefully)
 952      _url: null, // url sent by open
 953      _method: null, // get or post
 954      _async: null, // sync or async sent by open
 955      _headers: new Object(), //request headers to send, actually sent as form vars
 956      _response: new Object(), //response headers received
 957      _phpclass: null, //class to send
 958      _phpmethod: null, //method to send
 959      _history: null, // opera has to have history munging
 960  
 961      // Stops the current request
 962      abort: function()
 963      {
 964          var iframe = document.getElementById(this._id);
 965          if (iframe) {
 966              document.body.removeChild(iframe);
 967          }
 968          if (this._timeout) {
 969              window.clearTimeout(this._timeout);
 970          }
 971          this.readyState = 1;
 972          if (typeof(this.onreadystatechange) == "function") {
 973              this.onreadystatechange();
 974          }
 975      },
 976  
 977      // This will send all headers in this._response and will include lastModified and contentType if not already set
 978      getAllResponseHeaders: function()
 979      {
 980          var string = '';
 981          for (i in this._response) {
 982              string += i + ' : ' + this._response[i] + "\n";
 983          }
 984          return string;
 985      },
 986  
 987      // This will use lastModified and contentType if they're not set
 988      getResponseHeader: function(header)
 989      {
 990          return (this._response[header] ? this._response[header] : null);
 991      },
 992  
 993      // Assigns a label/value pair to the header to be sent with a request
 994      setRequestHeader: function(label, value) {
 995          this._headers[label] = value;
 996          return; },
 997  
 998      // Assigns destination URL, method, and other optional attributes of a pending request
 999      open: function(method, url, async, username, password)
1000      {
1001          if (!document.body) {
1002              throw('CANNOT_OPEN_SEND_IN_DOCUMENT_HEAD');
1003          }
1004          //exceptions for not enough arguments
1005          if (!method || !url) {
1006              throw('NOT_ENOUGH_ARGUMENTS:METHOD_URL_REQUIRED');
1007          }
1008          //get and post are only methods accepted
1009          this._method = (method.toUpperCase() == 'POST' ? 'POST' : 'GET');
1010          this._decodeUrl(url);
1011          this._async = async;
1012          if(!this._async && document.readyState && !window.opera) {
1013              throw('IE_DOES_NOT_SUPPORT_SYNC_WITH_IFRAMEXHR');
1014          }
1015          //set status to loading and call onreadystatechange
1016          this.readyState = 1;
1017          if(typeof(this.onreadystatechange) == "function") {
1018              this.onreadystatechange();
1019          }
1020      },
1021  
1022      // Transmits the request, optionally with postable string or DOM object data
1023      send: function(content)
1024      {
1025          //attempt opera history munging
1026          if (window.opera) {
1027              this._history = window.history.length;
1028          }
1029          //create a "form" for the contents of the iframe
1030          var form = '<html><body><form method="'
1031              + (this._url.indexOf('px=') < 0 ? this._method : 'post')
1032              + '" action="' + this._url + '">';
1033          //tell iframe unwrapper this IS an iframe
1034          form += '<input name="Iframe_XHR" value="1" />';
1035          //class and method
1036          if (this._phpclass != null) {
1037              form += '<input name="Iframe_XHR_class" value="' + this._phpclass + '" />';
1038          }
1039          if (this._phpmethod != null) {
1040              form += '<input name="Iframe_XHR_method" value="' + this._phpmethod + '" />';
1041          }
1042          // fake headers
1043          for (label in this._headers) {
1044              form += '<textarea name="Iframe_XHR_headers[]">' + label +':'+ this._headers[label] + '</textarea>';
1045          }
1046          // add id
1047          form += '<textarea name="Iframe_XHR_id">' + this._id + '</textarea>';
1048          if (content != null && content.length > 0) {
1049              form += '<textarea name="Iframe_XHR_data">' + content + '</textarea>';
1050          }
1051          form += '<input name="Iframe_XHR_HTTP_method" value="' + this._method + '" />';
1052          form += '<s'+'cript>document.forms[0].submit();</s'+'cript></form></body></html>';
1053          form = "javascript:document.write('" + form.replace(/\'/g,"\\'") + "');void(0);";
1054          this.readyState = 2;
1055          if (typeof(this.onreadystatechange) == "function") {
1056              this.onreadystatechange();
1057          }
1058          // try to create an iframe with createElement and append node
1059          try {
1060              var iframe = document.createElement('iframe');
1061              iframe.id = this._id;
1062              // display: none will fail on some browsers
1063              iframe.style.visibility = 'hidden';
1064              // for old browsers with crappy css
1065              iframe.style.border = '0';
1066              iframe.style.width = '0';
1067              iframe.style.height = '0';
1068              
1069              if (document.all) {
1070                  // MSIE, opera
1071                  iframe.src = form;
1072                  document.body.appendChild(iframe);
1073              } else {
1074                  document.body.appendChild(iframe);
1075                  iframe.src = form;
1076              }
1077          } catch(exception) {
1078              // dom failed, write the sucker manually
1079              var html = '<iframe src="' + form +'" id="' + this._id + '" style="visibility:hidden;border:0;height:0;width:0;"></iframe>';
1080              document.body.innerHTML += html;
1081          }
1082          if (this._async == true) {
1083              //avoid race state if onload is called first
1084              if (this.readyState < 3) {
1085                  this.readyState = 3;
1086                  if(typeof(this.onreadystatechange) == "function") {
1087                      this.onreadystatechange();
1088                  }
1089              }
1090          } else {
1091              //we force a while loop for sync, it's ugly but hopefully it works
1092              while (this.readyState != 4) {
1093                  //just check to see if we can up readyState
1094                  if (this.readyState < 3) {
1095                      this.readyState = 3;
1096                      if(typeof(this.onreadystatechange) == "function") {
1097                          this.onreadystatechange();
1098                      }
1099                  }
1100              }
1101          }
1102      },
1103  
1104      // attached as an onload function to the iframe to trigger when we're done
1105      isLoaded: function(headers, data)
1106      {
1107          this.readyState = 4;
1108          //set responseText, Status, StatusText
1109          this.status = 200;
1110          this.statusText = 'OK';
1111          this.responseText = data;
1112          this._response = headers;
1113          if (!this._response['Last-Modified']) {
1114              string += 'Last-Modified : ' + document.getElementById(this._id).lastModified + "\n";
1115          }
1116          if (!this._response['Content-Type']) {
1117              string += 'Content-Type : ' + document.getElementById(this._id).contentType + "\n";
1118          }
1119          // if this is xml populate responseXML accordingly
1120          if (this._response['Content-Type'] == 'application/xml')
1121          {
1122              return new DOMParser().parseFromString(this.responseText, 'application/xml');
1123          }
1124          //attempt opera history munging in opera 8+ - this is a REGRESSION IN OPERA
1125          if (window.opera && window.opera.version) {
1126              //go back current history - old history
1127              window.history.go(this._history - window.history.length);
1128          }
1129          if (typeof(this.onreadystatechange) == "function") {
1130              this.onreadystatechange();
1131          }
1132          document.body.removeChild(document.getElementById(this._id));
1133      },
1134  
1135      // strip off the c and m from the url send...yuck
1136      _decodeUrl: function(querystring)
1137      {
1138          //opera 7 is too stupid to do a relative url...go figure
1139          var url = unescape(location.href);
1140          url = url.substring(0, url.lastIndexOf("/") + 1);
1141          var item = querystring.split('?');
1142          //rip off any path info and append to path above <-  relative paths (../) WILL screw this
1143          this._url = url + item[0].substring(item[0].lastIndexOf("/") + 1,item[0].length);
1144          if(item[1]) {
1145              item = item[1].split('&');
1146              for (i in item) {
1147                  var v = item[i].split('=');
1148                  if (v[0] == 'c') {
1149                      this._phpclass = v[1];
1150                  } else if (v[0] == 'm') {
1151                      this._phpmethod = v[1];
1152                  }
1153              }
1154          }
1155          if (!this._phpclass || !this._phpmethod) {
1156              var cloc = window.location.href;
1157              this._url = cloc + (cloc.indexOf('?') >= 0 ? '&' : '?') + 'px=' + escape(HTML_AJAX_Util.absoluteURL(querystring));
1158          }
1159      }
1160  }
1161  // serializer/UrlSerializer.js
1162  // {{{ HTML_AJAX_Serialize_Urlencoded
1163  /**
1164   * URL-encoding serializer
1165   *
1166   * This class can be used to serialize and unserialize data in a
1167   * format compatible with PHP's handling of HTTP query strings.
1168   * Due to limitations of the format, all input is serialized as an
1169   * array or a string. See examples/serialize.url.examples.php
1170   *
1171   * @version    0.0.1
1172   * @copyright    2005 Arpad Ray <arpad@php.net>
1173   * @license    http://www.opensource.org/licenses/lgpl-license.php  LGPL
1174   *
1175   * See Main.js for Author/license details
1176   */
1177  function HTML_AJAX_Serialize_Urlencoded() {}
1178  HTML_AJAX_Serialize_Urlencoded.prototype = {
1179      contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
1180      base: '_HTML_AJAX',
1181      _keys: [],
1182      error: false,
1183      message: "",
1184      cont: "",
1185      // {{{ serialize
1186      /**
1187       *  Serializes a variable
1188       *
1189       *  @param    mixed  inp the variable to serialize
1190       *  @return    string   a string representation of the input, 
1191       *                      which can be reconstructed by unserialize()
1192       */
1193      serialize: function(input, _internal) {
1194          if (typeof input == 'undefined') {
1195              return '';
1196          }
1197          if (!_internal) {
1198              this._keys = [];
1199          }
1200          var ret = '', first = true;
1201          for (i = 0; i < this._keys.length; i++) {
1202              ret += (first ? HTML_AJAX_Util.encodeUrl(this._keys[i]) : '[' + HTML_AJAX_Util.encodeUrl(this._keys[i]) + ']');
1203              first = false;
1204          }
1205          ret += '=';
1206          switch (HTML_AJAX_Util.getType(input)) {
1207              case 'string': 
1208              case 'number':
1209                  ret += HTML_AJAX_Util.encodeUrl(input.toString());
1210                  break;
1211              case 'boolean':
1212                  ret += (input ? '1' : '0');
1213                  break;
1214              case 'array':
1215              case 'object':
1216                  ret = '';
1217                  for (i in input) {
1218                      this._keys.push(i);
1219                      ret += this.serialize(input[i], true) + '&';
1220                      this._keys.pop();
1221                  }
1222                  ret = ret.substr(0, ret.length - 1);
1223          }
1224          return ret;
1225      },
1226      // }}}
1227      // {{{ unserialize
1228      /**
1229       *  Reconstructs a serialized variable
1230       *
1231       *  @param    string inp the string to reconstruct
1232       *  @return    array an array containing the variable represented by the input string, or void on failure
1233       */
1234      unserialize: function(input) {
1235          if (!input.length || input.length == 0) {
1236              // null
1237              return;
1238          }
1239          if (!/^(\w+(\[[^\[\]]*\])*=[^&]*(&|$))+$/.test(input)) {
1240              this.raiseError("invalidly formed input", input);
1241              return;
1242          }
1243          input = input.split("&");
1244          var pos, key, keys, val, _HTML_AJAX = [];
1245          if (input.length == 1) {
1246              return HTML_AJAX_Util.decodeUrl(input[0].substr(this.base.length + 1));
1247          }
1248          for (var i in input) {
1249              pos = input[i].indexOf("=");
1250              if (pos < 1 || input[i].length - pos - 1 < 1) {
1251                  this.raiseError("input is too short", input[i]);
1252                  return;
1253              }
1254              key = HTML_AJAX_Util.decodeUrl(input[i].substr(0, pos));
1255              val = HTML_AJAX_Util.decodeUrl(input[i].substr(pos + 1));
1256              key = key.replace(/\[((\d*\D+)+)\]/g, '["$1"]');
1257              keys = key.split(']');
1258              for (j in keys) {
1259                  if (!keys[j].length || keys[j].length == 0) {
1260                      continue;
1261                  }
1262                  try {
1263                      if (eval('typeof ' + keys[j] + ']') == 'undefined') {
1264                          var ev = keys[j] + ']=[];';
1265                          eval(ev);
1266                      }
1267                  } catch (e) {
1268                      this.raiseError("error evaluating key", ev);
1269                      return; 
1270                  }
1271              }
1272              try {
1273                  eval(key + '="' + val + '";');
1274              } catch (e) {
1275                  this.raiseError("error evaluating value", input);
1276                  return; 
1277              }
1278          }
1279          return _HTML_AJAX;
1280      },
1281      // }}}
1282      // {{{ getError
1283      /**
1284      *  Gets the last error message
1285      *
1286      *  @return    string   the last error message from unserialize()
1287      */    
1288      getError: function() {
1289          return this.message + "\n" + this.cont;
1290      },
1291      // }}}
1292      // {{{ raiseError
1293      /**
1294      *  Raises an eror (called by unserialize().)
1295      *
1296      *  @param    string    message    the error message
1297      *  @param    string    cont       the remaining unserialized content
1298      */    
1299      raiseError: function(message, cont) {
1300          this.error = 1;
1301          this.message = message;
1302          this.cont = cont;
1303      }
1304      // }}}
1305  }
1306  // }}}
1307  // serializer/phpSerializer.js
1308  // {{{ HTML_AJAX_Serialize_PHP
1309  /**
1310   * PHP serializer
1311   *
1312   * This class can be used to serialize and unserialize data in a
1313   * format compatible with PHP's native serialization functions.
1314   *
1315   * @version    0.0.3
1316   * @copyright    2005 Arpad Ray <arpad@php.net>
1317   * @license    http://www.opensource.org/licenses/lgpl-license.php  LGPL
1318   *
1319   * See Main.js for Author/license details
1320   */
1321  
1322  function HTML_AJAX_Serialize_PHP() {}
1323  HTML_AJAX_Serialize_PHP.prototype = {
1324      error: false,
1325      message: "",
1326      cont: "",
1327      defaultEncoding: 'UTF-8',
1328      contentType: 'application/php-serialized; charset: UTF-8',
1329      // {{{ serialize
1330      /**
1331      *  Serializes a variable
1332      *
1333      *  @param    mixed  inp the variable to serialize
1334      *  @return    string   a string representation of the input, 
1335      *                      which can be reconstructed by unserialize()
1336      *  @author Arpad Ray <arpad@rajeczy.com>
1337      *  @author David Coallier <davidc@php.net>
1338      */
1339      serialize: function(inp) {
1340          var type = HTML_AJAX_Util.getType(inp);
1341          var val;
1342          switch (type) {
1343              case "undefined":
1344                  val = "N";
1345                  break;
1346              case "boolean":
1347                  val = "b:" + (inp ? "1" : "0");
1348                  break;
1349              case "number":
1350                  val = (Math.round(inp) == inp ? "i" : "d") + ":" + inp;
1351                  break;
1352              case "string":
1353                  val = "s:" + inp.length + ":\"" + inp + "\"";
1354                  break;
1355              case "array":
1356                  val = "a";
1357              case "object":
1358                  if (type == "object") {
1359                      var objname = inp.constructor.toString().match(/(\w+)\(\)/);
1360                      if (objname == undefined) {
1361                          return;
1362                      }
1363                      objname[1] = this.serialize(objname[1]);
1364                      val = "O" + objname[1].substring(1, objname[1].length - 1);
1365                  }
1366                  var count = 0;
1367                  var vals = "";
1368                  var okey;
1369                  for (key in inp) {
1370                      okey = (key.match(/^[0-9]+$/) ? parseInt(key) : key);
1371                      vals += this.serialize(okey) + 
1372                              this.serialize(inp[key]);
1373                      count++;
1374                  }
1375                  val += ":" + count + ":{" + vals + "}";
1376                  break;
1377          }
1378          if (type != "object" && type != "array") val += ";";
1379          return val;
1380      },
1381      // }}} 
1382      // {{{ unserialize
1383      /**
1384       *  Reconstructs a serialized variable
1385       *
1386       *  @param    string inp the string to reconstruct
1387       *  @return   mixed the variable represented by the input string, or void on failure
1388       */
1389      unserialize: function(inp) {
1390          this.error = 0;
1391          if (inp == "" || inp.length < 2) {
1392              this.raiseError("input is too short");
1393              return;
1394          }
1395          var val, kret, vret, cval;
1396          var type = inp.charAt(0);
1397          var cont = inp.substring(2);
1398          var size = 0, divpos = 0, endcont = 0, rest = "", next = "";
1399  
1400          switch (type) {
1401          case "N": // null
1402              if (inp.charAt(1) != ";") {
1403                  this.raiseError("missing ; for null", cont);
1404              }
1405              // leave val undefined
1406              rest = cont;
1407              break;
1408          case "b": // boolean
1409              if (!/[01];/.test(cont.substring(0,2))) {
1410                  this.raiseError("value not 0 or 1, or missing ; for boolean", cont);
1411              }
1412              val = (cont.charAt(0) == "1");
1413              rest = cont.substring(1);
1414              break;
1415          case "s": // string
1416              val = "";
1417              divpos = cont.indexOf(":");
1418              if (divpos == -1) {
1419                  this.raiseError("missing : for string", cont);
1420                  break;
1421              }
1422              size = parseInt(cont.substring(0, divpos));
1423              if (size == 0) {
1424                  if (cont.length - divpos < 4) {
1425                      this.raiseError("string is too short", cont);
1426                      break;
1427                  }
1428                  rest = cont.substring(divpos + 4);
1429                  break;
1430              }
1431              if ((cont.length - divpos - size) < 4) {
1432                  this.raiseError("string is too short", cont);
1433                  break;
1434              }
1435              if (cont.substring(divpos + 2 + size, divpos + 4 + size) != "\";") {
1436                  this.raiseError("string is too long, or missing \";", cont);
1437              }
1438              val = cont.substring(divpos + 2, divpos + 2 + size);
1439              rest = cont.substring(divpos + 4 + size);
1440              break;
1441          case "i": // integer
1442          case "d": // float
1443              var dotfound = 0;
1444              for (var i = 0; i < cont.length; i++) {
1445                  cval = cont.charAt(i);
1446                  if (isNaN(parseInt(cval)) && !(type == "d" && cval == "." && !dotfound++)) {
1447                      endcont = i;
1448                      break;
1449                  }
1450              }
1451              if (!endcont || cont.charAt(endcont) != ";") {
1452                  this.raiseError("missing or invalid value, or missing ; for int/float", cont);
1453              }
1454              val = cont.substring(0, endcont);
1455              val = (type == "i" ? parseInt(val) : parseFloat(val));
1456              rest = cont.substring(endcont + 1);
1457              break;
1458          case "a": // array
1459              if (cont.length < 4) {
1460                  this.raiseError("array is too short", cont);
1461                  return;
1462              }
1463              divpos = cont.indexOf(":", 1);
1464              if (divpos == -1) {
1465                  this.raiseError("missing : for array", cont);
1466                  return;
1467              }
1468              size = parseInt(cont.substring(0, divpos));
1469              cont = cont.substring(divpos + 2);
1470              val = new Array();
1471              if (cont.length < 1) {
1472                  this.raiseError("array is too short", cont);
1473                  return;
1474              }
1475              for (var i = 0; i < size; i++) {
1476                  kret = this.unserialize(cont, 1);
1477                  if (this.error || kret[0] == undefined || kret[1] == "") {
1478                      this.raiseError("missing or invalid key, or missing value for array", cont);
1479                      return;
1480                  }
1481                  vret = this.unserialize(kret[1], 1);
1482                  if (this.error) {
1483                      this.raiseError("invalid value for array", cont);
1484                      return;
1485                  }
1486                  val[kret[0]] = vret[0];
1487                  cont = vret[1];
1488              }
1489              if (cont.charAt(0) != "}") {
1490                  this.raiseError("missing ending }, or too many values for array", cont);
1491                  return; 
1492              }
1493              rest = cont.substring(1);
1494              break;
1495          case "O": // object
1496              divpos = cont.indexOf(":");
1497              if (divpos == -1) {
1498                  this.raiseError("missing : for object", cont);
1499                  return;
1500              }
1501              size = parseInt(cont.substring(0, divpos));
1502              var objname = cont.substring(divpos + 2, divpos + 2 + size);
1503              if (cont.substring(divpos + 2 + size, divpos + 4 + size) != "\":") {
1504                  this.raiseError("object name is too long, or missing \":", cont);
1505                  return;
1506              }
1507              var objprops = this.unserialize("a:" + cont.substring(divpos + 4 + size), 1);
1508              if (this.error) {
1509                  this.raiseError("invalid object properties", cont);
1510                  return;
1511              }
1512              rest = objprops[1];
1513              var objout = "function " + objname + "(){";
1514              for (key in objprops[0]) {
1515                  objout += "this." + key + "=objprops[0]['" + key + "'];";
1516              }
1517              objout += "}val=new " + objname + "();";
1518              eval(objout);
1519              break;
1520          default:
1521              this.raiseError("invalid input type", cont);
1522          }
1523          return (arguments.length == 1 ? val : [val, rest]);
1524      },
1525      // }}}
1526      // {{{ getError
1527      /**
1528      *  Gets the last error message
1529      *
1530      *  @return    string   the last error message from unserialize()
1531      */    
1532      getError: function() {
1533          return this.message + "\n" + this.cont;
1534      },
1535      // }}}
1536      // {{{ raiseError
1537      /**
1538      *  Raises an eror (called by unserialize().)
1539      *
1540      *  @param    string    message    the error message
1541      *  @param    string    cont       the remaining unserialized content
1542      */    
1543      raiseError: function(message, cont) {
1544          this.error = 1;
1545          this.message = message;
1546          this.cont = cont;
1547      }
1548      // }}}
1549  }
1550  // }}}
1551  
1552  // Dispatcher.js
1553  /**
1554   * Class that is used by generated stubs to make actual AJAX calls
1555   *
1556   * @category    HTML
1557   * @package     AJAX
1558   * @author    Joshua Eichorn <josh@bluga.net>
1559   * @copyright   2005 Joshua Eichorn
1560   * @license     http://www.opensource.org/licenses/lgpl-license.php  LGPL
1561   */
1562  function HTML_AJAX_Dispatcher(className,mode,callback,serverUrl,serializerType) 
1563  {
1564      this.className = className;
1565      this.mode = mode;
1566      this.callback = callback;
1567      this.serializerType = serializerType;
1568  
1569      if (serverUrl) {
1570          this.serverUrl = serverUrl
1571      }
1572      else {
1573          this.serverUrl = window.location;
1574      }
1575  }
1576  
1577  HTML_AJAX_Dispatcher.prototype = {
1578      /**
1579       * Queue to use when making a request
1580       */
1581      queue: 'default',
1582  
1583      /**
1584       * Timeout for async calls
1585       */
1586      timeout: 20000,
1587   
1588      /**
1589       * Default request priority
1590       */
1591      priority: 0,
1592  
1593      /**
1594       * Request options 
1595       */
1596      options: {},
1597      
1598      /**
1599       * Make an ajax call
1600       *
1601       * @param   string callName
1602       * @param   Array   args    arguments to the report method
1603       */
1604      doCall: function(callName,args) 
1605      {
1606          var request = new HTML_AJAX_Request();
1607          request.requestUrl = this.serverUrl;
1608          request.className = this.className;
1609          request.methodName = callName;
1610          request.timeout = this.timeout;
1611          request.contentType = this.contentType;
1612          request.serializer = eval('new HTML_AJAX_Serialize_'+this.serializerType);
1613          request.queue = this.queue;
1614          request.priority = this.priority;
1615  
1616          for(var i in this.options) {
1617              request[i] = this.options[i];
1618          }
1619          
1620          for(var i=0; i < args.length; i++) {
1621              request.addArg(i,args[i]);
1622          };
1623  
1624          if ( this.mode == "async" ) {
1625              request.isAsync = true;
1626              if (this.callback[callName]) {
1627                  var self = this;
1628                  request.callback = function(result) { self.callback[callName](result); }
1629              }
1630  
1631          } else {
1632              request.isAsync = false;
1633          }
1634  
1635          return HTML_AJAX.makeRequest(request);
1636      },
1637  
1638      Sync: function() 
1639      {
1640          this.mode = 'sync';
1641      },
1642  
1643      Async: function(callback)
1644      {
1645          this.mode = 'async';
1646          if (callback) {
1647              this.callback = callback;
1648          }
1649      }
1650  };
1651  // HttpClient.js
1652  /**
1653   * XMLHttpRequest Wrapper
1654   * @category    HTML
1655   * @package     AJAX
1656   * @author      Joshua Eichorn <josh@bluga.net>
1657   * @copyright   2005 Joshua Eichorn
1658   * @license     http://www.opensource.org/licenses/lgpl-license.php  LGPL
1659   */
1660  function HTML_AJAX_HttpClient() { }
1661  HTML_AJAX_HttpClient.prototype = {
1662      // request object
1663      request: null,
1664  
1665      // timeout id
1666      _timeoutId: null,
1667  
1668      callbackComplete: true,
1669  
1670      // has this request been aborted
1671      aborted: false,
1672      
1673      // method to initialize an xmlhttpclient
1674      init:function() 
1675      {
1676          try {
1677              // Mozilla / Safari
1678              //this.xmlhttp = new HTML_AJAX_IframeXHR(); //uncomment these two lines to test iframe
1679              //return;
1680              this.xmlhttp = new XMLHttpRequest();
1681          } catch (e) {
1682              // IE
1683              var XMLHTTP_IDS = new Array(
1684              'MSXML2.XMLHTTP.5.0',
1685              'MSXML2.XMLHTTP.4.0',
1686              'MSXML2.XMLHTTP.3.0',
1687              'MSXML2.XMLHTTP',
1688              'Microsoft.XMLHTTP' );
1689              var success = false;
1690              for (var i=0;i < XMLHTTP_IDS.length && !success; i++) {
1691                  try {
1692                      this.xmlhttp = new ActiveXObject(XMLHTTP_IDS[i]);
1693                      success = true;
1694                  } catch (e) {}
1695              }
1696              if (!success) {
1697                  try{
1698                      this.xmlhttp = new HTML_AJAX_IframeXHR();
1699                      this.request.iframe = true;
1700                  } catch(e) {
1701                      throw new Error('Unable to create XMLHttpRequest.');
1702                  }
1703              }
1704          }
1705      },
1706  
1707      // check if there is a call in progress
1708      callInProgress: function() 
1709      {
1710          switch ( this.xmlhttp.readyState ) {
1711              case 1:
1712              case 2:
1713              case 3:
1714                  return true;
1715              break;
1716              default:
1717                  return false;
1718              break;
1719          }
1720      },
1721  
1722      // make the request defined in the request object
1723      makeRequest: function() 
1724      {
1725          if (!this.xmlhttp) {
1726              this.init();
1727          }
1728  
1729          try {
1730              if (this.request.Open) {
1731                  this.request.Open();
1732              }
1733              else if (HTML_AJAX.Open) {
1734                  HTML_AJAX.Open(this.request);
1735              }
1736  
1737              if (this.request.multipart) {
1738                  if (document.all) {
1739                      this.iframe = true;
1740                  } else {
1741                      this.xmlhttp.multipart = true;
1742                  }
1743              }
1744      
1745              // set onreadystatechange here since it will be reset after a completed call in Mozilla
1746              var self = this;
1747              this.xmlhttp.open(this.request.requestType,this.request.completeUrl(),this.request.isAsync);
1748              if (this.request.customHeaders) {
1749                  for (i in this.request.customHeaders) {
1750                      this.xmlhttp.setRequestHeader(i, this.request.customHeaders[i]);
1751                  }
1752              }
1753              if (this.request.customHeaders && !this.request.customHeaders['Content-Type']) {
1754                  var content = this.request.getContentType();
1755                  //opera is stupid for anything but plain text or xml!!
1756                  if(window.opera && content != 'application/xml')
1757                  {
1758                      this.xmlhttp.setRequestHeader('Content-Type','text/plain; charset=utf-8');
1759                      this.xmlhttp.setRequestHeader('x-Content-Type', content + '; charset=utf-8');
1760                  }
1761                  else
1762                  {
1763                      this.xmlhttp.setRequestHeader('Content-Type', content +  '; charset=utf-8');
1764                  }
1765              }
1766  
1767              if (this.request.isAsync) {
1768                  if (this.request.callback) {
1769                      this.callbackComplete = false;
1770                  }
1771                  this.xmlhttp.onreadystatechange = function() { self._readyStateChangeCallback(); }
1772              } else {
1773                  this.xmlhttp.onreadystatechange = function() {}
1774              }
1775              var payload = this.request.getSerializedPayload();
1776              if (payload) {
1777                  this.xmlhttp.setRequestHeader('Content-Length', payload.length);
1778              }
1779              this.xmlhttp.send(payload);
1780  
1781              if (!this.request.isAsync) {
1782                  if ( this.xmlhttp.status == 200 ) {
1783                      HTML_AJAX.requestComplete(this.request);
1784                      if (this.request.Load) {
1785                          this.request.Load();
1786                      } else if (HTML_AJAX.Load) {
1787                          HTML_AJAX.Load(this.request);
1788                      }
1789                          
1790                      return this._decodeResponse();
1791                  } else {
1792                      var e = new Error('['+this.xmlhttp.status +'] '+this.xmlhttp.statusText);
1793                      e.headers = this.xmlhttp.getAllResponseHeaders();
1794                      this._handleError(e);
1795                  }
1796              }
1797              else {
1798                  // setup timeout
1799                  var self = this;
1800                  this._timeoutId = window.setTimeout(function() { self.abort(true); },this.request.timeout);
1801              }
1802          } catch (e) {
1803              this._handleError(e);
1804          }
1805      },
1806      
1807      // abort an inprogress request
1808      abort: function (automatic) 
1809      {
1810          if (this.callInProgress()) {
1811              this.aborted = true;
1812              this.xmlhttp.abort();
1813  
1814              if (automatic) {
1815                  HTML_AJAX.requestComplete(this.request);
1816                  this._handleError(new Error('Request Timed Out: time out was '+this.request.timeout+'ms'));
1817              }
1818          }
1819      },
1820  
1821      // internal method used to handle ready state changes
1822      _readyStateChangeCallback:function() 
1823      {
1824          try {
1825              switch(this.xmlhttp.readyState) {
1826                  // XMLHTTPRequest.open() has just been called
1827                  case 1:
1828                      break;
1829                  // XMLHTTPRequest.send() has just been called
1830                  case 2:
1831                      if (this.request.Send) {
1832                          this.request.Send();
1833                      } else if (HTML_AJAX.Send) {
1834                          HTML_AJAX.Send(this.request);
1835                      }
1836                      break;
1837                  // Fetching response from server in progress
1838                  case 3:
1839                      if (this.request.Progress) {
1840                          this.request.Progress();
1841                      } else if (HTML_AJAX.Progress ) {
1842                          HTML_AJAX.Progress(this.request);
1843                      }
1844                  break;
1845                  // Download complete
1846                  case 4:
1847                      window.clearTimeout(this._timeoutId);
1848                      if (this.aborted) {
1849                          if (this.request.Load) {
1850                              this.request.Load();
1851                          } else if (HTML_AJAX.Load) {
1852                              HTML_AJAX.Load(this.request);
1853                          }
1854                      }
1855                      else if (this.xmlhttp.status == 200) {
1856                          if (this.request.Load) {
1857                              this.request.Load();
1858                          } else if (HTML_AJAX.Load ) {
1859                              HTML_AJAX.Load(this.request);
1860                          }
1861  
1862                          var response = this._decodeResponse();
1863  
1864                          if (this.request.callback) {
1865                              this.request.callback(response);
1866                              this.callbackComplete = true;
1867                          }
1868                      }
1869                      else {
1870                          var e = new Error('HTTP Error Making Request: ['+this.xmlhttp.status+'] '+this.xmlhttp.statusText);
1871                          this._handleError(e);
1872                      }
1873                      HTML_AJAX.requestComplete(this.request);
1874                  break;
1875              }
1876          } catch (e) {
1877                  this._handleError(e);
1878          }
1879      },
1880  
1881      // decode response as needed
1882      _decodeResponse: function() {
1883          //try for x-Content-Type first
1884          var content = null;
1885          try {
1886              content = this.xmlhttp.getResponseHeader('X-Content-Type');
1887          } catch(e) {}
1888          if(!content || content == null)
1889          {
1890              content = this.xmlhttp.getResponseHeader('Content-Type');
1891          }
1892          //strip anything after ;
1893          if(content.indexOf(';') != -1)
1894          {
1895              content = content.substring(0, content.indexOf(';'));
1896          }
1897          // hook for xml, it doesn't need to be unserialized
1898          if(content == 'application/xml')
1899          {
1900              return this.xmlhttp.responseXML;
1901          }
1902          var unserializer = HTML_AJAX.serializerForEncoding(content);
1903          //alert(this.xmlhttp.getAllResponseHeaders()); // some sort of debug hook is needed here
1904          return unserializer.unserialize(this.xmlhttp.responseText);
1905      },
1906  
1907      // handle sending an error where it needs to go
1908      _handleError: function(e) 
1909      {
1910          HTML_AJAX.requestComplete(this.request,e);
1911          if (this.request.onError) {
1912              this.request.onError(e);
1913          } else if (HTML_AJAX.onError) {
1914              HTML_AJAX.onError(e,this.request);
1915          }
1916          else {
1917              throw e;
1918          }
1919      }
1920  }
1921  // Request.js
1922  /**
1923   * Class that contains everything needed to make a request
1924   * This includes:
1925   *    The url were calling
1926   *    If were calling a remote method, the class and method name
1927   *    The payload, unserialized
1928   *    The timeout for async calls
1929   *    The callback method
1930   *    Optional event handlers: onError, Load, Send
1931   *    A serializer instance
1932   *
1933   * @category    HTML
1934   * @package    AJAX
1935   * @author    Joshua Eichorn <josh@bluga.net>
1936   * @copyright    2005 Joshua Eichorn
1937   * @license    http://www.opensource.org/licenses/lgpl-license.php  LGPL
1938   *
1939   * See Main.js for author/license details
1940   */
1941  function HTML_AJAX_Request(serializer) {
1942      this.serializer = serializer;
1943  }
1944  HTML_AJAX_Request.prototype = {
1945  
1946      // Instance of a serializer
1947      serializer: null,
1948  
1949      // Is this an async request
1950      isAsync: false,
1951  
1952      // HTTP verb
1953      requestType: 'POST',
1954  
1955      // The actual URL the request is sent to
1956      requestUrl: '',
1957  
1958      // Remote Class
1959      className: null,
1960  
1961      // Remote Method
1962      methodName: null,
1963  
1964      // Timeout in milliseconds for requests
1965      timeout: 20000,
1966  
1967      // unserialized data, for rpc calls use add args, to send raw data just set this directly
1968      args: null,
1969  
1970      // async callback method
1971      callback: null,
1972  
1973      // Queue to push this request too
1974      queue: 'default',
1975  
1976      // default priority
1977      priority: 0,
1978  
1979      // a hash of headers to add to add to this request
1980      customHeaders: {},
1981  
1982      // true if this request will be sent using iframes
1983      iframe: false,
1984  
1985      // is this a grab request? if so we need to proxy for iframes
1986      grab: false,
1987  
1988      // true if this request should expect a multipart response
1989      multipart: false,
1990  
1991      // remote callback
1992      phpCallback: false,
1993  
1994      /**
1995       * Add an argument for the remote method
1996       * @param string argument name
1997       * @param mixed value
1998       * @return void
1999       * @throws Error code 1004
2000       */
2001      addArg: function(name, value) 
2002      {
2003          if ( !this.args ) {
2004              this.args = [];
2005          }
2006          if (!/[^a-zA-Z_0-9]/.test(name) ) {
2007              this.args[name] = value;
2008          } else {
2009              throw new Error('Invalid parameter name ('+name+')');
2010          }
2011      },
2012  
2013      /**
2014       * Get the payload in a serialized manner
2015       */
2016      getSerializedPayload: function() {
2017          return this.serializer.serialize(this.args);
2018      },
2019  
2020      /**
2021       * Get the content type
2022       */
2023      getContentType: function() {
2024          return this.serializer.contentType;
2025      },
2026  
2027      /**
2028       * Get the complete url, adding in any needed get params for rpc
2029       */
2030      completeUrl: function() {
2031          if (this.className || this.methodName) {
2032              this.addGet('c', this.className);
2033              this.addGet('m', this.methodName);
2034          }
2035          if (this.phpCallback) {
2036              if (HTML_AJAX_Util.getType(this.phpCallback) == 'array') {
2037                  this.phpCallback = this.phpCallback.join('.');
2038              }
2039              this.addGet('cb', this.phpCallback);
2040          }
2041          if (this.multipart) {
2042              this.addGet('multipart', '1');
2043          }
2044          return this.requestUrl;
2045      },
2046  
2047      /**
2048       * Compare to another request by priority
2049       */
2050      compareTo: function(other) {
2051          if (this.priority == other.priority) {
2052              return 0;
2053          }
2054          return (this.priority > other.priority ? 1 : -1);
2055      },
2056  
2057      /**
2058       * Add a GET argument
2059       */
2060      addGet: function(name, value) {
2061          var url = new String(this.requestUrl);
2062          url += (url.indexOf('?') < 0 ? '?' : '&') + escape(name) + '=' + escape(value);
2063          this.requestUrl = url;
2064      }
2065  }
2066  // serializer/JSON.js
2067  /*
2068  Copyright (c) 2005 JSON.org
2069  
2070  Permission is hereby granted, free of charge, to any person obtaining a copy
2071  of this software and associated documentation files (the "Software"), to deal
2072  in the Software without restriction, including without limitation the rights
2073  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2074  copies of the Software, and to permit persons to whom the Software is
2075  furnished to do so, subject to the following conditions:
2076  
2077  The Software shall be used for Good, not Evil.
2078  
2079  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2080  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2081  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2082  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2083  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2084  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2085  SOFTWARE.
2086  */
2087  
2088  Array.prototype.______array = '______array';
2089  
2090  var HTML_AJAX_JSON = {
2091      org: 'http://www.JSON.org',
2092      copyright: '(c)2005 JSON.org',
2093      license: 'http://www.crockford.com/JSON/license.html',
2094  
2095      stringify: function (arg) {
2096          var c, i, l, s = '', v;
2097  
2098          switch (typeof arg) {
2099          case 'object':
2100              if (arg) {
2101                  if (arg.______array == '______array') {
2102                      for (i = 0; i < arg.length; ++i) {
2103                          v = this.stringify(arg[i]);
2104                          if (s) {
2105                              s += ',';
2106                          }
2107                          s += v;
2108                      }
2109                      return '[' + s + ']';
2110                  } else if (typeof arg.toString != 'undefined') {
2111                      for (i in arg) {
2112                          v = arg[i];
2113                          if (typeof v != 'undefined' && typeof v != 'function') {
2114                              v = this.stringify(v);
2115                              if (s) {
2116                                  s += ',';
2117                              }
2118                              s += this.stringify(i) + ':' + v;
2119                          }
2120                      }
2121                      return '{' + s + '}';
2122                  }
2123              }
2124              return 'null';
2125          case 'number':
2126              return isFinite(arg) ? String(arg) : 'null';
2127          case 'string':
2128              l = arg.length;
2129              s = '"';
2130              for (i = 0; i < l; i += 1) {
2131                  c = arg.charAt(i);
2132                  if (c >= ' ') {
2133                      if (c == '\\' || c == '"') {
2134                          s += '\\';
2135                      }
2136                      s += c;
2137                  } else {
2138                      switch (c) {
2139                          case '\b':
2140                              s += '\\b';
2141                              break;
2142                          case '\f':
2143                              s += '\\f';
2144                              break;
2145                          case '\n':
2146                              s += '\\n';
2147                              break;
2148                          case '\r':
2149                              s += '\\r';
2150                              break;
2151                          case '\t':
2152                              s += '\\t';
2153                              break;
2154                          default:
2155                              c = c.charCodeAt();
2156                              s += '\\u00' + Math.floor(c / 16).toString(16) +
2157                                  (c % 16).toString(16);
2158                      }
2159                  }
2160              }
2161              return s + '"';
2162          case 'boolean':
2163              return String(arg);
2164          default:
2165              return 'null';
2166          }
2167      },
2168      parse: function (text) {
2169          var at = 0;
2170          var ch = ' ';
2171  
2172  		function error(m) {
2173              throw {
2174                  name: 'JSONError',
2175                  message: m,
2176                  at: at - 1,
2177                  text: text
2178              };
2179          }
2180  
2181  		function next() {
2182              ch = text.charAt(at);
2183              at += 1;
2184              return ch;
2185          }
2186  
2187  		function white() {
2188              while (ch) {
2189                  if (ch <= ' ') {
2190                      next();
2191                  } else if (ch == '/') {
2192                      switch (next()) {
2193                          case '/':
2194                              while (next() && ch != '\n' && ch != '\r') {}
2195                              break;
2196                          case '*':
2197                              next();
2198                              for (;;) {
2199                                  if (ch) {
2200                                      if (ch == '*') {
2201                                          if (next() == '/') {
2202                                              next();
2203                                              break;
2204                                          }
2205                                      } else {
2206                                          next();
2207                                      }
2208                                  } else {
2209                                      error("Unterminated comment");
2210                                  }
2211                              }
2212                              break;
2213                          default:
2214                              error("Syntax error");
2215                      }
2216                  } else {
2217                      break;
2218                  }
2219              }
2220          }
2221  
2222  		function string() {
2223              var i, s = '', t, u;
2224  
2225              if (ch == '"') {
2226  outer:          while (next()) {
2227                      if (ch == '"') {
2228                          next();
2229                          return s;
2230                      } else if (ch == '\\') {
2231                          switch (next()) {
2232                          case 'b':
2233                              s += '\b';
2234                              break;
2235                          case 'f':
2236                              s += '\f';
2237                              break;
2238                          case 'n':
2239                              s += '\n';
2240                              break;
2241                          case 'r':
2242                              s += '\r';
2243                              break;
2244                          case 't':
2245                              s += '\t';
2246                              break;
2247                          case 'u':
2248                              u = 0;
2249                              for (i = 0; i < 4; i += 1) {
2250                                  t = parseInt(next(), 16);
2251                                  if (!isFinite(t)) {
2252                                      break outer;
2253                                  }
2254                                  u = u * 16 + t;
2255                              }
2256                              s += String.fromCharCode(u);
2257                              break;
2258                          default:
2259                              s += ch;
2260                          }
2261                      } else {
2262                          s += ch;
2263                      }
2264                  }
2265              }
2266              error("Bad string");
2267          }
2268  
2269  		function array() {
2270              var a = [];
2271  
2272              if (ch == '[') {
2273                  next();
2274                  white();
2275                  if (ch == ']') {
2276                      next();
2277                      return a;
2278                  }
2279                  while (ch) {
2280                      a.push(value());
2281                      white();
2282                      if (ch == ']') {
2283                          next();
2284                          return a;
2285                      } else if (ch != ',') {
2286                          break;
2287                      }
2288                      next();
2289                      white();
2290                  }
2291              }
2292              error("Bad array");
2293          }
2294  
2295  		function object() {
2296              var k, o = {};
2297  
2298              if (ch == '{') {
2299                  next();
2300                  white();
2301                  if (ch == '}') {
2302                      next();
2303                      return o;
2304                  }
2305                  while (ch) {
2306                      k = string();
2307                      white();
2308                      if (ch != ':') {
2309                          break;
2310                      }
2311                      next();
2312                      o[k] = value();
2313                      white();
2314                      if (ch == '}') {
2315                          next();
2316                          return o;
2317                      } else if (ch != ',') {
2318                          break;
2319                      }
2320                      next();
2321                      white();
2322                  }
2323              }
2324              error("Bad object");
2325          }
2326  
2327  		function number() {
2328              var n = '', v;
2329              if (ch == '-') {
2330                  n = '-';
2331                  next();
2332              }
2333              while (ch >= '0' && ch <= '9') {
2334                  n += ch;
2335                  next();
2336              }
2337              if (ch == '.') {
2338                  n += '.';
2339                  while (next() && ch >= '0' && ch <= '9') {
2340                      n += ch;
2341                  }
2342              }
2343              if (ch == 'e' || ch == 'E') {
2344                  n += 'e';
2345                  next();
2346                  if (ch == '-' || ch == '+') {
2347                      n += ch;
2348                      next();
2349                  }
2350                  while (ch >= '0' && ch <= '9') {
2351                      n += ch;
2352                      next();
2353                  }
2354              }
2355              v = +n;
2356              if (!isFinite(v)) {
2357                  ////error("Bad number");
2358              } else {
2359                  return v;
2360              }
2361          }
2362  
2363  		function word() {
2364              switch (ch) {
2365                  case 't':
2366                      if (next() == 'r' && next() == 'u' && next() == 'e') {
2367                          next();
2368                          return true;
2369                      }
2370                      break;
2371                  case 'f':
2372                      if (next() == 'a' && next() == 'l' && next() == 's' &&
2373                              next() == 'e') {
2374                          next();
2375                          return false;
2376                      }
2377                      break;
2378                  case 'n':
2379                      if (next() == 'u' && next() == 'l' && next() == 'l') {
2380                          next();
2381                          return null;
2382                      }
2383                      break;
2384              }
2385              error("Syntax error");
2386          }
2387  
2388  		function value() {
2389              white();
2390              switch (ch) {
2391                  case '{':
2392                      return object();
2393                  case '[':
2394                      return array();
2395                  case '"':
2396                      return string();
2397                  case '-':
2398                      return number();
2399                  default:
2400                      return ch >= '0' && ch <= '9' ? number() : word();
2401              }
2402          }
2403  
2404          return value();
2405      }
2406  };
2407  // serializer/haSerializer.js
2408  /**
2409   * HTML_AJAX_Serialize_HA  - custom serialization
2410   *
2411   * This class is used with the JSON serializer and the HTML_AJAX_Action php class
2412   * to allow users to easily write data handling and dom manipulation related to
2413   * ajax actions directly from their php code
2414   *
2415   * See Main.js for Author/license details
2416   */
2417  function HTML_AJAX_Serialize_HA() { }
2418  HTML_AJAX_Serialize_HA.prototype =
2419  {
2420      /**
2421       *  Takes data from JSON - which should be parseable into a nice array
2422       *  reads the action to take and pipes it to the right method
2423       *
2424       *  @param    string payload incoming data from php
2425       *  @return   true on success, false on failure
2426       */
2427      unserialize: function(payload)
2428      {
2429          var actions = eval(payload);
2430          for(var i = 0; i < actions.length; i++)
2431          {
2432              var action = actions[i];
2433              switch(action.action)
2434              {
2435                  case 'prepend':
2436                      this._prependAttr(action.id, action.attributes);
2437                      break;
2438                  case 'append':
2439                      this._appendAttr(action.id, action.attributes);
2440                      break;
2441                  case 'assign':
2442                      this._assignAttr(action.id, action.attributes);
2443                      break;
2444                  case 'clear':
2445                      this._clearAttr(action.id, action.attributes);
2446                      break;
2447                  case 'create':
2448                      this._createNode(action.id, action.tag, action.attributes, action.type);
2449                      break;
2450                  case 'replace':
2451                      this._replaceNode(action.id, action.tag, action.attributes);
2452                      break;
2453                  case 'remove':
2454                      this._removeNode(action.id);
2455                      break;
2456                  case 'script':
2457                      this._insertScript(action.data);
2458                      break;
2459                  case 'alert':
2460                      this._insertAlert(action.data);
2461                      break;
2462              }
2463          }
2464      },
2465      _prependAttr: function(id, attributes)
2466      {
2467          var node = document.getElementById(id);
2468          for (var i in attributes)
2469          {
2470              //innerHTML hack bailout
2471              if(i == 'innerHTML')
2472              {
2473                  HTML_AJAX_Util.setInnerHTML(node, attributes[i], 'prepend');
2474              }
2475              //value hack
2476              else if(i == 'value')
2477              {
2478                  node.value = attributes[i];
2479              }
2480              //I'd use hasAttribute but IE is stupid stupid stupid
2481              else
2482              {
2483                  var value = node.getAttribute(i);
2484                  if(value)
2485                  {
2486                      node.setAttribute(i, attributes[i] + value);
2487                  }
2488                  else
2489                  {
2490                      node.setAttribute(i, attributes[i]);
2491                  }
2492              }
2493          }
2494      },
2495      _appendAttr: function(id, attributes)
2496      {
2497          var node = document.getElementById(id);
2498          for (var i in attributes)
2499          {
2500              //innerHTML hack bailout
2501              if(i == 'innerHTML')
2502              {
2503                  HTML_AJAX_Util.setInnerHTML(node, attributes[i], 'append');
2504              }
2505              //value hack
2506              else if(i == 'value')
2507              {
2508                  node.value = attributes[i];
2509              }
2510              //I'd use hasAttribute but IE is stupid stupid stupid
2511              else
2512              {
2513                  var value = node.getAttribute(i);
2514                  if(value)
2515                  {
2516                      node.setAttribute(i, value + attributes[i]);
2517                  }
2518                  else
2519                  {
2520                      node.setAttribute(i, attributes[i]);
2521                  }
2522              }
2523          }
2524      },
2525      _assignAttr: function(id, attributes)
2526      {
2527          var node = document.getElementById(id);
2528          for (var i in attributes)
2529          {
2530              //innerHTML hack bailout
2531              if(i == 'innerHTML')
2532              {
2533                  HTML_AJAX_Util.setInnerHTML(node,attributes[i]);
2534              }
2535              //value hack
2536              else if(i == 'value')
2537              {
2538                  node.value = attributes[i];
2539              }
2540              //IE doesn't support setAttribute on style so we need to break it out and set each property individually
2541              else if(i == 'style')
2542              {
2543                  var styles = [];
2544                  if (attributes[i].indexOf(';')) {
2545                      styles = attributes[i].split(';');
2546                  }
2547                  else {
2548                      styles.push(attributes[i]);
2549                  }
2550                  for(var i = 0; i < styles.length; i++) {
2551                      var r = styles[i].match(/^\s*(.+)\s*:\s*(.+)\s*$/);
2552                      if(r) {
2553                          node.style[this._camelize(r[1])] = r[2];
2554                      }
2555                  }
2556              }
2557              //no special rules know for this node so lets try our best
2558              else
2559              {
2560                  try {
2561                      node[i] = attributes[i];
2562                  } catch(e) {
2563                  }
2564              node.setAttribute(i, attributes[i]);
2565              }
2566          }
2567      },
2568      // should we move this to HTML_AJAX_Util???, just does the - case which we need for style
2569      _camelize: function(instr)
2570      {
2571          var p = instr.split('-');
2572          var out = p[0];
2573          for(var i = 1; i < p.length; i++) {
2574              out += p[i].charAt(0).toUpperCase()+p[i].substring(1);
2575          }
2576          return out;
2577      },
2578      _clearAttr: function(id, attributes)
2579      {
2580          var node = document.getElementById(id);
2581          for(var i = 0; i < attributes.length; i++)
2582          {
2583              //innerHTML hack bailout
2584              if(attributes[i] == 'innerHTML')
2585              {
2586                  node.innerHTML = '';
2587              }
2588              //value hack
2589              else if(attributes[i] == 'value')
2590              {
2591                  node.value = '';
2592              }
2593              //I'd use hasAttribute but IE is stupid stupid stupid
2594              else
2595              {
2596                  node.removeAttribute(attributes[i]);
2597              }
2598          }
2599      },
2600      _createNode: function(id, tag, attributes, type)
2601      {
2602          var newnode = document.createElement(tag);
2603          for (var i in attributes)
2604          {
2605              //innerHTML hack bailout
2606              if(i == 'innerHTML')
2607              {
2608                  newnode.innerHTML = attributes[i];
2609              }
2610              //value hack
2611              else if(i == 'value')
2612              {
2613                  newnode.value = attributes[i];
2614              }
2615              //I'd use hasAttribute but IE is stupid stupid stupid
2616              else
2617              {
2618                  newnode.setAttribute(i, attributes[i]);
2619              }
2620          }
2621          switch(type)
2622          {
2623              case 'append':
2624                  document.getElementById(id).appendChild(newnode);
2625                  break
2626              case 'prepend':
2627                  var parent = document.getElementById(id);
2628                  var sibling = parent.firstChild;
2629                  parent.insertBefore(newnode, sibling);
2630                  break;
2631              case 'insertBefore':
2632                  var sibling = document.getElementById(id);
2633                  var parent = sibling.parentNode;
2634                  parent.insertBefore(newnode, sibling);
2635                  break;
2636              //this one is tricky, if it's the last one we use append child...ewww
2637              case 'insertAfter':
2638                  var sibling = document.getElementById(id);
2639                  var parent = sibling.parentNode;
2640                  var next = sibling.nextSibling;
2641                  if(next == null)
2642                  {
2643                      parent.appendChild(newnode);
2644                  }
2645                  else
2646                  {
2647                      parent.insertBefore(newnode, next);
2648                  }
2649                  break;
2650          }
2651      },
2652      _replaceNode: function(id, tag, attributes)
2653      {
2654          var node = document.getElementById(id);
2655          var parent = node.parentNode;
2656          var newnode = document.createElement(tag);
2657          for (var i in attributes)
2658          {
2659              //innerHTML hack bailout
2660              if(i == 'innerHTML')
2661              {
2662                  newnode.innerHTML = attributes[i];
2663              }
2664              //value hack
2665              else if(i == 'value')
2666              {
2667                  newnode.value = attributes[i];
2668              }
2669          }
2670          parent.replaceChild(newnode, node);
2671      },
2672      _removeNode: function(id)
2673      {
2674          var node = document.getElementById(id);
2675          if(node)
2676          {
2677              var parent = node.parentNode;
2678              parent.removeChild(node);
2679          }
2680      },
2681      _insertScript: function(data)
2682      {
2683          eval(data);
2684      },
2685      _insertAlert: function(data)
2686      {
2687          alert(data);
2688      }
2689  }
2690  // Loading.js
2691  /**
2692   * Default loading implementation
2693   *
2694   * @category    HTML
2695   * @package    Ajax
2696   * @license    http://www.opensource.org/licenses/lgpl-license.php  LGPL
2697   * @copyright    2005 Joshua Eichorn
2698   * see Main.js for license Author details
2699   */
2700  HTML_AJAX.Open = function(request) {
2701      var loading = document.getElementById('HTML_AJAX_LOADING');
2702      if (!loading) {
2703          loading = document.createElement('div');
2704          loading.id = 'HTML_AJAX_LOADING';
2705          loading.innerHTML = 'Loading...';
2706          
2707          loading.style.color     = '#fff';
2708          loading.style.position  = 'absolute';
2709          loading.style.top   = 0;
2710          loading.style.right     = 0;
2711          loading.style.backgroundColor = '#f00';
2712          loading.style.border        = '1px solid #f99';
2713          loading.style.width         = '80px';
2714          loading.style.padding       = '4px';
2715          loading.style.fontFamily    = 'Arial, Helvetica, sans';
2716          loading.count = 0;
2717      
2718          document.body.insertBefore(loading,document.body.firstChild);
2719      }
2720      else {
2721          if (loading.count == undefined) {
2722              loading.count = 0;
2723          }
2724      }
2725      loading.count++;
2726      if (request.isAsync) {
2727          request.loadingId = window.setTimeout(function() { loading.style.display = 'block'; },500);
2728      }
2729      else {
2730          loading.style.display = 'block';
2731      }
2732  }
2733  HTML_AJAX.Load = function(request) {
2734      if (request.loadingId) {
2735          window.clearTimeout(request.loadingId);
2736      }
2737      var loading = document.getElementById('HTML_AJAX_LOADING');
2738      loading.count--;
2739  
2740      if (loading.count == 0) {
2741          loading.style.display = 'none';
2742      }
2743  }
2744  // util.js
2745  /**
2746   * Utility methods
2747   *
2748   * @category    HTML
2749   * @package    Ajax
2750   * @license    http://www.opensource.org/licenses/lgpl-license.php  LGPL
2751   *
2752   * See Main.js for author/license details
2753   */
2754  // {{{ HTML_AJAX_Util
2755  /**
2756   * All the utilities we will be using thorough the classes
2757   */
2758  var HTML_AJAX_Util = {
2759      // Set the element event
2760      registerEvent: function(element, event, handler) 
2761      {
2762          element = this.getElement(element);
2763          if (typeof element.addEventListener != "undefined") {   //Dom2
2764              element.addEventListener(event, handler, false);
2765          } else if (typeof element.attachEvent != "undefined") { //IE 5+
2766              element.attachEvent("on" + event, handler);
2767          } else {
2768              if (element["on" + event] != null) {
2769                  var oldHandler = element["on" + event];
2770                  element["on" + event] = function(e) {
2771                      oldHander(e);
2772                      handler(e);
2773                  };
2774              } else {
2775                  element["on" + event] = handler;
2776              }
2777          }
2778      },
2779      // get the target of an event, automatically checks window.event for ie
2780      eventTarget: function(event) 
2781      {
2782          if (!event) var event = window.event;
2783          if (event.target) return event.target; // w3c
2784          if (event.srcElement) return event.srcElement; // ie 5
2785      },
2786      // gets the type of a variable or its primitive equivalent as a string
2787      getType: function(inp) 
2788      {
2789          var type = typeof inp, match;
2790          if(type == 'object' && !inp)
2791          {
2792              return 'null';
2793          }
2794          if (type == "object") {
2795              if(!inp.constructor)
2796              {
2797                  return 'object';
2798              }
2799              var cons = inp.constructor.toString();
2800              if (match = cons.match(/(\w+)\(/)) {
2801                  cons = match[1].toLowerCase();
2802              }
2803              var types = ["boolean", "number", "string", "array"];
2804              for (key in types) {
2805                  if (cons == types[key]) {
2806                      type = types[key];
2807                      break;
2808                  }
2809              }
2810          }
2811          return type;
2812      },
2813      // repeats the input string the number of times given by multiplier. exactly like PHP's str_repeat()
2814      strRepeat: function(inp, multiplier) {
2815          var ret = "";
2816          while (--multiplier > 0) ret += inp;
2817          return ret;
2818      },
2819      // encode a string allowing it to be used in a query string of a url
2820      encodeUrl: function(input) {
2821          return encodeURIComponent(input);
2822      },
2823      // decode a url encoded string
2824      decodeUrl: function(input) {
2825          return decodeURIComponent(input);
2826      },
2827      // recursive variable dumper similar in output to PHP's var_dump(), the differences being: this function displays JS types and type names; JS doesn't provide an object number like PHP does
2828      varDump: function(inp, printFuncs, _indent, _recursionLevel)
2829      {
2830          if (!_recursionLevel) _recursionLevel = 0;
2831          if (!_indent) _indent = 1;
2832          var tab = this.strRepeat("  ", ++_indent);    
2833          var type = this.getType(inp), out = type;
2834          var consrx = /(\w+)\(/;
2835          consrx.compile();
2836          if (++_recursionLevel > 6) {
2837              return tab + inp + "Loop Detected\n";
2838          }
2839          switch (type) {
2840              case "boolean":
2841              case "number":
2842                  out += "(" + inp.toString() + ")";
2843                  break;
2844              case "string":
2845                  out += "(" + inp.length + ") \"" + inp + "\"";
2846                  break;
2847              case "function":
2848                  if (printFuncs) {
2849                      out += inp.toString().replace(/\n/g, "\n" + tab);
2850                  }
2851                  break;
2852              case "array":
2853              case "object":
2854                  var atts = "", attc = 0;
2855                  try {
2856                      for (k in inp) {
2857                          atts += tab + "[" + (/\D/.test(k) ? "\"" + k + "\"" : k)
2858                              + "]=>\n" + tab + this.varDump(inp[k], printFuncs, _indent, _recursionLevel);
2859                          ++attc;
2860                      }
2861                  } catch (e) {}
2862                  if (type == "object") {
2863                      var objname, objstr = inp.toString();
2864                      if (objname = objstr.match(/^\[object (\w+)\]$/)) {
2865                          objname = objname[1];
2866                      } else {
2867                          try {
2868                              objname = inp.constructor.toString().match(consrx)[1];
2869                          } catch (e) {
2870                              objname = 'unknown';
2871                          }
2872                      }
2873                      out += "(" + objname + ") ";
2874                  }
2875                  out += "(" + attc + ") {\n" + atts + this.strRepeat("  ", _indent - 1) +"}";
2876                  break;
2877          }
2878          return out + "\n";
2879      },
2880      // non resursive simple debug printer
2881      quickPrint: function(input,sep) {
2882          if (!sep) {
2883              var sep = "\n";
2884          }
2885          var type = HTML_AJAX_Util.getType(input);
2886          switch (type) {
2887              case 'string':
2888                  return input;
2889              case 'array':
2890                  var ret = "";
2891                  for(var i = 0; i < input.length; i++) {
2892                      ret += i+':'+input[i]+sep;
2893                  }
2894                  return ret;
2895              default:
2896                  var ret = "";
2897                  for(var i in input) {
2898                      ret += i+':'+input[i]+sep;
2899                  }
2900                  return ret;
2901          }
2902      },
2903      //compat function for stupid browsers in which getElementsByTag with a * dunna work
2904      getAllElements: function(parentElement)
2905      {
2906          //check for idiot browsers
2907          if( document.all)
2908          {
2909              if(!parentElement) {
2910                  var allElements = document.all;
2911              }
2912              else
2913              {
2914                  var allElements = [], rightName = new RegExp( parentElement, 'i' ), i;
2915                  for( i=0; i<document.all.length; i++ ) {
2916                      if( rightName.test( document.all[i].parentElement ) )
2917                      allElements.push( document.all[i] );
2918                  }
2919              }
2920              return allElements;
2921          }
2922          //real browsers just do this
2923          else
2924          {
2925              if (!parentElement) { parentElement = document.body; }
2926              return parentElement.getElementsByTagName('*');
2927          }
2928      },
2929      getElementsByProperty: function(property, regex, parentElement) {
2930          var allElements = HTML_AJAX_Util.getAllElements(parentElement);
2931          var items = [];
2932          for(var i=0,j=allElements.length; i<j; i++)
2933          {
2934              if(regex.test(allElements[i][property]))
2935              {
2936                  items.push(allElements[i]);
2937              }
2938          }
2939          return items;
2940      },
2941      getElementsByClassName: function(className, parentElement) {
2942          return HTML_AJAX_Util.getElementsByProperty('className',new RegExp('(^| )' + className + '( |$)'),parentElement);
2943      },
2944      getElementsById: function(id, parentElement) {
2945          return HTML_AJAX_Util.getElementsByProperty('id',new RegExp(id),parentElement);
2946      },
2947      getElementsByCssSelector: function(selector,parentElement) {
2948          return cssQuery(selector,parentElement);
2949      },
2950      htmlEscape: function(inp) {
2951          var div = document.createElement('div');
2952          var text = document.createTextNode(inp);
2953          div.appendChild(text);
2954          return div.innerHTML;
2955      },
2956      // return the base of the given absolute url, or the filename if the second argument is true
2957      baseURL: function(absolute, filename) {
2958          var qPos = absolute.indexOf('?');
2959          if (qPos >= 0) {
2960              absolute = absolute.substr(0, qPos);
2961          }
2962          var slashPos = Math.max(absolute.lastIndexOf('/'), absolute.lastIndexOf('\\'));
2963          if (slashPos < 0) {
2964              return absolute;
2965          }
2966          return (filename ? absolute.substr(slashPos + 1) : absolute.substr(0, slashPos + 1));
2967      },
2968      // return the query string from a url
2969      queryString: function(url) {
2970          var qPos = url.indexOf('?');
2971          if (qPos >= 0) {
2972              return url.substr(qPos+1);
2973          }
2974      },
2975      // return the absolute path to the given relative url
2976      absoluteURL: function(rel, absolute) {
2977          if (/^https?:\/\//i.test(rel)) {
2978              return rel;
2979          }
2980          if (!absolute) {
2981              var bases = document.getElementsByTagName('base');
2982              for (i in bases) {
2983                  if (bases[i].href) {
2984                      absolute = bases[i].href;
2985                      break;
2986                  }
2987              }
2988              if (!absolute) {
2989                  absolute = window.location.href;
2990              }
2991          }
2992          if (rel == '') {
2993              return absolute;
2994          }
2995          if (rel.substr(0, 2) == '//') {
2996              // starts with '//', replace everything but the protocol
2997              var slashesPos = absolute.indexOf('//');
2998              if (slashesPos < 0) {
2999                  return 'http:' + rel;
3000              }
3001              return absolute.substr(0, slashesPos) + rel;
3002          }
3003          var base = this.baseURL(absolute);
3004          var absParts = base.substr(0, base.length - 1).split('/');
3005          var absHost = absParts.slice(0, 3).join('/') + '/';
3006          if (rel.substr(0, 1) == '/') {
3007              // starts with '/', append it to the host
3008              return absHost + rel;
3009          }
3010          if (rel.substr(0, 1) == '.' && rel.substr(1, 1) != '.') {
3011              // starts with '.', append it to the base
3012              return base + rel.substr(1);
3013          }
3014          // remove everything upto the path and beyond 
3015          absParts.splice(0, 3);
3016          var relParts = rel.split('/');
3017          var loopStart = relParts.length - 1;
3018          relParts = absParts.concat(relParts);
3019          for (i = loopStart; i < relParts.length;) {
3020              if (relParts[i] == '..') {
3021                  if (i == 0) {
3022                      return absolute;
3023                  }
3024                  relParts.splice(i - 1, 2);
3025                  --i;
3026                  continue;
3027              }
3028              i++;
3029          }
3030          return absHost + relParts.join('/');
3031      },
3032      // sets the innerHTML of an element. the third param decides how to write, it replaces by default, others are append|prepend
3033      setInnerHTML: function(node, innerHTML, type)
3034      {
3035          node = this.getElement(node);
3036  
3037          if (type != 'append') {
3038              if (type == 'prepend') {
3039                  var oldHtml = node.innerHTML;
3040              }
3041              node.innerHTML = '';
3042          }
3043          var good_browser = (window.opera || navigator.product == 'Gecko');
3044          var regex = /^([\s\S]*?)<script([\s\S]*?)>([\s\S]*?)<\/script>([\s\S]*)$/i;
3045          var regex_src = /src=["'](.*?)["']/i;
3046          var matches, id, script, output = '', subject = innerHTML;
3047          var scripts = [];
3048  
3049          while (true) {
3050              matches = regex.exec(subject);
3051              if (matches && matches[0]) {
3052                  subject = matches[4];
3053                  id = 'ih_' + Math.round(Math.random()*9999) + '_' + Math.round(Math.random()*9999);
3054  
3055                  var startLen = matches[3].length;
3056                  script = matches[3].replace(/document\.write\(([\s\S]*?)\)/ig, 
3057                      'document.getElementById("' + id + '").innerHTML+=$1');
3058  
3059                  output += matches[1];
3060                  if (startLen != script.length) {
3061                          output += '<span id="' + id + '"></span>';
3062                  }
3063                  
3064                  output += '<script' + matches[2] + '>' + script + '</script>';
3065                  if (good_browser) {
3066                      continue;
3067                  }
3068                  if (script) {
3069                      scripts.push(script);
3070                  }
3071                  if (regex_src.test(matches[2])) {
3072                      var script_el = document.createElement("SCRIPT");
3073                      var atts_regex = /(\w+)=["'](.*?)["']([\s\S]*)$/;
3074                      var atts = matches[2];
3075                      for (var i = 0; i < 5; i++) { 
3076                          var atts_matches = atts_regex.exec(atts);
3077                          if (atts_matches && atts_matches[0]) {
3078                              script_el.setAttribute(atts_matches[1], atts_matches[2]);
3079                              atts = atts_matches[3];
3080                          } else {
3081                              break;
3082                          }
3083                      }
3084                      scripts.push(script_el);
3085                  }
3086              } else {
3087                  output += subject;
3088                  break;
3089              }
3090          }
3091          innerHTML = output;
3092  
3093          if (good_browser) {
3094              var el = document.createElement('span');
3095              el.innerHTML = innerHTML;
3096  
3097              for(var i = 0; i < el.childNodes.length; i++) {
3098                  node.appendChild(el.childNodes[i].cloneNode(true));
3099              }
3100          }
3101          else {
3102              node.innerHTML += innerHTML;
3103          }
3104  
3105          if (oldHtml) {
3106              node.innerHTML += oldHtml;
3107          }
3108  
3109          if (!good_browser) {
3110              for(var i = 0; i < scripts.length; i++) {
3111                  if (HTML_AJAX_Util.getType(scripts[i]) == 'string') {
3112                      scripts[i] = scripts[i].replace(/^\s*<!(\[CDATA\[|--)|((\/\/)?--|\]\])>\s*$/g, '');
3113                      window.eval(scripts[i]);
3114                  }
3115                  else {
3116                      node.appendChild(scripts[i]);
3117                  }
3118              }
3119          }
3120          return;
3121      },
3122      classSep: '(^|$| )',
3123      hasClass: function(o, className) {
3124          var o = this.getElement(o);
3125          var regex = new RegExp(this.classSep + className + this.classSep);
3126          return regex.test(o.className);
3127      },
3128      addClass: function(o, className) {
3129          var o = this.getElement(o);
3130          if(!this.hasClass(o, className)) {
3131              o.className += " " + className;
3132          }
3133      },
3134      removeClass: function(o, className) {
3135          var o = this.getElement(o);
3136          var regex = new RegExp(this.classSep + className + this.classSep);
3137          o.className = o.className.replace(regex, " ");
3138      },
3139      replaceClass: function(o, oldClass, newClass) {
3140          var o = this.getElement(o);
3141          var regex = new RegExp(this.classSep + oldClass + this.classSep);
3142          o.className = o.className.replace(regex, newClass);
3143      },
3144      getElement: function(el) {
3145          if (typeof el == 'string') {
3146              return document.getElementById(el);
3147          }
3148          return el;
3149      }
3150  }
3151  // }}}
3152  // behavior/behavior.js
3153  /**
3154  
3155  ModifiedBehavior v1.0 by Ron Lancaster based on Ben Nolan's Behaviour, June 2005 implementation.
3156  Modified to use Dean Edward's CSS Query.
3157  
3158  Description
3159  ----------
3160  
3161  Uses css selectors  to apply javascript Behaviors to enable unobtrusive javascript in html documents.
3162  
3163  Dependencies
3164  ------------
3165  
3166  Requires [Dean Edwards CSSQuery](http://dean.edwards.name/my/cssQuery/ "CSSQuery").
3167  
3168  Usage
3169  ------
3170  
3171          Behavior.register(
3172              "b.someclass",
3173              function(element) {
3174                  element.onclick = function(){
3175                      alert(this.innerHTML);
3176                  }
3177              }
3178          );
3179  
3180          Behavior.register(
3181              "#someid u",
3182              function(element) {
3183                  element.onmouseover = function(){
3184                      this.innerHTML = "BLAH!";
3185                  }
3186              },
3187              getElementByID("parent")
3188          );
3189  
3190  Call `Behavior.apply()` to re-apply the rules (if you update the dom, etc).
3191  
3192  License
3193  ------
3194  
3195  Reproduced under BSD licensed. Same license as Ben Nolan's implementation.
3196  
3197  More information for Ben Nolan's implementation: <http://ripcord.co.nz/behaviour/>
3198  
3199  */
3200  
3201  var Behavior = {
3202      // so to an id to get debug timings
3203      debug : false,
3204  
3205      // private data member
3206      list : new Array(),
3207  
3208      // private method
3209      addLoadEvent : function(func) {
3210          var oldonload = window.onload;
3211  
3212          if (typeof window.onload != 'function') {
3213              window.onload = func;
3214          } else {
3215              window.onload = function() {
3216                  oldonload();
3217                  func();
3218              }
3219          }
3220      },
3221  
3222      // void apply() : Applies the registered ruleset.
3223      apply : function() {
3224          if (this.debug) {
3225              document.getElementById(this.debug).innerHTML += 'Apply: '+new Date()+'<br>';
3226              var total = 0;
3227          }
3228          if (Behavior.list.length > 2) {
3229              cssQuery.caching = true;
3230          }
3231          for (i = 0; i < Behavior.list.length; i++) {
3232              var rule = Behavior.list[i];
3233              
3234              if (this.debug) { var ds = new Date() };
3235              var tags = cssQuery(rule.selector, rule.from);
3236      
3237              if (this.debug) {
3238                  var de = new Date();
3239                  var ts = de.valueOf()-ds.valueOf();
3240                  document.getElementById(this.debug).innerHTML += 'Rule: '+rule.selector+' - Took: '+ts+' - Returned: '+tags.length+' tags<br>';
3241                  total += ts;
3242              }
3243              if (tags) {
3244                  for (j = 0; j < tags.length; j++) {
3245                      rule.action(tags[j]);
3246                  }
3247              }
3248          }
3249          if (Behavior.list.length > 2) {
3250              cssQuery.caching = false;
3251          }
3252  
3253          if (this.debug) {
3254              document.getElementById(this.debug).innerHTML += 'Total rule apply time: '+total;
3255          }
3256      },
3257  
3258      // void register() : register a css selector, and the action (function) to take,
3259      // from (optional) is a document, element or array of elements which is filtered by selector.
3260      register : function(selector, action, from) {
3261          Behavior.list.push(new BehaviorRule(selector, from, action));
3262      },
3263  
3264      // void start() : initial application of ruleset at document load.
3265      start : function() {
3266          Behavior.addLoadEvent(function() {
3267              Behavior.apply();
3268          });
3269      }
3270  }
3271  
3272  function BehaviorRule(selector, from, action) {
3273      this.selector = selector;
3274      this.from = from;
3275      this.action = action;
3276  }
3277  
3278  Behavior.start();
3279  // behavior/cssQuery-p.js
3280  /*
3281      cssQuery, version 2.0.2 (2005-08-19)
3282      Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
3283      License: http://creativecommons.org/licenses/LGPL/2.1/
3284  */
3285  eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('7 x=6(){7 1D="2.0.2";7 C=/\\s*,\\s*/;7 x=6(s,A){33{7 m=[];7 u=1z.32.2c&&!A;7 b=(A)?(A.31==22)?A:[A]:[1g];7 1E=18(s).1l(C),i;9(i=0;i<1E.y;i++){s=1y(1E[i]);8(U&&s.Z(0,3).2b("")==" *#"){s=s.Z(2);A=24([],b,s[1])}1A A=b;7 j=0,t,f,a,c="";H(j<s.y){t=s[j++];f=s[j++];c+=t+f;a="";8(s[j]=="("){H(s[j++]!=")")a+=s[j];a=a.Z(0,-1);c+="("+a+")"}A=(u&&V[c])?V[c]:21(A,t,f,a);8(u)V[c]=A}m=m.30(A)}2a x.2d;5 m}2Z(e){x.2d=e;5[]}};x.1Z=6(){5"6 x() {\\n  [1D "+1D+"]\\n}"};7 V={};x.2c=L;x.2Y=6(s){8(s){s=1y(s).2b("");2a V[s]}1A V={}};7 29={};7 19=L;x.15=6(n,s){8(19)1i("s="+1U(s));29[n]=12 s()};x.2X=6(c){5 c?1i(c):o};7 D={};7 h={};7 q={P:/\\[([\\w-]+(\\|[\\w-]+)?)\\s*(\\W?=)?\\s*([^\\]]*)\\]/};7 T=[];D[" "]=6(r,f,t,n){7 e,i,j;9(i=0;i<f.y;i++){7 s=X(f[i],t,n);9(j=0;(e=s[j]);j++){8(M(e)&&14(e,n))r.z(e)}}};D["#"]=6(r,f,i){7 e,j;9(j=0;(e=f[j]);j++)8(e.B==i)r.z(e)};D["."]=6(r,f,c){c=12 1t("(^|\\\\s)"+c+"(\\\\s|$)");7 e,i;9(i=0;(e=f[i]);i++)8(c.l(e.1V))r.z(e)};D[":"]=6(r,f,p,a){7 t=h[p],e,i;8(t)9(i=0;(e=f[i]);i++)8(t(e,a))r.z(e)};h["2W"]=6(e){7 d=Q(e);8(d.1C)9(7 i=0;i<d.1C.y;i++){8(d.1C[i]==e)5 K}};h["2V"]=6(e){};7 M=6(e){5(e&&e.1c==1&&e.1f!="!")?e:23};7 16=6(e){H(e&&(e=e.2U)&&!M(e))28;5 e};7 G=6(e){H(e&&(e=e.2T)&&!M(e))28;5 e};7 1r=6(e){5 M(e.27)||G(e.27)};7 1P=6(e){5 M(e.26)||16(e.26)};7 1o=6(e){7 c=[];e=1r(e);H(e){c.z(e);e=G(e)}5 c};7 U=K;7 1h=6(e){7 d=Q(e);5(2S d.25=="2R")?/\\.1J$/i.l(d.2Q):2P(d.25=="2O 2N")};7 Q=6(e){5 e.2M||e.1g};7 X=6(e,t){5(t=="*"&&e.1B)?e.1B:e.X(t)};7 17=6(e,t,n){8(t=="*")5 M(e);8(!14(e,n))5 L;8(!1h(e))t=t.2L();5 e.1f==t};7 14=6(e,n){5!n||(n=="*")||(e.2K==n)};7 1e=6(e){5 e.1G};6 24(r,f,B){7 m,i,j;9(i=0;i<f.y;i++){8(m=f[i].1B.2J(B)){8(m.B==B)r.z(m);1A 8(m.y!=23){9(j=0;j<m.y;j++){8(m[j].B==B)r.z(m[j])}}}}5 r};8(![].z)22.2I.z=6(){9(7 i=0;i<1z.y;i++){o[o.y]=1z[i]}5 o.y};7 N=/\\|/;6 21(A,t,f,a){8(N.l(f)){f=f.1l(N);a=f[0];f=f[1]}7 r=[];8(D[t]){D[t](r,A,f,a)}5 r};7 S=/^[^\\s>+~]/;7 20=/[\\s#.:>+~()@]|[^\\s#.:>+~()@]+/g;6 1y(s){8(S.l(s))s=" "+s;5 s.P(20)||[]};7 W=/\\s*([\\s>+~(),]|^|$)\\s*/g;7 I=/([\\s>+~,]|[^(]\\+|^)([#.:@])/g;7 18=6(s){5 s.O(W,"$1").O(I,"$1*$2")};7 1u={1Z:6(){5"\'"},P:/^(\'[^\']*\')|("[^"]*")$/,l:6(s){5 o.P.l(s)},1S:6(s){5 o.l(s)?s:o+s+o},1Y:6(s){5 o.l(s)?s.Z(1,-1):s}};7 1s=6(t){5 1u.1Y(t)};7 E=/([\\/()[\\]?{}|*+-])/g;6 R(s){5 s.O(E,"\\\\$1")};x.15("1j-2H",6(){D[">"]=6(r,f,t,n){7 e,i,j;9(i=0;i<f.y;i++){7 s=1o(f[i]);9(j=0;(e=s[j]);j++)8(17(e,t,n))r.z(e)}};D["+"]=6(r,f,t,n){9(7 i=0;i<f.y;i++){7 e=G(f[i]);8(e&&17(e,t,n))r.z(e)}};D["@"]=6(r,f,a){7 t=T[a].l;7 e,i;9(i=0;(e=f[i]);i++)8(t(e))r.z(e)};h["2G-10"]=6(e){5!16(e)};h["1x"]=6(e,c){c=12 1t("^"+c,"i");H(e&&!e.13("1x"))e=e.1n;5 e&&c.l(e.13("1x"))};q.1X=/\\\\:/g;q.1w="@";q.J={};q.O=6(m,a,n,c,v){7 k=o.1w+m;8(!T[k]){a=o.1W(a,c||"",v||"");T[k]=a;T.z(a)}5 T[k].B};q.1Q=6(s){s=s.O(o.1X,"|");7 m;H(m=s.P(o.P)){7 r=o.O(m[0],m[1],m[2],m[3],m[4]);s=s.O(o.P,r)}5 s};q.1W=6(p,t,v){7 a={};a.B=o.1w+T.y;a.2F=p;t=o.J[t];t=t?t(o.13(p),1s(v)):L;a.l=12 2E("e","5 "+t);5 a};q.13=6(n){1d(n.2D()){F"B":5"e.B";F"2C":5"e.1V";F"9":5"e.2B";F"1T":8(U){5"1U((e.2A.P(/1T=\\\\1v?([^\\\\s\\\\1v]*)\\\\1v?/)||[])[1]||\'\')"}}5"e.13(\'"+n.O(N,":")+"\')"};q.J[""]=6(a){5 a};q.J["="]=6(a,v){5 a+"=="+1u.1S(v)};q.J["~="]=6(a,v){5"/(^| )"+R(v)+"( |$)/.l("+a+")"};q.J["|="]=6(a,v){5"/^"+R(v)+"(-|$)/.l("+a+")"};7 1R=18;18=6(s){5 1R(q.1Q(s))}});x.15("1j-2z",6(){D["~"]=6(r,f,t,n){7 e,i;9(i=0;(e=f[i]);i++){H(e=G(e)){8(17(e,t,n))r.z(e)}}};h["2y"]=6(e,t){t=12 1t(R(1s(t)));5 t.l(1e(e))};h["2x"]=6(e){5 e==Q(e).1H};h["2w"]=6(e){7 n,i;9(i=0;(n=e.1F[i]);i++){8(M(n)||n.1c==3)5 L}5 K};h["1N-10"]=6(e){5!G(e)};h["2v-10"]=6(e){e=e.1n;5 1r(e)==1P(e)};h["2u"]=6(e,s){7 n=x(s,Q(e));9(7 i=0;i<n.y;i++){8(n[i]==e)5 L}5 K};h["1O-10"]=6(e,a){5 1p(e,a,16)};h["1O-1N-10"]=6(e,a){5 1p(e,a,G)};h["2t"]=6(e){5 e.B==2s.2r.Z(1)};h["1M"]=6(e){5 e.1M};h["2q"]=6(e){5 e.1q===L};h["1q"]=6(e){5 e.1q};h["1L"]=6(e){5 e.1L};q.J["^="]=6(a,v){5"/^"+R(v)+"/.l("+a+")"};q.J["$="]=6(a,v){5"/"+R(v)+"$/.l("+a+")"};q.J["*="]=6(a,v){5"/"+R(v)+"/.l("+a+")"};6 1p(e,a,t){1d(a){F"n":5 K;F"2p":a="2n";1a;F"2o":a="2n+1"}7 1m=1o(e.1n);6 1k(i){7 i=(t==G)?1m.y-i:i-1;5 1m[i]==e};8(!Y(a))5 1k(a);a=a.1l("n");7 m=1K(a[0]);7 s=1K(a[1]);8((Y(m)||m==1)&&s==0)5 K;8(m==0&&!Y(s))5 1k(s);8(Y(s))s=0;7 c=1;H(e=t(e))c++;8(Y(m)||m==1)5(t==G)?(c<=s):(s>=c);5(c%m)==s}});x.15("1j-2m",6(){U=1i("L;/*@2l@8(@\\2k)U=K@2j@*/");8(!U){X=6(e,t,n){5 n?e.2i("*",t):e.X(t)};14=6(e,n){5!n||(n=="*")||(e.2h==n)};1h=1g.1I?6(e){5/1J/i.l(Q(e).1I)}:6(e){5 Q(e).1H.1f!="2g"};1e=6(e){5 e.2f||e.1G||1b(e)};6 1b(e){7 t="",n,i;9(i=0;(n=e.1F[i]);i++){1d(n.1c){F 11:F 1:t+=1b(n);1a;F 3:t+=n.2e;1a}}5 t}}});19=K;5 x}();',62,190,'|||||return|function|var|if|for||||||||pseudoClasses||||test|||this||AttributeSelector|||||||cssQuery|length|push|fr|id||selectors||case|nextElementSibling|while||tests|true|false|thisElement||replace|match|getDocument|regEscape||attributeSelectors|isMSIE|cache||getElementsByTagName|isNaN|slice|child||new|getAttribute|compareNamespace|addModule|previousElementSibling|compareTagName|parseSelector|loaded|break|_0|nodeType|switch|getTextContent|tagName|document|isXML|eval|css|_1|split|ch|parentNode|childElements|nthChild|disabled|firstElementChild|getText|RegExp|Quote|x22|PREFIX|lang|_2|arguments|else|all|links|version|se|childNodes|innerText|documentElement|contentType|xml|parseInt|indeterminate|checked|last|nth|lastElementChild|parse|_3|add|href|String|className|create|NS_IE|remove|toString|ST|select|Array|null|_4|mimeType|lastChild|firstChild|continue|modules|delete|join|caching|error|nodeValue|textContent|HTML|prefix|getElementsByTagNameNS|end|x5fwin32|cc_on|standard||odd|even|enabled|hash|location|target|not|only|empty|root|contains|level3|outerHTML|htmlFor|class|toLowerCase|Function|name|first|level2|prototype|item|scopeName|toUpperCase|ownerDocument|Document|XML|Boolean|URL|unknown|typeof|nextSibling|previousSibling|visited|link|valueOf|clearCache|catch|concat|constructor|callee|try'.split('|'),0,{}))


Généré le : Fri Mar 30 01:27:52 2007 par Balluche grâce à PHPXref 0.7