Skip to content

banner ajax
The Complete Reference: Ajax

AjaxTCR Library Source

  • AjaxTCR Library
  1.  /*
  2.  
  3.   * AjaxTCR Library
  4.  
  5.   * Software License Agreement (BSD License)
  6.  
  7.   *
  8.  
  9.   * Copyright © 2007, Pint, Inc.
  10.  
  11.   * All rights reserved.
  12.  
  13.   *
  14.  
  15.   * Redistribution and use of this software in source and binary forms,
  16.  
  17.   * with or without modification, are permitted provided that the
  18.  
  19.   * following conditions are met:
  20.  
  21.   *
  22.  
  23.   * - Redistributions of source code must retain the above
  24.  
  25.   * copyright notice, this list of conditions and the following
  26.  
  27.   * disclaimer.
  28.  
  29.   *
  30.  
  31.   * - Redistributions in binary form must reproduce the above
  32.  
  33.   * copyright notice, this list of conditions and the
  34.  
  35.   * following disclaimer in the documentation and/or other materials
  36.  
  37.   * provided with the distribution.
  38.  
  39.   *
  40.  
  41.   * - Neither the name of Pint Inc. nor the names of its contributors
  42.  
  43.   * may be used to endorse or promote products derived from this
  44.  
  45.   * software without specific prior written permission of Pint Inc.
  46.  
  47.   *
  48.  
  49.   *
  50.  
  51.   *
  52.  
  53.   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  54.  
  55.   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  56.  
  57.   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  58.  
  59.   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  60.  
  61.   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  62.  
  63.   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  64.  
  65.   * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  66.  
  67.   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  68.  
  69.   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  70.  
  71.   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  72.  
  73.   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  74.  
  75.   *
  76.  
  77.   * Docs are generated using java -jar app/js.jar app/run.js -t=templates/htm -d=../docs ../ajaxtcr.js
  78.  
  79.   * OR for private included: java -jar app/js.jar app/run.js -p -t=templates/htm -d=../docsall ../ajaxtcr.js
  80.  
  81.   */
  82.  
  83.  
  84.  
  85.  /**
  86.  
  87.   * @fileOverview The AjaxTCR library was built to support "Ajax: The Complete Reference".
  88.  
  89.   * The primary purpose to cover all aspects of communications including XHR, fallback transports,
  90.  
  91.   * request queue, response queue, caching, templates, many entries to callbacks, form serialization, and proper
  92.  
  93.   * history management.
  94.  
  95.   * The library also includes supporting functions for data manipulation, dom access, event handling,
  96.  
  97.   * persistence, as well as caching, templates, and history outside of the scope of communications.
  98.  
  99.   * @name ajaxtcr.js
  100.  
  101.   */
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  /**
  108.  
  109.  * The AjaxTCR global namespace object.
  110.  
  111.  * @class AjaxTCR
  112.  
  113.  * @static
  114.  
  115.  */
  116.  
  117.  
  118.  
  119.  var AjaxTCR = {};
  120.  
  121.  
  122.  
  123.  /**
  124.  
  125.   * The communication class of the library. Contains communication methods
  126.  
  127.   * as well as subclasses for caching, queueing, collecting statistics, and accessing
  128.  
  129.   * cookies
  130.  
  131.   * @class AjaxTCR.comm
  132.  
  133.   * @static
  134.  
  135.   */
  136.  
  137.  AjaxTCR.comm = {
  138.  
  139.  
  140.  
  141.  /****************************************** Constants ******************************************/
  142.  
  143.  
  144.  
  145.  /** readyState constants as defined by w3c */
  146.  
  147.   UNSENT : 0,
  148.  
  149.   OPEN : 1,
  150.  
  151.   SENT : 2,
  152.  
  153.   LOADING : 3,
  154.  
  155.   DONE : 4,
  156.  
  157.  
  158.  
  159.  /** Default HTTP request method
  160.  
  161.   * @private
  162.  
  163.   */
  164.  
  165.  DEFAULT_REQUEST_METHOD : "GET",
  166.  
  167.  
  168.  
  169.  /** Default async option
  170.  
  171.   * @private
  172.  
  173.   */
  174.  
  175.  DEFAULT_ASYNC : true,
  176.  
  177.  
  178.  
  179.  /** Default option to prevent browser caching of request.
  180.  
  181.   * Only works with XHRs and is done by setting the "If-Modified-Since" header
  182.  
  183.   * @private
  184.  
  185.   */
  186.  
  187.  DEFAULT_PREVENT_CACHE: false,
  188.  
  189.  
  190.  
  191.  /** Default Request Content Type
  192.  
  193.   * @private
  194.  
  195.   */
  196.  
  197.  DEFAULT_CONTENT_TYPE : "application/x-www-form-urlencoded",
  198.  
  199.  
  200.  
  201.  /** Default Request Content Transfer Encoding
  202.  
  203.   * @private
  204.  
  205.   */
  206.  
  207.  DEFAULT_CONTENT_TRANSFER_ENCODING : "",
  208.  
  209.  
  210.  
  211.  /** Default indicate transport scheme used. If set will include the transport scheme in the headers or payload
  212.  
  213.   * @private
  214.  
  215.   */
  216.  
  217.  DEFAULT_TRANSPORT_INDICATOR : true,
  218.  
  219.  
  220.  
  221.  /** Default timeout in ms.
  222.  
  223.   * @private
  224.  
  225.   */
  226.  
  227.  DEFAULT_TIMEOUT : 0,
  228.  
  229.  
  230.  
  231.  /** Default number of Retries
  232.  
  233.   * @private
  234.  
  235.   */
  236.  
  237.  DEFAULT_RETRIES : 0,
  238.  
  239.  
  240.  
  241.  /** Default show progress
  242.  
  243.   * @private
  244.  
  245.   */
  246.  
  247.  DEFAULT_SHOW_PROGRESS : false,
  248.  
  249.  
  250.  
  251.  /** Default time to revisit our progress callback if monitoring progress
  252.  
  253.   * @private
  254.  
  255.   */
  256.  
  257.  DEFAULT_PROGRESS_INTERVAL : 1000,
  258.  
  259.  
  260.  
  261.  /** Default enforce order. If set, it will enforce order on all requests that have the value set, but not those without
  262.  
  263.   * @private
  264.  
  265.   */
  266.  
  267.  DEFAULT_ENFORCE_ORDER : false,
  268.  
  269.  
  270.  
  271.  /** Default Cache Response
  272.  
  273.   * @private
  274.  
  275.   */
  276.  
  277.  DEFAULT_CACHE_RESPONSE : false,
  278.  
  279.  
  280.  
  281.  /** Default to put the responseText into outputTarget
  282.  
  283.   * @private
  284.  
  285.   */
  286.  
  287.  DEFAULT_USE_RAW : true,
  288.  
  289.  
  290.  
  291.  /** Default one way transmission. Will not call any callbacks if set
  292.  
  293.   * @private
  294.  
  295.   */
  296.  
  297.  DEFAULT_ONEWAY : false,
  298.  
  299.  
  300.  
  301.  /** Default signature to use to sign request. Places value in the header
  302.  
  303.   * @private
  304.  
  305.   */
  306.  
  307.  DEFAULT_REQUEST_SIGNATURE : "X-Signature",
  308.  
  309.  
  310.  
  311.  /** Default option if the response is signed
  312.  
  313.   * @private
  314.  
  315.   */
  316.  
  317.  DEFAULT_SIGNED_RESPONSE : false,
  318.  
  319.  
  320.  
  321.  /** Default transport scheme
  322.  
  323.   * @private
  324.  
  325.   */
  326.  
  327.  DEFAULT_TRANSPORT : "xhr",
  328.  
  329.  
  330.  
  331.  /** Default transport string value. Name of the header or payload value that will be sent with request
  332.  
  333.   * @private
  334.  
  335.   */
  336.  
  337.  DEFAULT_TRANSPORT_HEADER : "X-Requested-By",
  338.  
  339.  
  340.  
  341.  /** Default values to set the transport value to.
  342.  
  343.   * @private
  344.  
  345.   */
  346.  
  347.  DEFAULT_XHR_TRANSPORT_VALUE: "XHR",
  348.  
  349.  DEFAULT_IFRAME_TRANSPORT_VALUE: "iframe",
  350.  
  351.  DEFAULT_IMAGE_TRANSPORT_VALUE: "image",
  352.  
  353.  DEFAULT_SCRIPT_TRANSPORT_VALUE: "HTMLScriptTag",
  354.  
  355.  
  356.  
  357.  /** Fallback to another transport if XHR fails
  358.  
  359.   * @private
  360.  
  361.   */
  362.  
  363.  DEFAULT_FALLBACK : true,
  364.  
  365.  
  366.  
  367.  /** Default fallback transport scheme
  368.  
  369.   * @private
  370.  
  371.   */
  372.  
  373.  DEFAULT_FALLBACK_TRANSPORT: "iframe",
  374.  
  375.  
  376.  
  377.  /** Default output handing. Places responseText into outputTarget with this method
  378.  
  379.   * @private
  380.  
  381.   */
  382.  
  383.  DEFAULT_INSERTION_METHOD : "replace",
  384.  
  385.  
  386.  
  387.  /** Cache the template
  388.  
  389.   * @private
  390.  
  391.   */
  392.  
  393.  DEFAULT_CACHE_TEMPLATE : true,
  394.  
  395.  
  396.  
  397.  /** Default location for rendering templates
  398.  
  399.   * @private
  400.  
  401.   */
  402.  
  403.  DEFAULT_TEMPLATE_RENDER : "client",
  404.  
  405.  
  406.  
  407.  /** Constant for server defined template file
  408.  
  409.   * @private
  410.  
  411.   */
  412.  
  413.  TEMPLATE_SERVER_DEFINED : "dynamic",
  414.  
  415.  
  416.  
  417.  
  418.  
  419.  /****************************************** Private Properties ****************************************************/
  420.  
  421.  
  422.  
  423.  /** the request id counter
  424.  
  425.   * @private
  426.  
  427.   */
  428.  
  429.   _requestID : 0,
  430.  
  431.  
  432.  
  433.  /** request counter shows outstanding requests
  434.  
  435.   * @private
  436.  
  437.   */
  438.  
  439.  _requestsOutstanding : 0,
  440.  
  441.  
  442.  
  443.  /** the statuses for possible network errors
  444.  
  445.   * 3507 = library error flag
  446.  
  447.   * @private
  448.  
  449.   */
  450.  
  451.   _networkErrorStatus : new Array(0, 408, 504, 3507, 12002, 12007, 12029, 12030, 12031, 12152),
  452.  
  453.  
  454.  
  455.  
  456.  
  457.   /***************************************** GETTERS/SETTERS ***********************************/
  458.  
  459.  
  460.  
  461.  /**
  462.  
  463.   * Updates a default value in the AjaxTCR.comm namespace.
  464.  
  465.   *
  466.  
  467.   * @param {string} option The name of the option to update
  468.  
  469.   * @config {string} DEFAULT_REQUEST_METHOD Possible values - any valid HTTP Method. Default: "GET"
  470.  
  471.   * @config {boolean} DEFAULT_ASYNC Default: true
  472.  
  473.   * @config {boolean}DEFAULT_PREVENT_CACHE Default: false,
  474.  
  475.   * @config {string} DEFAULT_CONTENT_TYPE Default : "application/x-www-form-urlencoded",
  476.  
  477.   * @config {string} DEFAULT_CONTENT_TRANSFER_ENCODING Default : "",
  478.  
  479.   * @config {boolean}DEFAULT_TRANSPORT_INDICATOR Default : true,
  480.  
  481.   * @config {integer} DEFAULT_TIMEOUT Default : 0,
  482.  
  483.   * @config {integer} DEFAULT_RETRIES Default : 0,
  484.  
  485.   * @config {boolean} DEFAULT_SHOW_PROGRESS Default : false,
  486.  
  487.   * @config {integer} DEFAULT_PROGRESS_INTERVAL Default : 1000,
  488.  
  489.   * @config {boolean} DEFAULT_ENFORCE_ORDER Default : false,
  490.  
  491.   * @config {boolean} DEFAULT_CACHE_RESPONSE Default : false,
  492.  
  493.   * @config {boolean} DEFAULT_USE_RAW Default : true,
  494.  
  495.   * @config {boolean} DEFAULT_ONEWAY Default : false,
  496.  
  497.   * @config {string} DEFAULT_REQUEST_SIGNATURE Default : "X-Signature",
  498.  
  499.   * @config {boolean} DEFAULT_SIGNED_RESPONSE Default : false,
  500.  
  501.   * @config {string} DEFAULT_TRANSPORT Default : "xhr",
  502.  
  503.   * @config {string} DEFAULT_TRANSPORT_HEADER Default : "X-Requested-By",
  504.  
  505.   * @config {string} DEFAULT_XHR_TRANSPORT_VALUE Default : "XHR",
  506.  
  507.   * @config {string} DEFAULT_IFRAME_TRANSPORT_VALUE Default : "iframe",
  508.  
  509.   * @config {string} DEFAULT_IMAGE_TRANSPORT_VALUE Default : "image",
  510.  
  511.   * @config {string} DEFAULT_SCRIPT_TRANSPORT_VALUE Default : "HTMLScriptTag",
  512.  
  513.   * @config {boolean} DEFAULT_FALLBACK Default : true,
  514.  
  515.   * @config {string} DEFAULT_FALLBACK_TRANSPORT Default : "iframe",
  516.  
  517.   * @config {string} DEFAULT_INSERTION_METHOD Default : "replace",
  518.  
  519.   * @config {boolean} DEFAULT_CACHE_TEMPLATE Default : true,
  520.  
  521.   * @config {string} DEFAULT_TEMPLATE_RENDER Default : "client",
  522.  
  523.   * @config {string} TEMPLATE_SERVER_DEFINED Default : "dynamic",
  524.  
  525.   * @param {object} value The value to set the option to.
  526.  
  527.   */
  528.  
  529.  setDefault : function(option, value){
  530.  
  531.   AjaxTCR.comm[option] = value;
  532.  
  533.  },
  534.  
  535.  
  536.  
  537.  /**
  538.  
  539.   * Retrieves the default value in the AjaxTCR.comm namespace for the given option
  540.  
  541.   *
  542.  
  543.   * @param {string} option The name of the option to fetch
  544.  
  545.   * @return {string} The value of the passed in option
  546.  
  547.   */
  548.  
  549.  getDefault : function(option){
  550.  
  551.   return AjaxTCR.comm[option]
  552.  
  553.  },
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  /****************************************** Public Methods ******************************************/
  560.  
  561.  
  562.  
  563.  /**
  564.  
  565.   * sendRequest - public method to create an Ajax style request
  566.  
  567.   *
  568.  
  569.   * @param url string of URL to send request to
  570.  
  571.   * @param options object containing the options for the request
  572.  
  573.   * @config {Boolean} async Defines if the request should be asynchronous or not. The default is true when not specified.
  574.  
  575.   * @config {string} cacheKey By default, when cache is turned on, items are saved in cache using the URL of the object as a key. If another value is desired you may set it through this property though you will be responsible for manually retrieving as the request system will use the URL of requests to determine if something is cached or not. Default is URL of request
  576.  
  577.   * @config {Boolean} cacheResponse Boolean to indicate if the response should be saved in the response cache. Default is false
  578.  
  579.   * @config {Boolean} cacheTemplate Indicates that if a cache is returned with the response if it should be saved in the template cache or not. Default is true
  580.  
  581.   * @config {string} cookieName The name of the cookie expected upon response when the transport type is image. If specified the responseText will be populated with the value of this cookie only. If unspecified responseText will contain the entire cookie and the developer is required to parse out the response manually. Should be set if outputTarget is also specified with request. Default is document.cookie
  582.  
  583.   * @config {Boolean} enforceOrder Boolean to force every response that has this value set to be returned in the order in which it was sent, this means that requests may be held until previous requests arrive. Default is false
  584.  
  585.   * @config {Boolean} fallback Defines if the communication mechanism should fallback to another method if the XHR fails for some reason. The fallback transport scheme is defined by fallbackTransport or the global default is consulted. Default is true
  586.  
  587.   * @config {string} fallbackTransport Options are "iframe" | "script" | "image" Defines the particular communication mechanism that should be used if XHRs fail for some reason fallback. If undefined the global default (iframe) is used unless it has been overridden. . Default is "iframe"
  588.  
  589.   * @config {object} headers Array-of-Header Objects An array of header objects to be sent with the request. The header object must have two properties called name and value with the appropriate values. It is set up in this manner to allow multiple values for a single name. The library will append these together with ‘,’. Note that setting a Cookie header should be avoided particularly if more than one value is set and document.cookie should be used instead. Default is []
  590.  
  591.   * @config {object} history Used to control the history mechanism on a request basis. The passed object has three properties, saveResponse, id, and title. The saveResponse property indicates that the response will be cached and when a user backs up to the page in question another request will not be issued. By default responses will not be saved. The id is the value used in the hash mark (ex. #currentState), the id is required. The title property is used to set the title of the page so as to reflect the current state of the application. Default is null
  592.  
  593.   * @config {string} insertionType "insertBefore" | "insertAfter" | "firstChild" | "lastChild" | "replace" Used in conjunction with outputTarget to define how content returned should be handled relative to the element specified by the outputTarget value. By default the returned content will replace the outputTarget element content. Other values include. <br />insertBefore put as element just before the specified element <br />insertAfter put as an element just after the specified element<br />firstChild put as the first child within the specified element<br />lastChild put as the last child within the specified element <br />Default is "replace"
  594.  
  595.   * @config {string} method HTTP-method Sets the method for the request to the string HTTP-method. No limit to what is settable, though some XHR implementations will not support some methods and of course destinations may reject methods. If unset a default method will be used. Note that some browsers XHR implementations will not allow for extended HTTP methods and that alternate transfers may be even more restrictive (iframe - GET and POST, all other transports - GET only) Default is "GET"
  596.  
  597.   * @config {function} onCreate Called right after the XHR object is created. Corresponds to readyState == 0. Passes the request object. Default is null
  598.  
  599.   * @config {Boolean} oneway Indicates if the request is one way and thus if the response should be ignored. Default is false
  600.  
  601.   * @config {function} onFail Callback that is called when a server error occurs. Most often this occurs when the status != 200. Passes the request object along with a message describing the error. Default is function () {}
  602.  
  603.   * @config {function} onLoading Callback that is called with the xhr.readyState == 3. This occurs when the data begins to come back. Passes the request object. Default is null
  604.  
  605.   * @config {function} onOpen Callback that is called when the xhr.readyState == 1. This occurs after xhr.open. Passes the request object. Default is null
  606.  
  607.   * @config {function} onPrefetch Callback that is invoked when you are prefetching data but not yet using it. Default is function (){}
  608.  
  609.   * @config {function} onProgress Callback invoked by default once every second. Useful for updating the user to the progress of long requests. Often used with the status object. You can override the default progressInterval of one second if desired. Default is function () {}
  610.  
  611.   * @config {function} onReceived Callback that corresponds to readyState 4 but without having looked at the success or failure of the request yet, thus it will be called before onSuccess or onFail. Default is null
  612.  
  613.   * @config {function} onRetry Callback function that is called when retry is enabled. Called very time a retry occurs. Default is function () {}
  614.  
  615.   * @config {function} onSent Callback that is called when the xhr.readyState = 2. This occurs right after xhr.send(). Passes the request object. Default is null
  616.  
  617.   * @config {function} onStatus Callback that is invoked for the corresponding status code. For example the callback for on404 is called when a response of 404 is received while an on500 is called when a 500 response code is received. Default is undefined
  618.  
  619.   * @config {function} onSuccess Primary callback that will be called whenever the request completes successfully with a status of 200. Passes the response object as a parameter. Default is function () {}
  620.  
  621.   * @config {function} onTimeout Callback that is invoked when a timeout occurs. If there are retries and continual failures this callback may be invoked numerous times. Default is function () {}
  622.  
  623.   * @config {object} outputTarget When specified the request’s responseText will be automatically inserted into the specified object using its innerHTML property. The object should be a reference to a DOM element or a string to be used that references an existing DOM element by its id attribute. The useRaw option can be set to false so that a user may desire to override the immediate placement of content but still use this property as a reference. Default is null
  624.  
  625.   * @config {string} password The password to be used when addressing HTTP authentication challenges. Only supported with the XHR transport. Default is ""
  626.  
  627.   * @config {string} payload The payload is a properly encoded string (or object) to be submitted in a query string or message body depending on the HTTP method used. Various AjaxTCR.data methods like encodeValue() and serializeForm() may be used to quickly form a payload. The payload must be in the format in which it is going to be used. Default is ""
  628.  
  629.   * @config {Boolean} preventCache When set to true, attempts to disable caching by setting the request header to a very old date. Users may also desire to add a unique query string as well. Default is false
  630.  
  631.   * @config {millisecond} progressInterval This value is used to indicate how often the request should be polled for progress updates in milliseconds. Defaults to 1 second (1000ms).
  632.  
  633.   * @config {string} requestContentType MimeType string The content type on the request. If the request is a POST, it will set the request Content-Type header to this value. Will base form serialization on it as well. Default is "application/x-www-form-urlencoded"
  634.  
  635.   * @config {string} requestContentTransferEncoding encodingType Sets the Content-Transfer-Encoding header on the request to the defined value. Default is ""
  636.  
  637.   * @config {string} requestSignature Indicates the header used when signing requests and will contain the contents of signRequest property if it is set. Default is "X-Signature"
  638.  
  639.   * @config {integer} retries Indicates if a request should be retried if an error is encountered or a timeout occurs. Set to false or 0 to not retry failed requests. Set this value larger than 0 to indicate number of retries Default is 0
  640.  
  641.   * @config {object} serializeForm Automatically encodes the contents of the form specified as an object, id or name. A default encoding of x-www-form-urlencoded will be used unless the requestContentType attribute is set. Default is null
  642.  
  643.   * @config {Boolean} showProgress Setting this property to true indicates that the progress event will fire. Default is false
  644.  
  645.   * @config {string} signRequest "signature string" Used to sign a request, typically it is an MD5 hash value that will be put in the Web page when generated by a server-side program. Default is null
  646.  
  647.   * @config {Boolean} signedResponse If the response is signed, the library will check the "Content-MD5" header in the response and compare it to a MD5 encoding of the responseText. If they do not match, onFail is called and the responseText is not returned. Default is false
  648.  
  649.   * @config {object} statusIndicator statusObject The property should be set to an object which contains visual display information for indicating status. At this point it supports an object with a single property progress set to an object containing type which can be either image or text, imageSrc which is the URL of the image to use in the case type is set to image, and text is a string to use in the case the type is set to text. A target property is set to the DOM id reference of the place the status should be displayed. Default is null
  650.  
  651.   * @config {string} template URL | "dynamic" If a URL is specified the template to apply to a response will be fetched. If the string value of “dynamic” is used a server-side program will respond and include a template value either as a string or as URL to fetch. These values are found in the response packet in JSON format at the properties templateText and templateURL respectively. Default is null
  652.  
  653.   * @config {string} templateRender "client" | "server" String indicating if a template should be rendered on client or server, only works if the template property is set. A default value of client is assumed when template is set but templateRender is not. Default is "client"
  654.  
  655.   * @config {number} timeout Indicates whether to timeout or not. False or 0 indicates not to catch timeouts. A number greater than 0 indicates the number of milliseconds before timing out. Default is false
  656.  
  657.   * @config {string} transport "xhr" | "iframe" | "script" | "image" Transport to make the request with. By default this will be XHR though you can change it on a per request basis. The global transport can be set with setDefault("transport",value) where value one of the defined strings. The transport choice may change a request depending on the capabilities of the transport indicated. For example, image and script transports will not accept a POST request and will convert it into a GET if possible. Default is "xhr"
  658.  
  659.   * @config {Boolean} transportIndicator Indicates if Ajax indicating headers such as X-Requested-By: XHR should be included. Normally defined by value AjaxTCR.comm.DEFAULT_TRANSPORT_INDICATOR. Setting as an option effects only the request made, use the general the getter/setter AjaxTCR.comm.setDefault("DEFAULT_TRANSPORT_INDICATOR", false); Default is true
  660.  
  661.   * @config {Boolean} useRaw By default this is set to true and is consulted when outputTarget is set. If set to false the response’s payload will not be directly put into the outputTarget forcing you to manually perform any decode and placement. Default is true
  662.  
  663.   * @config {string} username Used to specify the username for HTTP authentication challenges issued to a request. Only usable with an XHR transport. Default is ""
  664.  
  665.   * @config {Boolean} useRaw This value is consulted when outputTarget is set. If set to false the response’s payload will not be directly put into the outputTarget forcing you to manually perform any decode and placement. Default is true
  666.  
  667.   * @config {object} userVars Value attached to the request/response object that may contain any form of user defined data. Default is undefined
  668.  
  669.   * @return {object} The newly generated request object.
  670.  
  671.   */
  672.  
  673.   sendRequest : function (url,options) {
  674.  
  675.  
  676.  
  677.   var request = new Object();
  678.  
  679.  
  680.  
  681.   /* increment our requestId number */
  682.  
  683.   request.requestID = ++AjaxTCR.comm._requestID;
  684.  
  685.  
  686.  
  687.   /* basic communication defaults */
  688.  
  689.   request.method = AjaxTCR.comm.DEFAULT_REQUEST_METHOD;
  690.  
  691.   request.async = AjaxTCR.comm.DEFAULT_ASYNC;
  692.  
  693.   request.preventCache = AjaxTCR.comm.DEFAULT_PREVENT_CACHE;
  694.  
  695.   request.requestContentType = AjaxTCR.comm.DEFAULT_CONTENT_TYPE;
  696.  
  697.   request.requestContentTransferEncoding = AjaxTCR.comm.DEFAULT_CONTENT_TRANSFER_ENCODING;
  698.  
  699.   request.payload = "";
  700.  
  701.  
  702.  
  703.   /* header management */
  704.  
  705.   request.headers = new Array();
  706.  
  707.   request.transportIndicator = AjaxTCR.comm.DEFAULT_TRANSPORT_INDICATOR;
  708.  
  709.  
  710.  
  711.   /* standard callbacks */
  712.  
  713.   request.onSuccess = function(){};
  714.  
  715.   request.onFail = function(){};
  716.  
  717.  
  718.  
  719.   /* callbacks associated with readyState changes */
  720.  
  721.   request.onCreate = null;
  722.  
  723.   request.onOpen = null;
  724.  
  725.   request.onSent = null;
  726.  
  727.   request.onLoading = null;
  728.  
  729.   request.onReceived = null;
  730.  
  731.  
  732.  
  733.   /* communication status flags */
  734.  
  735.   request.abort = false;
  736.  
  737.   request.inProgress = true;
  738.  
  739.   request.received = false;
  740.  
  741.  
  742.  
  743.   /* progress management */
  744.  
  745.   request.showProgress = AjaxTCR.comm.DEFAULT_SHOW_PROGRESS;
  746.  
  747.   request.progressInterval = AjaxTCR.comm.DEFAULT_PROGRESS_INTERVAL;
  748.  
  749.   request.onProgress = function (){};
  750.  
  751.   request.progressTimerID = null;
  752.  
  753.  
  754.  
  755.   /* timeout parameters */
  756.  
  757.   request.timespent = 0;
  758.  
  759.   request.timeout = AjaxTCR.comm.DEFAULT_TIMEOUT;
  760.  
  761.   request.onTimeout = function(){};
  762.  
  763.   request.timeoutTimerID = null;
  764.  
  765.  
  766.  
  767.   /* retry parameters */
  768.  
  769.   request.retries = AjaxTCR.comm.DEFAULT_RETRIES;
  770.  
  771.   request.retryCount = 1;
  772.  
  773.   request.onRetry = function (){};
  774.  
  775.  
  776.  
  777.   /* sequencing */
  778.  
  779.   request.inQueue = false;
  780.  
  781.   request.responseQueueID = 0;
  782.  
  783.   request.enforceOrder = AjaxTCR.comm.DEFAULT_ENFORCE_ORDER;
  784.  
  785.  
  786.  
  787.   /* cache management */
  788.  
  789.   request.cacheResponse = AjaxTCR.comm.DEFAULT_CACHE_RESPONSE;
  790.  
  791.   request.fromCache = false;
  792.  
  793.  
  794.  
  795.   /* Prefetch */
  796.  
  797.   request.onPrefetch = function(){};
  798.  
  799.   request.isPrefetch = false;
  800.  
  801.  
  802.  
  803.   /* payload serialization */
  804.  
  805.   request.serializeForm = null;
  806.  
  807.   request.hasFile = false;
  808.  
  809.  
  810.  
  811.   /* output handling */
  812.  
  813.   request.outputTarget = null;
  814.  
  815.   request.useRaw = AjaxTCR.comm.DEFAULT_USE_RAW;
  816.  
  817.   request.insertionType = AjaxTCR.comm.DEFAULT_INSERTION_METHOD;
  818.  
  819.  
  820.  
  821.   /* transmission type */
  822.  
  823.   request.oneway = AjaxTCR.comm.DEFAULT_ONEWAY;
  824.  
  825.  
  826.  
  827.   /* authentication */
  828.  
  829.   request.username = null;
  830.  
  831.   request.password = null;
  832.  
  833.  
  834.  
  835.   /* security */
  836.  
  837.   request.requestSignature = AjaxTCR.comm.DEFAULT_REQUEST_SIGNATURE;
  838.  
  839.   request.signRequest = null;
  840.  
  841.   request.signedResponse = AjaxTCR.comm.DEFAULT_SIGNED_RESPONSE;
  842.  
  843.  
  844.  
  845.   /* history */
  846.  
  847.   request.history = null;
  848.  
  849.  
  850.  
  851.   /* transport/fallback */
  852.  
  853.   request.transport = AjaxTCR.comm.DEFAULT_TRANSPORT;
  854.  
  855.   request.fallback = AjaxTCR.comm.DEFAULT_FALLBACK;
  856.  
  857.   request.fallbackTransport = AjaxTCR.comm.DEFAULT_FALLBACK_TRANSPORT;
  858.  
  859.   request.cookieName = null;
  860.  
  861.  
  862.  
  863.   /* Templates */
  864.  
  865.   request.template = null;
  866.  
  867.   request.templateRender = AjaxTCR.comm.DEFAULT_TEMPLATE_RENDER;
  868.  
  869.  
  870.  
  871.   request.cacheTemplate = AjaxTCR.comm.DEFAULT_CACHE_TEMPLATE;
  872.  
  873.   request.shortTermCacheTemplate = false;
  874.  
  875.  
  876.  
  877.   request.statusIndicator = null;
  878.  
  879.  
  880.  
  881.   /* apply options defined by user */
  882.  
  883.   for (option in options)
  884.  
  885.   request[option] = options[option];
  886.  
  887.  
  888.  
  889.   if (request.isPrefetch)
  890.  
  891.   request.cacheResponse = true;
  892.  
  893.  
  894.  
  895.   /* Enable backguard if necessary */
  896.  
  897.   if (AjaxTCR.history._backGuardEnabled == AjaxTCR.history.BACK_GUARD_INITIALIZED)
  898.  
  899.   AjaxTCR.history._activateBackGuard();
  900.  
  901.  
  902.  
  903.   /* Check for/Fetch template */
  904.  
  905.   if (request.template && request.template != AjaxTCR.comm.TEMPLATE_SERVER_DEFINED && request.templateRender == "client")
  906.  
  907.   {
  908.  
  909.   if (!AjaxTCR.template.getFromCache(request.template))
  910.  
  911.   {
  912.  
  913.   request.enforceOrder = true;
  914.  
  915.   AjaxTCR.comm.sendRequest(request.template, {shortTermCacheTemplate:true, enforceOrder:true});
  916.  
  917.   }
  918.  
  919.   }
  920.  
  921.   else if (request.template && request.template != AjaxTCR.comm.TEMPLATE_SERVER_DEFINED && request.templateRender == "server")
  922.  
  923.   {
  924.  
  925.   if (request.payload != "")
  926.  
  927.   request.payload += "&";
  928.  
  929.   request.payload += "templateURL=" + request.template;
  930.  
  931.   }
  932.  
  933.  
  934.  
  935.   /* Serialize the given form if request.serialize is set */
  936.  
  937.   if (request.serializeForm)
  938.  
  939.   {
  940.  
  941.   /* Serialize given form */
  942.  
  943.   var newPayload = AjaxTCR.data.serializeForm(request.serializeForm,request.requestContentType);
  944.  
  945.  
  946.  
  947.   /* check to see if we have a fileupload situation */
  948.  
  949.   if (newPayload == "fileupload")
  950.  
  951.   request.hasFile = true;
  952.  
  953.   else
  954.  
  955.   {
  956.  
  957.   /* Check to see if payload exists */
  958.  
  959.   if (request.payload)
  960.  
  961.   {
  962.  
  963.   /* If payload is an object, use serializeObject otherwise append to end of the new payload */
  964.  
  965.   if (typeof(request.payload) == "object")
  966.  
  967.   newPayload = AjaxTCR.data.serializeObject(newPayload, request.payload, request.requestContentType);
  968.  
  969.   else if (request.requestContentType == AjaxTCR.comm.DEFAULT_CONTENT_TYPE)
  970.  
  971.   newPayload += "&" + request.payload;
  972.  
  973.   }
  974.  
  975.  
  976.  
  977.   request.payload = newPayload;
  978.  
  979.  
  980.  
  981.   /* Get all values into string format */
  982.  
  983.   if (request.requestContentType == "application/json")
  984.  
  985.   request.payload = AjaxTCR.data.encodeJSON(request.payload);
  986.  
  987.   else if (request.requestContentType == "text/xml")
  988.  
  989.   request.payload = AjaxTCR.data.serializeXML(request.payload);
  990.  
  991.  
  992.  
  993.   /* Encode it in base64 if that's set */
  994.  
  995.   if (request.requestContentTransferEncoding == "base64")
  996.  
  997.   request.payload = AjaxTCR.data.encode64(request.payload);
  998.  
  999.   }
  1000.  
  1001.   }
  1002.  
  1003.  
  1004.  
  1005.   /* Add to history */
  1006.  
  1007.   if (request.history)
  1008.  
  1009.   AjaxTCR.history.init(function(){});
  1010.  
  1011.  
  1012.  
  1013.   if (request.history && !request.history.saveResponse)
  1014.  
  1015.   AjaxTCR.history.addToHistory(request.history.id, "", request.history.title, url, options);
  1016.  
  1017.  
  1018.  
  1019.   /* If there is a file, we need to handle differently */
  1020.  
  1021.   if (request.hasFile)
  1022.  
  1023.   request.transport = "iframe";
  1024.  
  1025.  
  1026.  
  1027.   /* normalize the transport value */
  1028.  
  1029.   request.transport = request.transport.toLowerCase();
  1030.  
  1031.  
  1032.  
  1033.   if (request.transport == "script" || request.transport == "image")
  1034.  
  1035.   request.method = "GET";
  1036.  
  1037.  
  1038.  
  1039.   if (request.method.toUpperCase() == "GET" && request.payload != "")
  1040.  
  1041.   request.url = url + "?" + request.payload;
  1042.  
  1043.   else
  1044.  
  1045.   request.url = url;
  1046.  
  1047.  
  1048.  
  1049.   if (request.method.toUpperCase() == "POST")
  1050.  
  1051.   request.postBody = request.payload;
  1052.  
  1053.   else
  1054.  
  1055.   request.postBody = null;
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.   /* Add a queueID if necessary */
  1062.  
  1063.   if (request.enforceOrder)
  1064.  
  1065.   request.responseQueueID = AjaxTCR.comm.queue._responseQueue.maxID++;
  1066.  
  1067.  
  1068.  
  1069.   var cachedResponse = null;
  1070.  
  1071.   /* Check if the item is in the cache first */
  1072.  
  1073.   if (request.cacheResponse)
  1074.  
  1075.   {
  1076.  
  1077.   /* Check to see if we have a key for our cache */
  1078.  
  1079.   if (request.cacheKey == undefined)
  1080.  
  1081.   request.cacheKey = request.url;
  1082.  
  1083.  
  1084.  
  1085.   cachedResponse = AjaxTCR.comm.cache.get(request.cacheKey);
  1086.  
  1087.   if (cachedResponse)
  1088.  
  1089.   AjaxTCR.comm.cache._handleCacheResponse(request, cachedResponse);
  1090.  
  1091.   }
  1092.  
  1093.  
  1094.  
  1095.   /* invoke the request */
  1096.  
  1097.   if (!cachedResponse)
  1098.  
  1099.   AjaxTCR.comm._makeRequest(request);
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.   /* return object for local control */
  1106.  
  1107.   return request;
  1108.  
  1109.   },
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.   /**
  1116.  
  1117.   * Public method that will abort any passed request object and clean up
  1118.  
  1119.   * any timers for showing requqest state
  1120.  
  1121.   *
  1122.  
  1123.   * @param {object} request The request object generated through sendRequest.
  1124.  
  1125.   */
  1126.  
  1127.   abortRequest : function(request) {
  1128.  
  1129.  
  1130.  
  1131.   /* set the abort flag */
  1132.  
  1133.   request.abort = true;
  1134.  
  1135.  
  1136.  
  1137.   /* clear inProgress flag */
  1138.  
  1139.   request.inProgress = false;
  1140.  
  1141.  
  1142.  
  1143.   /* abort the request */
  1144.  
  1145.   request.xhr.abort();
  1146.  
  1147.  
  1148.  
  1149.   /* decrement outstand request count */
  1150.  
  1151.   AjaxTCR.comm._requestsOutstanding--;
  1152.  
  1153.  
  1154.  
  1155.   /* clear any timeout timers */
  1156.  
  1157.   clearTimeout(request.timeoutTimerID);
  1158.  
  1159.   request.timeoutTimerID = null;
  1160.  
  1161.  
  1162.  
  1163.   /* stop showing progress */
  1164.  
  1165.   if (request.progressTimerID)
  1166.  
  1167.   {
  1168.  
  1169.   clearTimeout(request.progressTimerID);
  1170.  
  1171.   request.progressTimerID = null;
  1172.  
  1173.   }
  1174.  
  1175.  
  1176.  
  1177.   /* Remove Progress Indicators */
  1178.  
  1179.   if (request.statusIndicator)
  1180.  
  1181.   {
  1182.  
  1183.   AjaxTCR.comm._removeProgressStatus(request.statusIndicator);
  1184.  
  1185.   }
  1186.  
  1187.  },
  1188.  
  1189.  
  1190.  
  1191.  /****************************************** Private Methods ******************************************/
  1192.  
  1193.  
  1194.  
  1195.  
  1196.  
  1197.   /**
  1198.  
  1199.   * _createXHR - private method acting as a wrapper to make an XMLHttpRequest object. Trys native
  1200.  
  1201.   * object first and then ActiveX control. Returns null if fails.
  1202.  
  1203.   *
  1204.  
  1205.   * @private
  1206.  
  1207.   * @return {object} Either the native XHR Object or the most current ActiveX version supported.
  1208.  
  1209.   */
  1210.  
  1211.   _createXHR : function() {
  1212.  
  1213.  
  1214.  
  1215.   try { return new XMLHttpRequest(); } catch(e) {}
  1216.  
  1217.   try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
  1218.  
  1219.   try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e) {}
  1220.  
  1221.   try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
  1222.  
  1223.   try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
  1224.  
  1225.  
  1226.  
  1227.   return null;
  1228.  
  1229.  },
  1230.  
  1231.  
  1232.  
  1233.  /**
  1234.  
  1235.   * Private method that decides which initializes the requesst, decides which transport to use, and calls the send method for that transport.
  1236.  
  1237.   *
  1238.  
  1239.   * @private
  1240.  
  1241.   * @param {object} the Request Object to make the request with.
  1242.  
  1243.   */
  1244.  
  1245.  
  1246.  
  1247.  _makeRequest : function (request) {
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.   /* Increment total requests */
  1254.  
  1255.   AjaxTCR.comm.stats._commResults.totalRequests++;
  1256.  
  1257.  
  1258.  
  1259.   /* Display status and start Progress Callback */
  1260.  
  1261.   if (!request.oneway)
  1262.  
  1263.   AjaxTCR.comm._initSend(request);
  1264.  
  1265.  
  1266.  
  1267.   /* Call back for ready state 0 if set */
  1268.  
  1269.   if (request.onCreate)
  1270.  
  1271.   request.onCreate(request);
  1272.  
  1273.  
  1274.  
  1275.   if (request.transport == "xhr")
  1276.  
  1277.   AjaxTCR.comm._sendXHR(request);
  1278.  
  1279.   else if (request.transport == "iframe")
  1280.  
  1281.   AjaxTCR.comm._sendIframe(request);
  1282.  
  1283.   else if (request.transport == "script")
  1284.  
  1285.   AjaxTCR.comm._sendScript(request);
  1286.  
  1287.   else if (request.transport == "image")
  1288.  
  1289.   AjaxTCR.comm._sendImage(request);
  1290.  
  1291.  
  1292.  
  1293.  },
  1294.  
  1295.  
  1296.  
  1297.  /**
  1298.  
  1299.   * Private method that sends an XHR request. It creates the XHR, fallsback if any problems are encountered, sets appropriate headers,
  1300.  
  1301.   * and sends the requesst.
  1302.  
  1303.   *
  1304.  
  1305.   * @private
  1306.  
  1307.   * @param {Object} request The request that contains the options that we wish to send.
  1308.  
  1309.   *
  1310.  
  1311.   */
  1312.  
  1313.  
  1314.  
  1315.  _sendXHR : function(request){
  1316.  
  1317.  
  1318.  
  1319.   request.xhr = AjaxTCR.comm._createXHR();
  1320.  
  1321.   if (!request.xhr)
  1322.  
  1323.   {
  1324.  
  1325.   AjaxTCR.comm._fallbackOrError(request);
  1326.  
  1327.   return;
  1328.  
  1329.   }
  1330.  
  1331.  
  1332.  
  1333.   /* open the request */
  1334.  
  1335.   try{
  1336.  
  1337.   request.xhr.open(request.method, request.url, request.async, request.username, request.password);
  1338.  
  1339.   }
  1340.  
  1341.   catch(e){
  1342.  
  1343.   AjaxTCR.comm._fallbackOrError(request);
  1344.  
  1345.   return;
  1346.  
  1347.   }
  1348.  
  1349.  
  1350.  
  1351.   /* clear an abort flag in case this is a retry */
  1352.  
  1353.   request.abort = false;
  1354.  
  1355.  
  1356.  
  1357.   /* set headers indicating we did this with Ajax and what our transaction id is */
  1358.  
  1359.   if (request.transportIndicator)
  1360.  
  1361.   {
  1362.  
  1363.   request.xhr.setRequestHeader(AjaxTCR.comm.DEFAULT_TRANSPORT_HEADER,AjaxTCR.comm.DEFAULT_XHR_TRANSPORT_VALUE);
  1364.  
  1365.   request.xhr.setRequestHeader("X-Request-Id",request.requestID);
  1366.  
  1367.   }
  1368.  
  1369.  
  1370.  
  1371.   /* Set signature header */
  1372.  
  1373.   if (request.signRequest)
  1374.  
  1375.   request.xhr.setRequestHeader(request.requestSignature, request.signRequest);
  1376.  
  1377.  
  1378.  
  1379.   /* set header(s) for POST */
  1380.  
  1381.   if (request.method.toUpperCase() == "POST")
  1382.  
  1383.   {
  1384.  
  1385.   request.xhr.setRequestHeader("Content-Type", request.requestContentType);
  1386.  
  1387.   if (request.requestContentTransferEncoding != "")
  1388.  
  1389.   request.xhr.setRequestHeader("Content-Transfer-Encoding", request.requestContentTransferEncoding);
  1390.  
  1391.   }
  1392.  
  1393.  
  1394.  
  1395.   /* Prevent Caching if set */
  1396.  
  1397.   if (request.preventCache)
  1398.  
  1399.   request.xhr.setRequestHeader("If-Modified-Since", "Wed, 15 Nov 1995 04:58:08 GMT");
  1400.  
  1401.  
  1402.  
  1403.   /* set user defined headers */
  1404.  
  1405.   request.headerObj = {};
  1406.  
  1407.   for (var i=0; i<request.headers.length;i++)
  1408.  
  1409.   {
  1410.  
  1411.   if (request.headers[i].name.toUpperCase() == "COOKIE")
  1412.  
  1413.   document.cookie = request.headers[i].value;
  1414.  
  1415.   else if(request.headerObj[request.headers[i].name] === undefined)
  1416.  
  1417.   request.headerObj[request.headers[i].name] = request.headers[i].value;
  1418.  
  1419.   else
  1420.  
  1421.   request.headerObj[request.headers[i].name] = request.headers[i].value + "," + request.headerObj[request.headers[i].name];
  1422.  
  1423.   }
  1424.  
  1425.  
  1426.  
  1427.   for (var header in request.headerObj)
  1428.  
  1429.   request.xhr.setRequestHeader(header, request.headerObj[header]);
  1430.  
  1431.  
  1432.  
  1433.  
  1434.  
  1435.   if (!request.oneway)
  1436.  
  1437.   {
  1438.  
  1439.   /* bind the success callback */
  1440.  
  1441.   request.xhr.onreadystatechange = function () {AjaxTCR.comm._handleReadyStateChange(request);};
  1442.  
  1443.  
  1444.  
  1445.   /* set a timeout if set */
  1446.  
  1447.   if (request.async && request.timeout && request.timeoutTimerID == null)
  1448.  
  1449.   request.timeoutTimerID = window.setTimeout( function(){AjaxTCR.comm._timeoutRequest(request);}, request.timeout);
  1450.  
  1451.  
  1452.  
  1453.   }
  1454.  
  1455.  
  1456.  
  1457.   /* send the request */
  1458.  
  1459.   request.xhr.send(request.postBody);
  1460.  
  1461.  },
  1462.  
  1463.  
  1464.  
  1465.  /**
  1466.  
  1467.   * Private method that creates a request using the script transport. Updates the payload to pass the transport method, creates a script element,
  1468.  
  1469.   * sends the request by adding the element to the page.
  1470.  
  1471.   *
  1472.  
  1473.   * @private
  1474.  
  1475.   * @param {Object} request The request object that is being sent.
  1476.  
  1477.   */
  1478.  
  1479.  _sendScript : function(request){
  1480.  
  1481.   var script = document.createElement('script');
  1482.  
  1483.   var callback = function(){AjaxTCR.comm._handleScriptResponse(request);};
  1484.  
  1485.  
  1486.  
  1487.   if (request.transportIndicator)
  1488.  
  1489.   {
  1490.  
  1491.   if (request.url.indexOf("?"))
  1492.  
  1493.   request.url += "&" + AjaxTCR.comm.DEFAULT_TRANSPORT_HEADER + "=" + AjaxTCR.comm.DEFAULT_SCRIPT_TRANSPORT_VALUE;
  1494.  
  1495.   else
  1496.  
  1497.   request.url += "?" + AjaxTCR.comm.DEFAULT_TRANSPORT_HEADER + "=" + AjaxTCR.comm.DEFAULT_SCRIPT_TRANSPORT_VALUE;
  1498.  
  1499.   }
  1500.  
  1501.  
  1502.  
  1503.   if (script.addEventListener)
  1504.  
  1505.   script.addEventListener("load", callback, false);
  1506.  
  1507.   else
  1508.  
  1509.   {
  1510.  
  1511.   script.onreadystatechange = function()
  1512.  
  1513.   {
  1514.  
  1515.   if (this.readyState == "complete")
  1516.  
  1517.   callback.call(this);
  1518.  
  1519.   };
  1520.  
  1521.   }
  1522.  
  1523.  
  1524.  
  1525.   script.src = request.url;
  1526.  
  1527.   script.type = "text/javascript";
  1528.  
  1529.   document.body.appendChild(script);
  1530.  
  1531.  },
  1532.  
  1533.  
  1534.  
  1535.  
  1536.  
  1537.  /**
  1538.  
  1539.   * Private method that creates a request using the iframe transport.
  1540.  
  1541.   * Updates the payload to pass the transport method, creates the iframe element.
  1542.  
  1543.   * Keeps the height at 1px and visiblity hidden.
  1544.  
  1545.   * Sets the callback and attaches it to the load events of the iframe
  1546.  
  1547.   * Simply sets the src for a GET and builds a form to submit for a POST
  1548.  
  1549.   *
  1550.  
  1551.   * @private
  1552.  
  1553.   * @param {Object} request The request object that is being sent.
  1554.  
  1555.   */
  1556.  
  1557.  _sendIframe : function(request){
  1558.  
  1559.   var iframeID = AjaxTCR.util.misc.generateUID("AjaxTCRIframe_");
  1560.  
  1561.  
  1562.  
  1563.   /* IE does not handle document.createElement("iframe"); */
  1564.  
  1565.   if(window.ActiveXObject)
  1566.  
  1567.   var iframe = document.createElement('<iframe id="' + iframeID + '" name="' + iframeID + '" />');
  1568.  
  1569.   else
  1570.  
  1571.   {
  1572.  
  1573.   var iframe = document.createElement("iframe");
  1574.  
  1575.   iframe.id = iframeID;
  1576.  
  1577.   iframe.name = iframeID;
  1578.  
  1579.   }
  1580.  
  1581.  
  1582.  
  1583.   iframe.style.height = "1px";
  1584.  
  1585.   iframe.style.visibility = "hidden";
  1586.  
  1587.  
  1588.  
  1589.   document.body.appendChild(iframe);
  1590.  
  1591.  
  1592.  
  1593.   var callback = function(){AjaxTCR.comm._handleIFrameResponse(request, iframe);};
  1594.  
  1595.  
  1596.  
  1597.   /* IE does not recognize iframe.onload */
  1598.  
  1599.   if(window.attachEvent)
  1600.  
  1601.   iframe.attachEvent('onload', callback);
  1602.  
  1603.   else
  1604.  
  1605.   iframe.addEventListener('load', callback, false);
  1606.  
  1607.  
  1608.  
  1609.  
  1610.  
  1611.   if (request.hasFile)
  1612.  
  1613.   {
  1614.  
  1615.   request.serializeForm.target = iframe.id;
  1616.  
  1617.   request.serializeForm.submit();
  1618.  
  1619.   }
  1620.  
  1621.   else if (request.method.toUpperCase() == "GET")
  1622.  
  1623.   {
  1624.  
  1625.   if (request.transportIndicator)
  1626.  
  1627.   {
  1628.  
  1629.   if (request.url.indexOf("?") > -1)
  1630.  
  1631.   request.url += "&" + AjaxTCR.comm.DEFAULT_TRANSPORT_HEADER + "=" + AjaxTCR.comm.DEFAULT_IFRAME_TRANSPORT_VALUE;
  1632.  
  1633.   else
  1634.  
  1635.   request.url += "?" + AjaxTCR.comm.DEFAULT_TRANSPORT_HEADER + "=" + AjaxTCR.comm.DEFAULT_IFRAME_TRANSPORT_VALUE;
  1636.  
  1637.   }
  1638.  
  1639.  
  1640.  
  1641.   iframe.src = request.url;
  1642.  
  1643.   }
  1644.  
  1645.   else
  1646.  
  1647.   {
  1648.  
  1649.   var ifrForm = makeIframeForm(iframe, request);
  1650.  
  1651.   ifrForm.submit();
  1652.  
  1653.   }
  1654.  
  1655.  
  1656.  
  1657.  
  1658.  
  1659.   function makeIframeForm(ifr, request)
  1660.  
  1661.   {
  1662.  
  1663.   var url = request.url;
  1664.  
  1665.   var payload = request.postBody;
  1666.  
  1667.  
  1668.  
  1669.   var ifrDoc = null;
  1670.  
  1671.   var ifrWindow = ifr.contentWindow || ifr.contentDocument;
  1672.  
  1673.   if (ifrWindow.document)
  1674.  
  1675.   ifrDoc = ifrWindow.document;
  1676.  
  1677.   else
  1678.  
  1679.   ifrDoc = ifrWindow;
  1680.  
  1681.  
  1682.  
  1683.   if (!ifrDoc.body)
  1684.  
  1685.   {
  1686.  
  1687.   var html = ifrDoc.createElement("HTML");
  1688.  
  1689.   ifrDoc.appendChild(html);
  1690.  
  1691.  
  1692.  
  1693.   var head = ifrDoc.createElement("HEAD");
  1694.  
  1695.   html.appendChild(head);
  1696.  
  1697.  
  1698.  
  1699.   var body = ifrDoc.createElement("BODY");
  1700.  
  1701.   html.appendChild(body);
  1702.  
  1703.   }
  1704.  
  1705.  
  1706.  
  1707.   var ifrForm = ifrDoc.createElement("FORM");
  1708.  
  1709.   ifrForm.action = url;
  1710.  
  1711.   ifrForm.method = "post";
  1712.  
  1713.   ifrDoc.body.appendChild(ifrForm);
  1714.  
  1715.   var keys = payload.split("&");
  1716.  
  1717.  
  1718.  
  1719.   for (var i=0;i<keys.length;i++)
  1720.  
  1721.   {
  1722.  
  1723.   var nv = keys[i].split("=");
  1724.  
  1725.   var ifrText = ifrDoc.createElement("INPUT");
  1726.  
  1727.   ifrText.type = "text";
  1728.  
  1729.   ifrText.name = nv[0];
  1730.  
  1731.   ifrText.value = nv[1];
  1732.  
  1733.   ifrForm.appendChild(ifrText);
  1734.  
  1735.   }
  1736.  
  1737.  
  1738.  
  1739.   if (request.transportIndicator)
  1740.  
  1741.   {
  1742.  
  1743.   var ifrText = ifrDoc.createElement("INPUT");
  1744.  
  1745.   ifrText.type = "text";
  1746.  
  1747.   ifrText.name = AjaxTCR.comm.DEFAULT_TRANSPORT_HEADER;
  1748.  
  1749.   ifrText.value = AjaxTCR.comm.DEFAULT_IFRAME_TRANSPORT_VALUE;
  1750.  
  1751.   ifrForm.appendChild(ifrText);
  1752.  
  1753.   }
  1754.  
  1755.  
  1756.  
  1757.   return ifrForm;
  1758.  
  1759.  
  1760.  
  1761.   }
  1762.  
  1763.  },
  1764.  
  1765.  
  1766.  
  1767.  
  1768.  
  1769.  
  1770.  
  1771.  /**
  1772.  
  1773.   * Private method that creates a request using the image/cookie transport.
  1774.  
  1775.   * Updates the payload to pass the transport method, creates an image element and sets the onload callback and the src to the URL.
  1776.  
  1777.   *
  1778.  
  1779.   * @private
  1780.  
  1781.   * @param {Object} request The request object that is being sent.
  1782.  
  1783.   */
  1784.  
  1785.  _sendImage : function(request){
  1786.  
  1787.   var callback = function(){AjaxTCR.comm._handleImageResponse(request);};
  1788.  
  1789.  
  1790.  
  1791.   if (request.transportIndicator)
  1792.  
  1793.   {
  1794.  
  1795.   if (request.url.indexOf("?"))
  1796.  
  1797.   request.url += "&" + AjaxTCR.comm.DEFAULT_TRANSPORT_HEADER + "=" + AjaxTCR.comm.DEFAULT_IMAGE_TRANSPORT_VALUE;
  1798.  
  1799.   else
  1800.  
  1801.   request.url += "?" + AjaxTCR.comm.DEFAULT_TRANSPORT_HEADER + "=" + AjaxTCR.comm.DEFAULT_IMAGE_TRANSPORT_VALUE;
  1802.  
  1803.   }
  1804.  
  1805.  
  1806.  
  1807.   var img = new Image();
  1808.  
  1809.   img.onload = callback;
  1810.  
  1811.   img.src = request.url;
  1812.  
  1813.  },
  1814.  
  1815.  
  1816.  
  1817.   /**
  1818.  
  1819.   * Private method called to init items that should be initialized no matter what communication technique is used.
  1820.  
  1821.   * Creates the statusIndicator and the progress timeout if they are used, updates startTime, requestOutstanding, and timespent.
  1822.  
  1823.   *
  1824.  
  1825.   * @private
  1826.  
  1827.   * @param {Object} request The request object that contains the options to update.
  1828.  
  1829.   */
  1830.  
  1831.  
  1832.  
  1833.   _initSend : function(request){
  1834.  
  1835.   /* Set Progress Indicators */
  1836.  
  1837.   if (request.statusIndicator)
  1838.  
  1839.   request.statusIndicator.element = AjaxTCR.comm._setProgressStatus(request.statusIndicator);
  1840.  
  1841.  
  1842.  
  1843.   /* set the time spent in case this is a retry */
  1844.  
  1845.   request.timespent = 0;
  1846.  
  1847.  
  1848.  
  1849.   /* set progress indicator to show something nearly every second */
  1850.  
  1851.   if (request.showProgress && request.progressTimerID == null)
  1852.  
  1853.   request.progressTimerID = window.setTimeout( function(){AjaxTCR.comm._progressRequest(request);}, request.progressInterval);
  1854.  
  1855.  
  1856.  
  1857.   /* Record start time of request */
  1858.  
  1859.   request.startTime = (new Date()).getTime();
  1860.  
  1861.  
  1862.  
  1863.   /* increment requests outstanding */
  1864.  
  1865.   AjaxTCR.comm._requestsOutstanding++;
  1866.  
  1867.  
  1868.  
  1869.  },
  1870.  
  1871.  
  1872.  
  1873.  /**
  1874.  
  1875.   * fallbackOrError : If an XHR does not work, tries to send request using fallbackTransport
  1876.  
  1877.   * If transport is changed to script or image, ensures that the method is set to GET.
  1878.  
  1879.   *
  1880.  
  1881.   * @private
  1882.  
  1883.   * @param request
  1884.  
  1885.   */
  1886.  
  1887.   _fallbackOrError : function(request){
  1888.  
  1889.   if (request.fallback)
  1890.  
  1891.   {
  1892.  
  1893.   request.transport = request.fallbackTransport.toLowerCase();
  1894.  
  1895.   if ((request.transport == "script" || request.transport == "image") && request.method.toUpperCase() == "POST")
  1896.  
  1897.   {
  1898.  
  1899.   request.method = "GET";
  1900.  
  1901.   request.url = request.url + "?" + request.postBody;
  1902.  
  1903.   request.postBody = null;
  1904.  
  1905.   }
  1906.  
  1907.   if (request.transport == "iframe")
  1908.  
  1909.   AjaxTCR.comm._sendIframe(request);
  1910.  
  1911.   else if (request.transport == "script")
  1912.  
  1913.   AjaxTCR.comm._sendScript(request);
  1914.  
  1915.   else if (request.transport == "image")
  1916.  
  1917.   AjaxTCR.comm._sendImage(request);
  1918.  
  1919.   else
  1920.  
  1921.   throw "AjaxTCR Error: Unknown fallback transport: " + request.transport;
  1922.  
  1923.   }
  1924.  
  1925.   else
  1926.  
  1927.   throw "AjaxTCR Error: XHR Creation failed and fallback is not enabled";
  1928.  
  1929.  },
  1930.  
  1931.  
  1932.  
  1933.  /**
  1934.  
  1935.   * Automatically called when the iframe completes loading.
  1936.  
  1937.   * Updates httpStatus and httpStatusText and sets responseText and responseXML to contents of the body.
  1938.  
  1939.   * Calls general _handleResponse function on completion.
  1940.  
  1941.   *
  1942.  
  1943.   * @private
  1944.  
  1945.   * @param {Object} response The response Object that contains all the settings for the request
  1946.  
  1947.   * @param {Object} iframe The iframe that was created in _sendIframe.
  1948.  
  1949.   */
  1950.  
  1951.  _handleIFrameResponse : function(response, iframe){
  1952.  
  1953.   response.httpStatus = 200;
  1954.  
  1955.   response.httpStatusText = "OK";
  1956.  
  1957.   if (iframe.contentWindow.document.body)
  1958.  
  1959.   response.responseText = iframe.contentWindow.document.body.innerHTML;
  1960.  
  1961.  
  1962.  
  1963.   if (iframe.contentWindow.document.XMLDocument)
  1964.  
  1965.   response.responseXML = iframe.contentWindow.document.XMLDocument;
  1966.  
  1967.   else
  1968.  
  1969.   response.responseXML = iframe.contentWindow.document;
  1970.  
  1971.  
  1972.  
  1973.   AjaxTCR.comm._handleResponse(response);
  1974.  
  1975.  },
  1976.  
  1977.  
  1978.  
  1979.  /**
  1980.  
  1981.   * Automatically called when the script completes loading.
  1982.  
  1983.   * Updates httpStatus and httpStatusText
  1984.  
  1985.   * Sets responseText to "" and responseXML to null as the contents will already have been evaluated.
  1986.  
  1987.   * Calls general _handleResponse function on completion.
  1988.  
  1989.   *
  1990.  
  1991.   * @private
  1992.  
  1993.   * @param {Object} response The response Object that contains all the settings for the request
  1994.  
  1995.   */
  1996.  
  1997.  _handleScriptResponse : function(response){
  1998.  
  1999.   response.httpStatus = 200;
  2000.  
  2001.   response.httpStatusText = "OK";
  2002.  
  2003.   response.responseText = "";
  2004.  
  2005.   response.responseXML = null;
  2006.  
  2007.   AjaxTCR.comm._handleResponse(response);
  2008.  
  2009.  },
  2010.  
  2011.  
  2012.  
  2013.  /**
  2014.  
  2015.   * Automatically called when the image completes loading.
  2016.  
  2017.   * Updates httpStatus and httpStatusText
  2018.  
  2019.   * Checks if the response.cookieName is set. If so, looks it up and sets responseText to the value.
  2020.  
  2021.   * Sets responseXML to null
  2022.  
  2023.   * Calls general _handleResponse function on completion.
  2024.  
  2025.   *
  2026.  
  2027.   * @private
  2028.  
  2029.   * @param {Object} response The response Object that contains all the settings for the request
  2030.  
  2031.   */
  2032.  
  2033.  _handleImageResponse : function(response){
  2034.  
  2035.   response.httpStatus = 200;
  2036.  
  2037.   response.httpStatusText = "OK";
  2038.  
  2039.   if (response.cookieName)
  2040.  
  2041.   response.responseText = AjaxTCR.comm.cookie.get(response.cookieName);
  2042.  
  2043.   else
  2044.  
  2045.   response.responseText = document.cookie;
  2046.  
  2047.   response.responseXML = null;
  2048.  
  2049.   AjaxTCR.comm._handleResponse(response);
  2050.  
  2051.  },
  2052.  
  2053.  
  2054.  
  2055.   /**
  2056.  
  2057.   * Private method called if timeout period occurs without the response returning
  2058.  
  2059.   * calls abortRequest method to abort the requesst and clean up timers
  2060.  
  2061.   * invokes any special timeout callback that may be defined.
  2062.  
  2063.   * Checks to see if we need to retry.
  2064.  
  2065.   *
  2066.  
  2067.   * @private
  2068.  
  2069.   * @param {object} request The object that contains all the settings for the request
  2070.  
  2071.   */
  2072.  
  2073.   _timeoutRequest : function(request) {
  2074.  
  2075.   /* make sure it is a proper time to abort */
  2076.  
  2077.   if (request.xhr.readyState != AjaxTCR.comm.DONE && request.xhr.readyState != AjaxTCR.comm.UNSENT)
  2078.  
  2079.   {
  2080.  
  2081.   /* abort the request */
  2082.  
  2083.   AjaxTCR.comm.abortRequest(request);
  2084.  
  2085.  
  2086.  
  2087.   /* Increment total timeouts */
  2088.  
  2089.   AjaxTCR.comm.stats._commResults.totalTimeouts++;
  2090.  
  2091.  
  2092.  
  2093.   /* do we need to retry? */
  2094.  
  2095.   if (request.retries)
  2096.  
  2097.   AjaxTCR.comm._retryRequest(request);
  2098.  
  2099.   else
  2100.  
  2101.   {
  2102.  
  2103.   request.onTimeout(request); /* invoke any timeout callback */
  2104.  
  2105.   AjaxTCR.comm.queue._checkRequestQueue(request);
  2106.  
  2107.   }
  2108.  
  2109.   }
  2110.  
  2111.   },
  2112.  
  2113.  
  2114.  
  2115.  /**
  2116.  
  2117.   * Private method called every request.progressInterval (default = 1 second) if showProgress is set.
  2118.  
  2119.   * Updates public timespent variable and invokes any special progress
  2120.  
  2121.   * callback that may be defined. Resets the timer.
  2122.  
  2123.   *
  2124.  
  2125.   * @private
  2126.  
  2127.   * @param {object} request The object that contains all the settings for the request
  2128.  
  2129.   */
  2130.  
  2131.  _progressRequest: function(request){
  2132.  
  2133.   if (!request.abort && !request.received)
  2134.  
  2135.   {
  2136.  
  2137.   request.timespent = Math.round((request.timespent + (parseInt(request.progressInterval) / 1000)) * 1000) / 1000;
  2138.  
  2139.   request.onProgress(request);
  2140.  
  2141.   /* Yes it is ridiculous that we have to clear the timeout that we are in a callback for, but such is IE */
  2142.  
  2143.   clearTimeout(request.progressTimerID);
  2144.  
  2145.   request.progressTimerID = null;
  2146.  
  2147.   request.progressTimerID = window.setTimeout( function(){AjaxTCR.comm._progressRequest(request);}, request.progressInterval);
  2148.  
  2149.   }
  2150.  
  2151.   },
  2152.  
  2153.  
  2154.  
  2155.  /**
  2156.  
  2157.   * Updates retry count. Checks to see if we should do another retry.
  2158.  
  2159.   * If so, sends off the request and then calls the onRetry callback function.
  2160.  
  2161.   * If not, calls the onTimeout callback function and sends the next requesst if applicable.
  2162.  
  2163.   *
  2164.  
  2165.   * @private
  2166.  
  2167.   * @param {Object} request The object that contains all the settings for the request
  2168.  
  2169.   */
  2170.  
  2171.  _retryRequest : function (request) {
  2172.  
  2173.   /* up our retry count */
  2174.  
  2175.   request.retryCount++;
  2176.  
  2177.  
  2178.  
  2179.   /* make sure we aren't done retrying */
  2180.  
  2181.   if (request.retryCount <= request.retries)
  2182.  
  2183.   {
  2184.  
  2185.   /* Increment total retries */
  2186.  
  2187.   AjaxTCR.comm.stats._commResults.totalRetries++;
  2188.  
  2189.   AjaxTCR.comm._makeRequest(request);
  2190.  
  2191.   request.onRetry(request);
  2192.  
  2193.   }
  2194.  
  2195.   else /* stop trying and perform callback */
  2196.  
  2197.   {
  2198.  
  2199.   request.onTimeout(request);
  2200.  
  2201.   AjaxTCR.comm.queue._checkRequestQueue(request);
  2202.  
  2203.   }
  2204.  
  2205.   },
  2206.  
  2207.  
  2208.  
  2209.  
  2210.  
  2211.  
  2212.  
  2213.  /**
  2214.  
  2215.   * Private method called after response comes back no matter what method of communication
  2216.  
  2217.   * Updates endTime, totalTime, received, requestsOutstanding. Clears any timers.
  2218.  
  2219.   * Caches, adds to history, clears status indicators, queues if applicable
  2220.  
  2221.   *
  2222.  
  2223.   * @private
  2224.  
  2225.   * @param {object} response The object that contains all the settings for the request
  2226.  
  2227.   */
  2228.  
  2229.  _handleResponse : function(response){
  2230.  
  2231.   /* Record end time of request */
  2232.  
  2233.   response.endTime = (new Date()).getTime();
  2234.  
  2235.   response.totalTime = (response.endTime - response.startTime);
  2236.  
  2237.  
  2238.  
  2239.   /* set a received flag to ensure you don't perform a progress callback after received. */
  2240.  
  2241.   response.received = true;
  2242.  
  2243.  
  2244.  
  2245.   /* clear any timeouts */
  2246.  
  2247.   if (response.timeoutTimerID)
  2248.  
  2249.   {
  2250.  
  2251.   clearTimeout(response.timeoutTimerID);
  2252.  
  2253.   response.timeoutTimerID = null;
  2254.  
  2255.   }
  2256.  
  2257.  
  2258.  
  2259.   /* clear our progress indicator */
  2260.  
  2261.   if (response.progressTimerID)
  2262.  
  2263.   {
  2264.  
  2265.   clearTimeout(response.progressTimerID);
  2266.  
  2267.   response.progressTimerID = null;
  2268.  
  2269.   }
  2270.  
  2271.  
  2272.  
  2273.   /* decrement outstand request count */
  2274.  
  2275.   AjaxTCR.comm._requestsOutstanding--;
  2276.  
  2277.  
  2278.  
  2279.   /* Cache Response */
  2280.  
  2281.   if (!response.fromCache && response.cacheResponse && response.httpStatus == 200 && !response.fail)
  2282.  
  2283.   AjaxTCR.comm.cache.add(response.cacheKey, response.responseText);
  2284.  
  2285.  
  2286.  
  2287.   /* Cache Template */
  2288.  
  2289.   if (response.shortTermCacheTemplate && response.httpStatus == 200 && !response.fail)
  2290.  
  2291.   AjaxTCR.template.addToCache(response.url, response.responseText);
  2292.  
  2293.  
  2294.  
  2295.   if (response.history && response.history.saveResponse)
  2296.  
  2297.   AjaxTCR.history.addToHistory(response.history.id, "", response.history.title, "", response);
  2298.  
  2299.  
  2300.  
  2301.   /* Remove Progress Indicators */
  2302.  
  2303.   if (response.statusIndicator)
  2304.  
  2305.   AjaxTCR.comm._removeProgressStatus(response.statusIndicator);
  2306.  
  2307.  
  2308.  
  2309.   /* Check to see if we need to wait for another request */
  2310.  
  2311.   /* Otherwise just handle callbacks */
  2312.  
  2313.   if (response.enforceOrder)
  2314.  
  2315.   AjaxTCR.comm.queue._handleQueue(response);
  2316.  
  2317.   else
  2318.  
  2319.   AjaxTCR.comm._handleCallbacks(response);
  2320.  
  2321.  
  2322.  
  2323.   /* If Request Queue is being used, send next request */
  2324.  
  2325.   AjaxTCR.comm.queue._checkRequestQueue(response);
  2326.  
  2327.   },
  2328.  
  2329.  /**
  2330.  
  2331.   * Private method called after response comes in to run numerous callbacks.
  2332.  
  2333.   * Checks http and response status to see which callbacks should be employed.
  2334.  
  2335.   * Handles template situations as well as direct consumption with outputTarget
  2336.  
  2337.   * Communication is complete at the end of this call and the response object is nulled out.
  2338.  
  2339.   *
  2340.  
  2341.   * @private
  2342.  
  2343.   * @param {object} response The object that contains all the settings for the request
  2344.  
  2345.   */
  2346.  
  2347.  _handleCallbacks : function(response) {
  2348.  
  2349.  
  2350.  
  2351.   /* clear inProgress flag */
  2352.  
  2353.   response.inProgress = false;
  2354.  
  2355.  
  2356.  
  2357.   /* Calculate Template Data if necessary */
  2358.  
  2359.   if (response.template && response.templateRender == "client")
  2360.  
  2361.   {
  2362.  
  2363.   var template = null;
  2364.  
  2365.   if (response.template != AjaxTCR.comm.TEMPLATE_SERVER_DEFINED)
  2366.  
  2367.   {
  2368.  
  2369.   template = AjaxTCR.template.getFromCache(response.template);
  2370.  
  2371.   if (!(response.cacheTemplate))
  2372.  
  2373.   AjaxTCR.template.removeFromCache(response.template);
  2374.  
  2375.   }
  2376.  
  2377.   else
  2378.  
  2379.   {
  2380.  
  2381.   var returnedObject = AjaxTCR.data.decodeJSON(response.responseText);
  2382.  
  2383.   if (returnedObject.templateURL && returnedObject.templateText)
  2384.  
  2385.   {
  2386.  
  2387.   template = returnedObject.templateText;
  2388.  
  2389.   if (response.cacheTemplate)
  2390.  
  2391.   AjaxTCR.template.addToCache(returnedObject.templateURL, returnedObject.templateText);
  2392.  
  2393.   }
  2394.  
  2395.   else if (returnedObject.templateText)
  2396.  
  2397.   template = returnedObject.templateText;
  2398.  
  2399.   else if (returnedObject.templateURL)
  2400.  
  2401.   {
  2402.  
  2403.   var template = AjaxTCR.template.getFromCache(returnedObject.templateURL);
  2404.  
  2405.   if (!template)
  2406.  
  2407.   {
  2408.  
  2409.   var templateRequest = AjaxTCR.comm.sendRequest(returnedObject.templateURL, {async:false});
  2410.  
  2411.   var template = templateRequest.responseText;
  2412.  
  2413.   if (response.cacheTemplate && template)
  2414.  
  2415.   AjaxTCR.template.addToCache(returnedObject.templateURL, template);
  2416.  
  2417.   }
  2418.  
  2419.   }
  2420.  
  2421.   }
  2422.  
  2423.  
  2424.  
  2425.   if (template)
  2426.  
  2427.   {
  2428.  
  2429.   try{
  2430.  
  2431.   var translatedResponse = AjaxTCR.template.translateString(template, response.responseText);
  2432.  
  2433.   if (translatedResponse)
  2434.  
  2435.   {
  2436.  
  2437.   response.rawResponseText = response.responseText;
  2438.  
  2439.   response.responseText = translatedResponse;
  2440.  
  2441.   }
  2442.  
  2443.   }
  2444.  
  2445.   catch(e){}
  2446.  
  2447.   }
  2448.  
  2449.   }
  2450.  
  2451.  
  2452.  
  2453.   /* Check if user wants to automatically consume output */
  2454.  
  2455.   if (response.outputTarget && response.useRaw && (response.transport == "xhr" || response.transport == "iframe"))
  2456.  
  2457.   {
  2458.  
  2459.   var outputTarget = response.outputTarget;
  2460.  
  2461.   if (outputTarget && typeof(outputTarget) == "string")
  2462.  
  2463.   outputTarget = document.getElementById(outputTarget);
  2464.  
  2465.  
  2466.  
  2467.   if (response.fail)
  2468.  
  2469.   outputTarget.innerHTML = response.fail;
  2470.  
  2471.   else
  2472.  
  2473.   {
  2474.  
  2475.   var span = document.createElement("span");
  2476.  
  2477.   span.innerHTML = response.responseText;
  2478.  
  2479.   var newParent = span;
  2480.  
  2481.  
  2482.  
  2483.   switch(response.insertionType.toLowerCase())
  2484.  
  2485.   {
  2486.  
  2487.   case("insertbefore"):
  2488.  
  2489.   var parent = outputTarget.parentNode;
  2490.  
  2491.   parent.insertBefore(span, outputTarget);
  2492.  
  2493.   break;
  2494.  
  2495.   case("insertafter"):
  2496.  
  2497.   var parent = outputTarget.parentNode;
  2498.  
  2499.   AjaxTCR.util.DOM.insertAfter(parent, span, outputTarget);
  2500.  
  2501.   break;
  2502.  
  2503.   case("firstchild"):
  2504.  
  2505.   var elm = outputTarget.firstChild;
  2506.  
  2507.   while (elm != null && elm.nodeType != 1)
  2508.  
  2509.   elm = elm.nextSibling;
  2510.  
  2511.  
  2512.  
  2513.   if (elm != null)
  2514.  
  2515.   outputTarget.insertBefore(span, elm);
  2516.  
  2517.   else
  2518.  
  2519.   outputTarget.appendChild(span);
  2520.  
  2521.   break;
  2522.  
  2523.   case("lastchild"):
  2524.  
  2525.   outputTarget.appendChild(span);
  2526.  
  2527.   break;
  2528.  
  2529.   default:
  2530.  
  2531.   outputTarget.innerHTML = response.responseText;
  2532.  
  2533.   newParent = outputTarget;
  2534.  
  2535.  
  2536.  
  2537.   break;
  2538.  
  2539.  
  2540.  
  2541.   }
  2542.  
  2543.   }
  2544.  
  2545.   }
  2546.  
  2547.  
  2548.  
  2549.  
  2550.  
  2551.   /* check to see if the user wants a specific callback for this request */
  2552.  
  2553.   if (response["on" + response.httpStatus] && !response.fail)
  2554.  
  2555.   response["on" + response.httpStatus](response);
  2556.  
  2557.  
  2558.  
  2559.   /* see if it is one of our retry statuses */
  2560.  
  2561.   if (response.retries)
  2562.  
  2563.   {
  2564.  
  2565.   for (var i=0;i<AjaxTCR.comm._networkErrorStatus.length;i++)
  2566.  
  2567.   {
  2568.  
  2569.   if (response.httpStatus == AjaxTCR.comm._networkErrorStatus[i])
  2570.  
  2571.   {
  2572.  
  2573.   AjaxTCR.comm._retryRequest(response);
  2574.  
  2575.   return;
  2576.  
  2577.   }
  2578.  
  2579.   }
  2580.  
  2581.   }
  2582.  
  2583.  
  2584.  
  2585.   /* call either success or fail callback */
  2586.  
  2587.   if (response.httpStatus == 200)
  2588.  
  2589.   {
  2590.  
  2591.   /*if they specified expected content type, we check for that.*/
  2592.  
  2593.   if (response.fail)
  2594.  
  2595.   AjaxTCR.comm._handleFail(response, response.fail);
  2596.  
  2597.   else if (response.responseContentType && response.transport == "xhr")
  2598.  
  2599.   {
  2600.  
  2601.   var responseContentType = response.xhr.getResponseHeader("Content-Type");
  2602.  
  2603.   responseContentType = responseContentType.substring(0, responseContentType.indexOf(";"));
  2604.  
  2605.   if (responseContentType != response.responseContentType)
  2606.  
  2607.   AjaxTCR.comm._handleFail(response, "Wrong Content-Type: " + responseContentType );
  2608.  
  2609.   else if (response.responseContentType == "text/xml" && (response.responseXML == null || response.responseXML.childNodes.length == 0 || response.responseXML.childNodes[0].nodeName == "parsererror"))
  2610.  
  2611.   AjaxTCR.comm._handleFail(response, "Invalid XML Data");
  2612.  
  2613.   else
  2614.  
  2615.   AjaxTCR.comm._handleSuccess(response);
  2616.  
  2617.   }
  2618.  
  2619.   else
  2620.  
  2621.   AjaxTCR.comm._handleSuccess(response);
  2622.  
  2623.   }
  2624.  
  2625.   else
  2626.  
  2627.   AjaxTCR.comm._handleFail(response, response.httpStatus + " " + response.httpStatusText);
  2628.  
  2629.  
  2630.  
  2631.  
  2632.  
  2633.  
  2634.  
  2635.  
  2636.  
  2637.   /* clear out the response */
  2638.  
  2639.   response = null;
  2640.  
  2641.   },
  2642.  
  2643.  
  2644.  
  2645.   /**
  2646.  
  2647.   * Private method called upon request failure. Updates the statistics object and calls the onFail callback.
  2648.  
  2649.   *
  2650.  
  2651.   * @private
  2652.  
  2653.   * @param {object} response The object that contains all the settings for the request
  2654.  
  2655.   * @param {string} message
  2656.  
  2657.   */
  2658.  
  2659.   _handleFail : function(response, message) {
  2660.  
  2661.   /* Increment total fails */
  2662.  
  2663.   AjaxTCR.comm.stats._commResults.totalFails++;
  2664.  
  2665.   response.fail = message;
  2666.  
  2667.  
  2668.  
  2669.   /* Save fail details */
  2670.  
  2671.   var fail = {};
  2672.  
  2673.   fail.url = response.url;
  2674.  
  2675.   fail.status = response.httpStatus;
  2676.  
  2677.   fail.message = message;
  2678.  
  2679.   AjaxTCR.comm.stats._commResults.requestFails.push(fail);
  2680.  
  2681.  
  2682.  
  2683.   response.onFail(response, message);
  2684.  
  2685.  },
  2686.  
  2687.  
  2688.  
  2689.  /**
  2690.  
  2691.   * Private method to handle success responses Updates the statistics log and then calls the proper success callback.
  2692.  
  2693.   *
  2694.  
  2695.   * @private
  2696.  
  2697.   * @param {Object} response The object that contains all the settings for the request
  2698.  
  2699.   */
  2700.  
  2701.   _handleSuccess : function(response) {
  2702.  
  2703.   /* Increment total success */
  2704.  
  2705.   AjaxTCR.comm.stats._commResults.totalSuccesses++;
  2706.  
  2707.   if (response.isPrefetch)
  2708.  
  2709.   response.onPrefetch(response);
  2710.  
  2711.   else
  2712.  
  2713.   response.onSuccess(response);
  2714.  
  2715.  },
  2716.  
  2717.  
  2718.  
  2719.   /**
  2720.  
  2721.   * Private method to check for response status, clear any timeouts and invoke callbacks for given readyState.
  2722.  
  2723.   * In readyState == 4, Checks signature if response is supposed to be signed before handling any data.
  2724.  
  2725.   * Sets the httpStatus, status, responseText, and responseXML objects
  2726.  
  2727.   *
  2728.  
  2729.   * @private
  2730.  
  2731.   * @param {Object} response The object that contains all the settings for the request
  2732.  
  2733.   */
  2734.  
  2735.   _handleReadyStateChange : function(response) {
  2736.  
  2737.   /* check if abort flag is set, if so bail out */
  2738.  
  2739.   if (response.abort)
  2740.  
  2741.   return;
  2742.  
  2743.  
  2744.  
  2745.   /* Check each readyState */
  2746.  
  2747.   if (response.xhr.readyState == AjaxTCR.comm.OPEN && response.onOpen)
  2748.  
  2749.   response.onOpen(response);
  2750.  
  2751.   else if (response.xhr.readyState == AjaxTCR.comm.SENT && response.onSent)
  2752.  
  2753.   response.onSent(response);
  2754.  
  2755.   else if (response.xhr.readyState == AjaxTCR.comm.LOADING && response.onLoading)
  2756.  
  2757.   response.onLoading(response);
  2758.  
  2759.   else if (response.xhr.readyState == AjaxTCR.comm.DONE)
  2760.  
  2761.   {
  2762.  
  2763.   if (response.signedResponse)
  2764.  
  2765.   {
  2766.  
  2767.   var signature = response.xhr.getResponseHeader("Content-MD5");
  2768.  
  2769.   var verifySignature = AjaxTCR.data.encodeMD5(response.xhr.responseText);
  2770.  
  2771.   if (signature != verifySignature)
  2772.  
  2773.   response.fail = "Response Packet Compromised.";
  2774.  
  2775.   }
  2776.  
  2777.  
  2778.  
  2779.   if (response.onReceived && !response.fail)
  2780.  
  2781.   response.onReceived(response);
  2782.  
  2783.  
  2784.  
  2785.   /* Danger: Firefox problems so we try-catch here */
  2786.  
  2787.   try { response.httpStatus = response.xhr.status; response.httpStatusText = response.xhr.statusText} catch(e) {response.httpStatus=3507;response.httpStatusText="Unknown Loss";}
  2788.  
  2789.   response.responseText = response.xhr.responseText;
  2790.  
  2791.   response.responseXML = response.xhr.responseXML;
  2792.  
  2793.  
  2794.  
  2795.   AjaxTCR.comm._handleResponse(response);
  2796.  
  2797.   }
  2798.  
  2799.  },
  2800.  
  2801.  
  2802.  
  2803.  
  2804.  
  2805.  /**
  2806.  
  2807.   * Creates the status indicator for the page based on the settings passed in.
  2808.  
  2809.   *
  2810.  
  2811.   * @private
  2812.  
  2813.   * @param {object} statusIndicator the status object
  2814.  
  2815.   * @config {object} target The DOM reference of the place to put the indicator
  2816.  
  2817.   * @config {string} type Either text or image. The Type of indicator to use
  2818.  
  2819.   * @config {string} text In the case of text, this is the message to put into the indicator
  2820.  
  2821.   * @config {integer} border In the case of image, this is the border for the image
  2822.  
  2823.   * @config {string} imgSrc In the case of image, this is the src of the image to use.
  2824.  
  2825.   */
  2826.  
  2827.  _setStatus : function(statusIndicator){
  2828.  
  2829.   if (statusIndicator.target)
  2830.  
  2831.   {
  2832.  
  2833.   if (typeof(statusIndicator.target) == "string")
  2834.  
  2835.   statusIndicator.target = document.getElementById(statusIndicator.target);
  2836.  
  2837.  
  2838.  
  2839.   if (statusIndicator.type == "text")
  2840.  
  2841.   {
  2842.  
  2843.   var statusDiv = document.createElement("div");
  2844.  
  2845.   statusDiv.innerHTML = statusIndicator.text;
  2846.  
  2847.   statusIndicator.target.appendChild(statusDiv);
  2848.  
  2849.   statusIndicator.element = statusDiv;
  2850.  
  2851.   }
  2852.  
  2853.   else if (statusIndicator.type == "image")
  2854.  
  2855.   {
  2856.  
  2857.   var statusImg = document.createElement("img");
  2858.  
  2859.   statusImg.id = "progressBar";
  2860.  
  2861.   if (statusIndicator.border)
  2862.  
  2863.   statusImg.border=statusIndicator.border;
  2864.  
  2865.   statusImg.src = statusIndicator.imgSrc;
  2866.  
  2867.   statusIndicator.target.appendChild(statusImg);
  2868.  
  2869.   statusIndicator.element = statusImg;
  2870.  
  2871.   }
  2872.  
  2873.   }
  2874.  
  2875.  },
  2876.  
  2877.  
  2878.  
  2879.  /**
  2880.  
  2881.   * sets status based on the statusIndicator.progress object
  2882.  
  2883.   *
  2884.  
  2885.   * @private
  2886.  
  2887.   * @param statusIndicator - the status object
  2888.  
  2889.   */
  2890.  
  2891.  _setProgressStatus : function(statusIndicator){
  2892.  
  2893.   if (statusIndicator.progress)
  2894.  
  2895.   return AjaxTCR.comm._setStatus(statusIndicator.progress);
  2896.  
  2897.  },
  2898.  
  2899.  
  2900.  
  2901.  /**
  2902.  
  2903.   * removes the pased in status object
  2904.  
  2905.   *
  2906.  
  2907.   * @private
  2908.  
  2909.   * @param statusIndicator - the status object to remove
  2910.  
  2911.   */
  2912.  
  2913.  _removeStatus : function(statusIndicator){
  2914.  
  2915.   if (statusIndicator.element)
  2916.  
  2917.   {
  2918.  
  2919.   statusIndicator.element.parentNode.removeChild(statusIndicator.element);
  2920.  
  2921.   statusIndicator.element = null;
  2922.  
  2923.   }
  2924.  
  2925.  },
  2926.  
  2927.  
  2928.  
  2929.  /**
  2930.  
  2931.   * removes the status set by the statusIndicator.progress object
  2932.  
  2933.   *
  2934.  
  2935.   * @private
  2936.  
  2937.   * @param statusIndicator - the status object
  2938.  
  2939.   */
  2940.  
  2941.  _removeProgressStatus : function (statusIndicator){
  2942.  
  2943.   if (statusIndicator.progress)
  2944.  
  2945.   AjaxTCR.comm._removeStatus(statusIndicator.progress);
  2946.  
  2947.  }
  2948.  
  2949.  
  2950.  
  2951.  };
  2952.  
  2953.  
  2954.  
  2955.  /************************************* AjaxTCR.comm.cache *****************************/
  2956.  
  2957.  /**
  2958.  
  2959.   * The caching class of the library. Is called directly from AjaxTCR.comm, but can also be called by the user.
  2960.  
  2961.   *
  2962.  
  2963.   * @class AjaxTCR.comm.cache
  2964.  
  2965.   * @static
  2966.  
  2967.   */
  2968.  
  2969.  AjaxTCR.comm.cache = {
  2970.  
  2971.  
  2972.  
  2973.  /****************************************** Private Properties ****************************************************/
  2974.  
  2975.  
  2976.  
  2977.  /** The cache object.
  2978.  
  2979.   * @private
  2980.  
  2981.   */
  2982.  
  2983.  _cache : new Array(),
  2984.  
  2985.  
  2986.  
  2987.  /** Caching Options w/defaults set
  2988.  
  2989.   * @private
  2990.  
  2991.   */
  2992.  
  2993.  _cacheOptions : {
  2994.  
  2995.   /* The max number of items to store in the cache */
  2996.  
  2997.   size : 100,
  2998.  
  2999.   /* The default algorithm for removing items. The choices are LRU, FIFO, and LFU */
  3000.  
  3001.   algorithm: "LRU",
  3002.  
  3003.   /* The default number of minutes an item can stay in the cache. Set to -1 for forever */
  3004.  
  3005.   expires: 60
  3006.  
  3007.  },
  3008.  
  3009.  
  3010.  
  3011.  /************************************* Public Cache Methods *****************************/
  3012.  
  3013.  
  3014.  
  3015.  /**
  3016.  
  3017.   * Adds a key/value pair to the cache. Removes any itmes first if necessary.
  3018.  
  3019.   *
  3020.  
  3021.   * @param {string} key The key to reference the stored object
  3022.  
  3023.   * @param {object} val The value to save
  3024.  
  3025.   */
  3026.  
  3027.  add : function(key, val){
  3028.  
  3029.   if (AjaxTCR.comm.cache._cache.length >= AjaxTCR.comm.cache._cacheOptions.size)
  3030.  
  3031.   {
  3032.  
  3033.   var algorithm = AjaxTCR.comm.cache._cacheOptions.algorithm;
  3034.  
  3035.   //we need to remove an item before adding another one.
  3036.  
  3037.   if ( algorithm == "FIFO")
  3038.  
  3039.   AjaxTCR.comm.cache._cache.splice(0, 1);
  3040.  
  3041.   else if (algorithm == "LFU")
  3042.  
  3043.   {
  3044.  
  3045.   var removeIndex = -1;
  3046.  
  3047.   for (var i=0;i<AjaxTCR.comm.cache._cache.length;i++)
  3048.  
  3049.   {
  3050.  
  3051.   if (removeIndex == -1 || AjaxTCR.comm.cache._cache[removeIndex].totalAccessed > AjaxTCR.comm.cache._cache[i].totalAccessed)
  3052.  
  3053.   removeIndex = i;
  3054.  
  3055.   }
  3056.  
  3057.  
  3058.  
  3059.   AjaxTCR.comm.cache._cache.splice(removeIndex,1);
  3060.  
  3061.   }
  3062.  
  3063.   else if (algorithm == "LRU")
  3064.  
  3065.   {
  3066.  
  3067.   var removeIndex = -1;
  3068.  
  3069.   for (var i=0;i<AjaxTCR.comm.cache._cache.length;i++)
  3070.  
  3071.   {
  3072.  
  3073.   if (removeIndex == -1 || AjaxTCR.comm.cache._cache[removeIndex].lastAccessed > AjaxTCR.comm.cache._cache[i].lastAccessed)
  3074.  
  3075.   removeIndex = i;
  3076.  
  3077.   }
  3078.  
  3079.  
  3080.  
  3081.   AjaxTCR.comm.cache._cache.splice(removeIndex,1);
  3082.  
  3083.   }
  3084.  
  3085.   }
  3086.  
  3087.  
  3088.  
  3089.   var item = AjaxTCR.comm.cache._createCacheItem(key, val);
  3090.  
  3091.   AjaxTCR.comm.cache._cache.push(item);
  3092.  
  3093.  },
  3094.  
  3095.  
  3096.  
  3097.  /**
  3098.  
  3099.   * Public method that resets the caches
  3100.  
  3101.   *
  3102.  
  3103.   */
  3104.  
  3105.  clear : function(){
  3106.  
  3107.   AjaxTCR.comm.cache._cache = new Array();
  3108.  
  3109.  },
  3110.  
  3111.  
  3112.  
  3113.  /**
  3114.  
  3115.   * Public method to fetch an object based on the key. Checks to see if the object has expired before returning it.
  3116.  
  3117.   *
  3118.  
  3119.   * @param {string} key The key to reference the stored object
  3120.  
  3121.   * @return {object} The stored value
  3122.  
  3123.   *
  3124.  
  3125.   */
  3126.  
  3127.  get: function(key){
  3128.  
  3129.   var cacheObject = null;
  3130.  
  3131.   /* Search for item */
  3132.  
  3133.   for (var i=0;i<AjaxTCR.comm.cache._cache.length;i++)
  3134.  
  3135.   {
  3136.  
  3137.   if (AjaxTCR.comm.cache._cache[i].key == key)
  3138.  
  3139.   {
  3140.  
  3141.   cacheObject = AjaxTCR.comm.cache._cache[i];
  3142.  
  3143.   break;
  3144.  
  3145.   }
  3146.  
  3147.   }
  3148.  
  3149.  
  3150.  
  3151.   if (cacheObject)
  3152.  
  3153.   {
  3154.  
  3155.   /* Update the properties */
  3156.  
  3157.   cacheObject.lastAccessed = new Date();
  3158.  
  3159.   cacheObject.totalAccessed++;
  3160.  
  3161.  
  3162.  
  3163.   /* Ensure it hasn't expired */
  3164.  
  3165.   if (AjaxTCR.comm.cache._cacheOptions.expires != -1)
  3166.  
  3167.   {
  3168.  
  3169.   var timeAdded = cacheObject.added;
  3170.  
  3171.   var now = new Date();
  3172.  
  3173.   now.setMinutes(now.getMinutes() - AjaxTCR.comm.cache._cacheOptions.expires);
  3174.  
  3175.   if (now > timeAdded)
  3176.  
  3177.   {
  3178.  
  3179.   AjaxTCR.comm.cache.remove(item.key);
  3180.  
  3181.   cacheObject = null;
  3182.  
  3183.   }
  3184.  
  3185.   }
  3186.  
  3187.   }
  3188.  
  3189.  
  3190.  
  3191.   if (cacheObject)
  3192.  
  3193.   return cacheObject.value;
  3194.  
  3195.   else
  3196.  
  3197.   return null;
  3198.  
  3199.  },
  3200.  
  3201.  
  3202.  
  3203.  
  3204.  
  3205.  /**
  3206.  
  3207.   * Returns the entire cache
  3208.  
  3209.   *
  3210.  
  3211.   * @return {object} The cache Object
  3212.  
  3213.   */
  3214.  
  3215.  getAll : function(){
  3216.  
  3217.   return AjaxTCR.comm.cache._cache;
  3218.  
  3219.  },
  3220.  
  3221.  
  3222.  
  3223.  /**
  3224.  
  3225.   * Returns the number of items currently in the cache
  3226.  
  3227.   *
  3228.  
  3229.   * @return {integer} The number of items in the cache
  3230.  
  3231.   */
  3232.  
  3233.  getSize : function(){
  3234.  
  3235.   return AjaxTCR.comm.cache._cache.length;
  3236.  
  3237.  },
  3238.  
  3239.  
  3240.  
  3241.  /**
  3242.  
  3243.   * Removes an item from the cache based on the key passed in
  3244.  
  3245.   *
  3246.  
  3247.   * @param {string} key The key to reference the item to remove.
  3248.  
  3249.   */
  3250.  
  3251.  remove : function(key){
  3252.  
  3253.   for (var i=0;i<AjaxTCR.comm.cache._cache.length;i++)
  3254.  
  3255.   {
  3256.  
  3257.   if (AjaxTCR.comm.cache._cache[i].key == key)
  3258.  
  3259.   {
  3260.  
  3261.   AjaxTCR.comm.cache._cache.splice(i,1);
  3262.  
  3263.   break;
  3264.  
  3265.   }
  3266.  
  3267.   }
  3268.  
  3269.  },
  3270.  
  3271.  
  3272.  
  3273.  
  3274.  
  3275.  /**
  3276.  
  3277.   * Changes the default options for the caching mechanism
  3278.  
  3279.   * @param {Object} the options to set
  3280.  
  3281.   * @config {integer} size The number of items to store in the cache Default is 100
  3282.  
  3283.   * @config {string} algorithm The algorithm to use to decide which item should be removed next.
  3284.  
  3285.   * Options are LRU (Least Recently Used), FIFO (First In First Out), and LFU(Least Frequently Used) Default is LRU
  3286.  
  3287.   * @config {integer} expires The number of minutes an item can stay in the cache. Default is 60. Use -1 to set forever.
  3288.  
  3289.   */
  3290.  
  3291.  setOptions : function(cacheOptions){
  3292.  
  3293.   /* apply options defined by user */
  3294.  
  3295.   for (option in cacheOptions)
  3296.  
  3297.   AjaxTCR.comm.cache._cacheOptions[option] = cacheOptions[option];
  3298.  
  3299.   },
  3300.  
  3301.  
  3302.  
  3303.  
  3304.  
  3305.  
  3306.  
  3307.  /************************************* Private Cache Methods *****************************/
  3308.  
  3309.  
  3310.  
  3311.  /**
  3312.  
  3313.   * When a page is returned from the cache, this method is called to initialize values
  3314.  
  3315.   * so that the handlResponse function will work properly.
  3316.  
  3317.   *
  3318.  
  3319.   * @private
  3320.  
  3321.   * @param {Object} response The object that contains all the settings for the request
  3322.  
  3323.   * @param {Object} responseText The value stored in the cache
  3324.  
  3325.   */
  3326.  
  3327.  _handleCacheResponse : function(response, responseText){
  3328.  
  3329.   response.xhr = {};
  3330.  
  3331.   response.xhr.responseText = response.responseText = responseText;
  3332.  
  3333.   response.xhr.responseXML = response.responseXML = null;
  3334.  
  3335.   if (responseText.indexOf("<?xml") > -1)
  3336.  
  3337.   response.xhr.responseXML = response.responseXML = AjaxTCR.data.serializeXMLString(responseText);
  3338.  
  3339.  
  3340.  
  3341.   response.xhr.status = response.httpStatus = 200;
  3342.  
  3343.   response.xhr.statusText = response.httpStatusText = "OK";
  3344.  
  3345.  
  3346.  
  3347.   response.fromCache = true;
  3348.  
  3349.   AjaxTCR.comm._handleResponse(response);
  3350.  
  3351.  },
  3352.  
  3353.  
  3354.  
  3355.  
  3356.  
  3357.  /**
  3358.  
  3359.   * createCacheItem - Private method that creates a cache object based on the given key and val
  3360.  
  3361.   *
  3362.  
  3363.   * @private
  3364.  
  3365.   * @param {string} key The key to set cacheObject.key to
  3366.  
  3367.   * @param {object} val The value to set cacheObject.value to
  3368.  
  3369.   * @return {object} The cacheObject
  3370.  
  3371.   */
  3372.  
  3373.  _createCacheItem : function(key, val){
  3374.  
  3375.   var cacheObject = {};
  3376.  
  3377.   cacheObject.key = key;
  3378.  
  3379.   cacheObject.value = val;
  3380.  
  3381.   cacheObject.lastAccessed = new Date();
  3382.  
  3383.   cacheObject.added = new Date();
  3384.  
  3385.   cacheObject.totalAccessed = 1;
  3386.  
  3387.   return cacheObject;
  3388.  
  3389.  }
  3390.  
  3391.  
  3392.  
  3393.  
  3394.  
  3395.  };
  3396.  
  3397.  
  3398.  
  3399.  /************************************* AjaxTCR.comm.queue *****************************/
  3400.  
  3401.  /**
  3402.  
  3403.   * The queuing class of the library. Is called directly from AjaxTCR.comm.
  3404.  
  3405.   *
  3406.  
  3407.   * @class AjaxTCR.comm.queue
  3408.  
  3409.   * @static
  3410.  
  3411.   */
  3412.  
  3413.  AjaxTCR.comm.queue = {
  3414.  
  3415.  
  3416.  
  3417.  /****************************************** Private Properties ****************************************************/
  3418.  
  3419.  
  3420.  
  3421.  /** The responseQueue Object
  3422.  
  3423.   * @private
  3424.  
  3425.   */
  3426.  
  3427.   _responseQueue : { queue: new Array(), currentIndex: 0, maxID: 0},
  3428.  
  3429.  
  3430.  
  3431.   /** The requestQueue Array
  3432.  
  3433.   * @private
  3434.  
  3435.   */
  3436.  
  3437.   _requestQueue : new Array(),
  3438.  
  3439.  
  3440.  
  3441.   /** The requestQueue counter
  3442.  
  3443.   * @private
  3444.  
  3445.   */
  3446.  
  3447.   _requestQueueID: 0,
  3448.  
  3449.  
  3450.  
  3451.   /** The number of active requests to send out when using request Queue */
  3452.  
  3453.   requestQueueConcurrentRequests : 1,
  3454.  
  3455.  
  3456.  
  3457.  /****************************************** Public Queue Methods ****************************************************/
  3458.  
  3459.  
  3460.  
  3461.  /**
  3462.  
  3463.   * Public method to add a request to the request queue.
  3464.  
  3465.   * If the request limit isn't being met yet, the request is sent right away, otherwise, it gets added to the queue.
  3466.  
  3467.   * If the priority is set and not to "normal", it places the new
  3468.  
  3469.   * request at the proper place. Otherwise, it inserts it at the end of the queue.
  3470.  
  3471.   *
  3472.  
  3473.   * @param {string} url - the url to add to the request queue
  3474.  
  3475.   * @param {object} options - the options object to send to sendRequest
  3476.  
  3477.   * @param {string} [priority] - the priority level of the entry - Choices are "normal", "next", and "faster"
  3478.  
  3479.   * @return {integer} The requestQueueid of the request
  3480.  
  3481.   */
  3482.  
  3483.  add : function(url, options, priority) {
  3484.  
  3485.   if (options)
  3486.  
  3487.   options.inQueue = true;
  3488.  
  3489.   else
  3490.  
  3491.   options = {inQueue:true};
  3492.  
  3493.  
  3494.  
  3495.   if (!priority)
  3496.  
  3497.   options.priority = "normal";
  3498.  
  3499.   else
  3500.  
  3501.   options.priority = priority.toLowerCase();
  3502.  
  3503.  
  3504.  
  3505.   /* Add Id */
  3506.  
  3507.   options.requestQueueID = ++AjaxTCR.comm.queue._requestQueueID;
  3508.  
  3509.  
  3510.  
  3511.   /* See if we should send it or add it to the queue */
  3512.  
  3513.   if (AjaxTCR.comm.stats.getRequestCount("active") >= AjaxTCR.comm.queue.requestQueueConcurrentRequests)
  3514.  
  3515.   {
  3516.  
  3517.   var request = {url: url, options: options};
  3518.  
  3519.   if (options.priority == "next")
  3520.  
  3521.   AjaxTCR.comm.queue._requestQueue.unshift(request);
  3522.  
  3523.   else if (priority && priority == "faster")
  3524.  
  3525.   {
  3526.  
  3527.   var set = false;
  3528.  
  3529.   for (var i=0;i<AjaxTCR.comm.queue._requestQueue.length;i++)
  3530.  
  3531.   {
  3532.  
  3533.   if (AjaxTCR.comm.queue._requestQueue[i].options.priority == "normal")
  3534.  
  3535.   {
  3536.  
  3537.   AjaxTCR.comm.queue._requestQueue.splice(i, 0, request);
  3538.  
  3539.   set = true;
  3540.  
  3541.   break;
  3542.  
  3543.   }
  3544.  
  3545.   }
  3546.  
  3547.   /* If nothing is normal, add to the end */
  3548.  
  3549.   if (!set)
  3550.  
  3551.   AjaxTCR.comm.queue._requestQueue.push(request);
  3552.  
  3553.   }
  3554.  
  3555.   else
  3556.  
  3557.   AjaxTCR.comm.queue._requestQueue.push(request);
  3558.  
  3559.   }
  3560.  
  3561.   else
  3562.  
  3563.   AjaxTCR.comm.sendRequest(url, options);
  3564.  
  3565.  
  3566.  
  3567.   return options.requestQueueID;
  3568.  
  3569.  },
  3570.  
  3571.  
  3572.  
  3573.  /**
  3574.  
  3575.   * A public method that clears out the request queue of any pending requests
  3576.  
  3577.   *
  3578.  
  3579.   */
  3580.  
  3581.  clear: function() {
  3582.  
  3583.   AjaxTCR.comm.queue._requestQueue.length = 0;
  3584.  
  3585.  },
  3586.  
  3587.  
  3588.  
  3589.  /**
  3590.  
  3591.   * Returns the item from the queue
  3592.  
  3593.   *
  3594.  
  3595.   * @param {integer} ID - ID of request to return
  3596.  
  3597.   * @return {object} The object that is stored in the queue
  3598.  
  3599.   *
  3600.  
  3601.   */
  3602.  
  3603.  get : function(ID) {
  3604.  
  3605.   for (var i=0;i<AjaxTCR.comm.queue._requestQueue.length;i++)
  3606.  
  3607.   {
  3608.  
  3609.   if ( AjaxTCR.comm.queue._requestQueue[i].options.requestQueueID == ID)
  3610.  
  3611.   return AjaxTCR.comm.queue._requestQueue[i];
  3612.  
  3613.   }
  3614.  
  3615.  
  3616.  
  3617.   return null;
  3618.  
  3619.  },
  3620.  
  3621.  
  3622.  
  3623.  /**
  3624.  
  3625.   * Returns the whole request queue
  3626.  
  3627.   *
  3628.  
  3629.   * @return {object} the request queue
  3630.  
  3631.   */
  3632.  
  3633.  getAll : function(){
  3634.  
  3635.   return AjaxTCR.comm.queue._requestQueue;
  3636.  
  3637.  },
  3638.  
  3639.  
  3640.  
  3641.  /**
  3642.  
  3643.   * Returns the position in the queue of the passed in ID.
  3644.  
  3645.   *
  3646.  
  3647.   * @param ID - ID of request that you wish to check
  3648.  
  3649.   * @return {integer} Returns -1 if not in queue. Otherwise returns th location in the queue. Starts at 0.
  3650.  
  3651.   *
  3652.  
  3653.   */
  3654.  
  3655.  getPosition : function(ID) {
  3656.  
  3657.   for (var i=0;i<AjaxTCR.comm.queue._requestQueue.length;i++)
  3658.  
  3659.   {
  3660.  
  3661.   if ( AjaxTCR.comm.queue._requestQueue[i].options.requestQueueID == ID)
  3662.  
  3663.   return i;
  3664.  
  3665.   }
  3666.  
  3667.  
  3668.  
  3669.   return -1;
  3670.  
  3671.  },
  3672.  
  3673.  
  3674.  
  3675.  /**
  3676.  
  3677.   * Returns the length request queue
  3678.  
  3679.   *
  3680.  
  3681.   * @return {integer} the request queue length
  3682.  
  3683.   */
  3684.  
  3685.  getSize : function(){
  3686.  
  3687.   return AjaxTCR.comm.queue._requestQueue.length;
  3688.  
  3689.  },
  3690.  
  3691.  
  3692.  
  3693.  /**
  3694.  
  3695.   * Removes the option with the given requestQueueID from the request Queue
  3696.  
  3697.   *
  3698.  
  3699.   * @param {integer{ ID ID of request to be removed from queue
  3700.  
  3701.   *
  3702.  
  3703.   */
  3704.  
  3705.  remove : function(ID) {
  3706.  
  3707.   for (var i=0;i<AjaxTCR.comm.queue._requestQueue.length;i++)
  3708.  
  3709.   {
  3710.  
  3711.   if ( AjaxTCR.comm.queue._requestQueue[i].options.requestQueueID == ID)
  3712.  
  3713.   {
  3714.  
  3715.   var ret = AjaxTCR.comm.queue._requestQueue[i];
  3716.  
  3717.   AjaxTCR.comm.queue._requestQueue.splice(i, 1);
  3718.  
  3719.   return ret;
  3720.  
  3721.   }
  3722.  
  3723.   }
  3724.  
  3725.  
  3726.  
  3727.   return false;
  3728.  
  3729.  },
  3730.  
  3731.  
  3732.  
  3733.  
  3734.  
  3735.  /****************************************** Private Queue Methods ****************************************************/
  3736.  
  3737.  
  3738.  
  3739.  /**
  3740.  
  3741.   * A private method that looks to see if a request queue is in use and sends the next
  3742.  
  3743.   * request off for processing if there is one
  3744.  
  3745.   *
  3746.  
  3747.   * @private
  3748.  
  3749.   * @param {object} response The object that contains all the settings for the request
  3750.  
  3751.   *
  3752.  
  3753.   */
  3754.  
  3755.  _checkRequestQueue : function(response){
  3756.  
  3757.   /* If Request Queue is being used, send next request */
  3758.  
  3759.   if (response.inQueue && AjaxTCR.comm.queue._requestQueue.length > 0)
  3760.  
  3761.   {
  3762.  
  3763.   var nextRequest = AjaxTCR.comm.queue._requestQueue.shift();
  3764.  
  3765.   AjaxTCR.comm.sendRequest(nextRequest.url, nextRequest.options);
  3766.  
  3767.   }
  3768.  
  3769.  },
  3770.  
  3771.  
  3772.  
  3773.  /**
  3774.  
  3775.   * Private method called after response comes in if request is in the response queue.
  3776.  
  3777.   * Adds response to response queue and then calls callbacks for any that are able to move forward
  3778.  
  3779.   *
  3780.  
  3781.   * @param {object} response The object that contains all the settings for the request
  3782.  
  3783.   */
  3784.  
  3785.  
  3786.  
  3787.  _handleQueue: function(response){
  3788.  
  3789.   /* add response into queue */
  3790.  
  3791.   AjaxTCR.comm.queue._responseQueue.queue[response.responseQueueID] = response;
  3792.  
  3793.  
  3794.  
  3795.   /* loop thru queue handling any received requests up to current point */
  3796.  
  3797.   while (AjaxTCR.comm.queue._responseQueue.queue[AjaxTCR.comm.queue._responseQueue.currentIndex] != undefined)
  3798.  
  3799.   {
  3800.  
  3801.   AjaxTCR.comm._handleCallbacks(AjaxTCR.comm.queue._responseQueue.queue[AjaxTCR.comm.queue._responseQueue.currentIndex]);
  3802.  
  3803.   AjaxTCR.comm.queue._responseQueue.currentIndex++;
  3804.  
  3805.   }
  3806.  
  3807.  }
  3808.  
  3809.  
  3810.  
  3811.  
  3812.  
  3813.  };
  3814.  
  3815.  
  3816.  
  3817.  /************************************* AjaxTCR.comm.stats *****************************/
  3818.  
  3819.  /**
  3820.  
  3821.   * The statistics class of the library. Collects statistics regarding total requests, timeouts, retries, successes, and failures
  3822.  
  3823.   * Can serialize and send this data to your server.
  3824.  
  3825.   *
  3826.  
  3827.   * @class AjaxTCR.comm.stats
  3828.  
  3829.   * @static
  3830.  
  3831.   */
  3832.  
  3833.  AjaxTCR.comm.stats = {
  3834.  
  3835.  
  3836.  
  3837.   /** stats object to hold results
  3838.  
  3839.   * @private
  3840.  
  3841.   * @config {integer} totalRequests
  3842.  
  3843.   * @config {integer} totalTimeouts
  3844.  
  3845.   * @config {integer} totalRetries
  3846.  
  3847.   * @config {integer} totalSuccesses
  3848.  
  3849.   * @config {integer} totalFails
  3850.  
  3851.   * @config {array} requestFails
  3852.  
  3853.   */
  3854.  
  3855.   _commResults : {
  3856.  
  3857.   totalRequests : 0,
  3858.  
  3859.   totalTimeouts : 0,
  3860.  
  3861.   totalRetries : 0,
  3862.  
  3863.   totalSuccesses : 0,
  3864.  
  3865.   totalFails : 0,
  3866.  
  3867.   requestFails : new Array()},
  3868.  
  3869.  
  3870.  
  3871.  
  3872.  
  3873.  /**
  3874.  
  3875.   * Sets up system to send results to the passed in URL on page unload. It passes them as a POST with an application/json body.
  3876.  
  3877.   *
  3878.  
  3879.   * @param {Object} url URL to send the results to
  3880.  
  3881.   */
  3882.  
  3883.  collect : function (url) {
  3884.  
  3885.   var sendConnectionStats = function(){
  3886.  
  3887.   var results = AjaxTCR.comm.stats.get();
  3888.  
  3889.   if (results.totalRequests > 0)
  3890.  
  3891.   {
  3892.  
  3893.   var payload = AjaxTCR.data.encodeJSON(results);
  3894.  
  3895.   AjaxTCR.comm.sendRequest(url, {method:"POST",payload:payload,requestContentType:"application/json",oneway:true});
  3896.  
  3897.   }
  3898.  
  3899.   };
  3900.  
  3901.  
  3902.  
  3903.   if(window.attachEvent)
  3904.  
  3905.   window.attachEvent('onunload', sendConnectionStats);
  3906.  
  3907.   else
  3908.  
  3909.   window.addEventListener('unload', sendConnectionStats, false);
  3910.  
  3911.  
  3912.  
  3913.  },
  3914.  
  3915.  
  3916.  
  3917.  /**
  3918.  
  3919.   * Returns the whole statistics object
  3920.  
  3921.   *
  3922.  
  3923.   * @return {object} the statistics object
  3924.  
  3925.   */
  3926.  
  3927.  get : function() {
  3928.  
  3929.   return AjaxTCR.comm.stats._commResults;
  3930.  
  3931.  },
  3932.  
  3933.  
  3934.  
  3935.  
  3936.  
  3937.  /**
  3938.  
  3939.   * Public method acting as simple getter for the count of requests currently out
  3940.  
  3941.   *
  3942.  
  3943.   * @param {string} type The type of requests that you want the count on. Options are "queued", "active", and "all"
  3944.  
  3945.   * @return - the number of outstanding requests
  3946.  
  3947.   */
  3948.  
  3949.  getRequestCount : function(type) {
  3950.  
  3951.   if (type == "queued")
  3952.  
  3953.   return AjaxTCR.comm.queue.getSize();
  3954.  
  3955.   else if (type == "active")
  3956.  
  3957.   return AjaxTCR.comm._requestsOutstanding;
  3958.  
  3959.   else
  3960.  
  3961.   return (AjaxTCR.comm.queue.getSize() + AjaxTCR.comm._requestsOutstanding);
  3962.  
  3963.  }
  3964.  
  3965.  
  3966.  
  3967.  
  3968.  
  3969.  };
  3970.  
  3971.  
  3972.  
  3973.  /************************************* AjaxTCR.comm.cookie *****************************/
  3974.  
  3975.  /**
  3976.  
  3977.   * The cookie class of the library. Allows setting and retrieving of cookies
  3978.  
  3979.   *
  3980.  
  3981.   * @class AjaxTCR.comm.cookie
  3982.  
  3983.   * @static
  3984.  
  3985.   */
  3986.  
  3987.  AjaxTCR.comm.cookie = {
  3988.  
  3989.  
  3990.  
  3991.  /**
  3992.  
  3993.   * Gets the value of a cookie with the given name.
  3994.  
  3995.   *
  3996.  
  3997.   * @param {String} name The name of the cookie to find
  3998.  
  3999.   * @return {String} The value of the specified cookie
  4000.  
  4001.   */
  4002.  
  4003.  get : function(name){
  4004.  
  4005.   var fullname = name + "=";
  4006.  
  4007.   var cookies = document.cookie.split(';');
  4008.  
  4009.   for(var i=0;i < cookies.length;i++)
  4010.  
  4011.   {
  4012.  
  4013.   var cookieNV = cookies[i];
  4014.  
  4015.   while (cookieNV.charAt(0)==' ')
  4016.  
  4017.   cookieNV = cookieNV.substring(1);
  4018.  
  4019.   if (cookieNV.indexOf(fullname) == 0)
  4020.  
  4021.   return cookieNV.substring(fullname.length);
  4022.  
  4023.   }
  4024.  
  4025.   return null;
  4026.  
  4027.  },
  4028.  
  4029.  
  4030.  
  4031.  /**
  4032.  
  4033.   * Create a cookie using document.cookie
  4034.  
  4035.   *
  4036.  
  4037.   * @param {string} key The cookie name
  4038.  
  4039.   * @param {string} value The cookie value
  4040.  
  4041.   * @param {string} expires The date of expiration. If not set, the cookie expires when the browser is closed.
  4042.  
  4043.   * @param {string} [path] The path to store the cookie. If not set, it is stored at "/"
  4044.  
  4045.   */
  4046.  
  4047.  set: function(key, value, expires, path){
  4048.  
  4049.  
  4050.  
  4051.   if (!path)
  4052.  
  4053.   path = "/";
  4054.  
  4055.  
  4056.  
  4057.   document.cookie = key+"="+value+"; expires=" + expires +"; path=" + path;
  4058.  
  4059.  
  4060.  
  4061.  },
  4062.  
  4063.  
  4064.  
  4065.  /**
  4066.  
  4067.   * Removes the cookie specified by key.
  4068.  
  4069.   * @param {Object} key The name of the cookie to remove
  4070.  
  4071.   * @param {Object} [path] The path where the cookie is stored. If not set, it checks "/"
  4072.  
  4073.   */
  4074.  
  4075.  remove: function(key, path){
  4076.  
  4077.  
  4078.  
  4079.   if (!path)
  4080.  
  4081.   path = "/";
  4082.  
  4083.  
  4084.  
  4085.   var now = new Date();
  4086.  
  4087.   now.setYear(now.getYear()-1);
  4088.  
  4089.   var expires = now.toGMTString();
  4090.  
  4091.   document.cookie = key+"=; expires=" + expires +"; path=" + path;
  4092.  
  4093.  
  4094.  
  4095.  }
  4096.  
  4097.  
  4098.  
  4099.  };
  4100.  
  4101.  
  4102.  
  4103.  /************************************* AjaxTCR.history *****************************/
  4104.  
  4105.  /**
  4106.  
  4107.   * The history class of the library. History is called directly from communications, but can also be called by the user.
  4108.  
  4109.   * If history is going to be used, you must call AjaxTCR.history.init() before usage.
  4110.  
  4111.   *
  4112.  
  4113.   * @class AjaxTCR.history
  4114.  
  4115.   * @static
  4116.  
  4117.   */
  4118.  
  4119.  AjaxTCR.history = {
  4120.  
  4121.  
  4122.  
  4123.  /** contstants
  4124.  
  4125.   * @private
  4126.  
  4127.   */
  4128.  
  4129.  BACK_GUARD_DISABLED : 0,
  4130.  
  4131.  BACK_GUARD_INITIALIZED : 1,
  4132.  
  4133.  BACK_GUARD_ENABLED : 2,
  4134.  
  4135.  
  4136.  
  4137.  /** Current State of application
  4138.  
  4139.   * @private
  4140.  
  4141.   */
  4142.  
  4143.  _currentState : "",
  4144.  
  4145.  
  4146.  
  4147.  /** function to call on statechange callback. Specifed in init()
  4148.  
  4149.   * @private
  4150.  
  4151.   */
  4152.  
  4153.  _onStateChangeCallback : function(){},
  4154.  
  4155.  
  4156.  
  4157.  /** html file that iframe points to. Does not need any contents, but does need to exist
  4158.  
  4159.   * @private
  4160.  
  4161.   */
  4162.  
  4163.  _iframeSrc : "blank.html",
  4164.  
  4165.  
  4166.  
  4167.  /** Boolean indicated whether to handle history
  4168.  
  4169.   * @private
  4170.  
  4171.   */
  4172.  
  4173.  _historyEnabled : false,
  4174.  
  4175.  
  4176.  
  4177.  /** The history array
  4178.  
  4179.   * @private
  4180.  
  4181.   */
  4182.  
  4183.  _history : new Array(),
  4184.  
  4185.  
  4186.  
  4187.  /** The current position in the history array
  4188.  
  4189.   * @private
  4190.  
  4191.   */
  4192.  
  4193.  _historyPosition : 0,
  4194.  
  4195.  
  4196.  
  4197.  /** Boolean indicated if library should warn on page unload
  4198.  
  4199.   * @private
  4200.  
  4201.   */
  4202.  
  4203.  _backGuardEnabled: 0,
  4204.  
  4205.  
  4206.  
  4207.  /** Message to alert when warning on page unload
  4208.  
  4209.   * @private
  4210.  
  4211.   */
  4212.  
  4213.  _backGuardMessage: "Are you sure you wish to end your session?",
  4214.  
  4215.  
  4216.  
  4217.  /**
  4218.  
  4219.   * Function that must be called before using the history mechanics.
  4220.  
  4221.   * It sets historyEnabled to true, sets the callback function,
  4222.  
  4223.   * sets up the timers to check for history change
  4224.  
  4225.   * and checks to see if the initial state is a bookmark
  4226.  
  4227.   *
  4228.  
  4229.   * @param {function} onStateChangeCallback The function to call if there is a state change outside of the XHR call
  4230.  
  4231.   * @param {Object} initState The data to pass back to the callback function
  4232.  
  4233.   */
  4234.  
  4235.  init : function(onStateChangeCallback, initState){
  4236.  
  4237.   if (AjaxTCR.history._historyEnabled)
  4238.  
  4239.   return;
  4240.  
  4241.   else
  4242.  
  4243.   AjaxTCR.history._historyEnabled = true;
  4244.  
  4245.  
  4246.  
  4247.  
  4248.  
  4249.   AjaxTCR.history._onStateChangeCallback = onStateChangeCallback;
  4250.  
  4251.  
  4252.  
  4253.   if(!(navigator.userAgent.toLowerCase().indexOf("msie")>-1))
  4254.  
  4255.   AjaxTCR.history._checkHash();
  4256.  
  4257.   else
  4258.  
  4259.   AjaxTCR.history._checkHashIE();
  4260.  
  4261.  
  4262.  
  4263.   if (!window.location.hash)
  4264.  
  4265.   AjaxTCR.history.addToHistory("AjaxTCRinit", initState, document.title);
  4266.  
  4267.   else if ((navigator.userAgent.toLowerCase().indexOf("msie")>-1))
  4268.  
  4269.   AjaxTCR.history._initIE();
  4270.  
  4271.  
  4272.  
  4273.  },
  4274.  
  4275.  
  4276.  
  4277.  /**
  4278.  
  4279.   * Adds an item to the browser history. Saves the title, position in history, and the data for later retrieval.
  4280.  
  4281.   *
  4282.  
  4283.   * @param {string} id the key to store the history item under
  4284.  
  4285.   * @param {object} data the data field to be returned to the callback function.
  4286.  
  4287.   * @param {title} [title] the title to change the page to
  4288.  
  4289.   * @param {string} [url] the url to request when page reloads.
  4290.  
  4291.   * @param {object} [options] the options for the request
  4292.  
  4293.   */
  4294.  
  4295.  addToHistory : function(id, data, title, url, options){
  4296.  
  4297.  
  4298.  
  4299.   if (id != "AjaxTCRinit")
  4300.  
  4301.   {
  4302.  
  4303.   window.location.hash =AjaxTCR.data.encodeValue(id).replace(/%2F/g, '/');;
  4304.  
  4305.   AjaxTCR.history._currentState = window.location.hash.substring(1);
  4306.  
  4307.   }
  4308.  
  4309.  
  4310.  
  4311.   var optionsString = "";
  4312.  
  4313.   var safeStateName = id.replace(/[%\+]/g, "");
  4314.  
  4315.  
  4316.  
  4317.   if (title)
  4318.  
  4319.   document.title = title;
  4320.  
  4321.  
  4322.  
  4323.   if (options)
  4324.  
  4325.   {
  4326.  
  4327.   options.url = url;
  4328.  
  4329.   if (navigator.userAgent.toLowerCase().indexOf("msie")>-1)
  4330.  
  4331.   options.responseXML = "iebug";
  4332.  
  4333.  
  4334.  
  4335.   optionsString = AjaxTCR.data.encode64(AjaxTCR.data.encodeJSON(options));
  4336.  
  4337.   }
  4338.  
  4339.   else if (data)
  4340.  
  4341.   {
  4342.  
  4343.   options = {value: data};
  4344.  
  4345.   optionsString = AjaxTCR.data.encode64(AjaxTCR.data.encodeJSON(options));
  4346.  
  4347.   }
  4348.  
  4349.  
  4350.  
  4351.   //update position
  4352.  
  4353.   AjaxTCR.history._historyPosition++;
  4354.  
  4355.  
  4356.  
  4357.   if(navigator.userAgent.toLowerCase().indexOf("msie")>-1)
  4358.  
  4359.   {
  4360.  
  4361.   var iframe = document.getElementById("ieFix");
  4362.  
  4363.   var html = '<html><head><title>IE History</title><STYLE>.userData {behavior:url(#default#userdata);}</STYLE></head><body><div class="userData" id="persistDiv"></div><div id="currentState">' + AjaxTCR.history._currentState + '</div></body></html>';
  4364.  
  4365.   var doc = iframe.contentWindow.document;
  4366.  
  4367.   doc.open();
  4368.  
  4369.   doc.write(html);
  4370.  
  4371.   doc.close();
  4372.  
  4373.  
  4374.  
  4375.   var persistDiv = doc.getElementById("persistDiv");
  4376.  
  4377.   AjaxTCR.storage.add("request", optionsString, persistDiv, safeStateName);
  4378.  
  4379.   if (title)
  4380.  
  4381.   AjaxTCR.storage.add("title", title, persistDiv, safeStateName);
  4382.  
  4383.   AjaxTCR.storage.add("position", AjaxTCR.history._historyPosition, persistDiv, safeStateName);
  4384.  
  4385.   }
  4386.  
  4387.   else if (safeStateName)
  4388.  
  4389.   {
  4390.  
  4391.   AjaxTCR.storage.add(safeStateName, optionsString);
  4392.  
  4393.   if (title)
  4394.  
  4395.   AjaxTCR.storage.add(safeStateName + "title", title);
  4396.  
  4397.   AjaxTCR.storage.add(safeStateName + "position", AjaxTCR.history._historyPosition);
  4398.  
  4399.   }
  4400.  
  4401.  
  4402.  
  4403.   /* Finally push onto history stack */
  4404.  
  4405.   var historyItem = {id: AjaxTCR.history._currentState, title: title};
  4406.  
  4407.   var diff = AjaxTCR.history._history.length - AjaxTCR.history._historyPosition + 1;
  4408.  
  4409.   if (diff > 0)
  4410.  
  4411.   AjaxTCR.history._history.splice(AjaxTCR.history._historyPosition-1,diff);
  4412.  
  4413.  
  4414.  
  4415.   AjaxTCR.history._history.push(historyItem);
  4416.  
  4417.  },
  4418.  
  4419.  
  4420.  
  4421.  /**
  4422.  
  4423.   * Returns the entire history array
  4424.  
  4425.   * @return {array} The history array
  4426.  
  4427.   */
  4428.  
  4429.  getAll : function(){
  4430.  
  4431.   return AjaxTCR.history._history;
  4432.  
  4433.  },
  4434.  
  4435.  
  4436.  
  4437.  /**
  4438.  
  4439.   * Returns the current position in the history stack
  4440.  
  4441.   * @return {integer} The current position in the history stack
  4442.  
  4443.   */
  4444.  
  4445.  getPosition : function(){
  4446.  
  4447.   return AjaxTCR.history._historyPosition;
  4448.  
  4449.  },
  4450.  
  4451.  
  4452.  
  4453.  /**
  4454.  
  4455.   * Sets up the system that will alert the user when they leave the page that they are leaving the application
  4456.  
  4457.   *
  4458.  
  4459.   * @param {string} [message] The message to alert the user
  4460.  
  4461.   * @param {Boolean} [immediate] If set to true, it immediately sets up the system. Otherwise, it sets it up on first sendRequest call.
  4462.  
  4463.   */
  4464.  
  4465.  enableBackGuard: function(message, immediate){
  4466.  
  4467.   if (AjaxTCR.history._backGuardEnabled)
  4468.  
  4469.   return;
  4470.  
  4471.  
  4472.  
  4473.   if (message != null && typeof(message) != "undefined")
  4474.  
  4475.   AjaxTCR.history._backGuardMessage = message;
  4476.  
  4477.  
  4478.  
  4479.   if (immediate)
  4480.  
  4481.   AjaxTCR.history._activateBackGuard();
  4482.  
  4483.   else
  4484.  
  4485.   AjaxTCR.history._backGuardEnabled = AjaxTCR.history.BACK_GUARD_INITIALIZED;
  4486.  
  4487.  
  4488.  
  4489.  },
  4490.  
  4491.  
  4492.  
  4493.  /**
  4494.  
  4495.   * Sets the onbeforeunload handler to alert when the user tries to leave the page
  4496.  
  4497.   * @private
  4498.  
  4499.   */
  4500.  
  4501.  _activateBackGuard: function(){
  4502.  
  4503.   var message = AjaxTCR.history._backGuardMessage;
  4504.  
  4505.   window.onbeforeunload = function () {return message;}
  4506.  
  4507.   AjaxTCR.history._backGuardEnabled = AjaxTCR.history.BACK_GUARD_ENABLED;
  4508.  
  4509.  },
  4510.  
  4511.  
  4512.  
  4513.  /**
  4514.  
  4515.   * Creates html page to write to the iframe in the case of IE
  4516.  
  4517.   *
  4518.  
  4519.   * @private
  4520.  
  4521.   */
  4522.  
  4523.  _initIE: function(){
  4524.  
  4525.   var iframe = document.getElementById("ieFix");
  4526.  
  4527.   var html = '<html><head><title>IE History</title><STYLE>.userData {behavior:url(#default#userdata);}</STYLE></head><body><div class="userData" id="persistDiv"></div><div id="currentState">' + window.location.hash.substring(1); + '</div></body></html>';
  4528.  
  4529.   var doc = iframe.contentWindow.document;
  4530.  
  4531.   doc.open();
  4532.  
  4533.   doc.write(html);
  4534.  
  4535.   doc.close();
  4536.  
  4537.  },
  4538.  
  4539.  
  4540.  
  4541.  
  4542.  
  4543.  /**
  4544.  
  4545.   * Checks to see if the state that is set in the IE Iframe matches the current state as set in the library. If they are not a match,
  4546.  
  4547.   * update the state of the page
  4548.  
  4549.   *
  4550.  
  4551.   * @private
  4552.  
  4553.   */
  4554.  
  4555.  _checkHashIE : function (){
  4556.  
  4557.   var iframe = document.getElementById("ieFix");
  4558.  
  4559.   if ( !iframe.contentWindow || !iframe.contentWindow.document )
  4560.  
  4561.   {
  4562.  
  4563.   setTimeout( _checkHashIE, 10 );
  4564.  
  4565.   return;
  4566.  
  4567.   }
  4568.  
  4569.  
  4570.  
  4571.   var doc = iframe.contentWindow.document;
  4572.  
  4573.   var keyObj = doc.getElementById("currentState");
  4574.  
  4575.   var key = "";
  4576.  
  4577.   if (keyObj)
  4578.  
  4579.   key = keyObj.innerText;
  4580.  
  4581.  
  4582.  
  4583.   if (key != AjaxTCR.history._currentState)
  4584.  
  4585.   {
  4586.  
  4587.   AjaxTCR.history._currentState = key;
  4588.  
  4589.   window.location.hash = key;
  4590.  
  4591.  
  4592.  
  4593.   var persistDiv = doc.getElementById("persistDiv");
  4594.  
  4595.   var safeStateName = AjaxTCR.history._currentState.replace(/[%\+]/g, "");
  4596.  
  4597.   if (!safeStateName)
  4598.  
  4599.   safeStateName = "AjaxTCRinit";
  4600.  
  4601.  
  4602.  
  4603.   var title = AjaxTCR.storage.get("title", persistDiv, safeStateName);
  4604.  
  4605.   if (title)
  4606.  
  4607.   document.title = title;
  4608.  
  4609.  
  4610.  
  4611.   AjaxTCR.history._historyPosition = AjaxTCR.storage.get("position", persistDiv, safeStateName);
  4612.  
  4613.   //check for bookmarked history position
  4614.  
  4615.   if (AjaxTCR.history._historyPosition > AjaxTCR.history._history.length)
  4616.  
  4617.   {
  4618.  
  4619.   AjaxTCR.history._historyPosition = 1;
  4620.  
  4621.   AjaxTCR.storage.add("position", AjaxTCR.history._historyPosition, persistDiv, safeStateName);
  4622.  
  4623.   var historyItem = {id: AjaxTCR.history._currentState, title: title};
  4624.  
  4625.   AjaxTCR.history._history.push(historyItem);
  4626.  
  4627.   }
  4628.  
  4629.  
  4630.  
  4631.   var optionsString = AjaxTCR.storage.get("request", persistDiv, safeStateName);
  4632.  
  4633.   AjaxTCR.history._handleHistoryCallback(optionsString);
  4634.  
  4635.  
  4636.  
  4637.   }
  4638.  
  4639.   setTimeout("AjaxTCR.history._checkHashIE();", 500);
  4640.  
  4641.  },
  4642.  
  4643.  
  4644.  
  4645.  /**
  4646.  
  4647.   * Checks to see if the current window.location.hash value matches the value saved in the currentState.
  4648.  
  4649.   * If they do not match, update the state of the page.
  4650.  
  4651.   *
  4652.  
  4653.   * @private
  4654.  
  4655.   */
  4656.  
  4657.  _checkHash : function () {
  4658.  
  4659.   if ((window.location.hash != "#" + AjaxTCR.history._currentState) && window.location.hash != AjaxTCR.history._currentState)
  4660.  
  4661.   {
  4662.  
  4663.   AjaxTCR.history._currentState = window.location.hash.substring(1);
  4664.  
  4665.   var safeStateName = AjaxTCR.history._currentState.replace(/[%\+]/g, "");
  4666.  
  4667.   if (!safeStateName)
  4668.  
  4669.   safeStateName = "AjaxTCRinit";
  4670.  
  4671.  
  4672.  
  4673.   var title = AjaxTCR.storage.get(safeStateName + "title");
  4674.  
  4675.   if (title)
  4676.  
  4677.   document.title = title.value;
  4678.  
  4679.  
  4680.  
  4681.  
  4682.  
  4683.   AjaxTCR.history._historyPosition = AjaxTCR.storage.get(safeStateName + "position").value;
  4684.  
  4685.   //check for bookmarked history position
  4686.  
  4687.   if (AjaxTCR.history._historyPosition > AjaxTCR.history._history.length)
  4688.  
  4689.   {
  4690.  
  4691.   AjaxTCR.history._historyPosition = 1;
  4692.  
  4693.   AjaxTCR.storage.add(safeStateName + "position", AjaxTCR.history._historyPosition);
  4694.  
  4695.   var historyItem = {id: AjaxTCR.history._currentState, title: title};
  4696.  
  4697.   AjaxTCR.history._history.push(historyItem);
  4698.  
  4699.   }
  4700.  
  4701.  
  4702.  
  4703.   var results = AjaxTCR.storage.get(safeStateName);
  4704.  
  4705.   if (results)
  4706.  
  4707.   AjaxTCR.history._handleHistoryCallback(results.value);
  4708.  
  4709.   else
  4710.  
  4711.   AjaxTCR.history._onStateChangeCallback(AjaxTCR.data.decodeValue(AjaxTCR.history._currentState));
  4712.  
  4713.  
  4714.  
  4715.   }
  4716.  
  4717.   setTimeout("AjaxTCR.history._checkHash();", 500);
  4718.  
  4719.  },
  4720.  
  4721.  
  4722.  
  4723.  /**
  4724.  
  4725.   * If the state on the page changes, this function is called to figure out how to restore the state of the new location.
  4726.  
  4727.   * Check the stored data and see if we need to call sendRequest/handleCacheResponse or if we need to call the callback function specified by the user in init.
  4728.  
  4729.   *
  4730.  
  4731.   * @private
  4732.  
  4733.   * @param {string} String value containing the JSON data that was saved on addToHistory
  4734.  
  4735.   */
  4736.  
  4737.  _handleHistoryCallback : function(optionsString){
  4738.  
  4739.   if (optionsString && optionsString != "")
  4740.  
  4741.   {
  4742.  
  4743.   var str = AjaxTCR.data.decode64(optionsString);
  4744.  
  4745.   var options = AjaxTCR.data.decodeJSON(AjaxTCR.data.decode64(optionsString));
  4746.  
  4747.   if (options.history)
  4748.  
  4749.   {
  4750.  
  4751.   if (options.history.saveResponse)
  4752.  
  4753.   {
  4754.  
  4755.   options.history = null;
  4756.  
  4757.   AjaxTCR.comm.cache._handleCacheResponse(options, options.responseText);
  4758.  
  4759.   }
  4760.  
  4761.   else
  4762.  
  4763.   {
  4764.  
  4765.   options.history = null;
  4766.  
  4767.   AjaxTCR.comm.sendRequest(options.url, options);
  4768.  
  4769.   }
  4770.  
  4771.   }
  4772.  
  4773.   else
  4774.  
  4775.   AjaxTCR.history._onStateChangeCallback(AjaxTCR.data.decodeValue(AjaxTCR.history._currentState), options.value);
  4776.  
  4777.   }
  4778.  
  4779.   else
  4780.  
  4781.   AjaxTCR.history._onStateChangeCallback(AjaxTCR.data.decodeValue(AjaxTCR.history._currentState));
  4782.  
  4783.  
  4784.  
  4785.  }
  4786.  
  4787.  
  4788.  
  4789.  };
  4790.  
  4791.  
  4792.  
  4793.  
  4794.  
  4795.  /********************************************* Storage Methods *********************************************/
  4796.  
  4797.  /**
  4798.  
  4799.   * The storage class of the library. Storage is called directly from history, but can also be called by the user.
  4800.  
  4801.   * If storage is going to be used, you must call AjaxTCR.storage.init() before usage.
  4802.  
  4803.   * The types of storage supported are IE Behaviors, WHATWG globalStorage, and cookies
  4804.  
  4805.   *
  4806.  
  4807.   * @class AjaxTCR.storage
  4808.  
  4809.   * @static
  4810.  
  4811.   */
  4812.  
  4813.  AjaxTCR.storage = {
  4814.  
  4815.  /** The max size to store in cookies */
  4816.  
  4817.  DEFAULT_MAX_COOKIE_SIZE: 4000,
  4818.  
  4819.  
  4820.  
  4821.  /**
  4822.  
  4823.   * Method must be called before using storage. The returned value must be passed to all future storage requests
  4824.  
  4825.   *
  4826.  
  4827.   * @returns {object} The newly created persitent Div object
  4828.  
  4829.   */
  4830.  
  4831.  init : function(){
  4832.  
  4833.  
  4834.  
  4835.   if (navigator.userAgent.toLowerCase().indexOf("msie")>-1 )
  4836.  
  4837.   {
  4838.  
  4839.   var persistDiv = document.createElement("div");
  4840.  
  4841.   persistDiv.id = "AjaxTCRPersistDiv";
  4842.  
  4843.   persistDiv.style.behavior = "url(#default#userData)";
  4844.  
  4845.   document.body.appendChild(persistDiv);
  4846.  
  4847.   return persistDiv;
  4848.  
  4849.   }
  4850.  
  4851.   return null;
  4852.  
  4853.  },
  4854.  
  4855.  
  4856.  
  4857.  /**
  4858.  
  4859.   * Adds an item to storage. Checks the browser support and chooses an appropriate method.
  4860.  
  4861.   *
  4862.  
  4863.   * @param {String} key The key to reference the stored string
  4864.  
  4865.   * @param {String} value The string to store in persistent data
  4866.  
  4867.   * @param {Object} persistObj The persistent Object returned from init
  4868.  
  4869.   * @param {string} [store] Optional value to name the store to save the data. Only applicable in IE
  4870.  
  4871.   */
  4872.  
  4873.  add : function(key, value, persistObj, store){
  4874.  
  4875.   var setFlag = 0;
  4876.  
  4877.   if(navigator.userAgent.toLowerCase().indexOf("msie")>-1 )
  4878.  
  4879.   {
  4880.  
  4881.   if (!store)
  4882.  
  4883.   store = "AjaxTCRStore";
  4884.  
  4885.  
  4886.  
  4887.   if (persistObj)
  4888.  
  4889.   {
  4890.  
  4891.   var allitemsString = AjaxTCR.storage.get("AjaxTCRAllItems", persistObj, store);
  4892.  
  4893.   if (!allitemsString)
  4894.  
  4895.   var allitemsObj = {};
  4896.  
  4897.   else
  4898.  
  4899.   var allitemsObj = AjaxTCR.data.decodeJSON(allitemsString);
  4900.  
  4901.  
  4902.  
  4903.   allitemsObj[key] = value;
  4904.  
  4905.   allitemsString = AjaxTCR.data.encodeJSON(allitemsObj);
  4906.  
  4907.   persistObj.setAttribute("AjaxTCRAllItems",allitemsString);
  4908.  
  4909.   persistObj.setAttribute(key,value);
  4910.  
  4911.   persistObj.save(store);
  4912.  
  4913.  
  4914.  
  4915.   setFlag = 1;
  4916.  
  4917.   }
  4918.  
  4919.   }
  4920.  
  4921.   else if (typeof(globalStorage) != "undefined")
  4922.  
  4923.   {
  4924.  
  4925.   try{
  4926.  
  4927.   var storage = globalStorage[document.domain];
  4928.  
  4929.   storage.setItem(key, value);
  4930.  
  4931.   setFlag = 1;
  4932.  
  4933.   }
  4934.  
  4935.   catch(e){}
  4936.  
  4937.   }
  4938.  
  4939.  
  4940.  
  4941.   if (!setFlag)
  4942.  
  4943.   {
  4944.  
  4945.   /* Update all records */
  4946.  
  4947.   var allitemsString = AjaxTCR.storage.get("AjaxTCRAllItems");
  4948.  
  4949.   if (!allitemsString)
  4950.  
  4951.   var allitemsObj = new Array();
  4952.  
  4953.   else
  4954.  
  4955.   var allitemsObj = AjaxTCR.data.decodeJSON(allitemsString);
  4956.  
  4957.  
  4958.  
  4959.   allitemsObj.push(key);
  4960.  
  4961.   allitemsString = AjaxTCR.data.encodeJSON(allitemsObj);
  4962.  
  4963.   var now = new Date();
  4964.  
  4965.   now.setMonth(now.getMonth()+1);
  4966.  
  4967.   var expires = now.toGMTString();
  4968.  
  4969.   var pieces = Math.floor(allitemsString.length/AjaxTCR.storage.DEFAULT_MAX_COOKIE_SIZE + 1);
  4970.  
  4971.   for (var i=0;i<pieces;i++)
  4972.  
  4973.   AjaxTCR.comm.cookie.set("AjaxTCRAllItems"+i.toString(), allitemsString.substring(i*AjaxTCR.storage.DEFAULT_MAX_COOKIE_SIZE, AjaxTCR.storage.DEFAULT_MAX_COOKIE_SIZE), expires);
  4974.  
  4975.  
  4976.  
  4977.   /* Add Item */
  4978.  
  4979.   var pieces = Math.floor(value.length/AjaxTCR.storage.DEFAULT_MAX_COOKIE_SIZE + 1);
  4980.  
  4981.   for (var i=0;i<pieces;i++)
  4982.  
  4983.   AjaxTCR.comm.cookie.set(key+i.toString(), value.substring(i*AjaxTCR.storage.DEFAULT_MAX_COOKIE_SIZE, AjaxTCR.storage.DEFAULT_MAX_COOKIE_SIZE), expires);
  4984.  
  4985.  
  4986.  
  4987.   }
  4988.  
  4989.   },
  4990.  
  4991.  
  4992.  
  4993.  /**
  4994.  
  4995.   * Retrives the saved value from persisted data.
  4996.  
  4997.   *
  4998.  
  4999.   * @param {String} key The key of the value to retrieve
  5000.  
  5001.   * @param {Object} persistObj The persistent Object returned from init
  5002.  
  5003.   * @param {String} [store] Optional value to name the store to save the data. Only applicable in IE
  5004.  
  5005.   */
  5006.  
  5007.  get : function(key, persistObj, store){
  5008.  
  5009.  
  5010.  
  5011.   if(navigator.userAgent.toLowerCase().indexOf("msie")>-1)
  5012.  
  5013.   {
  5014.  
  5015.   if (!store)
  5016.  
  5017.   store = "AjaxTCRStore";
  5018.  
  5019.  
  5020.  
  5021.   if (persistObj)
  5022.  
  5023.   {
  5024.  
  5025.   persistObj.load(store);
  5026.  
  5027.   return persistObj.getAttribute(key);
  5028.  
  5029.   }
  5030.  
  5031.   }
  5032.  
  5033.   else if (typeof(globalStorage) != "undefined")
  5034.  
  5035.   {
  5036.  
  5037.   try{
  5038.  
  5039.   var storage = globalStorage[document.domain];
  5040.  
  5041.   return storage.getItem(key);
  5042.  
  5043.   }
  5044.  
  5045.   catch(e){}
  5046.  
  5047.   }
  5048.  
  5049.  
  5050.  
  5051.   //if it the storage hasn't been found, check cookies
  5052.  
  5053.   var i=0;
  5054.  
  5055.   var fullvalue = "";
  5056.  
  5057.   do
  5058.  
  5059.   {
  5060.  
  5061.   var val = AjaxTCR.comm.cookie.get(key+i.toString());
  5062.  
  5063.   if (val)
  5064.  
  5065.   fullvalue += val;
  5066.  
  5067.   i++;
  5068.  
  5069.   }while(val);
  5070.  
  5071.  
  5072.  
  5073.   if (fullvalue != "")
  5074.  
  5075.   return fullvalue;
  5076.  
  5077.  
  5078.  
  5079.  
  5080.  
  5081.   return null;
  5082.  
  5083.  },
  5084.  
  5085.  
  5086.  
  5087.  /**
  5088.  
  5089.   * Returns all items from the storage in an associative array of name/value pairs
  5090.  
  5091.   *
  5092.  
  5093.   * @param {Object} persistObj The persistent Object returned from init
  5094.  
  5095.   * @param {String} [store] Optional value to name the store to save the data. Only applicable in IE
  5096.  
  5097.   */
  5098.  
  5099.  getAll : function(persistObj, store){
  5100.  
  5101.  
  5102.  
  5103.   if(navigator.userAgent.toLowerCase().indexOf("msie")>-1)
  5104.  
  5105.   {
  5106.  
  5107.   if (!store)
  5108.  
  5109.   store = "AjaxTCRStore";
  5110.  
  5111.  
  5112.  
  5113.   if (persistObj)
  5114.  
  5115.   {
  5116.  
  5117.   var allitems = AjaxTCR.storage.get("AjaxTCRAllItems", persistObj, store);
  5118.  
  5119.   return AjaxTCR.data.decodeJSON(allitems);
  5120.  
  5121.   }
  5122.  
  5123.   }
  5124.  
  5125.   else if (typeof(globalStorage) != "undefined")
  5126.  
  5127.   {
  5128.  
  5129.   try{
  5130.  
  5131.   var storage = globalStorage[document.domain];
  5132.  
  5133.   return storage;
  5134.  
  5135.   }
  5136.  
  5137.   catch(e){}
  5138.  
  5139.   }
  5140.  
  5141.  
  5142.  
  5143.  
  5144.  
  5145.   //if it the storage hasn't been found, check cookies
  5146.  
  5147.  
  5148.  
  5149.   var allitems = AjaxTCR.storage.get("AjaxTCRAllItems");
  5150.  
  5151.   if (allitems)
  5152.  
  5153.   {
  5154.  
  5155.   var items = {};
  5156.  
  5157.   var keys = AjaxTCR.data.decodeJSON(allitems);
  5158.  
  5159.   for (var i=0;i<keys.length;i++)
  5160.  
  5161.   items[keys[i]] = AjaxTCR.storage.get(keys[i]);
  5162.  
  5163.   return items;
  5164.  
  5165.   }
  5166.  
  5167.  
  5168.  
  5169.  
  5170.  
  5171.   return null;
  5172.  
  5173.  },
  5174.  
  5175.  
  5176.  
  5177.  /**
  5178.  
  5179.   * Removes all items from persistent storage.
  5180.  
  5181.   *
  5182.  
  5183.   * @param {Object} persistObj The persistent Object returned from init
  5184.  
  5185.   * @param {String} [store] Optional value to name the store to save the data. Only applicable in IE
  5186.  
  5187.   */
  5188.  
  5189.  clear : function(persistObj, store){
  5190.  
  5191.  
  5192.  
  5193.   var allItems = AjaxTCR.storage.getAll(persistObj, store);
  5194.  
  5195.   for (var i in allItems)
  5196.  
  5197.   AjaxTCR.storage.remove(i, persistObj, store);
  5198.  
  5199.  },
  5200.  
  5201.  
  5202.  
  5203.  /**
  5204.  
  5205.   * Remove the given item from persistent storage.
  5206.  
  5207.   *
  5208.  
  5209.   * @param {string} key The name of the item to remove from storage
  5210.  
  5211.   * @param {Object} persistObj The persistent Object returned from init
  5212.  
  5213.   * @param {String} [store] Optional value to name the store to save the data. Only applicable in IE
  5214.  
  5215.   */
  5216.  
  5217.  remove : function(key, persistObj, store){
  5218.  
  5219.   var removeFlag = 0;
  5220.  
  5221.   if(navigator.userAgent.toLowerCase().indexOf("msie")>-1 )
  5222.  
  5223.   {
  5224.  
  5225.   if (!store)
  5226.  
  5227.   store = "AjaxTCRStore";
  5228.  
  5229.  
  5230.  
  5231.   if (persistObj)
  5232.  
  5233.   {
  5234.  
  5235.   var allitems = AjaxTCR.storage.get("AjaxTCRAllItems", persistObj, store);
  5236.  
  5237.   if (allitems)
  5238.  
  5239.   {
  5240.  
  5241.   allitems = AjaxTCR.data.decodeJSON(allitems);
  5242.  
  5243.   if (allitems[key])
  5244.  
  5245.   delete allitems[key];
  5246.  
  5247.   allitems = AjaxTCR.data.encodeJSON(allitems);
  5248.  
  5249.   persistObj.setAttribute("AjaxTCRAllItems",allitems);
  5250.  
  5251.   }
  5252.  
  5253.  
  5254.  
  5255.   persistObj.removeAttribute(key);
  5256.  
  5257.   persistObj.save(store);
  5258.  
  5259.  
  5260.  
  5261.   removeFlag = 1;
  5262.  
  5263.   }
  5264.  
  5265.   }
  5266.  
  5267.   else if (typeof(globalStorage) != "undefined")
  5268.  
  5269.   {
  5270.  
  5271.   try{
  5272.  
  5273.   var storage = globalStorage[document.domain];
  5274.  
  5275.   delete storage[key];
  5276.  
  5277.   removeFlag = 1;
  5278.  
  5279.   }
  5280.  
  5281.   catch(e){}
  5282.  
  5283.   }
  5284.  
  5285.  
  5286.  
  5287.   if (!removeFlag)
  5288.  
  5289.   {
  5290.  
  5291.   /* First remove from global object */
  5292.  
  5293.   var allitems = AjaxTCR.storage.get("AjaxTCRAllItems", persistObj, store);
  5294.  
  5295.   if (allitems)
  5296.  
  5297.   {
  5298.  
  5299.   allitems = AjaxTCR.data.decodeJSON(allitems);
  5300.  
  5301.   for (var i=allitems.length-1;i>=0;i--)
  5302.  
  5303.   {
  5304.  
  5305.   if (allitems[i] == key)
  5306.  
  5307.   delete allitems[i];
  5308.  
  5309.   }
  5310.  
  5311.   var allitemsString = AjaxTCR.data.encodeJSON(allitems);
  5312.  
  5313.   var loops = Math.floor(allitemsString.length/AjaxTCR.storage.DEFAULT_MAX_COOKIE_SIZE + 1);
  5314.  
  5315.   var now = new Date();
  5316.  
  5317.   now.setMonth(now.getMonth()+1);
  5318.  
  5319.   var expires = now.toGMTString();
  5320.  
  5321.   for (var i=0;i<loops;i++)
  5322.  
  5323.   AjaxTCR.comm.cookie.set("AjaxTCRAllItems"+i.toString(), allitemsString.substring(i*AjaxTCR.storage.DEFAULT_MAX_COOKIE_SIZE, AjaxTCR.storage.DEFAULT_MAX_COOKIE_SIZE), expires);
  5324.  
  5325.  
  5326.  
  5327.   var i=0;
  5328.  
  5329.   do
  5330.  
  5331.   {
  5332.  
  5333.   var val = AjaxTCR.comm.cookie.get(key+i.toString());
  5334.  
  5335.   if (val)
  5336.  
  5337.   AjaxTCR.comm.cookie.remove(key+i.toString());
  5338.  
  5339.   i++;
  5340.  
  5341.   }while(val);
  5342.  
  5343.  
  5344.  
  5345.   }
  5346.  
  5347.  
  5348.  
  5349.  
  5350.  
  5351.   }
  5352.  
  5353.   }
  5354.  
  5355.  };
  5356.  
  5357.  
  5358.  
  5359.  
  5360.  
  5361.  /************************************* AjaxTCR.template *****************************/
  5362.  
  5363.  /**
  5364.  
  5365.   * The template class of the library. Is called directly from AjaxTCR.comm, but can also be called by the user.
  5366.  
  5367.   *
  5368.  
  5369.   * @class AjaxTCR.template
  5370.  
  5371.   * @static
  5372.  
  5373.   */
  5374.  
  5375.  AjaxTCR.template = {
  5376.  
  5377.  
  5378.  
  5379.   /** flag to indicate if we already included the template library
  5380.  
  5381.   * @private
  5382.  
  5383.   */
  5384.  
  5385.   _libraryIncluded : false,
  5386.  
  5387.  
  5388.  
  5389.   /** The cache object
  5390.  
  5391.   * @private
  5392.  
  5393.   */
  5394.  
  5395.   _cache : new Array(),
  5396.  
  5397.  
  5398.  
  5399.  /**
  5400.  
  5401.   * Method that takes a template and a JSON object and converts into output
  5402.  
  5403.   * @param {string} template template string.
  5404.  
  5405.   * @param {JSON string} data a JSON string to be used in rendering template
  5406.  
  5407.   * @return {string} String formatted by template and populated with data from data
  5408.  
  5409.   */
  5410.  
  5411.  translateString : function(template, data){
  5412.  
  5413.   var myTemplateObj = TrimPath.parseTemplate(template);
  5414.  
  5415.   var result = myTemplateObj.process(AjaxTCR.data.decodeJSON(data));
  5416.  
  5417.   return result;
  5418.  
  5419.  },
  5420.  
  5421.  
  5422.  
  5423.  /**
  5424.  
  5425.   * Method that takes a template filename and a JSON object, fetches the file, and converts into output
  5426.  
  5427.   *
  5428.  
  5429.   * @param {string} template template filename.
  5430.  
  5431.   * @param {string} data a JSON string to be used in rendering template
  5432.  
  5433.   * @param {boolean} cache a boolean indicating whether to cache the response or not
  5434.  
  5435.   * @return {string} output string formatted by given template file and polulated with data from data.
  5436.  
  5437.   */
  5438.  
  5439.  translateFile : function(templatefilename, data, cache){
  5440.  
  5441.  
  5442.  
  5443.   if (typeof(cache) == "undefined")
  5444.  
  5445.   cache = true;
  5446.  
  5447.  
  5448.  
  5449.   var template = AjaxTCR.template.getFromCache(templatefilename);
  5450.  
  5451.   if (!template)
  5452.  
  5453.   {
  5454.  
  5455.   var templateRequest = AjaxTCR.comm.sendRequest(templatefilename, {async:false, cacheResponse:cache});
  5456.  
  5457.   var template = templateRequest.responseText;
  5458.  
  5459.   if (cache && template)
  5460.  
  5461.   AjaxTCR.template.addToCache(templatefilename, template);
  5462.  
  5463.   }
  5464.  
  5465.  
  5466.  
  5467.   if (typeof(data) == "string")
  5468.  
  5469.   data = AjaxTCR.data.decodeJSON(data);
  5470.  
  5471.  
  5472.  
  5473.   var myTemplateObj = TrimPath.parseTemplate(template);
  5474.  
  5475.   var result = myTemplateObj.process(data);
  5476.  
  5477.   return result;
  5478.  
  5479.  },
  5480.  
  5481.  
  5482.  
  5483.  /**
  5484.  
  5485.   * Method that caches a template file usually the URL of the template file is used as the key and template as the value.
  5486.  
  5487.   * @param {string} key key to add to the template cache
  5488.  
  5489.   * @param {string} val value to store in the template cache
  5490.  
  5491.   */
  5492.  
  5493.  addToCache : function(key, val){
  5494.  
  5495.  
  5496.  
  5497.   var item = AjaxTCR.template._createCacheItem(key, val);
  5498.  
  5499.   AjaxTCR.template._cache.push(item);
  5500.  
  5501.  },
  5502.  
  5503.  
  5504.  
  5505.  /**
  5506.  
  5507.   * Adds a url and optional value string to the template cache. If the value is set, it simply calls addToCache.
  5508.  
  5509.   * If value is not set, it requests the file at the given URL and caches the results
  5510.  
  5511.   *
  5512.  
  5513.   * @param {string} key key to add to the template cache
  5514.  
  5515.   * @param {string} val value to store in the template cache
  5516.  
  5517.   */
  5518.  
  5519.  cache : function(key, val){
  5520.  
  5521.  
  5522.  
  5523.   if (val)
  5524.  
  5525.   AjaxTCR.template.addToCache(key, val);
  5526.  
  5527.   else
  5528.  
  5529.   {
  5530.  
  5531.   var options = {cacheTemplate:true,
  5532.  
  5533.   onSuccess: function(response){
  5534.  
  5535.   if(response.responseText)
  5536.  
  5537.   AjaxTCR.template.addToCache(response.url, response.responseText);
  5538.  
  5539.   }
  5540.  
  5541.   };
  5542.  
  5543.   AjaxTCR.comm.sendRequest(key, options);
  5544.  
  5545.  
  5546.  
  5547.   }
  5548.  
  5549.  },
  5550.  
  5551.  
  5552.  
  5553.  /**
  5554.  
  5555.   * Fetches a page that contains a template bundle. The expected response is in this format:
  5556.  
  5557.   * &lt;!-- Template-Begin URL='rating-Ajax.tpl' --&gt;<br />
  5558.  
  5559.   * &lt;h3&gt;Thanks for voting!&lt;/h3&gt;<br />
  5560.  
  5561.   * &lt;p&gt;Your rating: {$userrating}. &lt;br /&gt;<br />
  5562.  
  5563.   * Average rating: {$avgrating}.&lt;br /&gt;<br />
  5564.  
  5565.   * Total votes: {$totalvotes}. &lt;br /&gt;<br />
  5566.  
  5567.   * &lt;/p&gt;<br />
  5568.  
  5569.   * &lt;!-- Template-End --&gt;<br />
  5570.  
  5571.   * &lt;!-- Template-Begin URL='thankyou-Ajax.tpl' --&gt;<br />
  5572.  
  5573.   * &lt;h2&gt;Thank you for registering {$username}&lt;/h2&gt;<br />
  5574.  
  5575.   * &lt;p&gt;Contact technical support at 555-1212&lt;/p&gt;<br />
  5576.  
  5577.   * &lt;!-- Template-End --&gt;<br />
  5578.  
  5579.   *
  5580.  
  5581.   * @param url - URL of the template bundle to fetch
  5582.  
  5583.   */
  5584.  
  5585.  cacheBundle : function(url){
  5586.  
  5587.  
  5588.  
  5589.   var options = {cacheTemplate:true,
  5590.  
  5591.   onSuccess: AjaxTCR.template._parseTemplateBundle};
  5592.  
  5593.   AjaxTCR.comm.sendRequest(url, options);
  5594.  
  5595.  },
  5596.  
  5597.  
  5598.  
  5599.  /**
  5600.  
  5601.   * Public method that resets the template's cache
  5602.  
  5603.   *
  5604.  
  5605.   */
  5606.  
  5607.  clearCache : function(){
  5608.  
  5609.   AjaxTCR.template._cache = new Array();
  5610.  
  5611.  },
  5612.  
  5613.  
  5614.  
  5615.  /**
  5616.  
  5617.   * public method to fetch a cached template based on the key
  5618.  
  5619.   * @param {string} key key to add to the template cache
  5620.  
  5621.   * @return {string} the cached object value if found
  5622.  
  5623.   */
  5624.  
  5625.  getFromCache: function(key){
  5626.  
  5627.   var cacheObject = null;
  5628.  
  5629.   /* Search for item */
  5630.  
  5631.   for (var i=0;i<AjaxTCR.template._cache.length;i++)
  5632.  
  5633.   {
  5634.  
  5635.   if (AjaxTCR.template._cache[i].key == key)
  5636.  
  5637.   {
  5638.  
  5639.   cacheObject = AjaxTCR.template._cache[i];
  5640.  
  5641.   break;
  5642.  
  5643.   }
  5644.  
  5645.   }
  5646.  
  5647.  
  5648.  
  5649.   if (cacheObject)
  5650.  
  5651.   return cacheObject.value;
  5652.  
  5653.   else
  5654.  
  5655.   return null;
  5656.  
  5657.  },
  5658.  
  5659.  
  5660.  
  5661.  /**
  5662.  
  5663.   * public method to remove an item from the template cache based on the key
  5664.  
  5665.   * @param {string} key key of item to remove from template cache
  5666.  
  5667.   */
  5668.  
  5669.  removeFromCache : function(key){
  5670.  
  5671.   for (var i=0;i<AjaxTCR.template._cache.length;i++)
  5672.  
  5673.   {
  5674.  
  5675.   if (AjaxTCR.template._cache[i].key == key)
  5676.  
  5677.   {
  5678.  
  5679.   AjaxTCR.template._cache.splice(i,1);
  5680.  
  5681.   break;
  5682.  
  5683.   }
  5684.  
  5685.   }
  5686.  
  5687.  },
  5688.  
  5689.  
  5690.  
  5691.  
  5692.  
  5693.  /************************************* Private Template Methods *****************************/
  5694.  
  5695.  
  5696.  
  5697.  /**
  5698.  
  5699.   * private method that creates a cache object based on the given key and val
  5700.  
  5701.   *
  5702.  
  5703.   * @private
  5704.  
  5705.   * @param {string} key Key of the new cache object
  5706.  
  5707.   * @param {string} val Value of the new cache object
  5708.  
  5709.   */
  5710.  
  5711.  _createCacheItem : function(key, val){
  5712.  
  5713.   var cacheObject = {};
  5714.  
  5715.   cacheObject.key = key;
  5716.  
  5717.   cacheObject.value = val;
  5718.  
  5719.   return cacheObject;
  5720.  
  5721.  },
  5722.  
  5723.  
  5724.  
  5725.  /**
  5726.  
  5727.   * Dynamically include the template library on usage.
  5728.  
  5729.   *
  5730.  
  5731.   * @private
  5732.  
  5733.   */
  5734.  
  5735.  _includeLibrary : function(){
  5736.  
  5737.   if (!AjaxTCR.template._libraryIncluded)
  5738.  
  5739.   document.write('<sc' + 'ript type="text/javascript" src="http://ajaxref.com/lib/trimpath/template.js"></sc' + 'ript>');
  5740.  
  5741.  
  5742.  
  5743.   AjaxTCR.template._libraryIncluded = true;
  5744.  
  5745.  },
  5746.  
  5747.  
  5748.  
  5749.  /**
  5750.  
  5751.   * Takes a template bundle, parses it, and adds each item to the cache
  5752.  
  5753.   *
  5754.  
  5755.   * @private
  5756.  
  5757.   * @param {response} The response object from the XHR
  5758.  
  5759.   *
  5760.  
  5761.   */
  5762.  
  5763.  _parseTemplateBundle : function(response){
  5764.  
  5765.   var bundle = response.responseText;
  5766.  
  5767.   var re = /\s*\<!--\s*Template-Begin([\w\W]*?)\<!--\s*Template-End\s*--\>\s*/ig;
  5768.  
  5769.   var matches = bundle.match(re);
  5770.  
  5771.   for (var i=0;i<matches.length;i++)
  5772.  
  5773.   {
  5774.  
  5775.   var parts = /\s*\<!--\s*Template-Begin\s*URL=['"]([^'"]*)['"]\s*--\>([\w\W]*?)\<!--\s*Template-End\s*--\>\s*/i;
  5776.  
  5777.   var data = parts.exec(matches[i]);
  5778.  
  5779.   if (data)
  5780.  
  5781.   AjaxTCR.template.addToCache(data[1], data[2]);
  5782.  
  5783.   }
  5784.  
  5785.  }
  5786.  
  5787.  
  5788.  
  5789.  
  5790.  
  5791.  };
  5792.  
  5793.  
  5794.  
  5795.  
  5796.  
  5797.  
  5798.  
  5799.  /********************************************* Data Handling Methods *********************************************/
  5800.  
  5801.  /**
  5802.  
  5803.   * Several useful data functions. encode/decode/serialize for several different data formats. Many of these are
  5804.  
  5805.   * called from other parts of the library.
  5806.  
  5807.   *
  5808.  
  5809.   * @class AjaxTCR.data
  5810.  
  5811.   * @static
  5812.  
  5813.   */
  5814.  
  5815.  AjaxTCR.data = {
  5816.  
  5817.  
  5818.  
  5819.  /**
  5820.  
  5821.   * Public method to encode passed string values to make the URL safe.
  5822.  
  5823.   * Strictly encodes to x-www-urlencoded format vs. native methods found in JavaScript.
  5824.  
  5825.   *
  5826.  
  5827.   * @param {string} val - the value to encode
  5828.  
  5829.   * @return {string} a string that is properly x-www-urlencoded as a browser would do it
  5830.  
  5831.   */
  5832.  
  5833.  encodeValue : function(val) {
  5834.  
  5835.  
  5836.  
  5837.   var encodedVal;
  5838.  
  5839.  
  5840.  
  5841.   if (!encodeURIComponent)
  5842.  
  5843.   {
  5844.  
  5845.   encodedVal = escape(val);
  5846.  
  5847.   /* fix the omissions */
  5848.  
  5849.   encodedVal = encodedVal.replace(/@/g, '%40');
  5850.  
  5851.   encodedVal = encodedVal.replace(/\//g, '%2F');
  5852.  
  5853.   encodedVal = encodedVal.replace(/\+/g, '%2B');
  5854.  
  5855.   }
  5856.  
  5857.   else
  5858.  
  5859.   {
  5860.  
  5861.   encodedVal = encodeURIComponent(val);
  5862.  
  5863.   /* fix the omissions */
  5864.  
  5865.   encodedVal = encodedVal.replace(/~/g, '%7E');
  5866.  
  5867.   encodedVal = encodedVal.replace(/!/g, '%21');
  5868.  
  5869.   encodedVal = encodedVal.replace(/\(/g, '%28');
  5870.  
  5871.   encodedVal = encodedVal.replace(/\)/g, '%29');
  5872.  
  5873.   encodedVal = encodedVal.replace(/'/g, '%27');
  5874.  
  5875.   }
  5876.  
  5877.  
  5878.  
  5879.   /* clean up the spaces and return */
  5880.  
  5881.   return encodedVal.replace(/\%20/g,'+');
  5882.  
  5883.  } ,
  5884.  
  5885.  
  5886.  
  5887.  /**
  5888.  
  5889.   * Public method to decode passed string values from a URL safe string.
  5890.  
  5891.   *
  5892.  
  5893.   * @param {string} val - the value to decode
  5894.  
  5895.   * @return {string} a string that is properly reversed from the proper x-www-urlencoded format
  5896.  
  5897.   */
  5898.  
  5899.  decodeValue : function(val) {
  5900.  
  5901.   var decodedVal;
  5902.  
  5903.  
  5904.  
  5905.   if (!decodeURIComponent)
  5906.  
  5907.   {
  5908.  
  5909.   decodedVal = val;
  5910.  
  5911.   /* fix the omissions */
  5912.  
  5913.   decodedVal = decodedVal.replace(/\%40/g, '@');
  5914.  
  5915.   decodedVal = decodedVal.replace(/\%2F/g, '/');
  5916.  
  5917.   decodedVal = decodedVal.replace(/\%2B/g, '+');
  5918.  
  5919.   decodedVal = unescape(val);
  5920.  
  5921.  
  5922.  
  5923.   }
  5924.  
  5925.   else
  5926.  
  5927.   {
  5928.  
  5929.   /* fix the omissions */
  5930.  
  5931.   decodedVal = val;
  5932.  
  5933.   decodedVal = decodedVal.replace(/\%7E/g, '~');
  5934.  
  5935.   decodedVal = decodedVal.replace(/\%21/g, '!');
  5936.  
  5937.   decodedVal = decodedVal.replace(/\%28/g, '(');
  5938.  
  5939.   decodedVal = decodedVal.replace(/\%29/g, ')');
  5940.  
  5941.   decodedVal = decodedVal.replace(/\%27/g, "'");
  5942.  
  5943.  
  5944.  
  5945.   decodedVal = decodeURIComponent(val);
  5946.  
  5947.  
  5948.  
  5949.   }
  5950.  
  5951.  
  5952.  
  5953.   /* clean up the spaces and return */
  5954.  
  5955.   return decodedVal.replace(/\+/g,' ');
  5956.  
  5957.   } ,
  5958.  
  5959.  
  5960.  
  5961.  /**
  5962.  
  5963.   * Public method to convert tag characters to &lt; and &gt; and change \n to <br />
  5964.  
  5965.   *
  5966.  
  5967.   * @param {string} str String to modify
  5968.  
  5969.   * @return {string} The str value with the conversions in place
  5970.  
  5971.   */
  5972.  
  5973.  encodeAsHTML : function(str) {
  5974.  
  5975.   var convertedString = str.replace(/<([^>]*)>/g, "&lt;$1&gt;")
  5976.  
  5977.   convertedString = convertedString.replace(/\n/g, "<br/>");
  5978.  
  5979.   return convertedString;
  5980.  
  5981.   },
  5982.  
  5983.  
  5984.  
  5985.  /**
  5986.  
  5987.   * Public method to encode passed string values into base64.
  5988.  
  5989.   *
  5990.  
  5991.   * @param {string} inputStr A string value to encode
  5992.  
  5993.   * @return {string} The inputStr value encoded in base64
  5994.  
  5995.   */
  5996.  
  5997.  encode64 : function(inputStr)
  5998.  
  5999.  {
  6000.  
  6001.   var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  6002.  
  6003.   var outputStr = "";
  6004.  
  6005.   var i = 0;
  6006.  
  6007.  
  6008.  
  6009.   while (i<inputStr.length)
  6010.  
  6011.   {
  6012.  
  6013.   var byte1 = inputStr.charCodeAt(i++);
  6014.  
  6015.   var byte2 = inputStr.charCodeAt(i++);
  6016.  
  6017.   var byte3 = inputStr.charCodeAt(i++);
  6018.  
  6019.  
  6020.  
  6021.   var enc1 = byte1 >> 2;
  6022.  
  6023.   var enc2 = ((byte1 & 3) << 4) | (byte2 >> 4);
  6024.  
  6025.  
  6026.  
  6027.   var enc3, enc4;
  6028.  
  6029.   if (isNaN(byte2))
  6030.  
  6031.   enc3 = enc4 = 64;
  6032.  
  6033.   else
  6034.  
  6035.   {
  6036.  
  6037.   enc3 = ((byte2 & 15) << 2) | (byte3 >> 6);
  6038.  
  6039.   if (isNaN(byte3))
  6040.  
  6041.   enc4 = 64;
  6042.  
  6043.   else
  6044.  
  6045.   enc4 = byte3 & 63;
  6046.  
  6047.   }
  6048.  
  6049.  
  6050.  
  6051.   outputStr += b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4);
  6052.  
  6053.   }
  6054.  
  6055.  
  6056.  
  6057.   return outputStr;
  6058.  
  6059.  },
  6060.  
  6061.  
  6062.  
  6063.  /**
  6064.  
  6065.   * Public method to decode passed string values from base64.
  6066.  
  6067.   *
  6068.  
  6069.   * @param {string} inputStr A string in base64 format
  6070.  
  6071.   * @return {string} The decoded string
  6072.  
  6073.   */
  6074.  
  6075.  decode64 : function(inputStr)
  6076.  
  6077.  {
  6078.  
  6079.   var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  6080.  
  6081.   var outputStr = "";
  6082.  
  6083.   var i = 0;
  6084.  
  6085.   inputStr = inputStr.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  6086.  
  6087.  
  6088.  
  6089.   while (i<inputStr.length)
  6090.  
  6091.   {
  6092.  
  6093.   var dec1 = b64.indexOf(inputStr.charAt(i++));
  6094.  
  6095.   var dec2 = b64.indexOf(inputStr.charAt(i++));
  6096.  
  6097.   var dec3 = b64.indexOf(inputStr.charAt(i++));
  6098.  
  6099.   var dec4 = b64.indexOf(inputStr.charAt(i++));
  6100.  
  6101.  
  6102.  
  6103.   var byte1 = (dec1 << 2) | (dec2 >> 4);
  6104.  
  6105.   var byte2 = ((dec2 & 15) << 4) | (dec3 >> 2);
  6106.  
  6107.   var byte3 = ((dec3 & 3) << 6) | dec4;
  6108.  
  6109.  
  6110.  
  6111.   outputStr += String.fromCharCode(byte1);
  6112.  
  6113.   if (dec3 != 64)
  6114.  
  6115.   outputStr += String.fromCharCode(byte2);
  6116.  
  6117.   if (dec4 != 64)
  6118.  
  6119.   outputStr += String.fromCharCode(byte3);
  6120.  
  6121.   }
  6122.  
  6123.  
  6124.  
  6125.   return outputStr;
  6126.  
  6127.  },
  6128.  
  6129.  
  6130.  
  6131.  /**
  6132.  
  6133.   * Public method to create a serialized payload based on the contents of a form and the specified encoding value.
  6134.  
  6135.   * trigger and evt are optional and used to firm up the accuracy between what the browser would send and what we send.
  6136.  
  6137.   *
  6138.  
  6139.   * @param {object} form The form to be serialized
  6140.  
  6141.   * @param {string} encoding The encoding of the result. Options are "application/json", "application/x-www-form-urlencoded", "text/plain", "text/xml"
  6142.  
  6143.   * @param {object} trigger The element that caused the submission of the form. input type="button" fields will only be included in the payload if they triggered the submission.
  6144.  
  6145.   * @param {object} evt In the case that a input type="image" caused the submission, if the evt is passed in, the coordinates of the click will be put in the payload
  6146.  
  6147.   * @return {string} The payload serialized according to the specified encoding.
  6148.  
  6149.   */
  6150.  
  6151.  
  6152.  
  6153.  serializeForm : function(form, encoding, trigger, evt) {
  6154.  
  6155.   if (typeof(form) == "string")
  6156.  
  6157.   {
  6158.  
  6159.   var formObject = document.forms[form];
  6160.  
  6161.   if (formObject == null)
  6162.  
  6163.   formObject = document.getElementById(form);
  6164.  
  6165.  
  6166.  
  6167.   form = formObject;
  6168.  
  6169.   }
  6170.  
  6171.   var x=0,y=0;
  6172.  
  6173.   if (trigger && trigger.type == "image" && trigger.name)
  6174.  
  6175.   {
  6176.  
  6177.   if (window.event)
  6178.  
  6179.   {
  6180.  
  6181.   x = window.event.offsetX;
  6182.  
  6183.   y = window.event.offsetY;
  6184.  
  6185.   }
  6186.  
  6187.   else if (evt.target)
  6188.  
  6189.   {
  6190.  
  6191.   var coords = {x: 0, y: 0 };
  6192.  
  6193.   var elmt = trigger;
  6194.  
  6195.   while (elmt)
  6196.  
  6197.   {
  6198.  
  6199.   coords.x += elmt.offsetLeft;
  6200.  
  6201.   coords.y += elmt.offsetTop;
  6202.  
  6203.   elmt = elmt.offsetParent;
  6204.  
  6205.   }
  6206.  
  6207.  
  6208.  
  6209.   x = evt.clientX + window.scrollX - coords.x - 1 ;
  6210.  
  6211.   y = evt.clientY + window.scrollY - coords.y - 1;
  6212.  
  6213.   }
  6214.  
  6215.   }
  6216.  
  6217.  
  6218.  
  6219.   var formValues = AjaxTCR.data._beginEncode(encoding);
  6220.  
  6221.   for (var i =0; i < form.elements.length; i++)
  6222.  
  6223.   {
  6224.  
  6225.   var currentField = form.elements[i];
  6226.  
  6227.   var fieldName = currentField.name;
  6228.  
  6229.   var fieldType = currentField.type;
  6230.  
  6231.  
  6232.  
  6233.   /* Disabled and unnamed fields are not sent by browsers so ignore them */
  6234.  
  6235.   if ((!currentField.disabled) && fieldName)
  6236.  
  6237.   {
  6238.  
  6239.   switch (fieldType)
  6240.  
  6241.   {
  6242.  
  6243.   case "text":
  6244.  
  6245.   case "password":
  6246.  
  6247.   case "hidden":
  6248.  
  6249.   case "textarea": formValues = AjaxTCR.data._encode(formValues, fieldName, currentField.value, encoding);
  6250.  
  6251.   break;
  6252.  
  6253.   case "radio":
  6254.  
  6255.   case "checkbox": if (currentField.checked)
  6256.  
  6257.   formValues = AjaxTCR.data._encode(formValues, fieldName, currentField.value, encoding);
  6258.  
  6259.   break;
  6260.  
  6261.   case 'select-one':
  6262.  
  6263.   case 'select-multiple': for (var j=0; j< currentField.options.length; j++)
  6264.  
  6265.   if (currentField.options[j].selected)
  6266.  
  6267.   {
  6268.  
  6269.   formValues = AjaxTCR.data._encode(formValues, fieldName, (currentField.options[j].value != null && currentField.options[j].value != "") ? currentField.options[j].value : currentField.options[j].text , encoding);
  6270.  
  6271.   }
  6272.  
  6273.   break;
  6274.  
  6275.   case "file": if (currentField.value)
  6276.  
  6277.   return "fileupload";
  6278.  
  6279.   else
  6280.  
  6281.   formValues = AjaxTCR.data._encode(formValues, fieldName, currentField.value, encoding);
  6282.  
  6283.   break;
  6284.  
  6285.   case "submit": if (currentField == trigger)
  6286.  
  6287.   formValues = AjaxTCR.data._encode(formValues, fieldName, currentField.value, encoding);
  6288.  
  6289.   break;
  6290.  
  6291.   default: continue; /* everything else like fieldset you don't want */
  6292.  
  6293.   }
  6294.  
  6295.   }
  6296.  
  6297.  
  6298.  
  6299.   }
  6300.  
  6301.  
  6302.  
  6303.   if (trigger && trigger.type == "image" && trigger.name)
  6304.  
  6305.   {
  6306.  
  6307.   /* this is where we need to insert the trigger image information */
  6308.  
  6309.   formValues = AjaxTCR.data._encode(formValues, trigger.name + ".x", x, encoding);
  6310.  
  6311.   formValues = AjaxTCR.data._encode(formValues, trigger.name + ".y", y, encoding);
  6312.  
  6313.   formValues = AjaxTCR.data._encode(formValues, trigger.name, trigger.value, encoding);
  6314.  
  6315.   }
  6316.  
  6317.  
  6318.  
  6319.   /* Clean up payload string */
  6320.  
  6321.   formValues = AjaxTCR.data._completeEncoding(formValues, encoding);
  6322.  
  6323.  
  6324.  
  6325.   return formValues;
  6326.  
  6327.   },
  6328.  
  6329.  
  6330.  
  6331.  /**
  6332.  
  6333.   * Public method to create/modify a serialized object based on an object
  6334.  
  6335.  
  6336.  
  6337.   * @param {object} payload the current object that will be appended to.
  6338.  
  6339.   * @param {object} obj is the object to add to the payload
  6340.  
  6341.   * @param {string} encoding The encoding of the result. Options are "application/json", "application/x-www-form-urlencoded", "text/plain", "text/xml"
  6342.  
  6343.   * @return {object} The new payload with the object included
  6344.  
  6345.   */
  6346.  
  6347.  
  6348.  
  6349.  serializeObject : function(payload, obj, encoding){
  6350.  
  6351.   /* Take care of any necessary bits if payload isn't empty */
  6352.  
  6353.   payload = AjaxTCR.data._continueEncoding(payload, encoding);
  6354.  
  6355.  
  6356.  
  6357.   /* encode each value in the object */
  6358.  
  6359.   for (var key in obj)
  6360.  
  6361.   payload = AjaxTCR.data._encode(payload, key, obj[key], encoding);
  6362.  
  6363.  
  6364.  
  6365.   /* Clean up payload string */
  6366.  
  6367.   payload = AjaxTCR.data._completeEncoding(payload, encoding);
  6368.  
  6369.   return payload;
  6370.  
  6371.  },
  6372.  
  6373.  
  6374.  
  6375.  /**
  6376.  
  6377.   * private method to encode one name/value pair and add it to a payload.
  6378.  
  6379.   *
  6380.  
  6381.   * @private
  6382.  
  6383.   * @param {object} payload is current object that will be appended to. It can be null.
  6384.  
  6385.   * @param {string} fieldName The name of the item to encode
  6386.  
  6387.   * @param {string} fieldValue The value of the item to encode
  6388.  
  6389.   * @param {string} encoding The encoding of the result. Options are "application/json", "application/x-www-form-urlencoded", "text/plain", "text/xml"
  6390.  
  6391.   * @return {object} The new payload with the new name/value pair included
  6392.  
  6393.   */
  6394.  
  6395.  _encode : function(payload, fieldName, fieldValue, encoding){
  6396.  
  6397.   switch(encoding)
  6398.  
  6399.   {
  6400.  
  6401.   case "application/json":
  6402.  
  6403.   payload[fieldName] = fieldValue;
  6404.  
  6405.   break;
  6406.  
  6407.   case "application/x-www-form-urlencoded":
  6408.  
  6409.   payload+=AjaxTCR.data.encodeValue(fieldName)+"="+AjaxTCR.data.encodeValue(fieldValue)+"&"
  6410.  
  6411.   break;
  6412.  
  6413.   case "text/plain":
  6414.  
  6415.   payload+=fieldName.replace(/,/g, "%2C") + "=" + fieldValue.replace(/,/g, "%2C") +","
  6416.  
  6417.   break;
  6418.  
  6419.   case "text/xml":
  6420.  
  6421.   var node = payload.createElement(fieldName);
  6422.  
  6423.   node.appendChild(payload.createTextNode(fieldValue));
  6424.  
  6425.   payload.lastChild.appendChild(node);
  6426.  
  6427.  
  6428.  
  6429.   break;
  6430.  
  6431.   }
  6432.  
  6433.  
  6434.  
  6435.   return payload;
  6436.  
  6437.  },
  6438.  
  6439.  
  6440.  
  6441.  /**
  6442.  
  6443.   * private method to create the base for the encoding object
  6444.  
  6445.   *
  6446.  
  6447.   * @private
  6448.  
  6449.   * @param {string} encoding The encoding of the result. Options are "application/json", "application/x-www-form-urlencoded", "text/plain", "text/xml"
  6450.  
  6451.   * @return {object} Either an empty string, xml frame, or an empty object depending on type
  6452.  
  6453.   */
  6454.  
  6455.  _beginEncode : function(encoding){
  6456.  
  6457.   switch(encoding)
  6458.  
  6459.   {
  6460.  
  6461.   case "application/json":
  6462.  
  6463.   if (payload == null)
  6464.  
  6465.   payload = {};
  6466.  
  6467.  
  6468.  
  6469.   break;
  6470.  
  6471.   case "application/x-www-form-urlencoded":
  6472.  
  6473.   if (payload == null)
  6474.  
  6475.   payload = "";
  6476.  
  6477.  
  6478.  
  6479.   break;
  6480.  
  6481.   case "text/plain":
  6482.  
  6483.   if (payload == null)
  6484.  
  6485.   payload = "";
  6486.  
  6487.  
  6488.  
  6489.   break;
  6490.  
  6491.   case "text/xml":
  6492.  
  6493.   if (payload == null)
  6494.  
  6495.   {
  6496.  
  6497.   var payload = AjaxTCR.data._createXMLDocument();
  6498.  
  6499.   if (window.navigator.userAgent.indexOf('Opera') == -1)
  6500.  
  6501.   {
  6502.  
  6503.   var xmlStmt = payload.createProcessingInstruction("xml"," version=\"1.0\" encoding=\"UTF-8\" ");
  6504.  
  6505.   payload.appendChild(xmlStmt);
  6506.  
  6507.   }
  6508.  
  6509.  
  6510.  
  6511.   var root = payload.createElement("payload");
  6512.  
  6513.   payload.appendChild(root);
  6514.  
  6515.   }
  6516.  
  6517.  
  6518.  
  6519.  
  6520.  
  6521.   break;
  6522.  
  6523.   }
  6524.  
  6525.  
  6526.  
  6527.   return payload;
  6528.  
  6529.  },
  6530.  
  6531.  
  6532.  
  6533.  /**
  6534.  
  6535.   * private method to clean up payload string when finished encoding.
  6536.  
  6537.   *
  6538.  
  6539.   * @private
  6540.  
  6541.   * @param {object} payload The payload to clean
  6542.  
  6543.   * @param {string} encoding The encoding of the result. Options are "application/json", "application/x-www-form-urlencoded", "text/plain", "text/xml"
  6544.  
  6545.   * @return {object} The final payload object with no loose ends.
  6546.  
  6547.   */
  6548.  
  6549.  _completeEncoding : function (payload, encoding ){
  6550.  
  6551.   /* Trim off the end & but avoid edge case problems with an empty form */
  6552.  
  6553.   if ((encoding == "application/x-www-form-urlencoded" || encoding == "text/plain") && payload.length > 0)
  6554.  
  6555.   payload = payload.substring(0,payload.length-1);
  6556.  
  6557.  
  6558.  
  6559.   return payload;
  6560.  
  6561.  },
  6562.  
  6563.  
  6564.  
  6565.  /**
  6566.  
  6567.   * private method to get payload ready to be appended to.
  6568.  
  6569.   * @private
  6570.  
  6571.   * @param {object} payload The payload to prepare for being appended to
  6572.  
  6573.   * @param {string} encoding The encoding of the result. Options are "application/json", "application/x-www-form-urlencoded", "text/plain", "text/xml"
  6574.  
  6575.   * @return {object} The payload in a form that it can now have the next value written to it.
  6576.  
  6577.   */
  6578.  
  6579.  _continueEncoding : function(payload, encoding){
  6580.  
  6581.   if (payload != "")
  6582.  
  6583.   {
  6584.  
  6585.   if (encoding == "application/x-www-form-urlencoded")
  6586.  
  6587.   payload += "&";
  6588.  
  6589.   else if (encoding == "text/plain")
  6590.  
  6591.   payload += ",";
  6592.  
  6593.   }
  6594.  
  6595.   return payload;
  6596.  
  6597.   },
  6598.  
  6599.  
  6600.  
  6601.  /**
  6602.  
  6603.   * Finds the best native or ActiveX object to use for an XML Document
  6604.  
  6605.   *
  6606.  
  6607.   * @private
  6608.  
  6609.   * @return {object} The XML Document
  6610.  
  6611.   */
  6612.  
  6613.  _createXMLDocument : function(){
  6614.  
  6615.   var xmlDoc = null;
  6616.  
  6617.   if (window.ActiveXObject)
  6618.  
  6619.   {
  6620.  
  6621.   var versions = ["Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"];
  6622.  
  6623.  
  6624.  
  6625.   for (var i=0;i<versions.length;i++)
  6626.  
  6627.   {
  6628.  
  6629.   try
  6630.  
  6631.   {
  6632.  
  6633.   xmlDoc = new ActiveXObject(versions[i]);
  6634.  
  6635.   break;
  6636.  
  6637.   }
  6638.  
  6639.   catch(err){}
  6640.  
  6641.   }
  6642.  
  6643.   }
  6644.  
  6645.   else
  6646.  
  6647.   xmlDoc = document.implementation.createDocument("", "", null);
  6648.  
  6649.  
  6650.  
  6651.   return xmlDoc;
  6652.  
  6653.   },
  6654.  
  6655.  
  6656.  
  6657.  /**
  6658.  
  6659.   * Returns the string version of the given XML Object
  6660.  
  6661.   *
  6662.  
  6663.   * @param {object} xmlObject The xml object
  6664.  
  6665.   * @return {string} The xmlObject in string form
  6666.  
  6667.   */
  6668.  
  6669.  serializeXML : function(xmlObject){
  6670.  
  6671.   var xmlString = "";
  6672.  
  6673.  
  6674.  
  6675.   if (typeof XMLSerializer != "undefined")
  6676.  
  6677.   xmlString = (new XMLSerializer()).serializeToString(xmlObject);
  6678.  
  6679.   else if (xmlObject.xml)
  6680.  
  6681.   xmlString = xmlObject.xml;
  6682.  
  6683.  
  6684.  
  6685.   return xmlString;
  6686.  
  6687.  },
  6688.  
  6689.  
  6690.  
  6691.  /**
  6692.  
  6693.   * Returns the XML Object of the given string
  6694.  
  6695.   *
  6696.  
  6697.   * @param {string} xmlStr A string that can be converted to XML
  6698.  
  6699.   * @return {object} The xmlObject generated from the string
  6700.  
  6701.   */
  6702.  
  6703.  serializeXMLString : function(xmlStr){
  6704.  
  6705.   if (window.DOMParser)
  6706.  
  6707.   var xmlDoc = (new DOMParser()).parseFromString(xmlStr, "text/xml");
  6708.  
  6709.   else
  6710.  
  6711.   {
  6712.  
  6713.   var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
  6714.  
  6715.   xmlDoc.async="false";
  6716.  
  6717.   xmlDoc.loadXML(xmlStr);
  6718.  
  6719.   }
  6720.  
  6721.  
  6722.  
  6723.   return xmlDoc;
  6724.  
  6725.  },
  6726.  
  6727.  
  6728.  
  6729.  
  6730.  
  6731.  /**
  6732.  
  6733.   * Convert JSON into JavaScript values
  6734.  
  6735.   *
  6736.  
  6737.   * @param {string} jsonString A string that can be converted to JavaScript arrays and objects
  6738.  
  6739.   * @return {object} A javascript object generated from the passed in string.
  6740.  
  6741.   */
  6742.  
  6743.  decodeJSON : function(jsonString){
  6744.  
  6745.   var j;
  6746.  
  6747.   if (jsonString.length > 1 && jsonString.substring(0,2) == "/*")
  6748.  
  6749.   jsonString = jsonString.substring(2,jsonString.lastIndexOf("*/"));
  6750.  
  6751.  
  6752.  
  6753.   try {
  6754.  
  6755.   j = eval('(' + jsonString + ')');
  6756.  
  6757.   }
  6758.  
  6759.   catch (e) {
  6760.  
  6761.   throw new SyntaxError('parseJSON');
  6762.  
  6763.   }
  6764.  
  6765.   return j;
  6766.  
  6767.  },
  6768.  
  6769.  
  6770.  
  6771.  /**
  6772.  
  6773.   * Turn JavaScript values into a JSON String
  6774.  
  6775.   *
  6776.  
  6777.   * @param {object} o A object to be converted into a JSON string
  6778.  
  6779.   * @return {string} A string representation of the passed in object
  6780.  
  6781.   */
  6782.  
  6783.  encodeJSON : function(o){
  6784.  
  6785.   var useHasOwn = {}.hasOwnProperty ? true : false;
  6786.  
  6787.   var pad = function(n) {
  6788.  
  6789.   return n < 10 ? '0' + n : n;
  6790.  
  6791.   };
  6792.  
  6793.  
  6794.  
  6795.   var m = {
  6796.  
  6797.   '\b': '\\b',
  6798.  
  6799.   '\t': '\\t',
  6800.  
  6801.   '\n': '\\n',
  6802.  
  6803.   '\f': '\\f',
  6804.  
  6805.   '\r': '\\r',
  6806.  
  6807.   '"' : '\\"',
  6808.  
  6809.   '\\': '\\\\'
  6810.  
  6811.   };
  6812.  
  6813.  
  6814.  
  6815.   if(typeof o == 'undefined' || o === null)
  6816.  
  6817.   return 'null';
  6818.  
  6819.   else if(o instanceof Array)
  6820.  
  6821.   {
  6822.  
  6823.   var a = ['['], b, i, l = o.length, v;
  6824.  
  6825.   for (i = 0; i < l; i += 1) {
  6826.  
  6827.   v = o[i];
  6828.  
  6829.   switch (typeof v) {
  6830.  
  6831.   case 'undefined':
  6832.  
  6833.   // case 'function':
  6834.  
  6835.   case 'unknown':
  6836.  
  6837.   break;
  6838.  
  6839.   default:
  6840.  
  6841.   if (b) {
  6842.  
  6843.   a.push(',');
  6844.  
  6845.   }
  6846.  
  6847.   a.push(v === null ? "null" : AjaxTCR.data.encodeJSON(v));
  6848.  
  6849.   b = true;
  6850.  
  6851.   }
  6852.  
  6853.   }
  6854.  
  6855.   a.push(']');
  6856.  
  6857.   return a.join('');
  6858.  
  6859.   }
  6860.  
  6861.   else if(o instanceof Date)
  6862.  
  6863.   {
  6864.  
  6865.   return '"' + o.getFullYear() + '-' +
  6866.  
  6867.   pad(o.getMonth() + 1) + '-' +
  6868.  
  6869.   pad(o.getDate()) + 'T' +
  6870.  
  6871.   pad(o.getHours()) + ':' +
  6872.  
  6873.   pad(o.getMinutes()) + ':' +
  6874.  
  6875.   pad(o.getSeconds()) + '"';
  6876.  
  6877.   }
  6878.  
  6879.   else if(typeof o == 'string')
  6880.  
  6881.   {
  6882.  
  6883.   var s = o;
  6884.  
  6885.   if (/["\\\x00-\x1f]/.test(s))
  6886.  
  6887.   {
  6888.  
  6889.   return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b)
  6890.  
  6891.   {
  6892.  
  6893.   var c = m[b];
  6894.  
  6895.   if(c){
  6896.  
  6897.   return c;
  6898.  
  6899.   }
  6900.  
  6901.   c = b.charCodeAt();
  6902.  
  6903.   return '\\u00' +
  6904.  
  6905.   Math.floor(c / 16).toString(16) +
  6906.  
  6907.   (c % 16).toString(16);
  6908.  
  6909.   }) + '"';
  6910.  
  6911.   }
  6912.  
  6913.   return '"' + s + '"';
  6914.  
  6915.   }
  6916.  
  6917.   else if(typeof o == 'number')
  6918.  
  6919.   {
  6920.  
  6921.   return isFinite(o) ? String(o) : "null";
  6922.  
  6923.   }
  6924.  
  6925.   else if(typeof o == 'boolean')
  6926.  
  6927.   {
  6928.  
  6929.   return String(o);
  6930.  
  6931.   }
  6932.  
  6933.   else if (typeof o == 'function')
  6934.  
  6935.   {
  6936.  
  6937.   //return String(o).replace(/\n/g, " ");
  6938.  
  6939.   return '( ' + String(o) + ' )';
  6940.  
  6941.   }
  6942.  
  6943.   else
  6944.  
  6945.   {
  6946.  
  6947.   var a = ['{'], b, i, v;
  6948.  
  6949.   for (var i in o) {
  6950.  
  6951.   try{
  6952.  
  6953.   if(!useHasOwn || o.hasOwnProperty(i)) {
  6954.  
  6955.   v = o[i];
  6956.  
  6957.   switch (typeof v) {
  6958.  
  6959.   case 'undefined':
  6960.  
  6961.   // case 'function':
  6962.  
  6963.   case 'unknown':
  6964.  
  6965.   break;
  6966.  
  6967.   case 'function':
  6968.  
  6969.   if (String(v).indexOf("[native code]") > -1)
  6970.  
  6971.   break;
  6972.  
  6973.   default:
  6974.  
  6975.   if(b)
  6976.  
  6977.   a.push(',');
  6978.  
  6979.  
  6980.  
  6981.   a.push(AjaxTCR.data.encodeJSON(i), ':', v === null ? "null" : AjaxTCR.data.encodeJSON(v));
  6982.  
  6983.   b = true;
  6984.  
  6985.   }
  6986.  
  6987.   }
  6988.  
  6989.   }
  6990.  
  6991.   catch(e){};
  6992.  
  6993.   }
  6994.  
  6995.   a.push('}');
  6996.  
  6997.   return a.join('');
  6998.  
  6999.   }
  7000.  
  7001.  },
  7002.  
  7003.  
  7004.  
  7005.  
  7006.  
  7007.  /**
  7008.  
  7009.   * encodeMD5(string)
  7010.  
  7011.   *
  7012.  
  7013.   * public method to get md5 encode a string
  7014.  
  7015.   * Based on Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
  7016.  
  7017.   * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
  7018.  
  7019.   * Distributed under the BSD License
  7020.  
  7021.   * See http://pajhome.org.uk/crypt/md5 for more info.
  7022.  
  7023.   *
  7024.  
  7025.   * @param {string} str The string to encode
  7026.  
  7027.   * @return {string} A string that is encoded in MD5 format
  7028.  
  7029.   */
  7030.  
  7031.  encodeMD5 : function(str){
  7032.  
  7033.   var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
  7034.  
  7035.   var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
  7036.  
  7037.   var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
  7038.  
  7039.  
  7040.  
  7041.   var len = str.length * chrsz;
  7042.  
  7043.  
  7044.  
  7045.   var x = Array();
  7046.  
  7047.   var mask = (1 << chrsz) - 1;
  7048.  
  7049.   for(var i = 0; i < len; i += chrsz)
  7050.  
  7051.   {
  7052.  
  7053.   x[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
  7054.  
  7055.   }
  7056.  
  7057.  
  7058.  
  7059.   /* append padding */
  7060.  
  7061.   x[len >> 5] |= 0x80 << ((len) % 32);
  7062.  
  7063.   x[(((len + 64) >>> 9) << 4) + 14] = len;
  7064.  
  7065.  
  7066.  
  7067.   var a = 1732584193;
  7068.  
  7069.   var b = -271733879;
  7070.  
  7071.   var c = -1732584194;
  7072.  
  7073.   var d = 271733878;
  7074.  
  7075.  
  7076.  
  7077.   for(var i = 0; i < x.length; i += 16)
  7078.  
  7079.   {
  7080.  
  7081.   var olda = a;
  7082.  
  7083.   var oldb = b;
  7084.  
  7085.   var oldc = c;
  7086.  
  7087.   var oldd = d;
  7088.  
  7089.  
  7090.  
  7091.   a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
  7092.  
  7093.   d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
  7094.  
  7095.   c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
  7096.  
  7097.   b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
  7098.  
  7099.   a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
  7100.  
  7101.   d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
  7102.  
  7103.   c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
  7104.  
  7105.   b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
  7106.  
  7107.   a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
  7108.  
  7109.   d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
  7110.  
  7111.   c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
  7112.  
  7113.   b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
  7114.  
  7115.   a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
  7116.  
  7117.   d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
  7118.  
  7119.   c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
  7120.  
  7121.   b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
  7122.  
  7123.  
  7124.  
  7125.   a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
  7126.  
  7127.   d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
  7128.  
  7129.   c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
  7130.  
  7131.   b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
  7132.  
  7133.   a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
  7134.  
  7135.   d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
  7136.  
  7137.   c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
  7138.  
  7139.   b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
  7140.  
  7141.   a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
  7142.  
  7143.   d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
  7144.  
  7145.   c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
  7146.  
  7147.   b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
  7148.  
  7149.   a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
  7150.  
  7151.   d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
  7152.  
  7153.   c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
  7154.  
  7155.   b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
  7156.  
  7157.  
  7158.  
  7159.   a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
  7160.  
  7161.   d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
  7162.  
  7163.   c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
  7164.  
  7165.   b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
  7166.  
  7167.   a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
  7168.  
  7169.   d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
  7170.  
  7171.   c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
  7172.  
  7173.   b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
  7174.  
  7175.   a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
  7176.  
  7177.   d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
  7178.  
  7179.   c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
  7180.  
  7181.   b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
  7182.  
  7183.   a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
  7184.  
  7185.   d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
  7186.  
  7187.   c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
  7188.  
  7189.   b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
  7190.  
  7191.  
  7192.  
  7193.   a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
  7194.  
  7195.   d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
  7196.  
  7197.   c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
  7198.  
  7199.   b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
  7200.  
  7201.   a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
  7202.  
  7203.   d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
  7204.  
  7205.   c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
  7206.  
  7207.   b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
  7208.  
  7209.   a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
  7210.  
  7211.   d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
  7212.  
  7213.   c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
  7214.  
  7215.   b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
  7216.  
  7217.   a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
  7218.  
  7219.   d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
  7220.  
  7221.   c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
  7222.  
  7223.   b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
  7224.  
  7225.  
  7226.  
  7227.   a = safe_add(a, olda);
  7228.  
  7229.   b = safe_add(b, oldb);
  7230.  
  7231.   c = safe_add(c, oldc);
  7232.  
  7233.   d = safe_add(d, oldd);
  7234.  
  7235.   }
  7236.  
  7237.  
  7238.  
  7239.   var binarray = Array(a, b, c, d);
  7240.  
  7241.   var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  7242.  
  7243.   var str = "";
  7244.  
  7245.   for(var i = 0; i < binarray.length * 4; i++)
  7246.  
  7247.   {
  7248.  
  7249.   str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
  7250.  
  7251.   }
  7252.  
  7253.  
  7254.  
  7255.   return str;
  7256.  
  7257.  
  7258.  
  7259.   /*
  7260.  
  7261.   * Add integers, wrapping at 2^32. This uses 16-bit operations internally
  7262.  
  7263.   * to work around bugs in some JS interpreters.
  7264.  
  7265.   */
  7266.  
  7267.   function safe_add(x, y)
  7268.  
  7269.   {
  7270.  
  7271.   var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  7272.  
  7273.   var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  7274.  
  7275.   return (msw << 16) | (lsw & 0xFFFF);
  7276.  
  7277.   }
  7278.  
  7279.  
  7280.  
  7281.   /*
  7282.  
  7283.   * Bitwise rotate a 32-bit number to the left.
  7284.  
  7285.   */
  7286.  
  7287.   function bit_rol(num, cnt)
  7288.  
  7289.   {
  7290.  
  7291.   return (num << cnt) | (num >>> (32 - cnt));
  7292.  
  7293.   }
  7294.  
  7295.  
  7296.  
  7297.   /*
  7298.  
  7299.   * These functions implement the four basic operations the algorithm uses.
  7300.  
  7301.   */
  7302.  
  7303.   function md5_cmn(q, a, b, x, s, t)
  7304.  
  7305.   {
  7306.  
  7307.   return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
  7308.  
  7309.   }
  7310.  
  7311.   function md5_ff(a, b, c, d, x, s, t)
  7312.  
  7313.   {
  7314.  
  7315.   return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
  7316.  
  7317.   }
  7318.  
  7319.   function md5_gg(a, b, c, d, x, s, t)
  7320.  
  7321.   {
  7322.  
  7323.   return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
  7324.  
  7325.   }
  7326.  
  7327.   function md5_hh(a, b, c, d, x, s, t)
  7328.  
  7329.   {
  7330.  
  7331.   return md5_cmn(b ^ c ^ d, a, b, x, s, t);
  7332.  
  7333.   }
  7334.  
  7335.   function md5_ii(a, b, c, d, x, s, t)
  7336.  
  7337.   {
  7338.  
  7339.   return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
  7340.  
  7341.   }
  7342.  
  7343.  
  7344.  
  7345.  }
  7346.  
  7347.  
  7348.  
  7349.  };
  7350.  
  7351.  
  7352.  
  7353.  
  7354.  
  7355.  /**
  7356.  
  7357.   * While the main purpose of the library is communication functions, it was necessary to add in some utility methods.
  7358.  
  7359.   * The AjaxTCR.util holds these methods.
  7360.  
  7361.   *
  7362.  
  7363.   * @class AjaxTCR.util
  7364.  
  7365.   * @static
  7366.  
  7367.   */
  7368.  
  7369.  AjaxTCR.util = {};
  7370.  
  7371.  /**
  7372.  
  7373.   * Several useful utility DOM functions. Many of these are called from other parts of the library.
  7374.  
  7375.   *
  7376.  
  7377.   * @class AjaxTCR.util.DOM
  7378.  
  7379.   * @static
  7380.  
  7381.   */
  7382.  
  7383.  AjaxTCR.util.DOM = {
  7384.  
  7385.  
  7386.  
  7387.   /** by default enable shorthanding of function names */
  7388.  
  7389.   enableDOMShorthand : true,
  7390.  
  7391.  
  7392.  
  7393.   /**
  7394.  
  7395.   * Find elements by class, will be overriden by native if found
  7396.  
  7397.   * If startNode is specified, starts the search there, otherwise starts at document.
  7398.  
  7399.   *
  7400.  
  7401.   * @param {string} classToFind the string class name to search for
  7402.  
  7403.   * @param {object} startNode the DOM node to start the search at. Default is the document node.
  7404.  
  7405.   * @return {array} array of elements that match the given class name.
  7406.  
  7407.   */
  7408.  
  7409.   getElementsByClassName : function(classToFind,startNode){
  7410.  
  7411.   if (document.getElementsByClassName)
  7412.  
  7413.   return document.getElementsByClassName(classToFind,startNode);
  7414.  
  7415.  
  7416.  
  7417.   /* find all the elements within a particular document or in the whole document */
  7418.  
  7419.   var elements;
  7420.  
  7421.   if (startNode)
  7422.  
  7423.   elements = startNode.getElementsByTagName("*");
  7424.  
  7425.   else
  7426.  
  7427.   elements = document.getElementsByTagName("*");
  7428.  
  7429.  
  7430.  
  7431.   var classElements = new Array();
  7432.  
  7433.   var classCount = 0;
  7434.  
  7435.  
  7436.  
  7437.   var pattern = new RegExp("(^|\\s)"+classToFind+"(\\s|$)");
  7438.  
  7439.  
  7440.  
  7441.   /* look over the elements and find those who match the class passed */
  7442.  
  7443.   for (var i = 0; i < elements.length; i++)
  7444.  
  7445.   if (pattern.test(elements[i].className) )
  7446.  
  7447.   classElements[classCount++] = elements[i];
  7448.  
  7449.  
  7450.  
  7451.   return classElements;
  7452.  
  7453.   },
  7454.  
  7455.  
  7456.  
  7457.   /**
  7458.  
  7459.   * Returns element or element array specified by given string or strings.
  7460.  
  7461.   *
  7462.  
  7463.   * @param {object} element(s) strings to search for element.
  7464.  
  7465.   * @param {object} startNode the DOM node to start the search at. Default is the document node.
  7466.  
  7467.   * @return {object} if single string, it returns the element. Otherwise it returns an array of elements
  7468.  
  7469.   */
  7470.  
  7471.   getElementsById : function(){
  7472.  
  7473.   var elements = new Array();
  7474.  
  7475.   var startNode = document;
  7476.  
  7477.   var length = arguments.length;
  7478.  
  7479.   if (typeof(arguments[length-1]) == "object" && arguments[length-1] != document)
  7480.  
  7481.   {
  7482.  
  7483.   startNode = arguments[length-1];
  7484.  
  7485.   length--;
  7486.  
  7487.   var allElements = startNode.getElementsByTagName("*");
  7488.  
  7489.   for (var j=0; j<allElements.length; j++)
  7490.  
  7491.   {
  7492.  
  7493.   for (var i=0;i<length;i++)
  7494.  
  7495.   {
  7496.  
  7497.   if (allElements[j].id == arguments[i])
  7498.  
  7499.   {
  7500.  
  7501.   elements.push(allElements[j]);
  7502.  
  7503.   break;
  7504.  
  7505.   }
  7506.  
  7507.   }
  7508.  
  7509.   }
  7510.  
  7511.   }
  7512.  
  7513.   else
  7514.  
  7515.   {
  7516.  
  7517.   if (arguments[length-1] == document)
  7518.  
  7519.   length--;
  7520.  
  7521.  
  7522.  
  7523.   for (var i=0; i<length; i++)
  7524.  
  7525.   {
  7526.  
  7527.   var elm = document.getElementById(arguments[i]);
  7528.  
  7529.   if (elm != null)
  7530.  
  7531.   elements.push(elm);
  7532.  
  7533.   }
  7534.  
  7535.   }
  7536.  
  7537.  
  7538.  
  7539.   if (elements.length == 1)
  7540.  
  7541.   return elements[0];
  7542.  
  7543.   else if (elements.length > 0)
  7544.  
  7545.   return elements;
  7546.  
  7547.   else
  7548.  
  7549.   return null;
  7550.  
  7551.   },
  7552.  
  7553.  
  7554.  
  7555.   /**
  7556.  
  7557.   * Modified version of getElementById to return single node match.
  7558.  
  7559.   * If startNode is not set to document, it starts the search at the node
  7560.  
  7561.   * If deepSearch is set to true, it does not use getElementById, but instead loops through the whole structure.
  7562.  
  7563.   *
  7564.  
  7565.   * @param {string} id the string to match with the id attribute
  7566.  
  7567.   * @param {object} startNode the DOM node to start searching in the document
  7568.  
  7569.   * @param {boolean} deepSearch true if wanted to search node by node instead of document.getElementById
  7570.  
  7571.   */
  7572.  
  7573.   getElementById : function(id, startNode, deepSearch){
  7574.  
  7575.   if (!startNode)
  7576.  
  7577.   startNode = document;
  7578.  
  7579.  
  7580.  
  7581.   if (startNode == document && !deepSearch)
  7582.  
  7583.   return document.getElementById(id);
  7584.  
  7585.   else
  7586.  
  7587.   {
  7588.  
  7589.   var allElements = startNode.getElementsByTagName("*");
  7590.  
  7591.   for (var j=0; j<allElements.length; j++)
  7592.  
  7593.   {
  7594.  
  7595.   if (allElements[j].getAttribute("id") == id)
  7596.  
  7597.   {
  7598.  
  7599.   return allElements[j];
  7600.  
  7601.   break;
  7602.  
  7603.   }
  7604.  
  7605.   }
  7606.  
  7607.   }
  7608.  
  7609.   },
  7610.  
  7611.  
  7612.  
  7613.  
  7614.  
  7615.   /**
  7616.  
  7617.   * Select nodes that match the given selector. The selector is expected to be in CSS format
  7618.  
  7619.   *
  7620.  
  7621.   * @param {string} selector string indicating the selection to match
  7622.  
  7623.   * @param {object} treeRoot DOM element to start search. Default is the document node
  7624.  
  7625.   * @return array of matching elements
  7626.  
  7627.   *
  7628.  
  7629.   */
  7630.  
  7631.   getElementsBySelector : function(selector,treeRoot,selectorType){
  7632.  
  7633.   var matches = new Array();
  7634.  
  7635.   var parents = new Array();
  7636.  
  7637.   var savematches = new Array();
  7638.  
  7639.   if (treeRoot)
  7640.  
  7641.   {
  7642.  
  7643.   if (treeRoot.length)
  7644.  
  7645.   {
  7646.  
  7647.   for (var i=0;i<treeRoot.length;i++)
  7648.  
  7649.   parents.push(treeRoot[i]);
  7650.  
  7651.   }
  7652.  
  7653.   else
  7654.  
  7655.   parents.push(treeRoot);
  7656.  
  7657.   }
  7658.  
  7659.   else
  7660.  
  7661.   parents.push(document);
  7662.  
  7663.  
  7664.  
  7665.   if (!selectorType)
  7666.  
  7667.   selectorType = "CSS";
  7668.  
  7669.   if (selectorType.toUpperCase() == "CSS")
  7670.  
  7671.   {
  7672.  
  7673.   selector = selector.replace(/([>\+,])/g, " $1 ").replace(/[\s]+/g," ");
  7674.  
  7675.  
  7676.  
  7677.   var selectors = selector.split(" ");
  7678.  
  7679.   while (selectors.length > 0)
  7680.  
  7681.   {
  7682.  
  7683.   var curSelector = selectors.shift();
  7684.  
  7685.   if (curSelector == "")
  7686.  
  7687.   continue;
  7688.  
  7689.  
  7690.  
  7691.   /* check for expressions */
  7692.  
  7693.   var options = {};
  7694.  
  7695.   switch(curSelector.charAt(0))
  7696.  
  7697.   {
  7698.  
  7699.   case(">"):
  7700.  
  7701.   options.type = "childOnly";
  7702.  
  7703.   break;
  7704.  
  7705.   case("+"):
  7706.  
  7707.   options.type = "nextSibling";
  7708.  
  7709.   break;
  7710.  
  7711.   case ("~"):
  7712.  
  7713.   options.type = "futureSibling";
  7714.  
  7715.   break;
  7716.  
  7717.   case(","):
  7718.  
  7719.   while(matches.length > 0)
  7720.  
  7721.   savematches.push(matches.shift());
  7722.  
  7723.  
  7724.  
  7725.   parents.length = 0;
  7726.  
  7727.   if (treeRoot)
  7728.  
  7729.   parents.push(treeRoot);
  7730.  
  7731.   else
  7732.  
  7733.   parents.push(document);
  7734.  
  7735.  
  7736.  
  7737.   continue;
  7738.  
  7739.   break;
  7740.  
  7741.   }
  7742.  
  7743.  
  7744.  
  7745.   if (options.type)
  7746.  
  7747.   {
  7748.  
  7749.   if (curSelector.length == 1)
  7750.  
  7751.   curSelector = selectors.shift();
  7752.  
  7753.   else
  7754.  
  7755.   curSelector = curSelector.substring(1);
  7756.  
  7757.   }
  7758.  
  7759.  
  7760.  
  7761.   /* Check to see if we already looped though. If so, we have a different starting point */
  7762.  
  7763.   if (matches.length)
  7764.  
  7765.   {
  7766.  
  7767.   parents.length = 0;
  7768.  
  7769.   while(matches.length > 0)
  7770.  
  7771.   parents.push(matches.shift());
  7772.  
  7773.   }
  7774.  
  7775.  
  7776.  
  7777.  
  7778.  
  7779.   /* Check for Pseudo-classes */
  7780.  
  7781.   if (curSelector.indexOf(":") > -1)
  7782.  
  7783.   {
  7784.  
  7785.   var newSelector = curSelector.substring(0, curSelector.indexOf(":"));
  7786.  
  7787.   var optionsType = curSelector.substring(curSelector.indexOf(":")+1);
  7788.  
  7789.  
  7790.  
  7791.   curSelector = newSelector;
  7792.  
  7793.   options.type = optionsType.toLowerCase();
  7794.  
  7795.  
  7796.  
  7797.   if (options.type.indexOf("nth-child") == 0)
  7798.  
  7799.   {
  7800.  
  7801.   options.childNumber = options.type.substring(10,options.type.length-1);
  7802.  
  7803.   options.type = "nth-child";
  7804.  
  7805.   }
  7806.  
  7807.   else if (options.type.indexOf("not") == 0)
  7808.  
  7809.   {
  7810.  
  7811.   //use optionsType to preserve case
  7812.  
  7813.   options.notString = optionsType.substring(4,options.type.length-1).replace(/^\s+|\s+$/g,"");
  7814.  
  7815.   options.type = "not";
  7816.  
  7817.   var notSelector = curSelector;
  7818.  
  7819.   if (notSelector == "*")
  7820.  
  7821.   notSelector = "";
  7822.  
  7823.   if (/^[:#\[\.].*/.test(options.notString))
  7824.  
  7825.   options.notSelector = notSelector + options.notString;
  7826.  
  7827.   else
  7828.  
  7829.   options.notSelector = notSelector + " " + options.notString;
  7830.  
  7831.  
  7832.  
  7833.   options.notObjects = AjaxTCR.util.DOM.getElementsBySelector(options.notSelector, parents);
  7834.  
  7835.   }
  7836.  
  7837.   }
  7838.  
  7839.  
  7840.  
  7841.   /* Check for Attributes */
  7842.  
  7843.   if (curSelector.indexOf("[") > -1)
  7844.  
  7845.   {
  7846.  
  7847.   var tokens = curSelector.split("[");
  7848.  
  7849.   curSelector = tokens[0];
  7850.  
  7851.   options.type = "attribute";
  7852.  
  7853.   options.attribute = tokens[1].substring(0,tokens[1].length-1).toLowerCase();
  7854.  
  7855.   }
  7856.  
  7857.  
  7858.  
  7859.   if (curSelector == "")
  7860.  
  7861.   curSelector = "*";
  7862.  
  7863.  
  7864.  
  7865.   /* Inspect class selectors */
  7866.  
  7867.   if (curSelector.indexOf(".") > -1)
  7868.  
  7869.   {
  7870.  
  7871.   /* Cases:
  7872.  
  7873.   * p.class1
  7874.  
  7875.   * .class2
  7876.  
  7877.   * div.class1.class2
  7878.  
  7879.   */
  7880.  
  7881.   var classNames = curSelector.split(".");
  7882.  
  7883.   var elementName = classNames.shift();
  7884.  
  7885.   /* First get the element at the beginning if necessary */
  7886.  
  7887.   if (elementName != "")
  7888.  
  7889.   {
  7890.  
  7891.   for (var j=0;j<parents.length;j++)
  7892.  
  7893.   {
  7894.  
  7895.   var elms = AjaxTCR.util.DOM._getElementsByTagName(parents[j],elementName,options);
  7896.  
  7897.   for (var k=0;k<elms.length;k++)
  7898.  
  7899.   {
  7900.  
  7901.   if (checkFilter(elms[k], parents[j], options))
  7902.  
  7903.   matches.push(elms[k]);
  7904.  
  7905.   }
  7906.  
  7907.   }
  7908.  
  7909.   }
  7910.  
  7911.   else if (classNames.length > 0)
  7912.  
  7913.   {
  7914.  
  7915.   /* if no element is specified, use getElementsByClassName for the first class */
  7916.  
  7917.   var firstClass = classNames.shift();
  7918.  
  7919.   for (var j=0;j<parents.length;j++)
  7920.  
  7921.   {
  7922.  
  7923.   var elms = AjaxTCR.util.DOM.getElementsByClassName(firstClass, parents[j]);
  7924.  
  7925.   for (var k=0;k<elms.length;k++)
  7926.  
  7927.   {
  7928.  
  7929.   if (checkFilter(elms[k],parents[j],options))
  7930.  
  7931.   matches.push(elms[k]);
  7932.  
  7933.   }
  7934.  
  7935.   }
  7936.  
  7937.   }
  7938.  
  7939.  
  7940.  
  7941.   /* Now get the (rest of the) classes */
  7942.  
  7943.   for (var j=matches.length-1;j>=0;j--)
  7944.  
  7945.   {
  7946.  
  7947.   for (var k=0;k<classNames.length;k++)
  7948.  
  7949.   {
  7950.  
  7951.   var pattern = new RegExp("(^|\\s)"+classNames[k]+"(\\s|$)");
  7952.  
  7953.   if (!pattern.test(matches[j].className))
  7954.  
  7955.   {
  7956.  
  7957.   matches.splice(j,1);
  7958.  
  7959.   break;
  7960.  
  7961.   }
  7962.  
  7963.   }
  7964.  
  7965.   }
  7966.  
  7967.   }
  7968.  
  7969.  
  7970.  
  7971.   /* Inspect id selectors */
  7972.  
  7973.   else if (curSelector.indexOf("#") > -1)
  7974.  
  7975.   {
  7976.  
  7977.   /* Cases:
  7978.  
  7979.   * p#id1
  7980.  
  7981.   * #id2
  7982.  
  7983.   */
  7984.  
  7985.   var idNames = curSelector.split("#");
  7986.  
  7987.   var elementName = idNames[0];
  7988.  
  7989.   var id = idNames[1];
  7990.  
  7991.  
  7992.  
  7993.   /* First get the element at the beginning if necessary */
  7994.  
  7995.   if (elementName != "")
  7996.  
  7997.   {
  7998.  
  7999.   for (var j=0;j<parents.length;j++)
  8000.  
  8001.   {
  8002.  
  8003.   var elms = AjaxTCR.util.DOM._getElementsByTagName(parents[j],elementName,options);
  8004.  
  8005.   for (var k=0;k<elms.length;k++)
  8006.  
  8007.   {
  8008.  
  8009.   if (elms[k].id == id && checkFilter(elms[k], parents[j], options))
  8010.  
  8011.   matches.push(elms[k]);
  8012.  
  8013.   }
  8014.  
  8015.   }
  8016.  
  8017.   }
  8018.  
  8019.   else
  8020.  
  8021.   {
  8022.  
  8023.   for (var j=0;j<parents.length;j++)
  8024.  
  8025.   {
  8026.  
  8027.   var elms = AjaxTCR.util.DOM.getElementsById(id, parents[j]);
  8028.  
  8029.   if (checkFilter(elms, parents[j], options))
  8030.  
  8031.   matches.push(elms);
  8032.  
  8033.   }
  8034.  
  8035.   }
  8036.  
  8037.   }
  8038.  
  8039.   /* Simple tagname selects */
  8040.  
  8041.   else
  8042.  
  8043.   {
  8044.  
  8045.   for (var j=0;j<parents.length;j++)
  8046.  
  8047.   {
  8048.  
  8049.   var elms =AjaxTCR.util.DOM._getElementsByTagName(parents[j],curSelector,options);
  8050.  
  8051.   for (var k=0;k<elms.length;k++)
  8052.  
  8053.   {
  8054.  
  8055.   if (checkFilter(elms[k], parents[j], options))
  8056.  
  8057.   matches.push(elms[k]);
  8058.  
  8059.   }
  8060.  
  8061.   }
  8062.  
  8063.   }
  8064.  
  8065.   }
  8066.  
  8067.   }
  8068.  
  8069.  
  8070.  
  8071.  
  8072.  
  8073.   function checkFilter(element, parent, options)
  8074.  
  8075.   {
  8076.  
  8077.   var valid = false;
  8078.  
  8079.  
  8080.  
  8081.   if (element == null)
  8082.  
  8083.   return false;
  8084.  
  8085.   else if (!options.type)
  8086.  
  8087.   return true;
  8088.  
  8089.  
  8090.  
  8091.   //handle the case of the parent element being the document
  8092.  
  8093.   if (parent == document)
  8094.  
  8095.   {
  8096.  
  8097.   var allElms = document.getElementsByTagName("*");
  8098.  
  8099.   for (var i=0;i<allElms.length;i++)
  8100.  
  8101.   {
  8102.  
  8103.   if( checkFilter(element, allElms[i], options))
  8104.  
  8105.   {
  8106.  
  8107.   valid = true;
  8108.  
  8109.   break;
  8110.  
  8111.   }
  8112.  
  8113.   }
  8114.  
  8115.  
  8116.  
  8117.   return valid;
  8118.  
  8119.   }
  8120.  
  8121.  
  8122.  
  8123.  
  8124.  
  8125.   if (options.type == "childOnly")
  8126.  
  8127.   valid = (element.parentNode == parent);
  8128.  
  8129.   else if (options.type == "nextSibling")
  8130.  
  8131.   {
  8132.  
  8133.   var elm = parent.nextSibling;
  8134.  
  8135.   while (elm != null && elm.nodeType != 1)
  8136.  
  8137.   elm = elm.nextSibling;
  8138.  
  8139.   valid = (elm == element);
  8140.  
  8141.   }
  8142.  
  8143.   else if (options.type == "futureSibling")
  8144.  
  8145.   {
  8146.  
  8147.   var elm = parent.nextSibling;
  8148.  
  8149.   while (elm != null)
  8150.  
  8151.   {
  8152.  
  8153.   if (elm == element)
  8154.  
  8155.   {
  8156.  
  8157.   valid = true;
  8158.  
  8159.   break;
  8160.  
  8161.   }
  8162.  
  8163.   elm = elm.nextSibling;
  8164.  
  8165.   }
  8166.  
  8167.   }
  8168.  
  8169.   else if (options.type == "first-child")
  8170.  
  8171.   {
  8172.  
  8173.   var elm = parent.firstChild;
  8174.  
  8175.   while (elm != null && elm.nodeType != 1)
  8176.  
  8177.   elm = elm.nextSibling;
  8178.  
  8179.   valid = (elm == element);
  8180.  
  8181.   }
  8182.  
  8183.   else if (options.type == "last-child")
  8184.  
  8185.   {
  8186.  
  8187.   var elm = parent.lastChild;
  8188.  
  8189.   while (elm != null && elm.nodeType != 1)
  8190.  
  8191.   elm = elm.previousSibling;
  8192.  
  8193.   valid = (elm == element);
  8194.  
  8195.   }
  8196.  
  8197.   else if (options.type == "only-child")
  8198.  
  8199.   {
  8200.  
  8201.   var elm = parent.firstChild;
  8202.  
  8203.   while (elm != null && elm.nodeType != 1)
  8204.  
  8205.   elm = elm.nextSibling;
  8206.  
  8207.  
  8208.  
  8209.   if (elm == element)
  8210.  
  8211.   {
  8212.  
  8213.   var elm = parent.lastChild;
  8214.  
  8215.   while (elm != null && elm.nodeType != 1)
  8216.  
  8217.   elm = elm.previousSibling;
  8218.  
  8219.   }
  8220.  
  8221.  
  8222.  
  8223.   valid = (elm == element);
  8224.  
  8225.   }
  8226.  
  8227.   else if (options.type == "nth-child")
  8228.  
  8229.   {
  8230.  
  8231.   var count = 0;
  8232.  
  8233.   var elm = parent.firstChild;
  8234.  
  8235.   while (elm != null && count < options.childNumber)
  8236.  
  8237.   {
  8238.  
  8239.   if (elm.nodeType == 1)
  8240.  
  8241.   count++;
  8242.  
  8243.  
  8244.  
  8245.   if (count == options.childNumber)
  8246.  
  8247.   break;
  8248.  
  8249.  
  8250.  
  8251.   elm = elm.nextSibling;
  8252.  
  8253.   }
  8254.  
  8255.  
  8256.  
  8257.   valid = (elm == element);
  8258.  
  8259.   }
  8260.  
  8261.   else if (options.type == "empty")
  8262.  
  8263.   valid = (element.childNodes.length == 0);
  8264.  
  8265.   else if (options.type == "enabled")
  8266.  
  8267.   valid = (!element.disabled);
  8268.  
  8269.   else if (options.type == "disabled")
  8270.  
  8271.   valid = (element.disabled);
  8272.  
  8273.   else if (options.type == "checked")
  8274.  
  8275.   valid = (element.checked);
  8276.  
  8277.   else if (options.type == "selected")
  8278.  
  8279.   valid = (element.selected);
  8280.  
  8281.   else if (options.type == "attribute")
  8282.  
  8283.   {
  8284.  
  8285.   var pattern = /^\s*([\w-]+)\s*([!*$^~=]*)\s*(['|\"]?)(.*)\3/;
  8286.  
  8287.   var attRules = pattern.exec(options.attribute);
  8288.  
  8289.  
  8290.  
  8291.   if (attRules[2] == "")
  8292.  
  8293.   valid = element.getAttribute(attRules[1]);
  8294.  
  8295.   else if (attRules[2] == "=")
  8296.  
  8297.   valid = (element.getAttribute(attRules[1]) && element.getAttribute(attRules[1]).toLowerCase() == attRules[4].toLowerCase());
  8298.  
  8299.   else if (attRules[2] == "^=")
  8300.  
  8301.   valid = (element.getAttribute(attRules[1]) && element.getAttribute(attRules[1]).toLowerCase().indexOf(attRules[4].toLowerCase()) == 0);
  8302.  
  8303.   else if (attRules[2] == "*=")
  8304.  
  8305.   valid = (element.getAttribute(attRules[1]) && element.getAttribute(attRules[1]).toLowerCase().indexOf(attRules[4].toLowerCase()) > -1);
  8306.  
  8307.   else if (attRules[2] == "$=")
  8308.  
  8309.   {
  8310.  
  8311.   var att =element.getAttribute(attRules[1]);
  8312.  
  8313.   if (att)
  8314.  
  8315.   valid = (att.toLowerCase().substring(att.length - attRules[4].length) == attRules[4].toLowerCase());
  8316.  
  8317.   }
  8318.  
  8319.   }
  8320.  
  8321.   else if (options.type == "not")
  8322.  
  8323.   {
  8324.  
  8325.   valid = true;
  8326.  
  8327.   for (var j=0;j<options.notObjects.length;j++)
  8328.  
  8329.   {
  8330.  
  8331.   if (options.notObjects[j] == element)
  8332.  
  8333.   {
  8334.  
  8335.   valid = false;
  8336.  
  8337.   break;
  8338.  
  8339.   }
  8340.  
  8341.   }
  8342.  
  8343.   }
  8344.  
  8345.  
  8346.  
  8347.  
  8348.  
  8349.   return valid;
  8350.  
  8351.   }
  8352.  
  8353.  
  8354.  
  8355.   /* get the results in the correct order */
  8356.  
  8357.   if (savematches.length)
  8358.  
  8359.   {
  8360.