PageRenderTime 84ms CodeModel.GetById 18ms app.highlight 56ms RepoModel.GetById 1ms app.codeStats 0ms

/hudson-war/src/main/webapp/scripts/yui/container/container_core-debug.js

http://github.com/hudson/hudson
JavaScript | 1906 lines | 831 code | 298 blank | 777 comment | 193 complexity | 1da0a8622fab67c0b70d6e35f858e697 MD5 | raw file

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

   1/*
   2Copyright (c) 2008, Yahoo! Inc. All rights reserved.
   3Code licensed under the BSD License:
   4http://developer.yahoo.net/yui/license.txt
   5version: 2.5.1
   6*/
   7(function () {
   8
   9    /**
  10    * Config is a utility used within an Object to allow the implementer to
  11    * maintain a list of local configuration properties and listen for changes 
  12    * to those properties dynamically using CustomEvent. The initial values are 
  13    * also maintained so that the configuration can be reset at any given point 
  14    * to its initial state.
  15    * @namespace YAHOO.util
  16    * @class Config
  17    * @constructor
  18    * @param {Object} owner The owner Object to which this Config Object belongs
  19    */
  20    YAHOO.util.Config = function (owner) {
  21
  22        if (owner) {
  23            this.init(owner);
  24        }
  25
  26        if (!owner) {  YAHOO.log("No owner specified for Config object", "error", "Config"); }
  27
  28    };
  29
  30
  31    var Lang = YAHOO.lang,
  32        CustomEvent = YAHOO.util.CustomEvent,
  33        Config = YAHOO.util.Config;
  34
  35
  36    /**
  37     * Constant representing the CustomEvent type for the config changed event.
  38     * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
  39     * @private
  40     * @static
  41     * @final
  42     */
  43    Config.CONFIG_CHANGED_EVENT = "configChanged";
  44    
  45    /**
  46     * Constant representing the boolean type string
  47     * @property YAHOO.util.Config.BOOLEAN_TYPE
  48     * @private
  49     * @static
  50     * @final
  51     */
  52    Config.BOOLEAN_TYPE = "boolean";
  53    
  54    Config.prototype = {
  55     
  56        /**
  57        * Object reference to the owner of this Config Object
  58        * @property owner
  59        * @type Object
  60        */
  61        owner: null,
  62        
  63        /**
  64        * Boolean flag that specifies whether a queue is currently 
  65        * being executed
  66        * @property queueInProgress
  67        * @type Boolean
  68        */
  69        queueInProgress: false,
  70        
  71        /**
  72        * Maintains the local collection of configuration property objects and 
  73        * their specified values
  74        * @property config
  75        * @private
  76        * @type Object
  77        */ 
  78        config: null,
  79        
  80        /**
  81        * Maintains the local collection of configuration property objects as 
  82        * they were initially applied.
  83        * This object is used when resetting a property.
  84        * @property initialConfig
  85        * @private
  86        * @type Object
  87        */ 
  88        initialConfig: null,
  89        
  90        /**
  91        * Maintains the local, normalized CustomEvent queue
  92        * @property eventQueue
  93        * @private
  94        * @type Object
  95        */ 
  96        eventQueue: null,
  97        
  98        /**
  99        * Custom Event, notifying subscribers when Config properties are set 
 100        * (setProperty is called without the silent flag
 101        * @event configChangedEvent
 102        */
 103        configChangedEvent: null,
 104    
 105        /**
 106        * Initializes the configuration Object and all of its local members.
 107        * @method init
 108        * @param {Object} owner The owner Object to which this Config 
 109        * Object belongs
 110        */
 111        init: function (owner) {
 112    
 113            this.owner = owner;
 114    
 115            this.configChangedEvent = 
 116                this.createEvent(Config.CONFIG_CHANGED_EVENT);
 117    
 118            this.configChangedEvent.signature = CustomEvent.LIST;
 119            this.queueInProgress = false;
 120            this.config = {};
 121            this.initialConfig = {};
 122            this.eventQueue = [];
 123        
 124        },
 125        
 126        /**
 127        * Validates that the value passed in is a Boolean.
 128        * @method checkBoolean
 129        * @param {Object} val The value to validate
 130        * @return {Boolean} true, if the value is valid
 131        */ 
 132        checkBoolean: function (val) {
 133            return (typeof val == Config.BOOLEAN_TYPE);
 134        },
 135        
 136        /**
 137        * Validates that the value passed in is a number.
 138        * @method checkNumber
 139        * @param {Object} val The value to validate
 140        * @return {Boolean} true, if the value is valid
 141        */
 142        checkNumber: function (val) {
 143            return (!isNaN(val));
 144        },
 145        
 146        /**
 147        * Fires a configuration property event using the specified value. 
 148        * @method fireEvent
 149        * @private
 150        * @param {String} key The configuration property's name
 151        * @param {value} Object The value of the correct type for the property
 152        */ 
 153        fireEvent: function ( key, value ) {
 154            YAHOO.log("Firing Config event: " + key + "=" + value, "info", "Config");
 155            var property = this.config[key];
 156        
 157            if (property && property.event) {
 158                property.event.fire(value);
 159            } 
 160        },
 161        
 162        /**
 163        * Adds a property to the Config Object's private config hash.
 164        * @method addProperty
 165        * @param {String} key The configuration property's name
 166        * @param {Object} propertyObject The Object containing all of this 
 167        * property's arguments
 168        */
 169        addProperty: function ( key, propertyObject ) {
 170            key = key.toLowerCase();
 171            YAHOO.log("Added property: " + key, "info", "Config");
 172        
 173            this.config[key] = propertyObject;
 174        
 175            propertyObject.event = this.createEvent(key, { scope: this.owner });
 176            propertyObject.event.signature = CustomEvent.LIST;
 177            
 178            
 179            propertyObject.key = key;
 180        
 181            if (propertyObject.handler) {
 182                propertyObject.event.subscribe(propertyObject.handler, 
 183                    this.owner);
 184            }
 185        
 186            this.setProperty(key, propertyObject.value, true);
 187            
 188            if (! propertyObject.suppressEvent) {
 189                this.queueProperty(key, propertyObject.value);
 190            }
 191            
 192        },
 193        
 194        /**
 195        * Returns a key-value configuration map of the values currently set in  
 196        * the Config Object.
 197        * @method getConfig
 198        * @return {Object} The current config, represented in a key-value map
 199        */
 200        getConfig: function () {
 201        
 202            var cfg = {},
 203                prop,
 204                property;
 205                
 206            for (prop in this.config) {
 207                property = this.config[prop];
 208                if (property && property.event) {
 209                    cfg[prop] = property.value;
 210                }
 211            }
 212            
 213            return cfg;
 214        },
 215        
 216        /**
 217        * Returns the value of specified property.
 218        * @method getProperty
 219        * @param {String} key The name of the property
 220        * @return {Object}  The value of the specified property
 221        */
 222        getProperty: function (key) {
 223            var property = this.config[key.toLowerCase()];
 224            if (property && property.event) {
 225                return property.value;
 226            } else {
 227                return undefined;
 228            }
 229        },
 230        
 231        /**
 232        * Resets the specified property's value to its initial value.
 233        * @method resetProperty
 234        * @param {String} key The name of the property
 235        * @return {Boolean} True is the property was reset, false if not
 236        */
 237        resetProperty: function (key) {
 238    
 239            key = key.toLowerCase();
 240        
 241            var property = this.config[key];
 242    
 243            if (property && property.event) {
 244    
 245                if (this.initialConfig[key] && 
 246                    !Lang.isUndefined(this.initialConfig[key])) {
 247    
 248                    this.setProperty(key, this.initialConfig[key]);
 249
 250                    return true;
 251    
 252                }
 253    
 254            } else {
 255    
 256                return false;
 257            }
 258    
 259        },
 260        
 261        /**
 262        * Sets the value of a property. If the silent property is passed as 
 263        * true, the property's event will not be fired.
 264        * @method setProperty
 265        * @param {String} key The name of the property
 266        * @param {String} value The value to set the property to
 267        * @param {Boolean} silent Whether the value should be set silently, 
 268        * without firing the property event.
 269        * @return {Boolean} True, if the set was successful, false if it failed.
 270        */
 271        setProperty: function (key, value, silent) {
 272        
 273            var property;
 274        
 275            key = key.toLowerCase();
 276            YAHOO.log("setProperty: " + key + "=" + value, "info", "Config");
 277        
 278            if (this.queueInProgress && ! silent) {
 279                // Currently running through a queue... 
 280                this.queueProperty(key,value);
 281                return true;
 282    
 283            } else {
 284                property = this.config[key];
 285                if (property && property.event) {
 286                    if (property.validator && !property.validator(value)) {
 287                        return false;
 288                    } else {
 289                        property.value = value;
 290                        if (! silent) {
 291                            this.fireEvent(key, value);
 292                            this.configChangedEvent.fire([key, value]);
 293                        }
 294                        return true;
 295                    }
 296                } else {
 297                    return false;
 298                }
 299            }
 300        },
 301        
 302        /**
 303        * Sets the value of a property and queues its event to execute. If the 
 304        * event is already scheduled to execute, it is
 305        * moved from its current position to the end of the queue.
 306        * @method queueProperty
 307        * @param {String} key The name of the property
 308        * @param {String} value The value to set the property to
 309        * @return {Boolean}  true, if the set was successful, false if 
 310        * it failed.
 311        */ 
 312        queueProperty: function (key, value) {
 313        
 314            key = key.toLowerCase();
 315            YAHOO.log("queueProperty: " + key + "=" + value, "info", "Config");
 316        
 317            var property = this.config[key],
 318                foundDuplicate = false,
 319                iLen,
 320                queueItem,
 321                queueItemKey,
 322                queueItemValue,
 323                sLen,
 324                supercedesCheck,
 325                qLen,
 326                queueItemCheck,
 327                queueItemCheckKey,
 328                queueItemCheckValue,
 329                i,
 330                s,
 331                q;
 332                                
 333            if (property && property.event) {
 334    
 335                if (!Lang.isUndefined(value) && property.validator && 
 336                    !property.validator(value)) { // validator
 337                    return false;
 338                } else {
 339        
 340                    if (!Lang.isUndefined(value)) {
 341                        property.value = value;
 342                    } else {
 343                        value = property.value;
 344                    }
 345        
 346                    foundDuplicate = false;
 347                    iLen = this.eventQueue.length;
 348        
 349                    for (i = 0; i < iLen; i++) {
 350                        queueItem = this.eventQueue[i];
 351        
 352                        if (queueItem) {
 353                            queueItemKey = queueItem[0];
 354                            queueItemValue = queueItem[1];
 355
 356                            if (queueItemKey == key) {
 357    
 358                                /*
 359                                    found a dupe... push to end of queue, null 
 360                                    current item, and break
 361                                */
 362    
 363                                this.eventQueue[i] = null;
 364    
 365                                this.eventQueue.push(
 366                                    [key, (!Lang.isUndefined(value) ? 
 367                                    value : queueItemValue)]);
 368    
 369                                foundDuplicate = true;
 370                                break;
 371                            }
 372                        }
 373                    }
 374                    
 375                    // this is a refire, or a new property in the queue
 376    
 377                    if (! foundDuplicate && !Lang.isUndefined(value)) { 
 378                        this.eventQueue.push([key, value]);
 379                    }
 380                }
 381        
 382                if (property.supercedes) {
 383
 384                    sLen = property.supercedes.length;
 385
 386                    for (s = 0; s < sLen; s++) {
 387
 388                        supercedesCheck = property.supercedes[s];
 389                        qLen = this.eventQueue.length;
 390
 391                        for (q = 0; q < qLen; q++) {
 392                            queueItemCheck = this.eventQueue[q];
 393
 394                            if (queueItemCheck) {
 395                                queueItemCheckKey = queueItemCheck[0];
 396                                queueItemCheckValue = queueItemCheck[1];
 397
 398                                if (queueItemCheckKey == 
 399                                    supercedesCheck.toLowerCase() ) {
 400
 401                                    this.eventQueue.push([queueItemCheckKey, 
 402                                        queueItemCheckValue]);
 403
 404                                    this.eventQueue[q] = null;
 405                                    break;
 406
 407                                }
 408                            }
 409                        }
 410                    }
 411                }
 412
 413                YAHOO.log("Config event queue: " + this.outputEventQueue(), "info", "Config");
 414
 415                return true;
 416            } else {
 417                return false;
 418            }
 419        },
 420        
 421        /**
 422        * Fires the event for a property using the property's current value.
 423        * @method refireEvent
 424        * @param {String} key The name of the property
 425        */
 426        refireEvent: function (key) {
 427    
 428            key = key.toLowerCase();
 429        
 430            var property = this.config[key];
 431    
 432            if (property && property.event && 
 433    
 434                !Lang.isUndefined(property.value)) {
 435    
 436                if (this.queueInProgress) {
 437    
 438                    this.queueProperty(key);
 439    
 440                } else {
 441    
 442                    this.fireEvent(key, property.value);
 443    
 444                }
 445    
 446            }
 447        },
 448        
 449        /**
 450        * Applies a key-value Object literal to the configuration, replacing  
 451        * any existing values, and queueing the property events.
 452        * Although the values will be set, fireQueue() must be called for their 
 453        * associated events to execute.
 454        * @method applyConfig
 455        * @param {Object} userConfig The configuration Object literal
 456        * @param {Boolean} init  When set to true, the initialConfig will 
 457        * be set to the userConfig passed in, so that calling a reset will 
 458        * reset the properties to the passed values.
 459        */
 460        applyConfig: function (userConfig, init) {
 461        
 462            var sKey,
 463                oConfig;
 464
 465            if (init) {
 466                oConfig = {};
 467                for (sKey in userConfig) {
 468                    if (Lang.hasOwnProperty(userConfig, sKey)) {
 469                        oConfig[sKey.toLowerCase()] = userConfig[sKey];
 470                    }
 471                }
 472                this.initialConfig = oConfig;
 473            }
 474
 475            for (sKey in userConfig) {
 476                if (Lang.hasOwnProperty(userConfig, sKey)) {
 477                    this.queueProperty(sKey, userConfig[sKey]);
 478                }
 479            }
 480        },
 481        
 482        /**
 483        * Refires the events for all configuration properties using their 
 484        * current values.
 485        * @method refresh
 486        */
 487        refresh: function () {
 488        
 489            var prop;
 490        
 491            for (prop in this.config) {
 492                this.refireEvent(prop);
 493            }
 494        },
 495        
 496        /**
 497        * Fires the normalized list of queued property change events
 498        * @method fireQueue
 499        */
 500        fireQueue: function () {
 501        
 502            var i, 
 503                queueItem,
 504                key,
 505                value,
 506                property;
 507        
 508            this.queueInProgress = true;
 509            for (i = 0;i < this.eventQueue.length; i++) {
 510                queueItem = this.eventQueue[i];
 511                if (queueItem) {
 512        
 513                    key = queueItem[0];
 514                    value = queueItem[1];
 515                    property = this.config[key];
 516        
 517                    property.value = value;
 518        
 519                    this.fireEvent(key,value);
 520                }
 521            }
 522            
 523            this.queueInProgress = false;
 524            this.eventQueue = [];
 525        },
 526        
 527        /**
 528        * Subscribes an external handler to the change event for any 
 529        * given property. 
 530        * @method subscribeToConfigEvent
 531        * @param {String} key The property name
 532        * @param {Function} handler The handler function to use subscribe to 
 533        * the property's event
 534        * @param {Object} obj The Object to use for scoping the event handler 
 535        * (see CustomEvent documentation)
 536        * @param {Boolean} override Optional. If true, will override "this"  
 537        * within the handler to map to the scope Object passed into the method.
 538        * @return {Boolean} True, if the subscription was successful, 
 539        * otherwise false.
 540        */ 
 541        subscribeToConfigEvent: function (key, handler, obj, override) {
 542    
 543            var property = this.config[key.toLowerCase()];
 544    
 545            if (property && property.event) {
 546                if (!Config.alreadySubscribed(property.event, handler, obj)) {
 547                    property.event.subscribe(handler, obj, override);
 548                }
 549                return true;
 550            } else {
 551                return false;
 552            }
 553    
 554        },
 555        
 556        /**
 557        * Unsubscribes an external handler from the change event for any 
 558        * given property. 
 559        * @method unsubscribeFromConfigEvent
 560        * @param {String} key The property name
 561        * @param {Function} handler The handler function to use subscribe to 
 562        * the property's event
 563        * @param {Object} obj The Object to use for scoping the event 
 564        * handler (see CustomEvent documentation)
 565        * @return {Boolean} True, if the unsubscription was successful, 
 566        * otherwise false.
 567        */
 568        unsubscribeFromConfigEvent: function (key, handler, obj) {
 569            var property = this.config[key.toLowerCase()];
 570            if (property && property.event) {
 571                return property.event.unsubscribe(handler, obj);
 572            } else {
 573                return false;
 574            }
 575        },
 576        
 577        /**
 578        * Returns a string representation of the Config object
 579        * @method toString
 580        * @return {String} The Config object in string format.
 581        */
 582        toString: function () {
 583            var output = "Config";
 584            if (this.owner) {
 585                output += " [" + this.owner.toString() + "]";
 586            }
 587            return output;
 588        },
 589        
 590        /**
 591        * Returns a string representation of the Config object's current 
 592        * CustomEvent queue
 593        * @method outputEventQueue
 594        * @return {String} The string list of CustomEvents currently queued 
 595        * for execution
 596        */
 597        outputEventQueue: function () {
 598
 599            var output = "",
 600                queueItem,
 601                q,
 602                nQueue = this.eventQueue.length;
 603              
 604            for (q = 0; q < nQueue; q++) {
 605                queueItem = this.eventQueue[q];
 606                if (queueItem) {
 607                    output += queueItem[0] + "=" + queueItem[1] + ", ";
 608                }
 609            }
 610            return output;
 611        },
 612
 613        /**
 614        * Sets all properties to null, unsubscribes all listeners from each 
 615        * property's change event and all listeners from the configChangedEvent.
 616        * @method destroy
 617        */
 618        destroy: function () {
 619
 620            var oConfig = this.config,
 621                sProperty,
 622                oProperty;
 623
 624
 625            for (sProperty in oConfig) {
 626            
 627                if (Lang.hasOwnProperty(oConfig, sProperty)) {
 628
 629                    oProperty = oConfig[sProperty];
 630
 631                    oProperty.event.unsubscribeAll();
 632                    oProperty.event = null;
 633
 634                }
 635            
 636            }
 637            
 638            this.configChangedEvent.unsubscribeAll();
 639            
 640            this.configChangedEvent = null;
 641            this.owner = null;
 642            this.config = null;
 643            this.initialConfig = null;
 644            this.eventQueue = null;
 645        
 646        }
 647
 648    };
 649    
 650    
 651    
 652    /**
 653    * Checks to determine if a particular function/Object pair are already 
 654    * subscribed to the specified CustomEvent
 655    * @method YAHOO.util.Config.alreadySubscribed
 656    * @static
 657    * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check 
 658    * the subscriptions
 659    * @param {Function} fn The function to look for in the subscribers list
 660    * @param {Object} obj The execution scope Object for the subscription
 661    * @return {Boolean} true, if the function/Object pair is already subscribed 
 662    * to the CustomEvent passed in
 663    */
 664    Config.alreadySubscribed = function (evt, fn, obj) {
 665    
 666        var nSubscribers = evt.subscribers.length,
 667            subsc,
 668            i;
 669
 670        if (nSubscribers > 0) {
 671            i = nSubscribers - 1;
 672            do {
 673                subsc = evt.subscribers[i];
 674                if (subsc && subsc.obj == obj && subsc.fn == fn) {
 675                    return true;
 676                }
 677            }
 678            while (i--);
 679        }
 680
 681        return false;
 682
 683    };
 684
 685    YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
 686
 687}());
 688
 689(function () {
 690
 691    /**
 692    * The Container family of components is designed to enable developers to 
 693    * create different kinds of content-containing modules on the web. Module 
 694    * and Overlay are the most basic containers, and they can be used directly 
 695    * or extended to build custom containers. Also part of the Container family 
 696    * are four UI controls that extend Module and Overlay: Tooltip, Panel, 
 697    * Dialog, and SimpleDialog.
 698    * @module container
 699    * @title Container
 700    * @requires yahoo, dom, event 
 701    * @optional dragdrop, animation, button
 702    */
 703    
 704    /**
 705    * Module is a JavaScript representation of the Standard Module Format. 
 706    * Standard Module Format is a simple standard for markup containers where 
 707    * child nodes representing the header, body, and footer of the content are 
 708    * denoted using the CSS classes "hd", "bd", and "ft" respectively. 
 709    * Module is the base class for all other classes in the YUI 
 710    * Container package.
 711    * @namespace YAHOO.widget
 712    * @class Module
 713    * @constructor
 714    * @param {String} el The element ID representing the Module <em>OR</em>
 715    * @param {HTMLElement} el The element representing the Module
 716    * @param {Object} userConfig The configuration Object literal containing 
 717    * the configuration that should be set for this module. See configuration 
 718    * documentation for more details.
 719    */
 720    YAHOO.widget.Module = function (el, userConfig) {
 721        if (el) {
 722            this.init(el, userConfig);
 723        } else {
 724            YAHOO.log("No element or element ID specified" + 
 725                " for Module instantiation", "error");
 726        }
 727    };
 728
 729    var Dom = YAHOO.util.Dom,
 730        Config = YAHOO.util.Config,
 731        Event = YAHOO.util.Event,
 732        CustomEvent = YAHOO.util.CustomEvent,
 733        Module = YAHOO.widget.Module,
 734
 735        m_oModuleTemplate,
 736        m_oHeaderTemplate,
 737        m_oBodyTemplate,
 738        m_oFooterTemplate,
 739
 740        /**
 741        * Constant representing the name of the Module's events
 742        * @property EVENT_TYPES
 743        * @private
 744        * @final
 745        * @type Object
 746        */
 747        EVENT_TYPES = {
 748            "BEFORE_INIT": "beforeInit",
 749            "INIT": "init",
 750            "APPEND": "append",
 751            "BEFORE_RENDER": "beforeRender",
 752            "RENDER": "render",
 753            "CHANGE_HEADER": "changeHeader",
 754            "CHANGE_BODY": "changeBody",
 755            "CHANGE_FOOTER": "changeFooter",
 756            "CHANGE_CONTENT": "changeContent",
 757            "DESTORY": "destroy",
 758            "BEFORE_SHOW": "beforeShow",
 759            "SHOW": "show",
 760            "BEFORE_HIDE": "beforeHide",
 761            "HIDE": "hide"
 762        },
 763            
 764        /**
 765        * Constant representing the Module's configuration properties
 766        * @property DEFAULT_CONFIG
 767        * @private
 768        * @final
 769        * @type Object
 770        */
 771        DEFAULT_CONFIG = {
 772        
 773            "VISIBLE": { 
 774                key: "visible", 
 775                value: true, 
 776                validator: YAHOO.lang.isBoolean 
 777            },
 778        
 779            "EFFECT": { 
 780                key: "effect", 
 781                suppressEvent: true, 
 782                supercedes: ["visible"] 
 783            },
 784
 785            "MONITOR_RESIZE": { 
 786                key: "monitorresize", 
 787                value: true  
 788            },
 789
 790            "APPEND_TO_DOCUMENT_BODY": { 
 791                key: "appendtodocumentbody", 
 792                value: false
 793            }
 794        };
 795    
 796    /**
 797    * Constant representing the prefix path to use for non-secure images
 798    * @property YAHOO.widget.Module.IMG_ROOT
 799    * @static
 800    * @final
 801    * @type String
 802    */
 803    Module.IMG_ROOT = null;
 804    
 805    /**
 806    * Constant representing the prefix path to use for securely served images
 807    * @property YAHOO.widget.Module.IMG_ROOT_SSL
 808    * @static
 809    * @final
 810    * @type String
 811    */
 812    Module.IMG_ROOT_SSL = null;
 813    
 814    /**
 815    * Constant for the default CSS class name that represents a Module
 816    * @property YAHOO.widget.Module.CSS_MODULE
 817    * @static
 818    * @final
 819    * @type String
 820    */
 821    Module.CSS_MODULE = "yui-module";
 822    
 823    /**
 824    * Constant representing the module header
 825    * @property YAHOO.widget.Module.CSS_HEADER
 826    * @static
 827    * @final
 828    * @type String
 829    */
 830    Module.CSS_HEADER = "hd";
 831
 832    /**
 833    * Constant representing the module body
 834    * @property YAHOO.widget.Module.CSS_BODY
 835    * @static
 836    * @final
 837    * @type String
 838    */
 839    Module.CSS_BODY = "bd";
 840    
 841    /**
 842    * Constant representing the module footer
 843    * @property YAHOO.widget.Module.CSS_FOOTER
 844    * @static
 845    * @final
 846    * @type String
 847    */
 848    Module.CSS_FOOTER = "ft";
 849    
 850    /**
 851    * Constant representing the url for the "src" attribute of the iframe 
 852    * used to monitor changes to the browser's base font size
 853    * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
 854    * @static
 855    * @final
 856    * @type String
 857    */
 858    Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
 859    
 860    /**
 861    * Singleton CustomEvent fired when the font size is changed in the browser.
 862    * Opera's "zoom" functionality currently does not support text 
 863    * size detection.
 864    * @event YAHOO.widget.Module.textResizeEvent
 865    */
 866    Module.textResizeEvent = new CustomEvent("textResize");
 867
 868    function createModuleTemplate() {
 869
 870        if (!m_oModuleTemplate) {
 871            m_oModuleTemplate = document.createElement("div");
 872            
 873            m_oModuleTemplate.innerHTML = ("<div class=\"" + 
 874                Module.CSS_HEADER + "\"></div>" + "<div class=\"" + 
 875                Module.CSS_BODY + "\"></div><div class=\"" + 
 876                Module.CSS_FOOTER + "\"></div>");
 877
 878            m_oHeaderTemplate = m_oModuleTemplate.firstChild;
 879            m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
 880            m_oFooterTemplate = m_oBodyTemplate.nextSibling;
 881        }
 882
 883        return m_oModuleTemplate;
 884    }
 885
 886    function createHeader() {
 887        if (!m_oHeaderTemplate) {
 888            createModuleTemplate();
 889        }
 890        return (m_oHeaderTemplate.cloneNode(false));
 891    }
 892
 893    function createBody() {
 894        if (!m_oBodyTemplate) {
 895            createModuleTemplate();
 896        }
 897        return (m_oBodyTemplate.cloneNode(false));
 898    }
 899
 900    function createFooter() {
 901        if (!m_oFooterTemplate) {
 902            createModuleTemplate();
 903        }
 904        return (m_oFooterTemplate.cloneNode(false));
 905    }
 906
 907    Module.prototype = {
 908
 909        /**
 910        * The class's constructor function
 911        * @property contructor
 912        * @type Function
 913        */
 914        constructor: Module,
 915        
 916        /**
 917        * The main module element that contains the header, body, and footer
 918        * @property element
 919        * @type HTMLElement
 920        */
 921        element: null,
 922
 923        /**
 924        * The header element, denoted with CSS class "hd"
 925        * @property header
 926        * @type HTMLElement
 927        */
 928        header: null,
 929
 930        /**
 931        * The body element, denoted with CSS class "bd"
 932        * @property body
 933        * @type HTMLElement
 934        */
 935        body: null,
 936
 937        /**
 938        * The footer element, denoted with CSS class "ft"
 939        * @property footer
 940        * @type HTMLElement
 941        */
 942        footer: null,
 943
 944        /**
 945        * The id of the element
 946        * @property id
 947        * @type String
 948        */
 949        id: null,
 950
 951        /**
 952        * A string representing the root path for all images created by
 953        * a Module instance.
 954        * @deprecated It is recommend that any images for a Module be applied
 955        * via CSS using the "background-image" property.
 956        * @property imageRoot
 957        * @type String
 958        */
 959        imageRoot: Module.IMG_ROOT,
 960
 961        /**
 962        * Initializes the custom events for Module which are fired 
 963        * automatically at appropriate times by the Module class.
 964        * @method initEvents
 965        */
 966        initEvents: function () {
 967
 968            var SIGNATURE = CustomEvent.LIST;
 969
 970            /**
 971            * CustomEvent fired prior to class initalization.
 972            * @event beforeInitEvent
 973            * @param {class} classRef class reference of the initializing 
 974            * class, such as this.beforeInitEvent.fire(Module)
 975            */
 976            this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
 977            this.beforeInitEvent.signature = SIGNATURE;
 978
 979            /**
 980            * CustomEvent fired after class initalization.
 981            * @event initEvent
 982            * @param {class} classRef class reference of the initializing 
 983            * class, such as this.beforeInitEvent.fire(Module)
 984            */  
 985            this.initEvent = this.createEvent(EVENT_TYPES.INIT);
 986            this.initEvent.signature = SIGNATURE;
 987
 988            /**
 989            * CustomEvent fired when the Module is appended to the DOM
 990            * @event appendEvent
 991            */
 992            this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
 993            this.appendEvent.signature = SIGNATURE;
 994
 995            /**
 996            * CustomEvent fired before the Module is rendered
 997            * @event beforeRenderEvent
 998            */
 999            this.beforeRenderEvent = this.createEvent(EVENT_TYPES.BEFORE_RENDER);
1000            this.beforeRenderEvent.signature = SIGNATURE;
1001        
1002            /**
1003            * CustomEvent fired after the Module is rendered
1004            * @event renderEvent
1005            */
1006            this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
1007            this.renderEvent.signature = SIGNATURE;
1008        
1009            /**
1010            * CustomEvent fired when the header content of the Module 
1011            * is modified
1012            * @event changeHeaderEvent
1013            * @param {String/HTMLElement} content String/element representing 
1014            * the new header content
1015            */
1016            this.changeHeaderEvent = this.createEvent(EVENT_TYPES.CHANGE_HEADER);
1017            this.changeHeaderEvent.signature = SIGNATURE;
1018            
1019            /**
1020            * CustomEvent fired when the body content of the Module is modified
1021            * @event changeBodyEvent
1022            * @param {String/HTMLElement} content String/element representing 
1023            * the new body content
1024            */  
1025            this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
1026            this.changeBodyEvent.signature = SIGNATURE;
1027            
1028            /**
1029            * CustomEvent fired when the footer content of the Module 
1030            * is modified
1031            * @event changeFooterEvent
1032            * @param {String/HTMLElement} content String/element representing 
1033            * the new footer content
1034            */
1035            this.changeFooterEvent = this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
1036            this.changeFooterEvent.signature = SIGNATURE;
1037        
1038            /**
1039            * CustomEvent fired when the content of the Module is modified
1040            * @event changeContentEvent
1041            */
1042            this.changeContentEvent = this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
1043            this.changeContentEvent.signature = SIGNATURE;
1044
1045            /**
1046            * CustomEvent fired when the Module is destroyed
1047            * @event destroyEvent
1048            */
1049            this.destroyEvent = this.createEvent(EVENT_TYPES.DESTORY);
1050            this.destroyEvent.signature = SIGNATURE;
1051
1052            /**
1053            * CustomEvent fired before the Module is shown
1054            * @event beforeShowEvent
1055            */
1056            this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
1057            this.beforeShowEvent.signature = SIGNATURE;
1058
1059            /**
1060            * CustomEvent fired after the Module is shown
1061            * @event showEvent
1062            */
1063            this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
1064            this.showEvent.signature = SIGNATURE;
1065
1066            /**
1067            * CustomEvent fired before the Module is hidden
1068            * @event beforeHideEvent
1069            */
1070            this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
1071            this.beforeHideEvent.signature = SIGNATURE;
1072
1073            /**
1074            * CustomEvent fired after the Module is hidden
1075            * @event hideEvent
1076            */
1077            this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
1078            this.hideEvent.signature = SIGNATURE;
1079        }, 
1080
1081        /**
1082        * String representing the current user-agent platform
1083        * @property platform
1084        * @type String
1085        */
1086        platform: function () {
1087            var ua = navigator.userAgent.toLowerCase();
1088
1089            if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
1090                return "windows";
1091            } else if (ua.indexOf("macintosh") != -1) {
1092                return "mac";
1093            } else {
1094                return false;
1095            }
1096        }(),
1097        
1098        /**
1099        * String representing the user-agent of the browser
1100        * @deprecated Use YAHOO.env.ua
1101        * @property browser
1102        * @type String
1103        */
1104        browser: function () {
1105            var ua = navigator.userAgent.toLowerCase();
1106            /*
1107                 Check Opera first in case of spoof and check Safari before
1108                 Gecko since Safari's user agent string includes "like Gecko"
1109            */
1110            if (ua.indexOf('opera') != -1) { 
1111                return 'opera';
1112            } else if (ua.indexOf('msie 7') != -1) {
1113                return 'ie7';
1114            } else if (ua.indexOf('msie') != -1) {
1115                return 'ie';
1116            } else if (ua.indexOf('safari') != -1) { 
1117                return 'safari';
1118            } else if (ua.indexOf('gecko') != -1) {
1119                return 'gecko';
1120            } else {
1121                return false;
1122            }
1123        }(),
1124        
1125        /**
1126        * Boolean representing whether or not the current browsing context is 
1127        * secure (https)
1128        * @property isSecure
1129        * @type Boolean
1130        */
1131        isSecure: function () {
1132            if (window.location.href.toLowerCase().indexOf("https") === 0) {
1133                return true;
1134            } else {
1135                return false;
1136            }
1137        }(),
1138        
1139        /**
1140        * Initializes the custom events for Module which are fired 
1141        * automatically at appropriate times by the Module class.
1142        */
1143        initDefaultConfig: function () {
1144            // Add properties //
1145            /**
1146            * Specifies whether the Module is visible on the page.
1147            * @config visible
1148            * @type Boolean
1149            * @default true
1150            */
1151            this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
1152                handler: this.configVisible, 
1153                value: DEFAULT_CONFIG.VISIBLE.value, 
1154                validator: DEFAULT_CONFIG.VISIBLE.validator
1155            });
1156
1157            /**
1158            * Object or array of objects representing the ContainerEffect 
1159            * classes that are active for animating the container.
1160            * @config effect
1161            * @type Object
1162            * @default null
1163            */
1164            this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
1165                suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent, 
1166                supercedes: DEFAULT_CONFIG.EFFECT.supercedes
1167            });
1168
1169            /**
1170            * Specifies whether to create a special proxy iframe to monitor 
1171            * for user font resizing in the document
1172            * @config monitorresize
1173            * @type Boolean
1174            * @default true
1175            */
1176            this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
1177                handler: this.configMonitorResize,
1178                value: DEFAULT_CONFIG.MONITOR_RESIZE.value
1179            });
1180
1181            /**
1182            * Specifies if the module should be rendered as the first child 
1183            * of document.body or appended as the last child when render is called
1184            * with document.body as the "appendToNode".
1185            * <p>
1186            * Appending to the body while the DOM is still being constructed can 
1187            * lead to Operation Aborted errors in IE hence this flag is set to 
1188            * false by default.
1189            * </p>
1190            * 
1191            * @config appendtodocumentbody
1192            * @type Boolean
1193            * @default false
1194            */
1195            this.cfg.addProperty(DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.key, {
1196                value: DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.value
1197            });
1198        },
1199
1200        /**
1201        * The Module class's initialization method, which is executed for
1202        * Module and all of its subclasses. This method is automatically 
1203        * called by the constructor, and  sets up all DOM references for 
1204        * pre-existing markup, and creates required markup if it is not 
1205        * already present.
1206        * @method init
1207        * @param {String} el The element ID representing the Module <em>OR</em>
1208        * @param {HTMLElement} el The element representing the Module
1209        * @param {Object} userConfig The configuration Object literal 
1210        * containing the configuration that should be set for this module. 
1211        * See configuration documentation for more details.
1212        */
1213        init: function (el, userConfig) {
1214
1215            var elId, child;
1216
1217            this.initEvents();
1218            this.beforeInitEvent.fire(Module);
1219
1220            /**
1221            * The Module's Config object used for monitoring 
1222            * configuration properties.
1223            * @property cfg
1224            * @type YAHOO.util.Config
1225            */
1226            this.cfg = new Config(this);
1227
1228            if (this.isSecure) {
1229                this.imageRoot = Module.IMG_ROOT_SSL;
1230            }
1231
1232            if (typeof el == "string") {
1233                elId = el;
1234                el = document.getElementById(el);
1235                if (! el) {
1236                    el = (createModuleTemplate()).cloneNode(false);
1237                    el.id = elId;
1238                }
1239            }
1240
1241            this.element = el;
1242
1243            if (el.id) {
1244                this.id = el.id;
1245            }
1246
1247            child = this.element.firstChild;
1248
1249            if (child) {
1250                var fndHd = false, fndBd = false, fndFt = false;
1251                do {
1252                    // We're looking for elements
1253                    if (1 == child.nodeType) {
1254                        if (!fndHd && Dom.hasClass(child, Module.CSS_HEADER)) {
1255                            this.header = child;
1256                            fndHd = true;
1257                        } else if (!fndBd && Dom.hasClass(child, Module.CSS_BODY)) {
1258                            this.body = child;
1259                            fndBd = true;
1260                        } else if (!fndFt && Dom.hasClass(child, Module.CSS_FOOTER)){
1261                            this.footer = child;
1262                            fndFt = true;
1263                        }
1264                    }
1265                } while ((child = child.nextSibling));
1266            }
1267
1268            this.initDefaultConfig();
1269
1270            Dom.addClass(this.element, Module.CSS_MODULE);
1271
1272            if (userConfig) {
1273                this.cfg.applyConfig(userConfig, true);
1274            }
1275
1276            /*
1277                Subscribe to the fireQueue() method of Config so that any 
1278                queued configuration changes are excecuted upon render of 
1279                the Module
1280            */ 
1281
1282            if (!Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
1283                this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
1284            }
1285
1286            this.initEvent.fire(Module);
1287        },
1288
1289        /**
1290        * Initialize an empty IFRAME that is placed out of the visible area 
1291        * that can be used to detect text resize.
1292        * @method initResizeMonitor
1293        */
1294        initResizeMonitor: function () {
1295
1296            var isGeckoWin = (YAHOO.env.ua.gecko && this.platform == "windows");
1297            if (isGeckoWin) {
1298                // Help prevent spinning loading icon which 
1299                // started with FireFox 2.0.0.8/Win
1300                var self = this;
1301                setTimeout(function(){self._initResizeMonitor();}, 0);
1302            } else {
1303                this._initResizeMonitor();
1304            }
1305        },
1306
1307        /**
1308         * Create and initialize the text resize monitoring iframe.
1309         * 
1310         * @protected
1311         * @method _initResizeMonitor
1312         */
1313        _initResizeMonitor : function() {
1314
1315            var oDoc, 
1316                oIFrame, 
1317                sHTML;
1318
1319            function fireTextResize() {
1320                Module.textResizeEvent.fire();
1321            }
1322
1323            if (!YAHOO.env.ua.opera) {
1324                oIFrame = Dom.get("_yuiResizeMonitor");
1325
1326                var supportsCWResize = this._supportsCWResize();
1327
1328                if (!oIFrame) {
1329                    oIFrame = document.createElement("iframe");
1330
1331                    if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && YAHOO.env.ua.ie) {
1332                        oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
1333                    }
1334
1335                    if (!supportsCWResize) {
1336                        // Can't monitor on contentWindow, so fire from inside iframe
1337                        sHTML = ["<html><head><script ",
1338                                 "type=\"text/javascript\">",
1339                                 "window.onresize=function(){window.parent.",
1340                                 "YAHOO.widget.Module.textResizeEvent.",
1341                                 "fire();};<",
1342                                 "\/script></head>",
1343                                 "<body></body></html>"].join('');
1344
1345                        oIFrame.src = "data:text/html;charset=utf-8," + encodeURIComponent(sHTML);
1346                    }
1347
1348                    oIFrame.id = "_yuiResizeMonitor";
1349                    /*
1350                        Need to set "position" property before inserting the 
1351                        iframe into the document or Safari's status bar will 
1352                        forever indicate the iframe is loading 
1353                        (See SourceForge bug #1723064)
1354                    */
1355                    oIFrame.style.position = "absolute";
1356                    oIFrame.style.visibility = "hidden";
1357
1358                    var db = document.body,
1359                        fc = db.firstChild;
1360                    if (fc) {
1361                        db.insertBefore(oIFrame, fc);
1362                    } else {
1363                        db.appendChild(oIFrame);
1364                    }
1365
1366                    oIFrame.style.width = "10em";
1367                    oIFrame.style.height = "10em";
1368                    oIFrame.style.top = (-1 * oIFrame.offsetHeight) + "px";
1369                    oIFrame.style.left = (-1 * oIFrame.offsetWidth) + "px";
1370                    oIFrame.style.borderWidth = "0";
1371                    oIFrame.style.visibility = "visible";
1372
1373                    /*
1374                       Don't open/close the document for Gecko like we used to, since it
1375                       leads to duplicate cookies. (See SourceForge bug #1721755)
1376                    */
1377                    if (YAHOO.env.ua.webkit) {
1378                        oDoc = oIFrame.contentWindow.document;
1379                        oDoc.open();
1380                        oDoc.close();
1381                    }
1382                }
1383
1384                if (oIFrame && oIFrame.contentWindow) {
1385                    Module.textResizeEvent.subscribe(this.onDomResize, this, true);
1386
1387                    if (!Module.textResizeInitialized) {
1388                        if (supportsCWResize) {
1389                            if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
1390                                /*
1391                                     This will fail in IE if document.domain has 
1392                                     changed, so we must change the listener to 
1393                                     use the oIFrame element instead
1394                                */
1395                                Event.on(oIFrame, "resize", fireTextResize);
1396                            }
1397                        }
1398                        Module.textResizeInitialized = true;
1399                    }
1400                    this.resizeMonitor = oIFrame;
1401                }
1402            }
1403        },
1404
1405        /**
1406         * Text resize monitor helper method.
1407         * Determines if the browser supports resize events on iframe content windows.
1408         * 
1409         * @private
1410         * @method _supportsCWResize
1411         */
1412        _supportsCWResize : function() {
1413            /*
1414                Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
1415                Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
1416
1417                We don't want to start sniffing for patch versions, so fire textResize the same
1418                way on all FF, until 1.9 (3.x) is out
1419             */
1420            var bSupported = true;
1421            if (YAHOO.env.ua.gecko && YAHOO.env.ua.gecko <= 1.8) {
1422                bSupported = false;
1423                /*
1424                var v = navigator.userAgent.match(/rv:([^\s\)]*)/); // From YAHOO.env.ua
1425                if (v && v[0]) {
1426                    var sv = v[0].match(/\d\.\d\.(\d)/);
1427                    if (sv && sv[1]) {
1428                        if (parseInt(sv[1], 10) > 0) {
1429                            bSupported = true;
1430                        }
1431                    }
1432                }
1433                */
1434            }
1435            return bSupported;
1436        },
1437
1438        /**
1439        * Event handler fired when the resize monitor element is resized.
1440        * @method onDomResize
1441        * @param {DOMEvent} e The DOM resize event
1442        * @param {Object} obj The scope object passed to the handler
1443        */
1444        onDomResize: function (e, obj) {
1445
1446            var nLeft = -1 * this.resizeMonitor.offsetWidth,
1447                nTop = -1 * this.resizeMonitor.offsetHeight;
1448        
1449            this.resizeMonitor.style.top = nTop + "px";
1450            this.resizeMonitor.style.left =  nLeft + "px";
1451
1452        },
1453
1454        /**
1455        * Sets the Module's header content to the string specified, or appends 
1456        * the passed element to the header. If no header is present, one will 
1457        * be automatically created. An empty string can be passed to the method
1458        * to clear the contents of the header.
1459        * 
1460        * @method setHeader
1461        * @param {String} headerContent The string used to set the header.
1462        * As a convenience, non HTMLElement objects can also be passed into 
1463        * the method, and will be treated as strings, with the header innerHTML
1464        * set to their default toString implementations.
1465        * <em>OR</em>
1466        * @param {HTMLElement} headerContent The HTMLElement to append to 
1467        * <em>OR</em>
1468        * @param {DocumentFragment} headerContent The document fragment 
1469        * containing elements which are to be added to the header
1470        */
1471        setHeader: function (headerContent) {
1472            var oHeader = this.header || (this.header = createHeader());
1473
1474            if (headerContent.nodeName) {
1475                oHeader.innerHTML = "";
1476                oHeader.appendChild(headerContent);
1477            } else {
1478                oHeader.innerHTML = headerContent;
1479            }
1480
1481            this.changeHeaderEvent.fire(headerContent);
1482            this.changeContentEvent.fire();
1483
1484        },
1485
1486        /**
1487        * Appends the passed element to the header. If no header is present, 
1488        * one will be automatically created.
1489        * @method appendToHeader
1490        * @param {HTMLElement | DocumentFragment} element The element to 
1491        * append to the header. In the case of a document fragment, the
1492        * children of the fragment will be appended to t

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