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