PageRenderTime 75ms CodeModel.GetById 8ms app.highlight 56ms RepoModel.GetById 1ms app.codeStats 0ms

/hippo/src/main/webapp/yui/container/container_core-debug.js

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

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