PageRenderTime 83ms CodeModel.GetById 23ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 1ms

/src/main/resources/org/apache/struts2/static/datasource/datasource-debug.js

http://struts2yuiplugin.googlecode.com/
JavaScript | 3017 lines | 2092 code | 150 blank | 775 comment | 214 complexity | 5980c6ed5e3c258b42dd91a9e11a0d84 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2Copyright (c) 2009, Yahoo! Inc. All rights reserved.
   3Code licensed under the BSD License:
   4http://developer.yahoo.net/yui/license.txt
   5version: 2.7.0
   6*/
   7(function () {
   8
   9var lang   = YAHOO.lang,
  10    util   = YAHOO.util,
  11    Ev     = util.Event;
  12
  13/**
  14 * The DataSource utility provides a common configurable interface for widgets to
  15 * access a variety of data, from JavaScript arrays to online database servers.
  16 *
  17 * @module datasource
  18 * @requires yahoo, event
  19 * @optional json, get, connection 
  20 * @title DataSource Utility
  21 */
  22
  23/****************************************************************************/
  24/****************************************************************************/
  25/****************************************************************************/
  26
  27/**
  28 * Base class for the YUI DataSource utility.
  29 *
  30 * @namespace YAHOO.util
  31 * @class YAHOO.util.DataSourceBase
  32 * @constructor
  33 * @param oLiveData {HTMLElement}  Pointer to live data.
  34 * @param oConfigs {object} (optional) Object literal of configuration values.
  35 */
  36util.DataSourceBase = function(oLiveData, oConfigs) {
  37    if(oLiveData === null || oLiveData === undefined) {
  38        YAHOO.log("Could not instantiate DataSource due to invalid live database",
  39                "error", this.toString());
  40        return;
  41    }
  42    
  43    this.liveData = oLiveData;
  44    this._oQueue = {interval:null, conn:null, requests:[]};
  45    this.responseSchema = {};   
  46
  47    // Set any config params passed in to override defaults
  48    if(oConfigs && (oConfigs.constructor == Object)) {
  49        for(var sConfig in oConfigs) {
  50            if(sConfig) {
  51                this[sConfig] = oConfigs[sConfig];
  52            }
  53        }
  54    }
  55    
  56    // Validate and initialize public configs
  57    var maxCacheEntries = this.maxCacheEntries;
  58    if(!lang.isNumber(maxCacheEntries) || (maxCacheEntries < 0)) {
  59        maxCacheEntries = 0;
  60    }
  61
  62    // Initialize interval tracker
  63    this._aIntervals = [];
  64
  65    /////////////////////////////////////////////////////////////////////////////
  66    //
  67    // Custom Events
  68    //
  69    /////////////////////////////////////////////////////////////////////////////
  70
  71    /**
  72     * Fired when a request is made to the local cache.
  73     *
  74     * @event cacheRequestEvent
  75     * @param oArgs.request {Object} The request object.
  76     * @param oArgs.callback {Object} The callback object.
  77     * @param oArgs.caller {Object} (deprecated) Use callback.scope.
  78     */
  79    this.createEvent("cacheRequestEvent");
  80
  81    /**
  82     * Fired when data is retrieved from the local cache.
  83     *
  84     * @event cacheResponseEvent
  85     * @param oArgs.request {Object} The request object.
  86     * @param oArgs.response {Object} The response object.
  87     * @param oArgs.callback {Object} The callback object.
  88     * @param oArgs.caller {Object} (deprecated) Use callback.scope.
  89     */
  90    this.createEvent("cacheResponseEvent");
  91
  92    /**
  93     * Fired when a request is sent to the live data source.
  94     *
  95     * @event requestEvent
  96     * @param oArgs.request {Object} The request object.
  97     * @param oArgs.callback {Object} The callback object.
  98     * @param oArgs.tId {Number} Transaction ID.     
  99     * @param oArgs.caller {Object} (deprecated) Use callback.scope.
 100     */
 101    this.createEvent("requestEvent");
 102
 103    /**
 104     * Fired when live data source sends response.
 105     *
 106     * @event responseEvent
 107     * @param oArgs.request {Object} The request object.
 108     * @param oArgs.response {Object} The raw response object.
 109     * @param oArgs.callback {Object} The callback object.
 110     * @param oArgs.tId {Number} Transaction ID.     
 111     * @param oArgs.caller {Object} (deprecated) Use callback.scope.
 112     */
 113    this.createEvent("responseEvent");
 114
 115    /**
 116     * Fired when response is parsed.
 117     *
 118     * @event responseParseEvent
 119     * @param oArgs.request {Object} The request object.
 120     * @param oArgs.response {Object} The parsed response object.
 121     * @param oArgs.callback {Object} The callback object.
 122     * @param oArgs.caller {Object} (deprecated) Use callback.scope.
 123     */
 124    this.createEvent("responseParseEvent");
 125
 126    /**
 127     * Fired when response is cached.
 128     *
 129     * @event responseCacheEvent
 130     * @param oArgs.request {Object} The request object.
 131     * @param oArgs.response {Object} The parsed response object.
 132     * @param oArgs.callback {Object} The callback object.
 133     * @param oArgs.caller {Object} (deprecated) Use callback.scope.
 134     */
 135    this.createEvent("responseCacheEvent");
 136    /**
 137     * Fired when an error is encountered with the live data source.
 138     *
 139     * @event dataErrorEvent
 140     * @param oArgs.request {Object} The request object.
 141     * @param oArgs.callback {Object} The callback object.
 142     * @param oArgs.caller {Object} (deprecated) Use callback.scope.
 143     * @param oArgs.message {String} The error message.
 144     */
 145    this.createEvent("dataErrorEvent");
 146
 147    /**
 148     * Fired when the local cache is flushed.
 149     *
 150     * @event cacheFlushEvent
 151     */
 152    this.createEvent("cacheFlushEvent");
 153
 154    var DS = util.DataSourceBase;
 155    this._sName = "DataSource instance" + DS._nIndex;
 156    DS._nIndex++;
 157    YAHOO.log("DataSource initialized", "info", this.toString());
 158};
 159
 160var DS = util.DataSourceBase;
 161
 162lang.augmentObject(DS, {
 163
 164/////////////////////////////////////////////////////////////////////////////
 165//
 166// DataSourceBase public constants
 167//
 168/////////////////////////////////////////////////////////////////////////////
 169
 170/**
 171 * Type is unknown.
 172 *
 173 * @property TYPE_UNKNOWN
 174 * @type Number
 175 * @final
 176 * @default -1
 177 */
 178TYPE_UNKNOWN : -1,
 179
 180/**
 181 * Type is a JavaScript Array.
 182 *
 183 * @property TYPE_JSARRAY
 184 * @type Number
 185 * @final
 186 * @default 0
 187 */
 188TYPE_JSARRAY : 0,
 189
 190/**
 191 * Type is a JavaScript Function.
 192 *
 193 * @property TYPE_JSFUNCTION
 194 * @type Number
 195 * @final
 196 * @default 1
 197 */
 198TYPE_JSFUNCTION : 1,
 199
 200/**
 201 * Type is hosted on a server via an XHR connection.
 202 *
 203 * @property TYPE_XHR
 204 * @type Number
 205 * @final
 206 * @default 2
 207 */
 208TYPE_XHR : 2,
 209
 210/**
 211 * Type is JSON.
 212 *
 213 * @property TYPE_JSON
 214 * @type Number
 215 * @final
 216 * @default 3
 217 */
 218TYPE_JSON : 3,
 219
 220/**
 221 * Type is XML.
 222 *
 223 * @property TYPE_XML
 224 * @type Number
 225 * @final
 226 * @default 4
 227 */
 228TYPE_XML : 4,
 229
 230/**
 231 * Type is plain text.
 232 *
 233 * @property TYPE_TEXT
 234 * @type Number
 235 * @final
 236 * @default 5
 237 */
 238TYPE_TEXT : 5,
 239
 240/**
 241 * Type is an HTML TABLE element. Data is parsed out of TR elements from all TBODY elements.
 242 *
 243 * @property TYPE_HTMLTABLE
 244 * @type Number
 245 * @final
 246 * @default 6
 247 */
 248TYPE_HTMLTABLE : 6,
 249
 250/**
 251 * Type is hosted on a server via a dynamic script node.
 252 *
 253 * @property TYPE_SCRIPTNODE
 254 * @type Number
 255 * @final
 256 * @default 7
 257 */
 258TYPE_SCRIPTNODE : 7,
 259
 260/**
 261 * Type is local.
 262 *
 263 * @property TYPE_LOCAL
 264 * @type Number
 265 * @final
 266 * @default 8
 267 */
 268TYPE_LOCAL : 8,
 269
 270/**
 271 * Error message for invalid dataresponses.
 272 *
 273 * @property ERROR_DATAINVALID
 274 * @type String
 275 * @final
 276 * @default "Invalid data"
 277 */
 278ERROR_DATAINVALID : "Invalid data",
 279
 280/**
 281 * Error message for null data responses.
 282 *
 283 * @property ERROR_DATANULL
 284 * @type String
 285 * @final
 286 * @default "Null data"
 287 */
 288ERROR_DATANULL : "Null data",
 289
 290/////////////////////////////////////////////////////////////////////////////
 291//
 292// DataSourceBase private static properties
 293//
 294/////////////////////////////////////////////////////////////////////////////
 295
 296/**
 297 * Internal class variable to index multiple DataSource instances.
 298 *
 299 * @property DataSourceBase._nIndex
 300 * @type Number
 301 * @private
 302 * @static
 303 */
 304_nIndex : 0,
 305
 306/**
 307 * Internal class variable to assign unique transaction IDs.
 308 *
 309 * @property DataSourceBase._nTransactionId
 310 * @type Number
 311 * @private
 312 * @static
 313 */
 314_nTransactionId : 0,
 315
 316/////////////////////////////////////////////////////////////////////////////
 317//
 318// DataSourceBase public static methods
 319//
 320/////////////////////////////////////////////////////////////////////////////
 321
 322/**
 323 * Executes a configured callback.  For object literal callbacks, the third
 324 * param determines whether to execute the success handler or failure handler.
 325 *  
 326 * @method issueCallback
 327 * @param callback {Function|Object} the callback to execute
 328 * @param params {Array} params to be passed to the callback method
 329 * @param error {Boolean} whether an error occurred
 330 * @param scope {Object} the scope from which to execute the callback
 331 * (deprecated - use an object literal callback)
 332 * @static     
 333 */
 334issueCallback : function (callback,params,error,scope) {
 335    if (lang.isFunction(callback)) {
 336        callback.apply(scope, params);
 337    } else if (lang.isObject(callback)) {
 338        scope = callback.scope || scope || window;
 339        var callbackFunc = callback.success;
 340        if (error) {
 341            callbackFunc = callback.failure;
 342        }
 343        if (callbackFunc) {
 344            callbackFunc.apply(scope, params.concat([callback.argument]));
 345        }
 346    }
 347},
 348
 349/**
 350 * Converts data to type String.
 351 *
 352 * @method DataSourceBase.parseString
 353 * @param oData {String | Number | Boolean | Date | Array | Object} Data to parse.
 354 * The special values null and undefined will return null.
 355 * @return {String} A string, or null.
 356 * @static
 357 */
 358parseString : function(oData) {
 359    // Special case null and undefined
 360    if(!lang.isValue(oData)) {
 361        return null;
 362    }
 363    
 364    //Convert to string
 365    var string = oData + "";
 366
 367    // Validate
 368    if(lang.isString(string)) {
 369        return string;
 370    }
 371    else {
 372        YAHOO.log("Could not convert data " + lang.dump(oData) + " to type String", "warn", this.toString());
 373        return null;
 374    }
 375},
 376
 377/**
 378 * Converts data to type Number.
 379 *
 380 * @method DataSourceBase.parseNumber
 381 * @param oData {String | Number | Boolean} Data to convert. Note, the following
 382 * values return as null: null, undefined, NaN, "". 
 383 * @return {Number} A number, or null.
 384 * @static
 385 */
 386parseNumber : function(oData) {
 387    if(!lang.isValue(oData) || (oData === "")) {
 388        return null;
 389    }
 390
 391    //Convert to number
 392    var number = oData * 1;
 393    
 394    // Validate
 395    if(lang.isNumber(number)) {
 396        return number;
 397    }
 398    else {
 399        YAHOO.log("Could not convert data " + lang.dump(oData) + " to type Number", "warn", this.toString());
 400        return null;
 401    }
 402},
 403// Backward compatibility
 404convertNumber : function(oData) {
 405    YAHOO.log("The method YAHOO.util.DataSourceBase.convertNumber() has been" +
 406    " deprecated in favor of YAHOO.util.DataSourceBase.parseNumber()", "warn",
 407    this.toString());
 408    return DS.parseNumber(oData);
 409},
 410
 411/**
 412 * Converts data to type Date.
 413 *
 414 * @method DataSourceBase.parseDate
 415 * @param oData {Date | String | Number} Data to convert.
 416 * @return {Date} A Date instance.
 417 * @static
 418 */
 419parseDate : function(oData) {
 420    var date = null;
 421    
 422    //Convert to date
 423    if(!(oData instanceof Date)) {
 424        date = new Date(oData);
 425    }
 426    else {
 427        return oData;
 428    }
 429    
 430    // Validate
 431    if(date instanceof Date) {
 432        return date;
 433    }
 434    else {
 435        YAHOO.log("Could not convert data " + lang.dump(oData) + " to type Date", "warn", this.toString());
 436        return null;
 437    }
 438},
 439// Backward compatibility
 440convertDate : function(oData) {
 441    YAHOO.log("The method YAHOO.util.DataSourceBase.convertDate() has been" +
 442    " deprecated in favor of YAHOO.util.DataSourceBase.parseDate()", "warn",
 443    this.toString());
 444    return DS.parseDate(oData);
 445}
 446
 447});
 448
 449// Done in separate step so referenced functions are defined.
 450/**
 451 * Data parsing functions.
 452 * @property DataSource.Parser
 453 * @type Object
 454 * @static
 455 */
 456DS.Parser = {
 457    string   : DS.parseString,
 458    number   : DS.parseNumber,
 459    date     : DS.parseDate
 460};
 461
 462// Prototype properties and methods
 463DS.prototype = {
 464
 465/////////////////////////////////////////////////////////////////////////////
 466//
 467// DataSourceBase private properties
 468//
 469/////////////////////////////////////////////////////////////////////////////
 470
 471/**
 472 * Name of DataSource instance.
 473 *
 474 * @property _sName
 475 * @type String
 476 * @private
 477 */
 478_sName : null,
 479
 480/**
 481 * Local cache of data result object literals indexed chronologically.
 482 *
 483 * @property _aCache
 484 * @type Object[]
 485 * @private
 486 */
 487_aCache : null,
 488
 489/**
 490 * Local queue of request connections, enabled if queue needs to be managed.
 491 *
 492 * @property _oQueue
 493 * @type Object
 494 * @private
 495 */
 496_oQueue : null,
 497
 498/**
 499 * Array of polling interval IDs that have been enabled, needed to clear all intervals.
 500 *
 501 * @property _aIntervals
 502 * @type Array
 503 * @private
 504 */
 505_aIntervals : null,
 506
 507/////////////////////////////////////////////////////////////////////////////
 508//
 509// DataSourceBase public properties
 510//
 511/////////////////////////////////////////////////////////////////////////////
 512
 513/**
 514 * Max size of the local cache.  Set to 0 to turn off caching.  Caching is
 515 * useful to reduce the number of server connections.  Recommended only for data
 516 * sources that return comprehensive results for queries or when stale data is
 517 * not an issue.
 518 *
 519 * @property maxCacheEntries
 520 * @type Number
 521 * @default 0
 522 */
 523maxCacheEntries : 0,
 524
 525 /**
 526 * Pointer to live database.
 527 *
 528 * @property liveData
 529 * @type Object
 530 */
 531liveData : null,
 532
 533/**
 534 * Where the live data is held:
 535 * 
 536 * <dl>  
 537 *    <dt>TYPE_UNKNOWN</dt>
 538 *    <dt>TYPE_LOCAL</dt>
 539 *    <dt>TYPE_XHR</dt>
 540 *    <dt>TYPE_SCRIPTNODE</dt>
 541 *    <dt>TYPE_JSFUNCTION</dt>
 542 * </dl> 
 543 *  
 544 * @property dataType
 545 * @type Number
 546 * @default YAHOO.util.DataSourceBase.TYPE_UNKNOWN
 547 *
 548 */
 549dataType : DS.TYPE_UNKNOWN,
 550
 551/**
 552 * Format of response:
 553 *  
 554 * <dl>  
 555 *    <dt>TYPE_UNKNOWN</dt>
 556 *    <dt>TYPE_JSARRAY</dt>
 557 *    <dt>TYPE_JSON</dt>
 558 *    <dt>TYPE_XML</dt>
 559 *    <dt>TYPE_TEXT</dt>
 560 *    <dt>TYPE_HTMLTABLE</dt> 
 561 * </dl> 
 562 *
 563 * @property responseType
 564 * @type Number
 565 * @default YAHOO.util.DataSourceBase.TYPE_UNKNOWN
 566 */
 567responseType : DS.TYPE_UNKNOWN,
 568
 569/**
 570 * Response schema object literal takes a combination of the following properties:
 571 *
 572 * <dl>
 573 * <dt>resultsList</dt> <dd>Pointer to array of tabular data</dd>
 574 * <dt>resultNode</dt> <dd>Pointer to node name of row data (XML data only)</dd>
 575 * <dt>recordDelim</dt> <dd>Record delimiter (text data only)</dd>
 576 * <dt>fieldDelim</dt> <dd>Field delimiter (text data only)</dd>
 577 * <dt>fields</dt> <dd>Array of field names (aka keys), or array of object literals
 578 * such as: {key:"fieldname",parser:YAHOO.util.DataSourceBase.parseDate}</dd>
 579 * <dt>metaFields</dt> <dd>Object literal of keys to include in the oParsedResponse.meta collection</dd>
 580 * <dt>metaNode</dt> <dd>Name of the node under which to search for meta information in XML response data</dd>
 581 * </dl>
 582 *
 583 * @property responseSchema
 584 * @type Object
 585 */
 586responseSchema : null,
 587
 588/**
 589 * Additional arguments passed to the JSON parse routine.  The JSON string
 590 * is the assumed first argument (where applicable).  This property is not
 591 * set by default, but the parse methods will use it if present.
 592 *
 593 * @property parseJSONArgs
 594 * @type {MIXED|Array} If an Array, contents are used as individual arguments.
 595 *                     Otherwise, value is used as an additional argument.
 596 */
 597// property intentionally undefined
 598 
 599/////////////////////////////////////////////////////////////////////////////
 600//
 601// DataSourceBase public methods
 602//
 603/////////////////////////////////////////////////////////////////////////////
 604
 605/**
 606 * Public accessor to the unique name of the DataSource instance.
 607 *
 608 * @method toString
 609 * @return {String} Unique name of the DataSource instance.
 610 */
 611toString : function() {
 612    return this._sName;
 613},
 614
 615/**
 616 * Overridable method passes request to cache and returns cached response if any,
 617 * refreshing the hit in the cache as the newest item. Returns null if there is
 618 * no cache hit.
 619 *
 620 * @method getCachedResponse
 621 * @param oRequest {Object} Request object.
 622 * @param oCallback {Object} Callback object.
 623 * @param oCaller {Object} (deprecated) Use callback object.
 624 * @return {Object} Cached response object or null.
 625 */
 626getCachedResponse : function(oRequest, oCallback, oCaller) {
 627    var aCache = this._aCache;
 628
 629    // If cache is enabled...
 630    if(this.maxCacheEntries > 0) {        
 631        // Initialize local cache
 632        if(!aCache) {
 633            this._aCache = [];
 634            YAHOO.log("Cache initialized", "info", this.toString());
 635        }
 636        // Look in local cache
 637        else {
 638            var nCacheLength = aCache.length;
 639            if(nCacheLength > 0) {
 640                var oResponse = null;
 641                this.fireEvent("cacheRequestEvent", {request:oRequest,callback:oCallback,caller:oCaller});
 642        
 643                // Loop through each cached element
 644                for(var i = nCacheLength-1; i >= 0; i--) {
 645                    var oCacheElem = aCache[i];
 646        
 647                    // Defer cache hit logic to a public overridable method
 648                    if(this.isCacheHit(oRequest,oCacheElem.request)) {
 649                        // The cache returned a hit!
 650                        // Grab the cached response
 651                        oResponse = oCacheElem.response;
 652                        this.fireEvent("cacheResponseEvent", {request:oRequest,response:oResponse,callback:oCallback,caller:oCaller});
 653                        
 654                        // Refresh the position of the cache hit
 655                        if(i < nCacheLength-1) {
 656                            // Remove element from its original location
 657                            aCache.splice(i,1);
 658                            // Add as newest
 659                            this.addToCache(oRequest, oResponse);
 660                            YAHOO.log("Refreshed cache position of the response for \"" +  oRequest + "\"", "info", this.toString());
 661                        }
 662                        
 663                        // Add a cache flag
 664                        oResponse.cached = true;
 665                        break;
 666                    }
 667                }
 668                YAHOO.log("The cached response for \"" + lang.dump(oRequest) +
 669                        "\" is " + lang.dump(oResponse), "info", this.toString());
 670                return oResponse;
 671            }
 672        }
 673    }
 674    else if(aCache) {
 675        this._aCache = null;
 676        YAHOO.log("Cache destroyed", "info", this.toString());
 677    }
 678    return null;
 679},
 680
 681/**
 682 * Default overridable method matches given request to given cached request.
 683 * Returns true if is a hit, returns false otherwise.  Implementers should
 684 * override this method to customize the cache-matching algorithm.
 685 *
 686 * @method isCacheHit
 687 * @param oRequest {Object} Request object.
 688 * @param oCachedRequest {Object} Cached request object.
 689 * @return {Boolean} True if given request matches cached request, false otherwise.
 690 */
 691isCacheHit : function(oRequest, oCachedRequest) {
 692    return (oRequest === oCachedRequest);
 693},
 694
 695/**
 696 * Adds a new item to the cache. If cache is full, evicts the stalest item
 697 * before adding the new item.
 698 *
 699 * @method addToCache
 700 * @param oRequest {Object} Request object.
 701 * @param oResponse {Object} Response object to cache.
 702 */
 703addToCache : function(oRequest, oResponse) {
 704    var aCache = this._aCache;
 705    if(!aCache) {
 706        return;
 707    }
 708
 709    // If the cache is full, make room by removing stalest element (index=0)
 710    while(aCache.length >= this.maxCacheEntries) {
 711        aCache.shift();
 712    }
 713
 714    // Add to cache in the newest position, at the end of the array
 715    var oCacheElem = {request:oRequest,response:oResponse};
 716    aCache[aCache.length] = oCacheElem;
 717    this.fireEvent("responseCacheEvent", {request:oRequest,response:oResponse});
 718    YAHOO.log("Cached the response for \"" +  oRequest + "\"", "info", this.toString());
 719},
 720
 721/**
 722 * Flushes cache.
 723 *
 724 * @method flushCache
 725 */
 726flushCache : function() {
 727    if(this._aCache) {
 728        this._aCache = [];
 729        this.fireEvent("cacheFlushEvent");
 730        YAHOO.log("Flushed the cache", "info", this.toString());
 731    }
 732},
 733
 734/**
 735 * Sets up a polling mechanism to send requests at set intervals and forward
 736 * responses to given callback.
 737 *
 738 * @method setInterval
 739 * @param nMsec {Number} Length of interval in milliseconds.
 740 * @param oRequest {Object} Request object.
 741 * @param oCallback {Function} Handler function to receive the response.
 742 * @param oCaller {Object} (deprecated) Use oCallback.scope.
 743 * @return {Number} Interval ID.
 744 */
 745setInterval : function(nMsec, oRequest, oCallback, oCaller) {
 746    if(lang.isNumber(nMsec) && (nMsec >= 0)) {
 747        YAHOO.log("Enabling polling to live data for \"" + oRequest + "\" at interval " + nMsec, "info", this.toString());
 748        var oSelf = this;
 749        var nId = setInterval(function() {
 750            oSelf.makeConnection(oRequest, oCallback, oCaller);
 751        }, nMsec);
 752        this._aIntervals.push(nId);
 753        return nId;
 754    }
 755    else {
 756        YAHOO.log("Could not enable polling to live data for \"" + oRequest + "\" at interval " + nMsec, "info", this.toString());
 757    }
 758},
 759
 760/**
 761 * Disables polling mechanism associated with the given interval ID.
 762 *
 763 * @method clearInterval
 764 * @param nId {Number} Interval ID.
 765 */
 766clearInterval : function(nId) {
 767    // Remove from tracker if there
 768    var tracker = this._aIntervals || [];
 769    for(var i=tracker.length-1; i>-1; i--) {
 770        if(tracker[i] === nId) {
 771            tracker.splice(i,1);
 772            clearInterval(nId);
 773        }
 774    }
 775},
 776
 777/**
 778 * Disables all known polling intervals.
 779 *
 780 * @method clearAllIntervals
 781 */
 782clearAllIntervals : function() {
 783    var tracker = this._aIntervals || [];
 784    for(var i=tracker.length-1; i>-1; i--) {
 785        clearInterval(tracker[i]);
 786    }
 787    tracker = [];
 788},
 789
 790/**
 791 * First looks for cached response, then sends request to live data. The
 792 * following arguments are passed to the callback function:
 793 *     <dl>
 794 *     <dt><code>oRequest</code></dt>
 795 *     <dd>The same value that was passed in as the first argument to sendRequest.</dd>
 796 *     <dt><code>oParsedResponse</code></dt>
 797 *     <dd>An object literal containing the following properties:
 798 *         <dl>
 799 *         <dt><code>tId</code></dt>
 800 *         <dd>Unique transaction ID number.</dd>
 801 *         <dt><code>results</code></dt>
 802 *         <dd>Schema-parsed data results.</dd>
 803 *         <dt><code>error</code></dt>
 804 *         <dd>True in cases of data error.</dd>
 805 *         <dt><code>cached</code></dt>
 806 *         <dd>True when response is returned from DataSource cache.</dd> 
 807 *         <dt><code>meta</code></dt>
 808 *         <dd>Schema-parsed meta data.</dd>
 809 *         </dl>
 810 *     <dt><code>oPayload</code></dt>
 811 *     <dd>The same value as was passed in as <code>argument</code> in the oCallback object literal.</dd>
 812 *     </dl> 
 813 *
 814 * @method sendRequest
 815 * @param oRequest {Object} Request object.
 816 * @param oCallback {Object} An object literal with the following properties:
 817 *     <dl>
 818 *     <dt><code>success</code></dt>
 819 *     <dd>The function to call when the data is ready.</dd>
 820 *     <dt><code>failure</code></dt>
 821 *     <dd>The function to call upon a response failure condition.</dd>
 822 *     <dt><code>scope</code></dt>
 823 *     <dd>The object to serve as the scope for the success and failure handlers.</dd>
 824 *     <dt><code>argument</code></dt>
 825 *     <dd>Arbitrary data that will be passed back to the success and failure handlers.</dd>
 826 *     </dl> 
 827 * @param oCaller {Object} (deprecated) Use oCallback.scope.
 828 * @return {Number} Transaction ID, or null if response found in cache.
 829 */
 830sendRequest : function(oRequest, oCallback, oCaller) {
 831    // First look in cache
 832    var oCachedResponse = this.getCachedResponse(oRequest, oCallback, oCaller);
 833    if(oCachedResponse) {
 834        DS.issueCallback(oCallback,[oRequest,oCachedResponse],false,oCaller);
 835        return null;
 836    }
 837
 838
 839    // Not in cache, so forward request to live data
 840    YAHOO.log("Making connection to live data for \"" + oRequest + "\"", "info", this.toString());
 841    return this.makeConnection(oRequest, oCallback, oCaller);
 842},
 843
 844/**
 845 * Overridable default method generates a unique transaction ID and passes 
 846 * the live data reference directly to the  handleResponse function. This
 847 * method should be implemented by subclasses to achieve more complex behavior
 848 * or to access remote data.          
 849 *
 850 * @method makeConnection
 851 * @param oRequest {Object} Request object.
 852 * @param oCallback {Object} Callback object literal.
 853 * @param oCaller {Object} (deprecated) Use oCallback.scope.
 854 * @return {Number} Transaction ID.
 855 */
 856makeConnection : function(oRequest, oCallback, oCaller) {
 857    var tId = DS._nTransactionId++;
 858    this.fireEvent("requestEvent", {tId:tId, request:oRequest,callback:oCallback,caller:oCaller});
 859
 860    /* accounts for the following cases:
 861    YAHOO.util.DataSourceBase.TYPE_UNKNOWN
 862    YAHOO.util.DataSourceBase.TYPE_JSARRAY
 863    YAHOO.util.DataSourceBase.TYPE_JSON
 864    YAHOO.util.DataSourceBase.TYPE_HTMLTABLE
 865    YAHOO.util.DataSourceBase.TYPE_XML
 866    YAHOO.util.DataSourceBase.TYPE_TEXT
 867    */
 868    var oRawResponse = this.liveData;
 869    
 870    this.handleResponse(oRequest, oRawResponse, oCallback, oCaller, tId);
 871    return tId;
 872},
 873
 874/**
 875 * Receives raw data response and type converts to XML, JSON, etc as necessary.
 876 * Forwards oFullResponse to appropriate parsing function to get turned into
 877 * oParsedResponse. Calls doBeforeCallback() and adds oParsedResponse to 
 878 * the cache when appropriate before calling issueCallback().
 879 * 
 880 * The oParsedResponse object literal has the following properties:
 881 * <dl>
 882 *     <dd><dt>tId {Number}</dt> Unique transaction ID</dd>
 883 *     <dd><dt>results {Array}</dt> Array of parsed data results</dd>
 884 *     <dd><dt>meta {Object}</dt> Object literal of meta values</dd> 
 885 *     <dd><dt>error {Boolean}</dt> (optional) True if there was an error</dd>
 886 *     <dd><dt>cached {Boolean}</dt> (optional) True if response was cached</dd>
 887 * </dl>
 888 *
 889 * @method handleResponse
 890 * @param oRequest {Object} Request object
 891 * @param oRawResponse {Object} The raw response from the live database.
 892 * @param oCallback {Object} Callback object literal.
 893 * @param oCaller {Object} (deprecated) Use oCallback.scope.
 894 * @param tId {Number} Transaction ID.
 895 */
 896handleResponse : function(oRequest, oRawResponse, oCallback, oCaller, tId) {
 897    this.fireEvent("responseEvent", {tId:tId, request:oRequest, response:oRawResponse,
 898            callback:oCallback, caller:oCaller});
 899    YAHOO.log("Received live data response for \"" + oRequest + "\"", "info", this.toString());
 900    var xhr = (this.dataType == DS.TYPE_XHR) ? true : false;
 901    var oParsedResponse = null;
 902    var oFullResponse = oRawResponse;
 903    
 904    // Try to sniff data type if it has not been defined
 905    if(this.responseType === DS.TYPE_UNKNOWN) {
 906        var ctype = (oRawResponse && oRawResponse.getResponseHeader) ? oRawResponse.getResponseHeader["Content-Type"] : null;
 907        if(ctype) {
 908             // xml
 909            if(ctype.indexOf("text/xml") > -1) {
 910                this.responseType = DS.TYPE_XML;
 911            }
 912            else if(ctype.indexOf("application/json") > -1) { // json
 913                this.responseType = DS.TYPE_JSON;
 914            }
 915            else if(ctype.indexOf("text/plain") > -1) { // text
 916                this.responseType = DS.TYPE_TEXT;
 917            }
 918        }
 919        else {
 920            if(YAHOO.lang.isArray(oRawResponse)) { // array
 921                this.responseType = DS.TYPE_JSARRAY;
 922            }
 923             // xml
 924            else if(oRawResponse && oRawResponse.nodeType && oRawResponse.nodeType == 9) {
 925                this.responseType = DS.TYPE_XML;
 926            }
 927            else if(oRawResponse && oRawResponse.nodeName && (oRawResponse.nodeName.toLowerCase() == "table")) { // table
 928                this.responseType = DS.TYPE_HTMLTABLE;
 929            }    
 930            else if(YAHOO.lang.isObject(oRawResponse)) { // json
 931                this.responseType = DS.TYPE_JSON;
 932            }
 933            else if(YAHOO.lang.isString(oRawResponse)) { // text
 934                this.responseType = DS.TYPE_TEXT;
 935            }
 936        }
 937    }
 938
 939    switch(this.responseType) {
 940        case DS.TYPE_JSARRAY:
 941            if(xhr && oRawResponse && oRawResponse.responseText) {
 942                oFullResponse = oRawResponse.responseText; 
 943            }
 944            try {
 945                // Convert to JS array if it's a string
 946                if(lang.isString(oFullResponse)) {
 947                    var parseArgs = [oFullResponse].concat(this.parseJSONArgs);
 948                    // Check for YUI JSON Util
 949                    if(lang.JSON) {
 950                        oFullResponse = lang.JSON.parse.apply(lang.JSON,parseArgs);
 951                    }
 952                    // Look for JSON parsers using an API similar to json2.js
 953                    else if(window.JSON && JSON.parse) {
 954                        oFullResponse = JSON.parse.apply(JSON,parseArgs);
 955                    }
 956                    // Look for JSON parsers using an API similar to json.js
 957                    else if(oFullResponse.parseJSON) {
 958                        oFullResponse = oFullResponse.parseJSON.apply(oFullResponse,parseArgs.slice(1));
 959                    }
 960                    // No JSON lib found so parse the string
 961                    else {
 962                        // Trim leading spaces
 963                        while (oFullResponse.length > 0 &&
 964                                (oFullResponse.charAt(0) != "{") &&
 965                                (oFullResponse.charAt(0) != "[")) {
 966                            oFullResponse = oFullResponse.substring(1, oFullResponse.length);
 967                        }
 968
 969                        if(oFullResponse.length > 0) {
 970                            // Strip extraneous stuff at the end
 971                            var arrayEnd =
 972Math.max(oFullResponse.lastIndexOf("]"),oFullResponse.lastIndexOf("}"));
 973                            oFullResponse = oFullResponse.substring(0,arrayEnd+1);
 974
 975                            // Turn the string into an object literal...
 976                            // ...eval is necessary here
 977                            oFullResponse = eval("(" + oFullResponse + ")");
 978
 979                        }
 980                    }
 981                }
 982            }
 983            catch(e1) {
 984            }
 985            oFullResponse = this.doBeforeParseData(oRequest, oFullResponse, oCallback);
 986            oParsedResponse = this.parseArrayData(oRequest, oFullResponse);
 987            break;
 988        case DS.TYPE_JSON:
 989            if(xhr && oRawResponse && oRawResponse.responseText) {
 990                oFullResponse = oRawResponse.responseText;
 991            }
 992            try {
 993                // Convert to JSON object if it's a string
 994                if(lang.isString(oFullResponse)) {
 995                    var parseArgs = [oFullResponse].concat(this.parseJSONArgs);
 996                    // Check for YUI JSON Util
 997                    if(lang.JSON) {
 998                        oFullResponse = lang.JSON.parse.apply(lang.JSON,parseArgs);
 999                    }
1000                    // Look for JSON parsers using an API similar to json2.js
1001                    else if(window.JSON && JSON.parse) {
1002                        oFullResponse = JSON.parse.apply(JSON,parseArgs);
1003                    }
1004                    // Look for JSON parsers using an API similar to json.js
1005                    else if(oFullResponse.parseJSON) {
1006                        oFullResponse = oFullResponse.parseJSON.apply(oFullResponse,parseArgs.slice(1));
1007                    }
1008                    // No JSON lib found so parse the string
1009                    else {
1010                        // Trim leading spaces
1011                        while (oFullResponse.length > 0 &&
1012                                (oFullResponse.charAt(0) != "{") &&
1013                                (oFullResponse.charAt(0) != "[")) {
1014                            oFullResponse = oFullResponse.substring(1, oFullResponse.length);
1015                        }
1016    
1017                        if(oFullResponse.length > 0) {
1018                            // Strip extraneous stuff at the end
1019                            var objEnd = Math.max(oFullResponse.lastIndexOf("]"),oFullResponse.lastIndexOf("}"));
1020                            oFullResponse = oFullResponse.substring(0,objEnd+1);
1021    
1022                            // Turn the string into an object literal...
1023                            // ...eval is necessary here
1024                            oFullResponse = eval("(" + oFullResponse + ")");
1025    
1026                        }
1027                    }
1028                }
1029            }
1030            catch(e) {
1031            }
1032
1033            oFullResponse = this.doBeforeParseData(oRequest, oFullResponse, oCallback);
1034            oParsedResponse = this.parseJSONData(oRequest, oFullResponse);
1035            break;
1036        case DS.TYPE_HTMLTABLE:
1037            if(xhr && oRawResponse.responseText) {
1038                var el = document.createElement('div');
1039                el.innerHTML = oRawResponse.responseText;
1040                oFullResponse = el.getElementsByTagName('table')[0];
1041            }
1042            oFullResponse = this.doBeforeParseData(oRequest, oFullResponse, oCallback);
1043            oParsedResponse = this.parseHTMLTableData(oRequest, oFullResponse);
1044            break;
1045        case DS.TYPE_XML:
1046            if(xhr && oRawResponse.responseXML) {
1047                oFullResponse = oRawResponse.responseXML;
1048            }
1049            oFullResponse = this.doBeforeParseData(oRequest, oFullResponse, oCallback);
1050            oParsedResponse = this.parseXMLData(oRequest, oFullResponse);
1051            break;
1052        case DS.TYPE_TEXT:
1053            if(xhr && lang.isString(oRawResponse.responseText)) {
1054                oFullResponse = oRawResponse.responseText;
1055            }
1056            oFullResponse = this.doBeforeParseData(oRequest, oFullResponse, oCallback);
1057            oParsedResponse = this.parseTextData(oRequest, oFullResponse);
1058            break;
1059        default:
1060            oFullResponse = this.doBeforeParseData(oRequest, oFullResponse, oCallback);
1061            oParsedResponse = this.parseData(oRequest, oFullResponse);
1062            break;
1063    }
1064
1065
1066    // Clean up for consistent signature
1067    oParsedResponse = oParsedResponse || {};
1068    if(!oParsedResponse.results) {
1069        oParsedResponse.results = [];
1070    }
1071    if(!oParsedResponse.meta) {
1072        oParsedResponse.meta = {};
1073    }
1074
1075    // Success
1076    if(oParsedResponse && !oParsedResponse.error) {
1077        // Last chance to touch the raw response or the parsed response
1078        oParsedResponse = this.doBeforeCallback(oRequest, oFullResponse, oParsedResponse, oCallback);
1079        this.fireEvent("responseParseEvent", {request:oRequest,
1080                response:oParsedResponse, callback:oCallback, caller:oCaller});
1081        // Cache the response
1082        this.addToCache(oRequest, oParsedResponse);
1083    }
1084    // Error
1085    else {
1086        // Be sure the error flag is on
1087        oParsedResponse.error = true;
1088        this.fireEvent("dataErrorEvent", {request:oRequest, response: oRawResponse, callback:oCallback, 
1089                caller:oCaller, message:DS.ERROR_DATANULL});
1090        YAHOO.log(DS.ERROR_DATANULL, "error", this.toString());
1091    }
1092
1093    // Send the response back to the caller
1094    oParsedResponse.tId = tId;
1095    DS.issueCallback(oCallback,[oRequest,oParsedResponse],oParsedResponse.error,oCaller);
1096},
1097
1098/**
1099 * Overridable method gives implementers access to the original full response
1100 * before the data gets parsed. Implementers should take care not to return an
1101 * unparsable or otherwise invalid response.
1102 *
1103 * @method doBeforeParseData
1104 * @param oRequest {Object} Request object.
1105 * @param oFullResponse {Object} The full response from the live database.
1106 * @param oCallback {Object} The callback object.  
1107 * @return {Object} Full response for parsing.
1108  
1109 */
1110doBeforeParseData : function(oRequest, oFullResponse, oCallback) {
1111    return oFullResponse;
1112},
1113
1114/**
1115 * Overridable method gives implementers access to the original full response and
1116 * the parsed response (parsed against the given schema) before the data
1117 * is added to the cache (if applicable) and then sent back to callback function.
1118 * This is your chance to access the raw response and/or populate the parsed
1119 * response with any custom data.
1120 *
1121 * @method doBeforeCallback
1122 * @param oRequest {Object} Request object.
1123 * @param oFullResponse {Object} The full response from the live database.
1124 * @param oParsedResponse {Object} The parsed response to return to calling object.
1125 * @param oCallback {Object} The callback object. 
1126 * @return {Object} Parsed response object.
1127 */
1128doBeforeCallback : function(oRequest, oFullResponse, oParsedResponse, oCallback) {
1129    return oParsedResponse;
1130},
1131
1132/**
1133 * Overridable method parses data of generic RESPONSE_TYPE into a response object.
1134 *
1135 * @method parseData
1136 * @param oRequest {Object} Request object.
1137 * @param oFullResponse {Object} The full Array from the live database.
1138 * @return {Object} Parsed response object with the following properties:<br>
1139 *     - results {Array} Array of parsed data results<br>
1140 *     - meta {Object} Object literal of meta values<br>
1141 *     - error {Boolean} (optional) True if there was an error<br>
1142 */
1143parseData : function(oRequest, oFullResponse) {
1144    if(lang.isValue(oFullResponse)) {
1145        var oParsedResponse = {results:oFullResponse,meta:{}};
1146        YAHOO.log("Parsed generic data is " +
1147                lang.dump(oParsedResponse), "info", this.toString());
1148        return oParsedResponse;
1149
1150    }
1151    YAHOO.log("Generic data could not be parsed: " + lang.dump(oFullResponse), 
1152            "error", this.toString());
1153    return null;
1154},
1155
1156/**
1157 * Overridable method parses Array data into a response object.
1158 *
1159 * @method parseArrayData
1160 * @param oRequest {Object} Request object.
1161 * @param oFullResponse {Object} The full Array from the live database.
1162 * @return {Object} Parsed response object with the following properties:<br>
1163 *     - results (Array) Array of parsed data results<br>
1164 *     - error (Boolean) True if there was an error
1165 */
1166parseArrayData : function(oRequest, oFullResponse) {
1167    if(lang.isArray(oFullResponse)) {
1168        var results = [],
1169            i, j,
1170            rec, field, data;
1171        
1172        // Parse for fields
1173        if(lang.isArray(this.responseSchema.fields)) {
1174            var fields = this.responseSchema.fields;
1175            for (i = fields.length - 1; i >= 0; --i) {
1176                if (typeof fields[i] !== 'object') {
1177                    fields[i] = { key : fields[i] };
1178                }
1179            }
1180
1181            var parsers = {}, p;
1182            for (i = fields.length - 1; i >= 0; --i) {
1183                p = (typeof fields[i].parser === 'function' ?
1184                          fields[i].parser :
1185                          DS.Parser[fields[i].parser+'']) || fields[i].converter;
1186                if (p) {
1187                    parsers[fields[i].key] = p;
1188                }
1189            }
1190
1191            var arrType = lang.isArray(oFullResponse[0]);
1192            for(i=oFullResponse.length-1; i>-1; i--) {
1193                var oResult = {};
1194                rec = oFullResponse[i];
1195                if (typeof rec === 'object') {
1196                    for(j=fields.length-1; j>-1; j--) {
1197                        field = fields[j];
1198                        data = arrType ? rec[j] : rec[field.key];
1199
1200                        if (parsers[field.key]) {
1201                            data = parsers[field.key].call(this,data);
1202                        }
1203
1204                        // Safety measure
1205                        if(data === undefined) {
1206                            data = null;
1207                        }
1208
1209                        oResult[field.key] = data;
1210                    }
1211                }
1212                else if (lang.isString(rec)) {
1213                    for(j=fields.length-1; j>-1; j--) {
1214                        field = fields[j];
1215                        data = rec;
1216
1217                        if (parsers[field.key]) {
1218                            data = parsers[field.key].call(this,data);
1219                        }
1220
1221                        // Safety measure
1222                        if(data === undefined) {
1223                            data = null;
1224                        }
1225
1226                        oResult[field.key] = data;
1227                    }                
1228                }
1229                results[i] = oResult;
1230            }    
1231        }
1232        // Return entire data set
1233        else {
1234            results = oFullResponse;
1235        }
1236        var oParsedResponse = {results:results};
1237        YAHOO.log("Parsed array data is " +
1238                lang.dump(oParsedResponse), "info", this.toString());
1239        return oParsedResponse;
1240
1241    }
1242    YAHOO.log("Array data could not be parsed: " + lang.dump(oFullResponse), 
1243            "error", this.toString());
1244    return null;
1245},
1246
1247/**
1248 * Overridable method parses plain text data into a response object.
1249 *
1250 * @method parseTextData
1251 * @param oRequest {Object} Request object.
1252 * @param oFullResponse {Object} The full text response from the live database.
1253 * @return {Object} Parsed response object with the following properties:<br>
1254 *     - results (Array) Array of parsed data results<br>
1255 *     - error (Boolean) True if there was an error
1256 */
1257parseTextData : function(oRequest, oFullResponse) {
1258    if(lang.isString(oFullResponse)) {
1259        if(lang.isString(this.responseSchema.recordDelim) &&
1260                lang.isString(this.responseSchema.fieldDelim)) {
1261            var oParsedResponse = {results:[]};
1262            var recDelim = this.responseSchema.recordDelim;
1263            var fieldDelim = this.responseSchema.fieldDelim;
1264            if(oFullResponse.length > 0) {
1265                // Delete the last line delimiter at the end of the data if it exists
1266                var newLength = oFullResponse.length-recDelim.length;
1267                if(oFullResponse.substr(newLength) == recDelim) {
1268                    oFullResponse = oFullResponse.substr(0, newLength);
1269                }
1270                if(oFullResponse.length > 0) {
1271                    // Split along record delimiter to get an array of strings
1272                    var recordsarray = oFullResponse.split(recDelim);
1273                    // Cycle through each record
1274                    for(var i = 0, len = recordsarray.length, recIdx = 0; i < len; ++i) {
1275                        var bError = false,
1276                            sRecord = recordsarray[i];
1277                        if (lang.isString(sRecord) && (sRecord.length > 0)) {
1278                            // Split each record along field delimiter to get data
1279                            var fielddataarray = recordsarray[i].split(fieldDelim);
1280                            var oResult = {};
1281                            
1282                            // Filter for fields data
1283                            if(lang.isArray(this.responseSchema.fields)) {
1284                                var fields = this.responseSchema.fields;
1285                                for(var j=fields.length-1; j>-1; j--) {
1286                                    try {
1287                                        // Remove quotation marks from edges, if applicable
1288                                        var data = fielddataarray[j];
1289                                        if (lang.isString(data)) {
1290                                            if(data.charAt(0) == "\"") {
1291                                                data = data.substr(1);
1292                                            }
1293                                            if(data.charAt(data.length-1) == "\"") {
1294                                                data = data.substr(0,data.length-1);
1295                                            }
1296                                            var field = fields[j];
1297                                            var key = (lang.isValue(field.key)) ? field.key : field;
1298                                            // Backward compatibility
1299                                            if(!field.parser && field.converter) {
1300                                                field.parser = field.converter;
1301                                                YAHOO.log("The field property converter has been deprecated" +
1302                                                        " in favor of parser", "warn", this.toString());
1303                                            }
1304                                            var parser = (typeof field.parser === 'function') ?
1305                                                field.parser :
1306                                                DS.Parser[field.parser+''];
1307                                            if(parser) {
1308                                                data = parser.call(this, data);
1309                                            }
1310                                            // Safety measure
1311                                            if(data === undefined) {
1312                                                data = null;
1313                                            }
1314                                            oResult[key] = data;
1315                                        }
1316                                        else {
1317                                            bError = true;
1318                                        }
1319                                    }
1320                                    catch(e) {
1321                                        bError = true;
1322                                    }
1323                                }
1324                            }            
1325                            // No fields defined so pass along all data as an array
1326                            else {
1327                                oResult = fielddataarray;
1328                            }
1329                            if(!bError) {
1330                                oParsedResponse.results[recIdx++] = oResult;
1331                            }
1332                        }
1333                    }
1334                }
1335            }
1336            YAHOO.log("Parsed text data is " +
1337                    lang.dump(oParsedResponse), "info", this.toString());
1338            return oParsedResponse;
1339        }
1340    }
1341    YAHOO.log("Text data could not be parsed: " + lang.dump(oFullResponse), 
1342            "error", this.toString());
1343    return null;
1344            
1345},
1346
1347
1348/**
1349 * Overridable method parses XML data for one result into an object literal.
1350 *
1351 * @method parseXMLResult
1352 * @param result {XML} XML for one result.
1353 * @return {Object} Object literal of data for one result.
1354 */
1355parseXMLResult : function(result) {
1356    var oResult = {},
1357        schema = this.responseSchema;
1358        
1359    try {
1360        // Loop through each data field in each result using the schema
1361        for(var m = schema.fields.length-1; m >= 0 ; m--) {
1362            var field = schema.fields[m];
1363            var key = (lang.isValue(field.key)) ? field.key : field;
1364            var data = null;
1365            // Values may be held in an attribute...
1366            var xmlAttr = result.attributes.getNamedItem(key);
1367            if(xmlAttr) {
1368                data = xmlAttr.value;
1369            }
1370            // ...or in a node
1371            else {
1372                var xmlNode = result.getElementsByTagName(key);
1373                if(xmlNode && xmlNode.item(0)) {
1374                    var item = xmlNode.item(0);
1375                    // For IE, then DOM...
1376                    data = (item) ? ((item.text) ? item.text : (item.textContent) ? item.textContent : null) : null;
1377                    // ...then fallback, but check for multiple child nodes
1378                    if(!data) {
1379                        var datapieces = [];
1380                        for(var j=0, len=item.childNodes.length; j<len; j++) {
1381                            if(item.childNodes[j].nodeValue) {
1382                                datapieces[datapieces.length] = item.childNodes[j].nodeValue;
1383                            }
1384                        }
1385                        if(datapieces.length > 0) {
1386                            data = datapieces.join("");
1387                        }
1388                    }
1389                }
1390            }
1391            // Safety net
1392            if(data === null) {
1393                   data = "";
1394            }
1395            // Backward compatibility
1396            if(!field.parser && field.converter) {
1397                field.parser = field.converter;
1398                YAHOO.log("The field property converter has been deprecated" +
1399                        " in favor of parser", "warn", this.toString());
1400            }
1401            var parser = (typeof field.parser === 'function') ?
1402                field.parser :
1403                DS.Parser[field.parser+''];
1404            if(parser) {
1405                data = parser.call(this, data);
1406            }
1407            // Safety measure
1408            if(data === undefined) {
1409                data = null;
1410            }
1411            oResult[key] = data;
1412        }
1413    }
1414    catch(e) {
1415        YAHOO.log("Error while parsing XML result: " + e.message);
1416    }
1417
1418    return oResult;
1419},
1420
1421
1422
1423/**
1424 * Overridable method parses XML data into a response object.
1425 *
1426 * @method parseXMLData
1427 * @param oRequest {Object} Request object.
1428 * @param oFullResponse {Object} The full XML response from the live database.
1429 * @return {Object} Parsed response object with the following properties<br>
1430 *     - results (Array) Array of parsed data results<br>
1431 *     - error (Boolean) True if there was an error
1432 */
1433parseXMLData : function(oRequest, oFullResponse) {
1434    var bError = false,
1435        schema = this.responseSchema,
1436        oParsedResponse = {meta:{}},
1437        xmlList = null,
1438        metaNode      = schema.metaNode,
1439        metaLocators  = schema.metaFields || {},
1440        i,k,loc,v;
1441
1442    // In case oFullResponse is something funky
1443    try {
1444        xmlList = (schema.resultNode) ?
1445            oFullResponse.getElementsByTagName(schema.resultNode) :
1446            null;
1447
1448        // Pull any meta identified
1449        metaNode = metaNode ? oFullResponse.getElementsByTagName(metaNode)[0] :
1450                   oFullResponse;
1451
1452        if (metaNode) {
1453            for (k in metaLocators) {
1454                if (lang.hasOwnProperty(metaLocators, k)) {
1455              

Large files files are truncated, but you can click here to view the full file