/* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 0.12.0 */ /** * The YAHOO object is the single global object used by YUI Library. It * contains utility function for setting up namespaces, inheritance, and * logging. YAHOO.util, YAHOO.widget, and YAHOO.example are namespaces * created automatically for and used by the library. * @module yahoo * @title YAHOO Global */ /** * The YAHOO global namespace object * @class YAHOO * @static */ if (typeof YAHOO == "undefined") { var YAHOO = {}; } /** * Returns the namespace specified and creates it if it doesn't exist *
* YAHOO.namespace("property.package"); * YAHOO.namespace("YAHOO.property.package"); ** Either of the above would create YAHOO.property, then * YAHOO.property.package * * Be careful when naming packages. Reserved words may work in some browsers * and not others. For instance, the following will fail in Safari: *
* YAHOO.namespace("really.long.nested.namespace"); ** This fails because "long" is a future reserved word in ECMAScript * * @method namespace * @static * @param {String*} arguments 1-n namespaces to create * @return {Object} A reference to the last namespace object created */ YAHOO.namespace = function() { var a=arguments, o=null, i, j, d; for (i=0; i
", sourceAndDetail, ":
", msg, "
"] : ["", label, " ", totalTime, "ms (+", elapsedTime, ") ", localTime, ": ", sourceAndDetail, ": ", msg,"
"]; return output.join(""); }; /** * Converts input chars "<", ">", and "&" to HTML entities. * * @method html2Text * @param sHtml {String} String to convert. * @private */ YAHOO.widget.LogReader.prototype.html2Text = function(sHtml) { if(sHtml) { sHtml += ""; return sHtml.replace(/&/g, "&").replace(//g, ">"); } return ""; }; ///////////////////////////////////////////////////////////////////////////// // // Private member variables // ///////////////////////////////////////////////////////////////////////////// /** * Internal class member to index multiple log reader instances. * * @property _memberName * @static * @type Number * @default 0 * @private */ YAHOO.widget.LogReader._index = 0; /** * Name of LogReader instance. * * @property _sName * @type String * @private */ YAHOO.widget.LogReader.prototype._sName = null; /** * A class member shared by all log readers if a container needs to be * created during instantiation. Will be null if a container element never needs to * be created on the fly, such as when the implementer passes in their own element. * * @property _elDefaultContainer * @type HTMLElement * @private */ YAHOO.widget.LogReader._elDefaultContainer = null; /** * Buffer of log message objects for batch output. * * @property _buffer * @type Object[] * @private */ YAHOO.widget.LogReader.prototype._buffer = null; /** * Number of log messages output to console. * * @property _consoleMsgCount * @type Number * @default 0 * @private */ YAHOO.widget.LogReader.prototype._consoleMsgCount = 0; /** * Date of last output log message. * * @property _lastTime * @type Date * @private */ YAHOO.widget.LogReader.prototype._lastTime = null; /** * Batched output timeout ID. * * @property _timeout * @type Number * @private */ YAHOO.widget.LogReader.prototype._timeout = null; /** * Array of filters for log message categories. * * @property _categoryFilters * @type String[] * @private */ YAHOO.widget.LogReader.prototype._categoryFilters = null; /** * Array of filters for log message sources. * * @property _sourceFilters * @type String[] * @private */ YAHOO.widget.LogReader.prototype._sourceFilters = null; /** * Log reader container element. * * @property _elContainer * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._elContainer = null; /** * Log reader header element. * * @property _elHd * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._elHd = null; /** * Log reader collapse element. * * @property _elCollapse * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._elCollapse = null; /** * Log reader collapse button element. * * @property _btnCollapse * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._btnCollapse = null; /** * Log reader title header element. * * @property _title * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._title = null; /** * Log reader console element. * * @property _elConsole * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._elConsole = null; /** * Log reader footer element. * * @property _elFt * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._elFt = null; /** * Log reader buttons container element. * * @property _elBtns * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._elBtns = null; /** * Container element for log reader category filter checkboxes. * * @property _elCategoryFilters * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._elCategoryFilters = null; /** * Container element for log reader source filter checkboxes. * * @property _elSourceFilters * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._elSourceFilters = null; /** * Log reader pause button element. * * @property _btnPause * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._btnPause = null; /** * Clear button element. * * @property _btnClear * @type HTMLElement * @private */ YAHOO.widget.LogReader.prototype._btnClear = null; ///////////////////////////////////////////////////////////////////////////// // // Private methods // ///////////////////////////////////////////////////////////////////////////// /** * Creates the UI for a category filter in the log reader footer element. * * @method _createCategoryCheckbox * @param sCategory {String} Category name. * @private */ YAHOO.widget.LogReader.prototype._createCategoryCheckbox = function(sCategory) { var oSelf = this; if(this._elFt) { var elParent = this._elCategoryFilters; var filters = this._categoryFilters; var elFilter = elParent.appendChild(document.createElement("span")); elFilter.className = "yui-log-filtergrp"; // Append el at the end so IE 5.5 can set "type" attribute // and THEN set checked property var chkCategory = document.createElement("input"); chkCategory.id = "yui-log-filter-" + sCategory + this._sName; chkCategory.className = "yui-log-filter-" + sCategory; chkCategory.type = "checkbox"; chkCategory.category = sCategory; chkCategory = elFilter.appendChild(chkCategory); chkCategory.checked = true; // Add this checked filter to the internal array of filters filters.push(sCategory); // Subscribe to the click event YAHOO.util.Event.addListener(chkCategory,'click',oSelf._onCheckCategory,oSelf); // Create and class the text label var lblCategory = elFilter.appendChild(document.createElement("label")); lblCategory.htmlFor = chkCategory.id; lblCategory.className = sCategory; lblCategory.innerHTML = sCategory; } }; /** * Creates a checkbox in the log reader footer element to filter by source. * * @method _createSourceCheckbox * @param sSource {String} Source name. * @private */ YAHOO.widget.LogReader.prototype._createSourceCheckbox = function(sSource) { var oSelf = this; if(this._elFt) { var elParent = this._elSourceFilters; var filters = this._sourceFilters; var elFilter = elParent.appendChild(document.createElement("span")); elFilter.className = "yui-log-filtergrp"; // Append el at the end so IE 5.5 can set "type" attribute // and THEN set checked property var chkSource = document.createElement("input"); chkSource.id = "yui-log-filter" + sSource + this._sName; chkSource.className = "yui-log-filter" + sSource; chkSource.type = "checkbox"; chkSource.source = sSource; chkSource = elFilter.appendChild(chkSource); chkSource.checked = true; // Add this checked filter to the internal array of filters filters.push(sSource); // Subscribe to the click event YAHOO.util.Event.addListener(chkSource,'click',oSelf._onCheckSource,oSelf); // Create and class the text label var lblSource = elFilter.appendChild(document.createElement("label")); lblSource.htmlFor = chkSource.id; lblSource.className = sSource; lblSource.innerHTML = sSource; } }; /** * Reprints all log messages in the stack through filters. * * @method _filterLogs * @private */ YAHOO.widget.LogReader.prototype._filterLogs = function() { // Reprint stack with new filters if (this._elConsole !== null) { this._clearConsole(); this._printToConsole(YAHOO.widget.Logger.getStack()); } }; /** * Clears all outputted log messages from the console and resets the time of the * last output log message. * * @method _clearConsole * @private */ YAHOO.widget.LogReader.prototype._clearConsole = function() { // Clear the buffer of any pending messages this._timeout = null; this._buffer = []; this._consoleMsgCount = 0; // Reset the rolling timer this._lastTime = YAHOO.widget.Logger.getStartTime(); var elConsole = this._elConsole; while(elConsole.hasChildNodes()) { elConsole.removeChild(elConsole.firstChild); } }; /** * Sends buffer of log messages to output and clears buffer. * * @method _printBuffer * @private */ YAHOO.widget.LogReader.prototype._printBuffer = function() { this._timeout = null; if(this._elConsole !== null) { var thresholdMax = this.thresholdMax; thresholdMax = (thresholdMax && !isNaN(thresholdMax)) ? thresholdMax : 500; if(this._consoleMsgCount < thresholdMax) { var entries = []; for (var i=0; itag (for wrapping) var container = (this.verboseOutput) ? "CODE" : "PRE"; var oNewElement = (this.newestOnTop) ? this._elConsole.insertBefore( document.createElement(container),this._elConsole.firstChild): this._elConsole.appendChild(document.createElement(container)); oNewElement.innerHTML = output; this._consoleMsgCount++; this._lastTime = entry.time.getTime(); } } }; ///////////////////////////////////////////////////////////////////////////// // // Private event handlers // ///////////////////////////////////////////////////////////////////////////// /** * Handles Logger's categoryCreateEvent. * * @method _onCategoryCreate * @param sType {String} The event. * @param aArgs {Object[]} Data passed from event firer. * @param oSelf {Object} The LogReader instance. * @private */ YAHOO.widget.LogReader.prototype._onCategoryCreate = function(sType, aArgs, oSelf) { var category = aArgs[0]; if(oSelf._elFt) { oSelf._createCategoryCheckbox(category); } }; /** * Handles Logger's sourceCreateEvent. * * @method _onSourceCreate * @param sType {String} The event. * @param aArgs {Object[]} Data passed from event firer. * @param oSelf {Object} The LogReader instance. * @private */ YAHOO.widget.LogReader.prototype._onSourceCreate = function(sType, aArgs, oSelf) { var source = aArgs[0]; if(oSelf._elFt) { oSelf._createSourceCheckbox(source); } }; /** * Handles check events on the category filter checkboxes. * * @method _onCheckCategory * @param v {HTMLEvent} The click event. * @param oSelf {Object} The LogReader instance. * @private */ YAHOO.widget.LogReader.prototype._onCheckCategory = function(v, oSelf) { var newFilter = this.category; var filtersArray = oSelf._categoryFilters; if(!this.checked) { // Remove category from filters for(var i=0; i0) { // Substring until first space sClass = sSource.substring(0,spaceIndex); // The rest of the source sDetail = sSource.substring(spaceIndex,sSource.length); } else { sClass = sSource; } if(this._isNewSource(sClass)) { this._createNewSource(sClass); } } var timestamp = new Date(); var logEntry = new YAHOO.widget.LogMsg({ msg: sMsg, time: timestamp, category: sCategory, source: sClass, sourceDetail: sDetail }); var stack = this._stack; var maxStackEntries = this.maxStackEntries; if(maxStackEntries && !isNaN(maxStackEntries) && (stack.length >= maxStackEntries)) { stack.shift(); } stack.push(logEntry); this.newLogEvent.fire(logEntry); if(this._browserConsoleEnabled) { this._printToBrowserConsole(logEntry); } return true; } else { return false; } }; /** * Resets internal stack and startTime, enables Logger, and fires logResetEvent. * * @method reset */ YAHOO.widget.Logger.reset = function() { this._stack = []; this._startTime = new Date().getTime(); this.loggerEnabled = true; this.log("Logger reset"); this.logResetEvent.fire(); }; /** * Public accessor to internal stack of log message objects. * * @method getStack * @return {Object[]} Array of log message objects. */ YAHOO.widget.Logger.getStack = function() { return this._stack; }; /** * Public accessor to internal start time. * * @method getStartTime * @return {Date} Internal date of when Logger singleton was initialized. */ YAHOO.widget.Logger.getStartTime = function() { return this._startTime; }; /** * Disables output to the browser's global console.log() function, which is used * by the Firebug extension to Firefox as well as Safari. * * @method disableBrowserConsole */ YAHOO.widget.Logger.disableBrowserConsole = function() { YAHOO.log("Logger output to the function console.log() has been disabled."); this._browserConsoleEnabled = false; }; /** * Enables output to the browser's global console.log() function, which is used * by the Firebug extension to Firefox as well as Safari. * * @method enableBrowserConsole */ YAHOO.widget.Logger.enableBrowserConsole = function() { this._browserConsoleEnabled = true; YAHOO.log("Logger output to the function console.log() has been enabled."); }; ///////////////////////////////////////////////////////////////////////////// // // Public events // ///////////////////////////////////////////////////////////////////////////// /** * Fired when a new category has been created. * * @event categoryCreateEvent * @param sCategory {String} Category name. */ YAHOO.widget.Logger.categoryCreateEvent = new YAHOO.util.CustomEvent("categoryCreate", this, true); /** * Fired when a new source has been named. * * @event sourceCreateEvent * @param sSource {String} Source name. */ YAHOO.widget.Logger.sourceCreateEvent = new YAHOO.util.CustomEvent("sourceCreate", this, true); /** * Fired when a new log message has been created. * * @event newLogEvent * @param sMsg {String} Log message. */ YAHOO.widget.Logger.newLogEvent = new YAHOO.util.CustomEvent("newLog", this, true); /** * Fired when the Logger has been reset has been created. * * @event logResetEvent */ YAHOO.widget.Logger.logResetEvent = new YAHOO.util.CustomEvent("logReset", this, true); ///////////////////////////////////////////////////////////////////////////// // // Private methods // ///////////////////////////////////////////////////////////////////////////// /** * Creates a new category of log messages and fires categoryCreateEvent. * * @method _createNewCategory * @param sCategory {String} Category name. * @private */ YAHOO.widget.Logger._createNewCategory = function(sCategory) { this.categories.push(sCategory); this.categoryCreateEvent.fire(sCategory); }; /** * Checks to see if a category has already been created. * * @method _isNewCategory * @param sCategory {String} Category name. * @return {Boolean} Returns true if category is unknown, else returns false. * @private */ YAHOO.widget.Logger._isNewCategory = function(sCategory) { for(var i=0; i < this.categories.length; i++) { if(sCategory == this.categories[i]) { return false; } } return true; }; /** * Creates a new source of log messages and fires sourceCreateEvent. * * @method _createNewSource * @param sSource {String} Source name. * @private */ YAHOO.widget.Logger._createNewSource = function(sSource) { this.sources.push(sSource); this.sourceCreateEvent.fire(sSource); }; /** * Checks to see if a source already exists. * * @method _isNewSource * @param sSource {String} Source name. * @return {Boolean} Returns true if source is unknown, else returns false. * @private */ YAHOO.widget.Logger._isNewSource = function(sSource) { if(sSource) { for(var i=0; i < this.sources.length; i++) { if(sSource == this.sources[i]) { return false; } } return true; } }; /** * Outputs a log message to global console.log() function. * * @method _printToBrowserConsole * @param oEntry {Object} Log entry object. * @private */ YAHOO.widget.Logger._printToBrowserConsole = function(oEntry) { if(window.console && console.log) { var category = oEntry.category; var label = oEntry.category.substring(0,4).toUpperCase(); var time = oEntry.time; if (time.toLocaleTimeString) { var localTime = time.toLocaleTimeString(); } else { localTime = time.toString(); } var msecs = time.getTime(); var elapsedTime = (YAHOO.widget.Logger._lastTime) ? (msecs - YAHOO.widget.Logger._lastTime) : 0; YAHOO.widget.Logger._lastTime = msecs; var output = localTime + " (" + elapsedTime + "ms): " + oEntry.source + ": " + oEntry.msg; console.log(output); } }; ///////////////////////////////////////////////////////////////////////////// // // Private event handlers // ///////////////////////////////////////////////////////////////////////////// /** * Handles logging of messages due to window error events. * * @method _onWindowError * @param sMsg {String} The error message. * @param sUrl {String} URL of the error. * @param sLine {String} Line number of the error. * @private */ YAHOO.widget.Logger._onWindowError = function(sMsg,sUrl,sLine) { // Logger is not in scope of this event handler try { YAHOO.widget.Logger.log(sMsg+' ('+sUrl+', line '+sLine+')', "window"); if(YAHOO.widget.Logger._origOnWindowError) { YAHOO.widget.Logger._origOnWindowError(); } } catch(e) { return false; } }; ///////////////////////////////////////////////////////////////////////////// // // Enable handling of native JavaScript errors // NB: Not all browsers support the window.onerror event // ///////////////////////////////////////////////////////////////////////////// if(window.onerror) { // Save any previously defined handler to call YAHOO.widget.Logger._origOnWindowError = window.onerror; } window.onerror = YAHOO.widget.Logger._onWindowError; ///////////////////////////////////////////////////////////////////////////// // // First log // ///////////////////////////////////////////////////////////////////////////// YAHOO.widget.Logger.log("Logger initialized"); /* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 0.12.0 */ /** * The animation module provides allows effects to be added to HTMLElements. * @module animation */ /** * * Base animation class that provides the interface for building animated effects. * Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);
* @class Anim * @namespace YAHOO.util * @requires YAHOO.util.AnimMgr * @requires YAHOO.util.Easing * @requires YAHOO.util.Dom * @requires YAHOO.util.Event * @requires YAHOO.util.CustomEvent * @constructor * @param {String | HTMLElement} el Reference to the element that will be animated * @param {Object} attributes The attribute(s) to be animated. * Each attribute is an object with at minimum a "to" or "by" member defined. * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). * All attribute names use camelCase. * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) */ YAHOO.util.Anim = function(el, attributes, duration, method) { if (el) { this.init(el, attributes, duration, method); } }; YAHOO.util.Anim.prototype = { /** * Provides a readable name for the Anim instance. * @method toString * @return {String} */ toString: function() { var el = this.getEl(); var id = el.id || el.tagName; return ("Anim " + id); }, patterns: { // cached for performance noNegatives: /width|height|opacity|padding/i, // keep at zero or above offsetAttribute: /^((width|height)|(top|left))$/, // use offsetValue as default defaultUnit: /width|height|top$|bottom$|left$|right$/i, // use 'px' by default offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset }, /** * Returns the value computed by the animation's "method". * @method doMethod * @param {String} attr The name of the attribute. * @param {Number} start The value this attribute should start from for this animation. * @param {Number} end The value this attribute should end at for this animation. * @return {Number} The Value to be applied to the attribute. */ doMethod: function(attr, start, end) { return this.method(this.currentFrame, start, end - start, this.totalFrames); }, /** * Applies a value to an attribute. * @method setAttribute * @param {String} attr The name of the attribute. * @param {Number} val The value to be applied to the attribute. * @param {String} unit The unit ('px', '%', etc.) of the value. */ setAttribute: function(attr, val, unit) { if ( this.patterns.noNegatives.test(attr) ) { val = (val > 0) ? val : 0; } YAHOO.util.Dom.setStyle(this.getEl(), attr, val + unit); }, /** * Returns current value of the attribute. * @method getAttribute * @param {String} attr The name of the attribute. * @return {Number} val The current value of the attribute. */ getAttribute: function(attr) { var el = this.getEl(); var val = YAHOO.util.Dom.getStyle(el, attr); if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) { return parseFloat(val); } var a = this.patterns.offsetAttribute.exec(attr) || []; var pos = !!( a[3] ); // top or left var box = !!( a[2] ); // width or height // use offsets for width/height and abs pos top/left if ( box || (YAHOO.util.Dom.getStyle(el, 'position') == 'absolute' && pos) ) { val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)]; } else { // default to zero for other 'auto' val = 0; } return val; }, /** * Returns the unit to use when none is supplied. * @method getDefaultUnit * @param {attr} attr The name of the attribute. * @return {String} The default unit to be used. */ getDefaultUnit: function(attr) { if ( this.patterns.defaultUnit.test(attr) ) { return 'px'; } return ''; }, /** * Sets the actual values to be used during the animation. * @method setRuntimeAttribute * Should only be needed for subclass use. * @param {Object} attr The attribute object * @private */ setRuntimeAttribute: function(attr) { var start; var end; var attributes = this.attributes; this.runtimeAttributes[attr] = {}; var isset = function(prop) { return (typeof prop !== 'undefined'); }; if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) { return false; // note return; nothing to animate to } start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr); // To beats by, per SMIL 2.1 spec if ( isset(attributes[attr]['to']) ) { end = attributes[attr]['to']; } else if ( isset(attributes[attr]['by']) ) { if (start.constructor == Array) { end = []; for (var i = 0, len = start.length; i < len; ++i) { end[i] = start[i] + attributes[attr]['by'][i]; } } else { end = start + attributes[attr]['by']; } } this.runtimeAttributes[attr].start = start; this.runtimeAttributes[attr].end = end; // set units if needed this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr); }, /** * Constructor for Anim instance. * @method init * @param {String | HTMLElement} el Reference to the element that will be animated * @param {Object} attributes The attribute(s) to be animated. * Each attribute is an object with at minimum a "to" or "by" member defined. * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). * All attribute names use camelCase. * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) */ init: function(el, attributes, duration, method) { /** * Whether or not the animation is running. * @property isAnimated * @private * @type Boolean */ var isAnimated = false; /** * A Date object that is created when the animation begins. * @property startTime * @private * @type Date */ var startTime = null; /** * The number of frames this animation was able to execute. * @property actualFrames * @private * @type Int */ var actualFrames = 0; /** * The element to be animated. * @property el * @private * @type HTMLElement */ el = YAHOO.util.Dom.get(el); /** * The collection of attributes to be animated. * Each attribute must have at least a "to" or "by" defined in order to animate. * If "to" is supplied, the animation will end with the attribute at that value. * If "by" is supplied, the animation will end at that value plus its starting value. * If both are supplied, "to" is used, and "by" is ignored. * Optional additional member include "from" (the value the attribute should start animating from, defaults to current value), and "unit" (the units to apply to the values). * @property attributes * @type Object */ this.attributes = attributes || {}; /** * The length of the animation. Defaults to "1" (second). * @property duration * @type Number */ this.duration = duration || 1; /** * The method that will provide values to the attribute(s) during the animation. * Defaults to "YAHOO.util.Easing.easeNone". * @property method * @type Function */ this.method = method || YAHOO.util.Easing.easeNone; /** * Whether or not the duration should be treated as seconds. * Defaults to true. * @property useSeconds * @type Boolean */ this.useSeconds = true; // default to seconds /** * The location of the current animation on the timeline. * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time. * @property currentFrame * @type Int */ this.currentFrame = 0; /** * The total number of frames to be executed. * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time. * @property totalFrames * @type Int */ this.totalFrames = YAHOO.util.AnimMgr.fps; /** * Returns a reference to the animated element. * @method getEl * @return {HTMLElement} */ this.getEl = function() { return el; }; /** * Checks whether the element is currently animated. * @method isAnimated * @return {Boolean} current value of isAnimated. */ this.isAnimated = function() { return isAnimated; }; /** * Returns the animation start time. * @method getStartTime * @return {Date} current value of startTime. */ this.getStartTime = function() { return startTime; }; this.runtimeAttributes = {}; /** * Starts the animation by registering it with the animation manager. * @method animate */ this.animate = function() { if ( this.isAnimated() ) { return false; } this.currentFrame = 0; this.totalFrames = ( this.useSeconds ) ? Math.ceil(YAHOO.util.AnimMgr.fps * this.duration) : this.duration; YAHOO.util.AnimMgr.registerElement(this); }; /** * Stops the animation. Normally called by AnimMgr when animation completes. * @method stop * @param {Boolean} finish (optional) If true, animation will jump to final frame. */ this.stop = function(finish) { if (finish) { this.currentFrame = this.totalFrames; this._onTween.fire(); } YAHOO.util.AnimMgr.stop(this); }; var onStart = function() { this.onStart.fire(); this.runtimeAttributes = {}; for (var attr in this.attributes) { this.setRuntimeAttribute(attr); } isAnimated = true; actualFrames = 0; startTime = new Date(); }; /** * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s). * @private */ var onTween = function() { var data = { duration: new Date() - this.getStartTime(), currentFrame: this.currentFrame }; data.toString = function() { return ( 'duration: ' + data.duration + ', currentFrame: ' + data.currentFrame ); }; this.onTween.fire(data); var runtimeAttributes = this.runtimeAttributes; for (var attr in runtimeAttributes) { this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit); } actualFrames += 1; }; var onComplete = function() { var actual_duration = (new Date() - startTime) / 1000 ; var data = { duration: actual_duration, frames: actualFrames, fps: actualFrames / actual_duration }; data.toString = function() { return ( 'duration: ' + data.duration + ', frames: ' + data.frames + ', fps: ' + data.fps ); }; isAnimated = false; actualFrames = 0; this.onComplete.fire(data); }; /** * Custom event that fires after onStart, useful in subclassing * @private */ this._onStart = new YAHOO.util.CustomEvent('_start', this, true); /** * Custom event that fires when animation begins * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction) * @event onStart */ this.onStart = new YAHOO.util.CustomEvent('start', this); /** * Custom event that fires between each frame * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction) * @event onTween */ this.onTween = new YAHOO.util.CustomEvent('tween', this); /** * Custom event that fires after onTween * @private */ this._onTween = new YAHOO.util.CustomEvent('_tween', this, true); /** * Custom event that fires when animation ends * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction) * @event onComplete */ this.onComplete = new YAHOO.util.CustomEvent('complete', this); /** * Custom event that fires after onComplete * @private */ this._onComplete = new YAHOO.util.CustomEvent('_complete', this, true); this._onStart.subscribe(onStart); this._onTween.subscribe(onTween); this._onComplete.subscribe(onComplete); } }; /** * Handles animation queueing and threading. * Used by Anim and subclasses. * @class AnimMgr * @namespace YAHOO.util */ YAHOO.util.AnimMgr = new function() { /** * Reference to the animation Interval. * @property thread * @private * @type Int */ var thread = null; /** * The current queue of registered animation objects. * @property queue * @private * @type Array */ var queue = []; /** * The number of active animations. * @property tweenCount * @private * @type Int */ var tweenCount = 0; /** * Base frame rate (frames per second). * Arbitrarily high for better x-browser calibration (slower browsers drop more frames). * @property fps * @type Int * */ this.fps = 200; /** * Interval delay in milliseconds, defaults to fastest possible. * @property delay * @type Int * */ this.delay = 1; /** * Adds an animation instance to the animation queue. * All animation instances must be registered in order to animate. * @method registerElement * @param {object} tween The Anim instance to be be registered */ this.registerElement = function(tween) { queue[queue.length] = tween; tweenCount += 1; tween._onStart.fire(); this.start(); }; /** * removes an animation instance from the animation queue. * All animation instances must be registered in order to animate. * @method unRegister * @param {object} tween The Anim instance to be be registered * @param {Int} index The index of the Anim instance * @private */ this.unRegister = function(tween, index) { tween._onComplete.fire(); index = index || getIndex(tween); if (index != -1) { queue.splice(index, 1); } tweenCount -= 1; if (tweenCount <= 0) { this.stop(); } }; /** * Starts the animation thread. * Only one thread can run at a time. * @method start */ this.start = function() { if (thread === null) { thread = setInterval(this.run, this.delay); } }; /** * Stops the animation thread or a specific animation instance. * @method stop * @param {object} tween A specific Anim instance to stop (optional) * If no instance given, Manager stops thread and all animations. */ this.stop = function(tween) { if (!tween) { clearInterval(thread); for (var i = 0, len = queue.length; i < len; ++i) { if (queue[i].isAnimated()) { this.unRegister(tween, i); } } queue = []; thread = null; tweenCount = 0; } else { this.unRegister(tween); } }; /** * Called per Interval to handle each animation frame. * @method run */ this.run = function() { for (var i = 0, len = queue.length; i < len; ++i) { var tween = queue[i]; if ( !tween || !tween.isAnimated() ) { continue; } if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null) { tween.currentFrame += 1; if (tween.useSeconds) { correctFrame(tween); } tween._onTween.fire(); } else { YAHOO.util.AnimMgr.stop(tween, i); } } }; var getIndex = function(anim) { for (var i = 0, len = queue.length; i < len; ++i) { if (queue[i] == anim) { return i; // note return; } } return -1; }; /** * On the fly frame correction to keep animation on time. * @method correctFrame * @private * @param {Object} tween The Anim instance being corrected. */ var correctFrame = function(tween) { var frames = tween.totalFrames; var frame = tween.currentFrame; var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames); var elapsed = (new Date() - tween.getStartTime()); var tweak = 0; if (elapsed < tween.duration * 1000) { // check if falling behind tweak = Math.round((elapsed / expected - 1) * tween.currentFrame); } else { // went over duration, so jump to end tweak = frames - (frame + 1); } if (tweak > 0 && isFinite(tweak)) { // adjust if needed if (tween.currentFrame + tweak >= frames) {// dont go past last frame tweak = frames - (frame + 1); } tween.currentFrame += tweak; } }; }; /** * Used to calculate Bezier splines for any number of control points. * @class Bezier * @namespace YAHOO.util * */ YAHOO.util.Bezier = new function() { /** * Get the current position of the animated element based on t. * Each point is an array of "x" and "y" values (0 = x, 1 = y) * At least 2 points are required (start and end). * First point is start. Last point is end. * Additional control points are optional. * @method getPosition * @param {Array} points An array containing Bezier points * @param {Number} t A number between 0 and 1 which is the basis for determining current position * @return {Array} An array containing int x and y member data */ this.getPosition = function(points, t) { var n = points.length; var tmp = []; for (var i = 0; i < n; ++i){ tmp[i] = [points[i][0], points[i][1]]; // save input } for (var j = 1; j < n; ++j) { for (i = 0; i < n - j; ++i) { tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0]; tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1]; } } return [ tmp[0][0], tmp[0][1] ]; }; }; /** * Anim subclass for color transitions. *Usage:
* @class ColorAnim * @namespace YAHOO.util * @requires YAHOO.util.Anim * @requires YAHOO.util.AnimMgr * @requires YAHOO.util.Easing * @requires YAHOO.util.Bezier * @requires YAHOO.util.Dom * @requires YAHOO.util.Event * @constructor * @extends YAHOO.util.Anim * @param {HTMLElement | String} el Reference to the element that will be animated * @param {Object} attributes The attribute(s) to be animated. * Each attribute is an object with at minimum a "to" or "by" member defined. * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). * All attribute names use camelCase. * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) */ (function() { YAHOO.util.ColorAnim = function(el, attributes, duration, method) { YAHOO.util.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method); }; YAHOO.extend(YAHOO.util.ColorAnim, YAHOO.util.Anim); // shorthand var Y = YAHOO.util; var superclass = Y.ColorAnim.superclass; var proto = Y.ColorAnim.prototype; proto.toString = function() { var el = this.getEl(); var id = el.id || el.tagName; return ("ColorAnim " + id); }; proto.patterns.color = /color$/i; proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i; proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i; proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i; proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari /** * Attempts to parse the given string and return a 3-tuple. * @method parseColor * @param {String} s The string to parse. * @return {Array} The 3-tuple of rgb values. */ proto.parseColor = function(s) { if (s.length == 3) { return s; } var c = this.patterns.hex.exec(s); if (c && c.length == 4) { return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ]; } c = this.patterns.rgb.exec(s); if (c && c.length == 4) { return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ]; } c = this.patterns.hex3.exec(s); if (c && c.length == 4) { return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ]; } return null; }; proto.getAttribute = function(attr) { var el = this.getEl(); if ( this.patterns.color.test(attr) ) { var val = YAHOO.util.Dom.getStyle(el, attr); if (this.patterns.transparent.test(val)) { // bgcolor default var parent = el.parentNode; // try and get from an ancestor val = Y.Dom.getStyle(parent, attr); while (parent && this.patterns.transparent.test(val)) { parent = parent.parentNode; val = Y.Dom.getStyle(parent, attr); if (parent.tagName.toUpperCase() == 'HTML') { val = '#fff'; } } } } else { val = superclass.getAttribute.call(this, attr); } return val; }; proto.doMethod = function(attr, start, end) { var val; if ( this.patterns.color.test(attr) ) { val = []; for (var i = 0, len = start.length; i < len; ++i) { val[i] = superclass.doMethod.call(this, attr, start[i], end[i]); } val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')'; } else { val = superclass.doMethod.call(this, attr, start, end); } return val; }; proto.setRuntimeAttribute = function(attr) { superclass.setRuntimeAttribute.call(this, attr); if ( this.patterns.color.test(attr) ) { var attributes = this.attributes; var start = this.parseColor(this.runtimeAttributes[attr].start); var end = this.parseColor(this.runtimeAttributes[attr].end); // fix colors if going "by" if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) { end = this.parseColor(attributes[attr].by); for (var i = 0, len = start.length; i < len; ++i) { end[i] = start[i] + end[i]; } } this.runtimeAttributes[attr].start = start; this.runtimeAttributes[attr].end = end; } }; })();/* TERMS OF USE - EASING EQUATIONS Open source under the BSD License. Copyright 2001 Robert Penner All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * Singleton that determines how an animation proceeds from start to end. * @class Easing * @namespace YAHOO.util */ YAHOO.util.Easing = { /** * Uniform speed between points. * @method easeNone * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @return {Number} The computed value for the current animation frame */ easeNone: function (t, b, c, d) { return c*t/d + b; }, /** * Begins slowly and accelerates towards end. (quadratic) * @method easeIn * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @return {Number} The computed value for the current animation frame */ easeIn: function (t, b, c, d) { return c*(t/=d)*t + b; }, /** * Begins quickly and decelerates towards end. (quadratic) * @method easeOut * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @return {Number} The computed value for the current animation frame */ easeOut: function (t, b, c, d) { return -c *(t/=d)*(t-2) + b; }, /** * Begins slowly and decelerates towards end. (quadratic) * @method easeBoth * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @return {Number} The computed value for the current animation frame */ easeBoth: function (t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t + b; return -c/2 * ((--t)*(t-2) - 1) + b; }, /** * Begins slowly and accelerates towards end. (quartic) * @method easeInStrong * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @return {Number} The computed value for the current animation frame */ easeInStrong: function (t, b, c, d) { return c*(t/=d)*t*t*t + b; }, /** * Begins quickly and decelerates towards end. (quartic) * @method easeOutStrong * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @return {Number} The computed value for the current animation frame */ easeOutStrong: function (t, b, c, d) { return -c * ((t=t/d-1)*t*t*t - 1) + b; }, /** * Begins slowly and decelerates towards end. (quartic) * @method easeBothStrong * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @return {Number} The computed value for the current animation frame */ easeBothStrong: function (t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t*t + b; return -c/2 * ((t-=2)*t*t*t - 2) + b; }, /** * Snap in elastic effect. * @method elasticIn * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @param {Number} p Period (optional) * @return {Number} The computed value for the current animation frame */ elasticIn: function (t, b, c, d, a, p) { if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (!a || a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; }, /** * Snap out elastic effect. * @method elasticOut * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @param {Number} p Period (optional) * @return {Number} The computed value for the current animation frame */ elasticOut: function (t, b, c, d, a, p) { if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (!a || a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; }, /** * Snap both elastic effect. * @method elasticBoth * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @param {Number} p Period (optional) * @return {Number} The computed value for the current animation frame */ elasticBoth: function (t, b, c, d, a, p) { if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); if (!a || a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; }, /** * Backtracks slightly, then reverses direction and moves to end. * @method backIn * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @param {Number} s Overshoot (optional) * @return {Number} The computed value for the current animation frame */ backIn: function (t, b, c, d, s) { if (typeof s == 'undefined') s = 1.70158; return c*(t/=d)*t*((s+1)*t - s) + b; }, /** * Overshoots end, then reverses and comes back to end. * @method backOut * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @param {Number} s Overshoot (optional) * @return {Number} The computed value for the current animation frame */ backOut: function (t, b, c, d, s) { if (typeof s == 'undefined') s = 1.70158; return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; }, /** * Backtracks slightly, then reverses direction, overshoots end, * then reverses and comes back to end. * @method backBoth * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @param {Number} s Overshoot (optional) * @return {Number} The computed value for the current animation frame */ backBoth: function (t, b, c, d, s) { if (typeof s == 'undefined') s = 1.70158; if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; }, /** * Bounce off of start. * @method bounceIn * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @return {Number} The computed value for the current animation frame */ bounceIn: function (t, b, c, d) { return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b; }, /** * Bounces off end. * @method bounceOut * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @return {Number} The computed value for the current animation frame */ bounceOut: function (t, b, c, d) { if ((t/=d) < (1/2.75)) { return c*(7.5625*t*t) + b; } else if (t < (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; } else if (t < (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; } else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; } }, /** * Bounces off start and end. * @method bounceBoth * @param {Number} t Time value used to compute current value * @param {Number} b Starting value * @param {Number} c Delta between start and end values * @param {Number} d Total length of animation * @return {Number} The computed value for the current animation frame */ bounceBoth: function (t, b, c, d) { if (t < d/2) return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b; return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b; } }; /** * Anim subclass for moving elements along a path defined by the "points" * member of "attributes". All "points" are arrays with x, y coordinates. *var myAnim = new Y.ColorAnim(el, { backgroundColor: { from: '#FF0000', to: '#FFFFFF' } }, 1, Y.Easing.easeOut);
Color values can be specified with either 112233, #112233, * [255,255,255], or rgb(255,255,255)Usage:
* @class Motion * @namespace YAHOO.util * @requires YAHOO.util.Anim * @requires YAHOO.util.AnimMgr * @requires YAHOO.util.Easing * @requires YAHOO.util.Bezier * @requires YAHOO.util.Dom * @requires YAHOO.util.Event * @requires YAHOO.util.CustomEvent * @constructor * @extends YAHOO.util.Anim * @param {String | HTMLElement} el Reference to the element that will be animated * @param {Object} attributes The attribute(s) to be animated. * Each attribute is an object with at minimum a "to" or "by" member defined. * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). * All attribute names use camelCase. * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) */ (function() { YAHOO.util.Motion = function(el, attributes, duration, method) { if (el) { // dont break existing subclasses not using YAHOO.extend YAHOO.util.Motion.superclass.constructor.call(this, el, attributes, duration, method); } }; YAHOO.extend(YAHOO.util.Motion, YAHOO.util.ColorAnim); // shorthand var Y = YAHOO.util; var superclass = Y.Motion.superclass; var proto = Y.Motion.prototype; proto.toString = function() { var el = this.getEl(); var id = el.id || el.tagName; return ("Motion " + id); }; proto.patterns.points = /^points$/i; proto.setAttribute = function(attr, val, unit) { if ( this.patterns.points.test(attr) ) { unit = unit || 'px'; superclass.setAttribute.call(this, 'left', val[0], unit); superclass.setAttribute.call(this, 'top', val[1], unit); } else { superclass.setAttribute.call(this, attr, val, unit); } }; proto.getAttribute = function(attr) { if ( this.patterns.points.test(attr) ) { var val = [ superclass.getAttribute.call(this, 'left'), superclass.getAttribute.call(this, 'top') ]; } else { val = superclass.getAttribute.call(this, attr); } return val; }; proto.doMethod = function(attr, start, end) { var val = null; if ( this.patterns.points.test(attr) ) { var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100; val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t); } else { val = superclass.doMethod.call(this, attr, start, end); } return val; }; proto.setRuntimeAttribute = function(attr) { if ( this.patterns.points.test(attr) ) { var el = this.getEl(); var attributes = this.attributes; var start; var control = attributes['points']['control'] || []; var end; var i, len; if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points control = [control]; } else { // break reference to attributes.points.control var tmp = []; for (i = 0, len = control.length; i< len; ++i) { tmp[i] = control[i]; } control = tmp; } if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative Y.Dom.setStyle(el, 'position', 'relative'); } if ( isset(attributes['points']['from']) ) { Y.Dom.setXY(el, attributes['points']['from']); // set position to from point } else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position start = this.getAttribute('points'); // get actual top & left // TO beats BY, per SMIL 2.1 spec if ( isset(attributes['points']['to']) ) { end = translateValues.call(this, attributes['points']['to'], start); var pageXY = Y.Dom.getXY(this.getEl()); for (i = 0, len = control.length; i < len; ++i) { control[i] = translateValues.call(this, control[i], start); } } else if ( isset(attributes['points']['by']) ) { end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ]; for (i = 0, len = control.length; i < len; ++i) { control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ]; } } this.runtimeAttributes[attr] = [start]; if (control.length > 0) { this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control); } this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end; } else { superclass.setRuntimeAttribute.call(this, attr); } }; var translateValues = function(val, start) { var pageXY = Y.Dom.getXY(this.getEl()); val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ]; return val; }; var isset = function(prop) { return (typeof prop !== 'undefined'); }; })(); /** * Anim subclass for scrolling elements to a position defined by the "scroll" * member of "attributes". All "scroll" members are arrays with x, y scroll positions. *var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);
Usage:
* @class Scroll * @namespace YAHOO.util * @requires YAHOO.util.Anim * @requires YAHOO.util.AnimMgr * @requires YAHOO.util.Easing * @requires YAHOO.util.Bezier * @requires YAHOO.util.Dom * @requires YAHOO.util.Event * @requires YAHOO.util.CustomEvent * @extends YAHOO.util.Anim * @constructor * @param {String or HTMLElement} el Reference to the element that will be animated * @param {Object} attributes The attribute(s) to be animated. * Each attribute is an object with at minimum a "to" or "by" member defined. * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). * All attribute names use camelCase. * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) */ (function() { YAHOO.util.Scroll = function(el, attributes, duration, method) { if (el) { // dont break existing subclasses not using YAHOO.extend YAHOO.util.Scroll.superclass.constructor.call(this, el, attributes, duration, method); } }; YAHOO.extend(YAHOO.util.Scroll, YAHOO.util.ColorAnim); // shorthand var Y = YAHOO.util; var superclass = Y.Scroll.superclass; var proto = Y.Scroll.prototype; proto.toString = function() { var el = this.getEl(); var id = el.id || el.tagName; return ("Scroll " + id); }; proto.doMethod = function(attr, start, end) { var val = null; if (attr == 'scroll') { val = [ this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames), this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames) ]; } else { val = superclass.doMethod.call(this, attr, start, end); } return val; }; proto.getAttribute = function(attr) { var val = null; var el = this.getEl(); if (attr == 'scroll') { val = [ el.scrollLeft, el.scrollTop ]; } else { val = superclass.getAttribute.call(this, attr); } return val; }; proto.setAttribute = function(attr, val, unit) { var el = this.getEl(); if (attr == 'scroll') { el.scrollLeft = val[0]; el.scrollTop = val[1]; } else { superclass.setAttribute.call(this, attr, val, unit); } }; })(); /* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 0.12.0 */ /** * @description * The Connection Manager provides a simplified interface to the XMLHttpRequest * object. It handles cross-browser instantiantion of XMLHttpRequest, negotiates the * interactive states and server response, returning the results to a pre-defined * callback you create. * * @namespace YAHOO.util * @module Connection * @Class Connect */ YAHOO.util.Connect = { /** * @description Array of MSFT ActiveX ids for XMLHttpRequest. * @property _msxml_progid * @private * @static * @type array */ _msxml_progid:[ 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ], /** * @description Object literal of HTTP header(s) * @property _http_header * @private * @static * @type object */ _http_header:{}, /** * @description Determines if HTTP headers are set. * @property _has_http_headers * @private * @static * @type boolean */ _has_http_headers:false, /** * @description Determines if a default header of * Content-Type of 'application/x-www-form-urlencoded' * will be added to any client HTTP headers sent for POST * transactions. * @property _use_default_post_header * @private * @static * @type boolean */ _use_default_post_header:true, /** * @description Determines if a default header of * Content-Type of 'application/x-www-form-urlencoded' * will be added to any client HTTP headers sent for POST * transactions. * @property _default_post_header * @private * @static * @type boolean */ _default_post_header:'application/x-www-form-urlencoded', /** * @description Property modified by setForm() to determine if the data * should be submitted as an HTML form. * @property _isFormSubmit * @private * @static * @type boolean */ _isFormSubmit:false, /** * @description Property modified by setForm() to determine if a file(s) * upload is expected. * @property _isFileUpload * @private * @static * @type boolean */ _isFileUpload:false, /** * @description Property modified by setForm() to set a reference to the HTML * form node if the desired action is file upload. * @property _formNode * @private * @static * @type object */ _formNode:null, /** * @description Property modified by setForm() to set the HTML form data * for each transaction. * @property _sFormData * @private * @static * @type string */ _sFormData:null, /** * @description Collection of polling references to the polling mechanism in handleReadyState. * @property _poll * @private * @static * @type object */ _poll:{}, /** * @description Queue of timeout values for each transaction callback with a defined timeout value. * @property _timeOut * @private * @static * @type object */ _timeOut:{}, /** * @description The polling frequency, in milliseconds, for HandleReadyState. * when attempting to determine a transaction's XHR readyState. * The default is 50 milliseconds. * @property _polling_interval * @private * @static * @type int */ _polling_interval:50, /** * @description A transaction counter that increments the transaction id for each transaction. * @property _transaction_id * @private * @static * @type int */ _transaction_id:0, /** * @description Member to add an ActiveX id to the existing xml_progid array. * In the event(unlikely) a new ActiveX id is introduced, it can be added * without internal code modifications. * @method setProgId * @public * @static * @param {string} id The ActiveX id to be added to initialize the XHR object. * @return void */ setProgId:function(id) { this._msxml_progid.unshift(id); }, /** * @description Member to enable or disable the default POST header. * @method setDefaultPostHeader * @public * @static * @param {boolean} b Set and use default header - true or false . * @return void */ setDefaultPostHeader:function(b) { this._use_default_post_header = b; }, /** * @description Member to modify the default polling interval. * @method setPollingInterval * @public * @static * @param {int} i The polling interval in milliseconds. * @return void */ setPollingInterval:function(i) { if(typeof i == 'number' && isFinite(i)){ this._polling_interval = i; } }, /** * @description Instantiates a XMLHttpRequest object and returns an object with two properties: * the XMLHttpRequest instance and the transaction id. * @method createXhrObject * @private * @static * @param {int} transactionId Property containing the transaction id for this transaction. * @return object */ createXhrObject:function(transactionId) { var obj,http; try { // Instantiates XMLHttpRequest in non-IE browsers and assigns to http. http = new XMLHttpRequest(); // Object literal with http and tId properties obj = { conn:http, tId:transactionId }; } catch(e) { for(var i=0; ivar myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);
= 200 && httpStatus < 300){ try { responseObject = this.createResponseObject(o, callback.argument); if(callback.success){ if(!callback.scope){ callback.success(responseObject); } else{ // If a scope property is defined, the callback will be fired from // the context of the object. callback.success.apply(callback.scope, [responseObject]); } } } catch(e){} } else{ try { switch(httpStatus){ // The following cases are wininet.dll error codes that may be encountered. case 12002: // Server timeout case 12029: // 12029 to 12031 correspond to dropped connections. case 12030: case 12031: case 12152: // Connection closed by server. case 13030: // See above comments for variable status. responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort?isAbort:false)); if(callback.failure){ if(!callback.scope){ callback.failure(responseObject); } else{ callback.failure.apply(callback.scope, [responseObject]); } } break; default: responseObject = this.createResponseObject(o, callback.argument); if(callback.failure){ if(!callback.scope){ callback.failure(responseObject); } else{ callback.failure.apply(callback.scope, [responseObject]); } } } } catch(e){} } this.releaseObject(o); responseObject = null; }, /** * @description This method evaluates the server response, creates and returns the results via * its properties. Success and failure cases will differ in the response * object's property values. * @method createResponseObject * @private * @static * @param {object} o The connection object * @param {callbackArg} callbackArg The user-defined argument or arguments to be passed to the callback * @return {object} */ createResponseObject:function(o, callbackArg) { var obj = {}; var headerObj = {}; try { var headerStr = o.conn.getAllResponseHeaders(); var header = headerStr.split('\n'); for(var i=0; i '); // IE will throw a security exception in an SSL environment if the // iframe source is undefined. if(typeof secureUri == 'boolean'){ io.src = 'javascript:false'; } else if(typeof secureURI == 'string'){ // Deprecated io.src = secureUri; } } else{ var io = document.createElement('iframe'); io.id = frameId; io.name = frameId; } io.style.position = 'absolute'; io.style.top = '-1000px'; io.style.left = '-1000px'; document.body.appendChild(io); }, /** * @description Parses the POST data and creates hidden form elements * for each key-value, and appends them to the HTML form object. * @method appendPostData * @private * @static * @param {string} postData The HTTP POST data * @return {array} formElements Collection of hidden fields. */ appendPostData:function(postData) { var formElements = new Array(); var postMessage = postData.split('&'); for(var i=0; i < postMessage.length; i++){ var delimitPos = postMessage[i].indexOf('='); if(delimitPos != -1){ formElements[i] = document.createElement('input'); formElements[i].type = 'hidden'; formElements[i].name = postMessage[i].substring(0,delimitPos); formElements[i].value = postMessage[i].substring(delimitPos+1); this._formNode.appendChild(formElements[i]); } } return formElements; }, /** * @description Uploads HTML form, including files/attachments, to the * iframe created in createFrame. * @method uploadFile * @private * @static * @param {int} id The transaction id. * @param {object} callback - User-defined callback object. * @param {string} uri Fully qualified path of resource. * @return {void} */ uploadFile:function(id, callback, uri, postData){ // Each iframe has an id prefix of "yuiIO" followed // by the unique transaction id. var frameId = 'yuiIO' + id; var io = document.getElementById(frameId); // Initialize the HTML form properties in case they are // not defined in the HTML form. this._formNode.action = uri; this._formNode.method = 'POST'; this._formNode.target = frameId; if(this._formNode.encoding){ // IE does not respect property enctype for HTML forms. // Instead use property encoding. this._formNode.encoding = 'multipart/form-data'; } else{ this._formNode.enctype = 'multipart/form-data'; } if(postData){ var oElements = this.appendPostData(postData); } this._formNode.submit(); if(oElements && oElements.length > 0){ try { for(var i=0; i < oElements.length; i++){ this._formNode.removeChild(oElements[i]); } } catch(e){} } // Reset HTML form status properties. this.resetFormState(); // Create the upload callback handler that fires when the iframe // receives the load event. Subsequently, the event handler is detached // and the iframe removed from the document. var uploadCallback = function() { var obj = {}; obj.tId = id; obj.argument = callback.argument; try { obj.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null; obj.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document; } catch(e){} if(callback.upload){ if(!callback.scope){ callback.upload(obj); } else{ callback.upload.apply(callback.scope, [obj]); } } if(YAHOO.util.Event){ YAHOO.util.Event.removeListener(io, "load", uploadCallback); } else if(window.detachEvent){ io.detachEvent('onload', uploadCallback); } else{ io.removeEventListener('load', uploadCallback, false); } setTimeout(function(){ document.body.removeChild(io); }, 100); }; // Bind the onload handler to the iframe to detect the file upload response. if(YAHOO.util.Event){ YAHOO.util.Event.addListener(io, "load", uploadCallback); } else if(window.attachEvent){ io.attachEvent('onload', uploadCallback); } else{ io.addEventListener('load', uploadCallback, false); } }, /** * @description Method to terminate a transaction, if it has not reached readyState 4. * @method abort * @public * @static * @param {object} o The connection object returned by asyncRequest. * @param {object} callback User-defined callback object. * @param {string} isTimeout boolean to indicate if abort was a timeout. * @return {boolean} */ abort:function(o, callback, isTimeout) { if(this.isCallInProgress(o)){ o.conn.abort(); window.clearInterval(this._poll[o.tId]); delete this._poll[o.tId]; if(isTimeout){ delete this._timeOut[o.tId]; } this.handleTransactionResponse(o, callback, true); return true; } else{ return false; } }, /** * Public method to check if the transaction is still being processed. * * @method isCallInProgress * @public * @static * @param {object} o The connection object returned by asyncRequest * @return {boolean} */ isCallInProgress:function(o) { // if the XHR object assigned to the transaction has not been dereferenced, // then check its readyState status. Otherwise, return false. if(o.conn){ return o.conn.readyState != 4 && o.conn.readyState != 0; } else{ //The XHR object has been destroyed. return false; } }, /** * @description Dereference the XHR instance and the connection object after the transaction is completed. * @method releaseObject * @private * @static * @param {object} o The connection object * @return {void} */ releaseObject:function(o) { //dereference the XHR instance. o.conn = null; //dereference the connection object. o = null; } }; /* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version 0.12.0 */ /** * Config is a utility used within an Object to allow the implementer to maintain a list of local configuration properties and listen for changes to those properties dynamically using CustomEvent. The initial values are also maintained so that the configuration can be reset at any given point to its initial state. * @class YAHOO.util.Config * @constructor * @param {Object} owner The owner Object to which this Config Object belongs */ YAHOO.util.Config = function(owner) { if (owner) { this.init(owner); } }; YAHOO.util.Config.prototype = { /** * Object reference to the owner of this Config Object * @property owner * @type Object */ owner : null, /** * Boolean flag that specifies whether a queue is currently being executed * @property queueInProgress * @type Boolean */ queueInProgress : false, /** * Validates that the value passed in is a Boolean. * @method checkBoolean * @param {Object} val The value to validate * @return {Boolean} true, if the value is valid */ checkBoolean: function(val) { if (typeof val == 'boolean') { return true; } else { return false; } }, /** * Validates that the value passed in is a number. * @method checkNumber * @param {Object} val The value to validate * @return {Boolean} true, if the value is valid */ checkNumber: function(val) { if (isNaN(val)) { return false; } else { return true; } } }; /** * Initializes the configuration Object and all of its local members. * @method init * @param {Object} owner The owner Object to which this Config Object belongs */ YAHOO.util.Config.prototype.init = function(owner) { this.owner = owner; /** * Object reference to the owner of this Config Object * @event configChangedEvent */ this.configChangedEvent = new YAHOO.util.CustomEvent("configChanged"); this.queueInProgress = false; /* Private Members */ /** * Maintains the local collection of configuration property objects and their specified values * @property config * @private * @type Object */ var config = {}; /** * Maintains the local collection of configuration property objects as they were initially applied. * This object is used when resetting a property. * @property initialConfig * @private * @type Object */ var initialConfig = {}; /** * Maintains the local, normalized CustomEvent queue * @property eventQueue * @private * @type Object */ var eventQueue = []; /** * Fires a configuration property event using the specified value. * @method fireEvent * @private * @param {String} key The configuration property's name * @param {value} Object The value of the correct type for the property */ var fireEvent = function( key, value ) { key = key.toLowerCase(); var property = config[key]; if (typeof property != 'undefined' && property.event) { property.event.fire(value); } }; /* End Private Members */ /** * Adds a property to the Config Object's private config hash. * @method addProperty * @param {String} key The configuration property's name * @param {Object} propertyObject The Object containing all of this property's arguments */ this.addProperty = function( key, propertyObject ) { key = key.toLowerCase(); config[key] = propertyObject; propertyObject.event = new YAHOO.util.CustomEvent(key); propertyObject.key = key; if (propertyObject.handler) { propertyObject.event.subscribe(propertyObject.handler, this.owner, true); } this.setProperty(key, propertyObject.value, true); if (! propertyObject.suppressEvent) { this.queueProperty(key, propertyObject.value); } }; /** * Returns a key-value configuration map of the values currently set in the Config Object. * @method getConfig * @return {Object} The current config, represented in a key-value map */ this.getConfig = function() { var cfg = {}; for (var prop in config) { var property = config[prop]; if (typeof property != 'undefined' && property.event) { cfg[prop] = property.value; } } return cfg; }; /** * Returns the value of specified property. * @method getProperty * @param {String} key The name of the property * @return {Object} The value of the specified property */ this.getProperty = function(key) { key = key.toLowerCase(); var property = config[key]; if (typeof property != 'undefined' && property.event) { return property.value; } else { return undefined; } }; /** * Resets the specified property's value to its initial value. * @method resetProperty * @param {String} key The name of the property * @return {Boolean} True is the property was reset, false if not */ this.resetProperty = function(key) { key = key.toLowerCase(); var property = config[key]; if (typeof property != 'undefined' && property.event) { if (initialConfig[key] && initialConfig[key] != 'undefined') { this.setProperty(key, initialConfig[key]); } return true; } else { return false; } }; /** * Sets the value of a property. If the silent property is passed as true, the property's event will not be fired. * @method setProperty * @param {String} key The name of the property * @param {String} value The value to set the property to * @param {Boolean} silent Whether the value should be set silently, without firing the property event. * @return {Boolean} True, if the set was successful, false if it failed. */ this.setProperty = function(key, value, silent) { key = key.toLowerCase(); if (this.queueInProgress && ! silent) { this.queueProperty(key,value); // Currently running through a queue... return true; } else { var property = config[key]; if (typeof property != 'undefined' && property.event) { if (property.validator && ! property.validator(value)) { // validator return false; } else { property.value = value; if (! silent) { fireEvent(key, value); this.configChangedEvent.fire([key, value]); } return true; } } else { return false; } } }; /** * Sets the value of a property and queues its event to execute. If the event is already scheduled to execute, it is * moved from its current position to the end of the queue. * @method queueProperty * @param {String} key The name of the property * @param {String} value The value to set the property to * @return {Boolean} true, if the set was successful, false if it failed. */ this.queueProperty = function(key, value) { key = key.toLowerCase(); var property = config[key]; if (typeof property != 'undefined' && property.event) { if (typeof value != 'undefined' && property.validator && ! property.validator(value)) { // validator return false; } else { if (typeof value != 'undefined') { property.value = value; } else { value = property.value; } var foundDuplicate = false; for (var i=0;i OR * @param {HTMLElement} el The element representing the Module * @param {Object} userConfig The configuration Object literal containing the configuration that should be set for this module. See configuration documentation for more details. */ YAHOO.widget.Module = function(el, userConfig) { if (el) { this.init(el, userConfig); } }; /** * Constant representing the prefix path to use for non-secure images * @property YAHOO.widget.Module.IMG_ROOT * @static * @final * @type String */ YAHOO.widget.Module.IMG_ROOT = "http://us.i1.yimg.com/us.yimg.com/i/"; /** * Constant representing the prefix path to use for securely served images * @property YAHOO.widget.Module.IMG_ROOT_SSL * @static * @final * @type String */ YAHOO.widget.Module.IMG_ROOT_SSL = "https://a248.e.akamai.net/sec.yimg.com/i/"; /** * Constant for the default CSS class name that represents a Module * @property YAHOO.widget.Module.CSS_MODULE * @static * @final * @type String */ YAHOO.widget.Module.CSS_MODULE = "module"; /** * Constant representing the module header * @property YAHOO.widget.Module.CSS_HEADER * @static * @final * @type String */ YAHOO.widget.Module.CSS_HEADER = "hd"; /** * Constant representing the module body * @property YAHOO.widget.Module.CSS_BODY * @static * @final * @type String */ YAHOO.widget.Module.CSS_BODY = "bd"; /** * Constant representing the module footer * @property YAHOO.widget.Module.CSS_FOOTER * @static * @final * @type String */ YAHOO.widget.Module.CSS_FOOTER = "ft"; /** * Constant representing the url for the "src" attribute of the iframe used to monitor changes to the browser's base font size * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL * @static * @final * @type String */ YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;"; YAHOO.widget.Module.prototype = { /** * The class's constructor function * @property contructor * @type Function */ constructor : YAHOO.widget.Module, /** * The main module element that contains the header, body, and footer * @property element * @type HTMLElement */ element : null, /** * The header element, denoted with CSS class "hd" * @property header * @type HTMLElement */ header : null, /** * The body element, denoted with CSS class "bd" * @property body * @type HTMLElement */ body : null, /** * The footer element, denoted with CSS class "ft" * @property footer * @type HTMLElement */ footer : null, /** * The id of the element * @property id * @type String */ id : null, /** * The String representing the image root * @property imageRoot * @type String */ imageRoot : YAHOO.widget.Module.IMG_ROOT, /** * Initializes the custom events for Module which are fired automatically at appropriate times by the Module class. * @method initEvents */ initEvents : function() { /** * CustomEvent fired prior to class initalization. * @event beforeInitEvent * @param {class} classRef class reference of the initializing class, such as this.beforeInitEvent.fire(YAHOO.widget.Module) */ this.beforeInitEvent = new YAHOO.util.CustomEvent("beforeInit"); /** * CustomEvent fired after class initalization. * @event initEvent * @param {class} classRef class reference of the initializing class, such as this.beforeInitEvent.fire(YAHOO.widget.Module) */ this.initEvent = new YAHOO.util.CustomEvent("init"); /** * CustomEvent fired when the Module is appended to the DOM * @event appendEvent */ this.appendEvent = new YAHOO.util.CustomEvent("append"); /** * CustomEvent fired before the Module is rendered * @event beforeRenderEvent */ this.beforeRenderEvent = new YAHOO.util.CustomEvent("beforeRender"); /** * CustomEvent fired after the Module is rendered * @event renderEvent */ this.renderEvent = new YAHOO.util.CustomEvent("render"); /** * CustomEvent fired when the header content of the Module is modified * @event changeHeaderEvent * @param {String/HTMLElement} content String/element representing the new header content */ this.changeHeaderEvent = new YAHOO.util.CustomEvent("changeHeader"); /** * CustomEvent fired when the body content of the Module is modified * @event changeBodyEvent * @param {String/HTMLElement} content String/element representing the new body content */ this.changeBodyEvent = new YAHOO.util.CustomEvent("changeBody"); /** * CustomEvent fired when the footer content of the Module is modified * @event changeFooterEvent * @param {String/HTMLElement} content String/element representing the new footer content */ this.changeFooterEvent = new YAHOO.util.CustomEvent("changeFooter"); /** * CustomEvent fired when the content of the Module is modified * @event changeContentEvent */ this.changeContentEvent = new YAHOO.util.CustomEvent("changeContent"); /** * CustomEvent fired when the Module is destroyed * @event destroyEvent */ this.destroyEvent = new YAHOO.util.CustomEvent("destroy"); /** * CustomEvent fired before the Module is shown * @event beforeShowEvent */ this.beforeShowEvent = new YAHOO.util.CustomEvent("beforeShow"); /** * CustomEvent fired after the Module is shown * @event showEvent */ this.showEvent = new YAHOO.util.CustomEvent("show"); /** * CustomEvent fired before the Module is hidden * @event beforeHideEvent */ this.beforeHideEvent = new YAHOO.util.CustomEvent("beforeHide"); /** * CustomEvent fired after the Module is hidden * @event hideEvent */ this.hideEvent = new YAHOO.util.CustomEvent("hide"); }, /** * String representing the current user-agent platform * @property platform * @type String */ platform : function() { var ua = navigator.userAgent.toLowerCase(); if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) { return "windows"; } else if (ua.indexOf("macintosh") != -1) { return "mac"; } else { return false; } }(), /** * String representing the current user-agent browser * @property browser * @type String */ browser : function() { var ua = navigator.userAgent.toLowerCase(); if (ua.indexOf('opera')!=-1) { // Opera (check first in case of spoof) return 'opera'; } else if (ua.indexOf('msie 7')!=-1) { // IE7 return 'ie7'; } else if (ua.indexOf('msie') !=-1) { // IE return 'ie'; } else if (ua.indexOf('safari')!=-1) { // Safari (check before Gecko because it includes "like Gecko") return 'safari'; } else if (ua.indexOf('gecko') != -1) { // Gecko return 'gecko'; } else { return false; } }(), /** * Boolean representing whether or not the current browsing context is secure (https) * @property isSecure * @type Boolean */ isSecure : function() { if (window.location.href.toLowerCase().indexOf("https") === 0) { return true; } else { return false; } }(), /** * Initializes the custom events for Module which are fired automatically at appropriate times by the Module class. */ initDefaultConfig : function() { // Add properties // /** * Specifies whether the Module is visible on the page. * @config visible * @type Boolean * @default true */ this.cfg.addProperty("visible", { value:true, handler:this.configVisible, validator:this.cfg.checkBoolean } ); /** * Object or array of objects representing the ContainerEffect classes that are active for animating the container. * @config effect * @type Object * @default null */ this.cfg.addProperty("effect", { suppressEvent:true, supercedes:["visible"] } ); /** * Specifies whether to create a special proxy iframe to monitor for user font resizing in the document * @config monitorresize * @type Boolean * @default true */ this.cfg.addProperty("monitorresize", { value:true, handler:this.configMonitorResize } ); }, /** * The Module class's initialization method, which is executed for Module and all of its subclasses. This method is automatically called by the constructor, and sets up all DOM references for pre-existing markup, and creates required markup if it is not already present. * @method init * @param {String} el The element ID representing the Module OR * @param {HTMLElement} el The element representing the Module * @param {Object} userConfig The configuration Object literal containing the configuration that should be set for this module. See configuration documentation for more details. */ init : function(el, userConfig) { this.initEvents(); this.beforeInitEvent.fire(YAHOO.widget.Module); /** * The Module's Config object used for monitoring configuration properties. * @property cfg * @type YAHOO.util.Config */ this.cfg = new YAHOO.util.Config(this); if (this.isSecure) { this.imageRoot = YAHOO.widget.Module.IMG_ROOT_SSL; } if (typeof el == "string") { var elId = el; el = document.getElementById(el); if (! el) { el = document.createElement("DIV"); el.id = elId; } } this.element = el; if (el.id) { this.id = el.id; } var childNodes = this.element.childNodes; if (childNodes) { for (var i=0;i OR * @param {HTMLElement} headerContent The HTMLElement to append to the header */ setHeader : function(headerContent) { if (! this.header) { this.header = document.createElement("DIV"); this.header.className = YAHOO.widget.Module.CSS_HEADER; } if (typeof headerContent == "string") { this.header.innerHTML = headerContent; } else { this.header.innerHTML = ""; this.header.appendChild(headerContent); } this.changeHeaderEvent.fire(headerContent); this.changeContentEvent.fire(); }, /** * Appends the passed element to the header. If no header is present, one will be automatically created. * @method appendToHeader * @param {HTMLElement} element The element to append to the header */ appendToHeader : function(element) { if (! this.header) { this.header = document.createElement("DIV"); this.header.className = YAHOO.widget.Module.CSS_HEADER; } this.header.appendChild(element); this.changeHeaderEvent.fire(element); this.changeContentEvent.fire(); }, /** * Sets the Module's body content to the HTML specified, or appends the passed element to the body. If no body is present, one will be automatically created. * @method setBody * @param {String} bodyContent The HTML used to set the body OR * @param {HTMLElement} bodyContent The HTMLElement to append to the body */ setBody : function(bodyContent) { if (! this.body) { this.body = document.createElement("DIV"); this.body.className = YAHOO.widget.Module.CSS_BODY; } if (typeof bodyContent == "string") { this.body.innerHTML = bodyContent; } else { this.body.innerHTML = ""; this.body.appendChild(bodyContent); } this.changeBodyEvent.fire(bodyContent); this.changeContentEvent.fire(); }, /** * Appends the passed element to the body. If no body is present, one will be automatically created. * @method appendToBody * @param {HTMLElement} element The element to append to the body */ appendToBody : function(element) { if (! this.body) { this.body = document.createElement("DIV"); this.body.className = YAHOO.widget.Module.CSS_BODY; } this.body.appendChild(element); this.changeBodyEvent.fire(element); this.changeContentEvent.fire(); }, /** * Sets the Module's footer content to the HTML specified, or appends the passed element to the footer. If no footer is present, one will be automatically created. * @method setFooter * @param {String} footerContent The HTML used to set the footer OR * @param {HTMLElement} footerContent The HTMLElement to append to the footer */ setFooter : function(footerContent) { if (! this.footer) { this.footer = document.createElement("DIV"); this.footer.className = YAHOO.widget.Module.CSS_FOOTER; } if (typeof footerContent == "string") { this.footer.innerHTML = footerContent; } else { this.footer.innerHTML = ""; this.footer.appendChild(footerContent); } this.changeFooterEvent.fire(footerContent); this.changeContentEvent.fire(); }, /** * Appends the passed element to the footer. If no footer is present, one will be automatically created. * @method appendToFooter * @param {HTMLElement} element The element to append to the footer */ appendToFooter : function(element) { if (! this.footer) { this.footer = document.createElement("DIV"); this.footer.className = YAHOO.widget.Module.CSS_FOOTER; } this.footer.appendChild(element); this.changeFooterEvent.fire(element); this.changeContentEvent.fire(); }, /** * Renders the Module by inserting the elements that are not already in the main Module into their correct places. Optionally appends the Module to the specified node prior to the render's execution. NOTE: For Modules without existing markup, the appendToNode argument is REQUIRED. If this argument is ommitted and the current element is not present in the document, the function will return false, indicating that the render was a failure. * @method render * @param {String} appendToNode The element id to which the Module should be appended to prior to rendering OR * @param {HTMLElement} appendToNode The element to which the Module should be appended to prior to rendering * @param {HTMLElement} moduleElement OPTIONAL. The element that represents the actual Standard Module container. * @return {Boolean} Success or failure of the render */ render : function(appendToNode, moduleElement) { this.beforeRenderEvent.fire(); if (! moduleElement) { moduleElement = this.element; } var me = this; var appendTo = function(element) { if (typeof element == "string") { element = document.getElementById(element); } if (element) { element.appendChild(me.element); me.appendEvent.fire(); } }; if (appendToNode) { appendTo(appendToNode); } else { // No node was passed in. If the element is not pre-marked up, this fails if (! YAHOO.util.Dom.inDocument(this.element)) { return false; } } // Need to get everything into the DOM if it isn't already if (this.header && ! YAHOO.util.Dom.inDocument(this.header)) { // There is a header, but it's not in the DOM yet... need to add it var firstChild = moduleElement.firstChild; if (firstChild) { // Insert before first child if exists moduleElement.insertBefore(this.header, firstChild); } else { // Append to empty body because there are no children moduleElement.appendChild(this.header); } } if (this.body && ! YAHOO.util.Dom.inDocument(this.body)) { // There is a body, but it's not in the DOM yet... need to add it if (this.footer && YAHOO.util.Dom.isAncestor(this.moduleElement, this.footer)) { // Insert before footer if exists in DOM moduleElement.insertBefore(this.body, this.footer); } else { // Append to element because there is no footer moduleElement.appendChild(this.body); } } if (this.footer && ! YAHOO.util.Dom.inDocument(this.footer)) { // There is a footer, but it's not in the DOM yet... need to add it moduleElement.appendChild(this.footer); } this.renderEvent.fire(); return true; }, /** * Removes the Module element from the DOM and sets all child elements to null. * @method destroy */ destroy : function() { if (this.element) { var parent = this.element.parentNode; } if (parent) { parent.removeChild(this.element); } this.element = null; this.header = null; this.body = null; this.footer = null; this.destroyEvent.fire(); }, /** * Shows the Module element by setting the visible configuration property to true. Also fires two events: beforeShowEvent prior to the visibility change, and showEvent after. * @method show */ show : function() { this.cfg.setProperty("visible", true); }, /** * Hides the Module element by setting the visible configuration property to false. Also fires two events: beforeHideEvent prior to the visibility change, and hideEvent after. * @method hide */ hide : function() { this.cfg.setProperty("visible", false); }, // BUILT-IN EVENT HANDLERS FOR MODULE // /** * Default event handler for changing the visibility property of a Module. By default, this is achieved by switching the "display" style between "block" and "none". * This method is responsible for firing showEvent and hideEvent. * @param {String} type The CustomEvent type (usually the property name) * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. * @method configVisible */ configVisible : function(type, args, obj) { var visible = args[0]; if (visible) { this.beforeShowEvent.fire(); YAHOO.util.Dom.setStyle(this.element, "display", "block"); this.showEvent.fire(); } else { this.beforeHideEvent.fire(); YAHOO.util.Dom.setStyle(this.element, "display", "none"); this.hideEvent.fire(); } }, /** * Default event handler for the "monitorresize" configuration property * @param {String} type The CustomEvent type (usually the property name) * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. * @method configMonitorResize */ configMonitorResize : function(type, args, obj) { var monitor = args[0]; if (monitor) { this.initResizeMonitor(); } else { YAHOO.util.Event.removeListener(this.resizeMonitor, "resize", this.onDomResize); this.resizeMonitor = null; } } }; /** * Returns a String representation of the Object. * @method toString * @return {String} The string representation of the Module */ YAHOO.widget.Module.prototype.toString = function() { return "Module " + this.id; }; /** * Overlay is a Module that is absolutely positioned above the page flow. It has convenience methods for positioning and sizing, as well as options for controlling zIndex and constraining the Overlay's position to the current visible viewport. Overlay also contains a dynamicly generated IFRAME which is placed beneath it for Internet Explorer 6 and 5.x so that it will be properly rendered above SELECT elements. * @class Overlay * @namespace YAHOO.widget * @extends YAHOO.widget.Module * @param {String} el The element ID representing the Overlay OR * @param {HTMLElement} el The element representing the Overlay * @param {Object} userConfig The configuration object literal containing 10/23/2006the configuration that should be set for this Overlay. See configuration documentation for more details. * @constructor */ YAHOO.widget.Overlay = function(el, userConfig) { YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig); }; YAHOO.extend(YAHOO.widget.Overlay, YAHOO.widget.Module); /** * The URL that will be placed in the iframe * @property YAHOO.widget.Overlay.IFRAME_SRC * @static * @final * @type String */ YAHOO.widget.Overlay.IFRAME_SRC = "javascript:false;" /** * Constant representing the top left corner of an element, used for configuring the context element alignment * @property YAHOO.widget.Overlay.TOP_LEFT * @static * @final * @type String */ YAHOO.widget.Overlay.TOP_LEFT = "tl"; /** * Constant representing the top right corner of an element, used for configuring the context element alignment * @property YAHOO.widget.Overlay.TOP_RIGHT * @static * @final * @type String */ YAHOO.widget.Overlay.TOP_RIGHT = "tr"; /** * Constant representing the top bottom left corner of an element, used for configuring the context element alignment * @property YAHOO.widget.Overlay.BOTTOM_LEFT * @static * @final * @type String */ YAHOO.widget.Overlay.BOTTOM_LEFT = "bl"; /** * Constant representing the bottom right corner of an element, used for configuring the context element alignment * @property YAHOO.widget.Overlay.BOTTOM_RIGHT * @static * @final * @type String */ YAHOO.widget.Overlay.BOTTOM_RIGHT = "br"; /** * Constant representing the default CSS class used for an Overlay * @property YAHOO.widget.Overlay.CSS_OVERLAY * @static * @final * @type String */ YAHOO.widget.Overlay.CSS_OVERLAY = "overlay"; /** * The Overlay initialization method, which is executed for Overlay and all of its subclasses. This method is automatically called by the constructor, and sets up all DOM references for pre-existing markup, and creates required markup if it is not already present. * @method init * @param {String} el The element ID representing the Overlay OR * @param {HTMLElement} el The element representing the Overlay * @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Overlay. See configuration documentation for more details. */ YAHOO.widget.Overlay.prototype.init = function(el, userConfig) { YAHOO.widget.Overlay.superclass.init.call(this, el/*, userConfig*/); // Note that we don't pass the user config in here yet because we only want it executed once, at the lowest subclass level this.beforeInitEvent.fire(YAHOO.widget.Overlay); YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Overlay.CSS_OVERLAY); if (userConfig) { this.cfg.applyConfig(userConfig, true); } if (this.platform == "mac" && this.browser == "gecko") { if (! YAHOO.util.Config.alreadySubscribed(this.showEvent,this.showMacGeckoScrollbars,this)) { this.showEvent.subscribe(this.showMacGeckoScrollbars,this,true); } if (! YAHOO.util.Config.alreadySubscribed(this.hideEvent,this.hideMacGeckoScrollbars,this)) { this.hideEvent.subscribe(this.hideMacGeckoScrollbars,this,true); } } this.initEvent.fire(YAHOO.widget.Overlay); }; /** * Initializes the custom events for Overlay which are fired automatically at appropriate times by the Overlay class. * @method initEvents */ YAHOO.widget.Overlay.prototype.initEvents = function() { YAHOO.widget.Overlay.superclass.initEvents.call(this); /** * CustomEvent fired before the Overlay is moved. * @event beforeMoveEvent * @param {Number} x x coordinate * @param {Number} y y coordinate */ this.beforeMoveEvent = new YAHOO.util.CustomEvent("beforeMove", this); /** * CustomEvent fired after the Overlay is moved. * @event moveEvent * @param {Number} x x coordinate * @param {Number} y y coordinate */ this.moveEvent = new YAHOO.util.CustomEvent("move", this); }; /** * Initializes the class's configurable properties which can be changed using the Overlay's Config object (cfg). * @method initDefaultConfig */ YAHOO.widget.Overlay.prototype.initDefaultConfig = function() { YAHOO.widget.Overlay.superclass.initDefaultConfig.call(this); // Add overlay config properties // /** * The absolute x-coordinate position of the Overlay * @config x * @type Number * @default null */ this.cfg.addProperty("x", { handler:this.configX, validator:this.cfg.checkNumber, suppressEvent:true, supercedes:["iframe"] } ); /** * The absolute y-coordinate position of the Overlay * @config y * @type Number * @default null */ this.cfg.addProperty("y", { handler:this.configY, validator:this.cfg.checkNumber, suppressEvent:true, supercedes:["iframe"] } ); /** * An array with the absolute x and y positions of the Overlay * @config xy * @type Number[] * @default null */ this.cfg.addProperty("xy",{ handler:this.configXY, suppressEvent:true, supercedes:["iframe"] } ); /** * The array of context arguments for context-sensitive positioning. The format is: [id or element, element corner, context corner]. For example, setting this property to ["img1", "tl", "bl"] would align the Overlay's top left corner to the context element's bottom left corner. * @config context * @type Array * @default null */ this.cfg.addProperty("context", { handler:this.configContext, suppressEvent:true, supercedes:["iframe"] } ); /** * True if the Overlay should be anchored to the center of the viewport. * @config fixedcenter * @type Boolean * @default false */ this.cfg.addProperty("fixedcenter", { value:false, handler:this.configFixedCenter, validator:this.cfg.checkBoolean, supercedes:["iframe","visible"] } ); /** * CSS width of the Overlay. * @config width * @type String * @default null */ this.cfg.addProperty("width", { handler:this.configWidth, suppressEvent:true, supercedes:["iframe"] } ); /** * CSS height of the Overlay. * @config height * @type String * @default null */ this.cfg.addProperty("height", { handler:this.configHeight, suppressEvent:true, supercedes:["iframe"] } ); /** * CSS z-index of the Overlay. * @config zIndex * @type Number * @default null */ this.cfg.addProperty("zIndex", { value:null, handler:this.configzIndex } ); /** * True if the Overlay should be prevented from being positioned out of the viewport. * @config constraintoviewport * @type Boolean * @default false */ this.cfg.addProperty("constraintoviewport", { value:false, handler:this.configConstrainToViewport, validator:this.cfg.checkBoolean, supercedes:["iframe","x","y","xy"] } ); /** * True if the Overlay should have an IFRAME shim (for correcting the select z-index bug in IE6 and below). * @config iframe * @type Boolean * @default true for IE6 and below, false for all others */ this.cfg.addProperty("iframe", { value:(this.browser == "ie" ? true : false), handler:this.configIframe, validator:this.cfg.checkBoolean, supercedes:["zIndex"] } ); }; /** * Moves the Overlay to the specified position. This function is identical to calling this.cfg.setProperty("xy", [x,y]); * @method moveTo * @param {Number} x The Overlay's new x position * @param {Number} y The Overlay's new y position */ YAHOO.widget.Overlay.prototype.moveTo = function(x, y) { this.cfg.setProperty("xy",[x,y]); }; /** * Adds a special CSS class to the Overlay when Mac/Gecko is in use, to work around a Gecko bug where * scrollbars cannot be hidden. See https://bugzilla.mozilla.org/show_bug.cgi?id=187435 * @method hideMacGeckoScrollbars */ YAHOO.widget.Overlay.prototype.hideMacGeckoScrollbars = function() { YAHOO.util.Dom.removeClass(this.element, "show-scrollbars"); YAHOO.util.Dom.addClass(this.element, "hide-scrollbars"); }; /** * Removes a special CSS class from the Overlay when Mac/Gecko is in use, to work around a Gecko bug where * scrollbars cannot be hidden. See https://bugzilla.mozilla.org/show_bug.cgi?id=187435 * @method showMacGeckoScrollbars */ YAHOO.widget.Overlay.prototype.showMacGeckoScrollbars = function() { YAHOO.util.Dom.removeClass(this.element, "hide-scrollbars"); YAHOO.util.Dom.addClass(this.element, "show-scrollbars"); }; // BEGIN BUILT-IN PROPERTY EVENT HANDLERS // /** * The default event handler fired when the "visible" property is changed. This method is responsible for firing showEvent and hideEvent. * @method configVisible * @param {String} type The CustomEvent type (usually the property name) * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. */ YAHOO.widget.Overlay.prototype.configVisible = function(type, args, obj) { var visible = args[0]; var currentVis = YAHOO.util.Dom.getStyle(this.element, "visibility"); if (currentVis == "inherit") { var e = this.element.parentNode; while (e.nodeType != 9 && e.nodeType != 11) { currentVis = YAHOO.util.Dom.getStyle(e, "visibility"); if (currentVis != "inherit") { break; } e = e.parentNode; } if (currentVis == "inherit") { currentVis = "visible"; } } var effect = this.cfg.getProperty("effect"); var effectInstances = []; if (effect) { if (effect instanceof Array) { for (var i=0;i rightConstraint) { x = rightConstraint; } if (y < topConstraint) { y = topConstraint; } else if (y > bottomConstraint) { y = bottomConstraint; } this.cfg.setProperty("x", x, true); this.cfg.setProperty("y", y, true); this.cfg.setProperty("xy", [x,y], true); }; /** * Centers the container in the viewport. * @method center */ YAHOO.widget.Overlay.prototype.center = function() { var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; var scrollY = document.documentElement.scrollTop || document.body.scrollTop; var viewPortWidth = YAHOO.util.Dom.getClientWidth(); var viewPortHeight = YAHOO.util.Dom.getClientHeight(); var elementWidth = this.element.offsetWidth; var elementHeight = this.element.offsetHeight; var x = (viewPortWidth / 2) - (elementWidth / 2) + scrollX; var y = (viewPortHeight / 2) - (elementHeight / 2) + scrollY; this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]); this.cfg.refireEvent("iframe"); }; /** * Synchronizes the Panel's "xy", "x", and "y" properties with the Panel's position in the DOM. This is primarily used to update position information during drag & drop. * @method syncPosition */ YAHOO.widget.Overlay.prototype.syncPosition = function() { var pos = YAHOO.util.Dom.getXY(this.element); this.cfg.setProperty("x", pos[0], true); this.cfg.setProperty("y", pos[1], true); this.cfg.setProperty("xy", pos, true); }; /** * Event handler fired when the resize monitor element is resized. * @method onDomResize * @param {DOMEvent} e The resize DOM event * @param {Object} obj The scope object */ YAHOO.widget.Overlay.prototype.onDomResize = function(e, obj) { YAHOO.widget.Overlay.superclass.onDomResize.call(this, e, obj); var me = this; setTimeout(function() { me.syncPosition(); me.cfg.refireEvent("iframe"); me.cfg.refireEvent("context"); }, 0); }; /** * Removes the Overlay element from the DOM and sets all child elements to null. * @method destroy */ YAHOO.widget.Overlay.prototype.destroy = function() { if (this.iframe) { this.iframe.parentNode.removeChild(this.iframe); } this.iframe = null; YAHOO.widget.Overlay.superclass.destroy.call(this); }; /** * Returns a String representation of the object. * @method toString * @return {String} The string representation of the Overlay. */ YAHOO.widget.Overlay.prototype.toString = function() { return "Overlay " + this.id; }; /** * A singleton CustomEvent used for reacting to the DOM event for window scroll * @event YAHOO.widget.Overlay.windowScrollEvent */ YAHOO.widget.Overlay.windowScrollEvent = new YAHOO.util.CustomEvent("windowScroll"); /** * A singleton CustomEvent used for reacting to the DOM event for window resize * @event YAHOO.widget.Overlay.windowResizeEvent */ YAHOO.widget.Overlay.windowResizeEvent = new YAHOO.util.CustomEvent("windowResize"); /** * The DOM event handler used to fire the CustomEvent for window scroll * @method YAHOO.widget.Overlay.windowScrollHandler * @static * @param {DOMEvent} e The DOM scroll event */ YAHOO.widget.Overlay.windowScrollHandler = function(e) { if (YAHOO.widget.Module.prototype.browser == "ie" || YAHOO.widget.Module.prototype.browser == "ie7") { if (! window.scrollEnd) { window.scrollEnd = -1; } clearTimeout(window.scrollEnd); window.scrollEnd = setTimeout(function() { YAHOO.widget.Overlay.windowScrollEvent.fire(); }, 1); } else { YAHOO.widget.Overlay.windowScrollEvent.fire(); } }; /** * The DOM event handler used to fire the CustomEvent for window resize * @method YAHOO.widget.Overlay.windowResizeHandler * @static * @param {DOMEvent} e The DOM resize event */ YAHOO.widget.Overlay.windowResizeHandler = function(e) { if (YAHOO.widget.Module.prototype.browser == "ie" || YAHOO.widget.Module.prototype.browser == "ie7") { if (! window.resizeEnd) { window.resizeEnd = -1; } clearTimeout(window.resizeEnd); window.resizeEnd = setTimeout(function() { YAHOO.widget.Overlay.windowResizeEvent.fire(); }, 100); } else { YAHOO.widget.Overlay.windowResizeEvent.fire(); } }; /** * A boolean that indicated whether the window resize and scroll events have already been subscribed to. * @property YAHOO.widget.Overlay._initialized * @private * @type Boolean */ YAHOO.widget.Overlay._initialized = null; if (YAHOO.widget.Overlay._initialized === null) { YAHOO.util.Event.addListener(window, "scroll", YAHOO.widget.Overlay.windowScrollHandler); YAHOO.util.Event.addListener(window, "resize", YAHOO.widget.Overlay.windowResizeHandler); YAHOO.widget.Overlay._initialized = true; } /** * OverlayManager is used for maintaining the focus status of multiple Overlays.* @namespace YAHOO.widget * @namespace YAHOO.widget * @class OverlayManager * @constructor * @param {Array} overlays Optional. A collection of Overlays to register with the manager. * @param {Object} userConfig The object literal representing the user configuration of the OverlayManager */ YAHOO.widget.OverlayManager = function(userConfig) { this.init(userConfig); }; /** * The CSS class representing a focused Overlay * @property YAHOO.widget.OverlayManager.CSS_FOCUSED * @static * @final * @type String */ YAHOO.widget.OverlayManager.CSS_FOCUSED = "focused"; YAHOO.widget.OverlayManager.prototype = { /** * The class's constructor function * @property contructor * @type Function */ constructor : YAHOO.widget.OverlayManager, /** * The array of Overlays that are currently registered * @property overlays * @type YAHOO.widget.Overlay[] */ overlays : null, /** * Initializes the default configuration of the OverlayManager * @method initDefaultConfig */ initDefaultConfig : function() { /** * The collection of registered Overlays in use by the OverlayManager * @config overlays * @type YAHOO.widget.Overlay[] * @default null */ this.cfg.addProperty("overlays", { suppressEvent:true } ); /** * The default DOM event that should be used to focus an Overlay * @config focusevent * @type String * @default "mousedown" */ this.cfg.addProperty("focusevent", { value:"mousedown" } ); }, /** * Initializes the OverlayManager * @method init * @param {YAHOO.widget.Overlay[]} overlays Optional. A collection of Overlays to register with the manager. * @param {Object} userConfig The object literal representing the user configuration of the OverlayManager */ init : function(userConfig) { /** * The OverlayManager's Config object used for monitoring configuration properties. * @property cfg * @type YAHOO.util.Config */ this.cfg = new YAHOO.util.Config(this); this.initDefaultConfig(); if (userConfig) { this.cfg.applyConfig(userConfig, true); } this.cfg.fireQueue(); /** * The currently activated Overlay * @property activeOverlay * @private * @type YAHOO.widget.Overlay */ var activeOverlay = null; /** * Returns the currently focused Overlay * @method getActive * @return {YAHOO.widget.Overlay} The currently focused Overlay */ this.getActive = function() { return activeOverlay; }; /** * Focuses the specified Overlay * @method focus * @param {YAHOO.widget.Overlay} overlay The Overlay to focus * @param {String} overlay The id of the Overlay to focus */ this.focus = function(overlay) { var o = this.find(overlay); if (o) { this.blurAll(); activeOverlay = o; YAHOO.util.Dom.addClass(activeOverlay.element, YAHOO.widget.OverlayManager.CSS_FOCUSED); this.overlays.sort(this.compareZIndexDesc); var topZIndex = YAHOO.util.Dom.getStyle(this.overlays[0].element, "zIndex"); if (! isNaN(topZIndex) && this.overlays[0] != overlay) { activeOverlay.cfg.setProperty("zIndex", (parseInt(topZIndex, 10) + 2)); } this.overlays.sort(this.compareZIndexDesc); } }; /** * Removes the specified Overlay from the manager * @method remove * @param {YAHOO.widget.Overlay} overlay The Overlay to remove * @param {String} overlay The id of the Overlay to remove */ this.remove = function(overlay) { var o = this.find(overlay); if (o) { var originalZ = YAHOO.util.Dom.getStyle(o.element, "zIndex"); o.cfg.setProperty("zIndex", -1000, true); this.overlays.sort(this.compareZIndexDesc); this.overlays = this.overlays.slice(0, this.overlays.length-1); o.cfg.setProperty("zIndex", originalZ, true); o.cfg.setProperty("manager", null); o.focusEvent = null; o.blurEvent = null; o.focus = null; o.blur = null; } }; /** * Removes focus from all registered Overlays in the manager * @method blurAll */ this.blurAll = function() { activeOverlay = null; for (var o=0;o 0) { return true; } } else { return false; } }, /** * Attempts to locate an Overlay by instance or ID. * @method find * @param {YAHOO.widget.Overlay} overlay An Overlay to locate within the manager * @param {String} overlay An Overlay id to locate within the manager * @return {YAHOO.widget.Overlay} The requested Overlay, if found, or null if it cannot be located. */ find : function(overlay) { if (overlay instanceof YAHOO.widget.Overlay) { for (var o=0;o zIndex2) { return -1; } else if (zIndex1 < zIndex2) { return 1; } else { return 0; } }, /** * Shows all Overlays in the manager. * @method showAll */ showAll : function() { for (var o=0;o OR * @param {HTMLElement} el The element representing the Tooltip * @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Overlay. See configuration documentation for more details. */ YAHOO.widget.Tooltip = function(el, userConfig) { YAHOO.widget.Tooltip.superclass.constructor.call(this, el, userConfig); }; YAHOO.extend(YAHOO.widget.Tooltip, YAHOO.widget.Overlay); /** * Constant representing the Tooltip CSS class * @property YAHOO.widget.Tooltip.CSS_TOOLTIP * @static * @final * @type String */ YAHOO.widget.Tooltip.CSS_TOOLTIP = "tt"; /** * The Tooltip initialization method. This method is automatically called by the constructor. A Tooltip is automatically rendered by the init method, and it also is set to be invisible by default, and constrained to viewport by default as well. * @method init * @param {String} el The element ID representing the Tooltip OR * @param {HTMLElement} el The element representing the Tooltip * @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Tooltip. See configuration documentation for more details. */ YAHOO.widget.Tooltip.prototype.init = function(el, userConfig) { if (document.readyState && document.readyState != "complete") { var deferredInit = function() { this.init(el, userConfig); }; YAHOO.util.Event.addListener(window, "load", deferredInit, this, true); } else { YAHOO.widget.Tooltip.superclass.init.call(this, el); this.beforeInitEvent.fire(YAHOO.widget.Tooltip); YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Tooltip.CSS_TOOLTIP); if (userConfig) { this.cfg.applyConfig(userConfig, true); } this.cfg.queueProperty("visible",false); this.cfg.queueProperty("constraintoviewport",true); this.setBody(""); this.render(this.cfg.getProperty("container")); this.initEvent.fire(YAHOO.widget.Tooltip); } }; /** * Initializes the class's configurable properties which can be changed using the Overlay's Config object (cfg). * @method initDefaultConfig */ YAHOO.widget.Tooltip.prototype.initDefaultConfig = function() { YAHOO.widget.Tooltip.superclass.initDefaultConfig.call(this); /** * Specifies whether the Tooltip should be kept from overlapping its context element. * @config preventoverlap * @type Boolean * @default true */ this.cfg.addProperty("preventoverlap", { value:true, validator:this.cfg.checkBoolean, supercedes:["x","y","xy"] } ); /** * The number of milliseconds to wait before showing a Tooltip on mouseover. * @config showdelay * @type Number * @default 200 */ this.cfg.addProperty("showdelay", { value:200, handler:this.configShowDelay, validator:this.cfg.checkNumber } ); /** * The number of milliseconds to wait before automatically dismissing a Tooltip after the mouse has been resting on the context element. * @config autodismissdelay * @type Number * @default 5000 */ this.cfg.addProperty("autodismissdelay", { value:5000, handler:this.configAutoDismissDelay, validator:this.cfg.checkNumber } ); /** * The number of milliseconds to wait before hiding a Tooltip on mouseover. * @config hidedelay * @type Number * @default 250 */ this.cfg.addProperty("hidedelay", { value:250, handler:this.configHideDelay, validator:this.cfg.checkNumber } ); /** * Specifies the Tooltip's text. * @config text * @type String * @default null */ this.cfg.addProperty("text", { handler:this.configText, suppressEvent:true } ); /** * Specifies the container element that the Tooltip's markup should be rendered into. * @config container * @type HTMLElement/String * @default document.body */ this.cfg.addProperty("container", { value:document.body, handler:this.configContainer } ); /** * Specifies the element or elements that the Tooltip should be anchored to on mouseover. * @config context * @type HTMLElement[]/String[] * @default null */ }; // BEGIN BUILT-IN PROPERTY EVENT HANDLERS // /** * The default event handler fired when the "text" property is changed. * @method configText * @param {String} type The CustomEvent type (usually the property name) * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. */ YAHOO.widget.Tooltip.prototype.configText = function(type, args, obj) { var text = args[0]; if (text) { this.setBody(text); } }; /** * The default event handler fired when the "container" property is changed. * @method configContainer * @param {String} type The CustomEvent type (usually the property name) * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. */ YAHOO.widget.Tooltip.prototype.configContainer = function(type, args, obj) { var container = args[0]; if (typeof container == 'string') { this.cfg.setProperty("container", document.getElementById(container), true); } }; /** * The default event handler fired when the "context" property is changed. * @method configContext * @param {String} type The CustomEvent type (usually the property name) * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. */ YAHOO.widget.Tooltip.prototype.configContext = function(type, args, obj) { var context = args[0]; if (context) { // Normalize parameter into an array if (! (context instanceof Array)) { if (typeof context == "string") { this.cfg.setProperty("context", [document.getElementById(context)], true); } else { // Assuming this is an element this.cfg.setProperty("context", [context], true); } context = this.cfg.getProperty("context"); } // Remove any existing mouseover/mouseout listeners if (this._context) { for (var c=0;c OR * @param {HTMLElement} el The element representing the Panel * @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Panel. See configuration documentation for more details. */ YAHOO.widget.Panel = function(el, userConfig) { YAHOO.widget.Panel.superclass.constructor.call(this, el, userConfig); }; YAHOO.extend(YAHOO.widget.Panel, YAHOO.widget.Overlay); /** * Constant representing the default CSS class used for a Panel * @property YAHOO.widget.Panel.CSS_PANEL * @static * @final * @type String */ YAHOO.widget.Panel.CSS_PANEL = "panel"; /** * Constant representing the default CSS class used for a Panel's wrapping container * @property YAHOO.widget.Panel.CSS_PANEL_CONTAINER * @static * @final * @type String */ YAHOO.widget.Panel.CSS_PANEL_CONTAINER = "panel-container"; /** * The Overlay initialization method, which is executed for Overlay and all of its subclasses. This method is automatically called by the constructor, and sets up all DOM references for pre-existing markup, and creates required markup if it is not already present. * @method init * @param {String} el The element ID representing the Overlay OR * @param {HTMLElement} el The element representing the Overlay * @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Overlay. See configuration documentation for more details. */ YAHOO.widget.Panel.prototype.init = function(el, userConfig) { YAHOO.widget.Panel.superclass.init.call(this, el/*, userConfig*/); // Note that we don't pass the user config in here yet because we only want it executed once, at the lowest subclass level this.beforeInitEvent.fire(YAHOO.widget.Panel); YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Panel.CSS_PANEL); this.buildWrapper(); if (userConfig) { this.cfg.applyConfig(userConfig, true); } this.beforeRenderEvent.subscribe(function() { var draggable = this.cfg.getProperty("draggable"); if (draggable) { if (! this.header) { this.setHeader(" "); } } }, this, true); var me = this; this.showMaskEvent.subscribe(function() { var checkFocusable = function(el) { if (el.tagName == "A" || el.tagName == "BUTTON" || el.tagName == "SELECT" || el.tagName == "INPUT" || el.tagName == "TEXTAREA" || el.tagName == "FORM") { if (! YAHOO.util.Dom.isAncestor(me.element, el)) { YAHOO.util.Event.addListener(el, "focus", el.blur); return true; } } else { return false; } }; this.focusableElements = YAHOO.util.Dom.getElementsBy(checkFocusable); }, this, true); this.hideMaskEvent.subscribe(function() { for (var i=0;i OR * @param {HTMLElement} appendToNode The element to which the Module should be appended to prior to rendering * @return {boolean} Success or failure of the render */ YAHOO.widget.Panel.prototype.render = function(appendToNode) { return YAHOO.widget.Panel.superclass.render.call(this, appendToNode, this.innerElement); }; /** * Returns a String representation of the object. * @method toString * @return {String} The string representation of the Panel. */ YAHOO.widget.Panel.prototype.toString = function() { return "Panel " + this.id; }; /** * Dialog is an implementation of Panel that can be used to submit form data. Built-in functionality for buttons with event handlers is included, and button sets can be build dynamically, or the preincluded ones for Submit/Cancel and OK/Cancel can be utilized. Forms can be processed in 3 ways -- via an asynchronous Connection utility call, a simple form POST or GET, or manually. * @namespace YAHOO.widget * @class Dialog * @extends YAHOO.widget.Panel * @constructor * @param {String} el The element ID representing the Dialog OR * @param {HTMLElement} el The element representing the Dialog * @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Dialog. See configuration documentation for more details. */ YAHOO.widget.Dialog = function(el, userConfig) { YAHOO.widget.Dialog.superclass.constructor.call(this, el, userConfig); }; YAHOO.extend(YAHOO.widget.Dialog, YAHOO.widget.Panel); /** * Constant representing the default CSS class used for a Dialog * @property YAHOO.widget.Dialog.CSS_DIALOG * @static * @final * @type String */ YAHOO.widget.Dialog.CSS_DIALOG = "dialog"; /** * Initializes the class's configurable properties which can be changed using the Dialog's Config object (cfg). * @method initDefaultConfig */ YAHOO.widget.Dialog.prototype.initDefaultConfig = function() { YAHOO.widget.Dialog.superclass.initDefaultConfig.call(this); /** * The internally maintained callback object for use with the Connection utility * @property callback * @type Object */ this.callback = { /** * The function to execute upon success of the Connection submission * @property callback.success * @type Function */ success : null, /** * The function to execute upon failure of the Connection submission * @property callback.failure * @type Function */ failure : null, /** * The arbitraty argument or arguments to pass to the Connection callback functions * @property callback.argument * @type Object */ argument: null }; // Add form dialog config properties // /** * The method to use for posting the Dialog's form. Possible values are "async", "form", and "manual". * @config postmethod * @type String * @default async */ this.cfg.addProperty("postmethod", { value:"async", validator:function(val) { if (val != "form" && val != "async" && val != "none" && val != "manual") { return false; } else { return true; } } }); /** * Object literal(s) defining the buttons for the Dialog's footer. * @config buttons * @type Object[] * @default "none" */ this.cfg.addProperty("buttons", { value:"none", handler:this.configButtons } ); }; /** * Initializes the custom events for Dialog which are fired automatically at appropriate times by the Dialog class. * @method initEvents */ YAHOO.widget.Dialog.prototype.initEvents = function() { YAHOO.widget.Dialog.superclass.initEvents.call(this); /** * CustomEvent fired prior to submission * @event beforeSumitEvent */ this.beforeSubmitEvent = new YAHOO.util.CustomEvent("beforeSubmit"); /** * CustomEvent fired after submission * @event submitEvent */ this.submitEvent = new YAHOO.util.CustomEvent("submit"); /** * CustomEvent fired prior to manual submission * @event manualSubmitEvent */ this.manualSubmitEvent = new YAHOO.util.CustomEvent("manualSubmit"); /** * CustomEvent fired prior to asynchronous submission * @event asyncSubmitEvent */ this.asyncSubmitEvent = new YAHOO.util.CustomEvent("asyncSubmit"); /** * CustomEvent fired prior to form-based submission * @event formSubmitEvent */ this.formSubmitEvent = new YAHOO.util.CustomEvent("formSubmit"); /** * CustomEvent fired after cancel * @event cancelEvent */ this.cancelEvent = new YAHOO.util.CustomEvent("cancel"); }; /** * The Dialog initialization method, which is executed for Dialog and all of its subclasses. This method is automatically called by the constructor, and sets up all DOM references for pre-existing markup, and creates required markup if it is not already present. * @method init * @param {String} el The element ID representing the Dialog OR * @param {HTMLElement} el The element representing the Dialog * @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Dialog. See configuration documentation for more details. */ YAHOO.widget.Dialog.prototype.init = function(el, userConfig) { YAHOO.widget.Dialog.superclass.init.call(this, el/*, userConfig*/); // Note that we don't pass the user config in here yet because we only want it executed once, at the lowest subclass level this.beforeInitEvent.fire(YAHOO.widget.Dialog); YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Dialog.CSS_DIALOG); this.cfg.setProperty("visible", false); if (userConfig) { this.cfg.applyConfig(userConfig, true); } this.renderEvent.subscribe(this.registerForm, this, true); this.showEvent.subscribe(this.focusFirst, this, true); this.beforeHideEvent.subscribe(this.blurButtons, this, true); this.beforeRenderEvent.subscribe(function() { var buttonCfg = this.cfg.getProperty("buttons"); if (buttonCfg && buttonCfg != "none") { if (! this.footer) { this.setFooter(""); } } }, this, true); this.initEvent.fire(YAHOO.widget.Dialog); }; /** * Performs the submission of the Dialog form depending on the value of "postmethod" property. * @method doSubmit */ YAHOO.widget.Dialog.prototype.doSubmit = function() { var pm = this.cfg.getProperty("postmethod"); switch (pm) { case "async": var method = this.form.getAttribute("method") || 'POST'; method = method.toUpperCase(); YAHOO.util.Connect.setForm(this.form); var cObj = YAHOO.util.Connect.asyncRequest(method, this.form.getAttribute("action"), this.callback); this.asyncSubmitEvent.fire(); break; case "form": this.form.submit(); this.formSubmitEvent.fire(); break; case "none": case "manual": this.manualSubmitEvent.fire(); break; } }; /** * Prepares the Dialog's internal FORM object, creating one if one is not currently present. * @method registerForm */ YAHOO.widget.Dialog.prototype.registerForm = function() { var form = this.element.getElementsByTagName("FORM")[0]; if (! form) { var formHTML = ""; this.body.innerHTML += formHTML; form = this.element.getElementsByTagName("FORM")[0]; } this.firstFormElement = function() { for (var f=0;f =0;f-- ) { var el = form.elements[f]; if (el.focus) { if (el.type && el.type != "hidden") { return el; } } } return null; }(); this.form = form; if (this.cfg.getProperty("modal") && this.form) { var me = this; var firstElement = this.firstFormElement || this.firstButton; if (firstElement) { this.preventBackTab = new YAHOO.util.KeyListener(firstElement, { shift:true, keys:9 }, {fn:me.focusLast, scope:me, correctScope:true} ); this.showEvent.subscribe(this.preventBackTab.enable, this.preventBackTab, true); this.hideEvent.subscribe(this.preventBackTab.disable, this.preventBackTab, true); } var lastElement = this.lastButton || this.lastFormElement; if (lastElement) { this.preventTabOut = new YAHOO.util.KeyListener(lastElement, { shift:false, keys:9 }, {fn:me.focusFirst, scope:me, correctScope:true} ); this.showEvent.subscribe(this.preventTabOut.enable, this.preventTabOut, true); this.hideEvent.subscribe(this.preventTabOut.disable, this.preventTabOut, true); } } }; // BEGIN BUILT-IN PROPERTY EVENT HANDLERS // /** * The default event handler for the "buttons" configuration property * @method configButtons * @param {String} type The CustomEvent type (usually the property name) * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. */ YAHOO.widget.Dialog.prototype.configButtons = function(type, args, obj) { var buttons = args[0]; if (buttons != "none") { this.buttonSpan = null; this.buttonSpan = document.createElement("SPAN"); this.buttonSpan.className = "button-group"; for (var b=0;b OR * @param {HTMLElement} el The element representing the SimpleDialog * @param {Object} userConfig The configuration object literal containing the configuration that should be set for this SimpleDialog. See configuration documentation for more details. */ YAHOO.widget.SimpleDialog = function(el, userConfig) { YAHOO.widget.SimpleDialog.superclass.constructor.call(this, el, userConfig); }; YAHOO.extend(YAHOO.widget.SimpleDialog, YAHOO.widget.Dialog); /** * Constant for the standard network icon for a blocking action * @property YAHOO.widget.SimpleDialog.ICON_BLOCK * @static * @final * @type String */ YAHOO.widget.SimpleDialog.ICON_BLOCK = "nt/ic/ut/bsc/blck16_1.gif"; /** * Constant for the standard network icon for alarm * @property YAHOO.widget.SimpleDialog.ICON_ALARM * @static * @final * @type String */ YAHOO.widget.SimpleDialog.ICON_ALARM = "nt/ic/ut/bsc/alrt16_1.gif"; /** * Constant for the standard network icon for help * @property YAHOO.widget.SimpleDialog.ICON_HELP * @static * @final * @type String */ YAHOO.widget.SimpleDialog.ICON_HELP = "nt/ic/ut/bsc/hlp16_1.gif"; /** * Constant for the standard network icon for info * @property YAHOO.widget.SimpleDialog.ICON_INFO * @static * @final * @type String */ YAHOO.widget.SimpleDialog.ICON_INFO = "nt/ic/ut/bsc/info16_1.gif"; /** * Constant for the standard network icon for warn * @property YAHOO.widget.SimpleDialog.ICON_WARN * @static * @final * @type String */ YAHOO.widget.SimpleDialog.ICON_WARN = "nt/ic/ut/bsc/warn16_1.gif"; /** * Constant for the standard network icon for a tip * @property YAHOO.widget.SimpleDialog.ICON_TIP * @static * @final * @type String */ YAHOO.widget.SimpleDialog.ICON_TIP = "nt/ic/ut/bsc/tip16_1.gif"; /** * Constant representing the default CSS class used for a SimpleDialog * @property YAHOO.widget.SimpleDialog.CSS_SIMPLEDIALOG * @static * @final * @type String */ YAHOO.widget.SimpleDialog.CSS_SIMPLEDIALOG = "simple-dialog"; /** * Initializes the class's configurable properties which can be changed using the SimpleDialog's Config object (cfg). * @method initDefaultConfig */ YAHOO.widget.SimpleDialog.prototype.initDefaultConfig = function() { YAHOO.widget.SimpleDialog.superclass.initDefaultConfig.call(this); // Add dialog config properties // /** * Sets the informational icon for the SimpleDialog * @config icon * @type String * @default "none" */ this.cfg.addProperty("icon", { value:"none", handler:this.configIcon, suppressEvent:true } ); /** * Sets the text for the SimpleDialog * @config text * @type String * @default "" */ this.cfg.addProperty("text", { value:"", handler:this.configText, suppressEvent:true, supercedes:["icon"] } ); }; /** * The SimpleDialog initialization method, which is executed for SimpleDialog and all of its subclasses. This method is automatically called by the constructor, and sets up all DOM references for pre-existing markup, and creates required markup if it is not already present. * @method init * @param {String} el The element ID representing the SimpleDialog OR * @param {HTMLElement} el The element representing the SimpleDialog * @param {Object} userConfig The configuration object literal containing the configuration that should be set for this SimpleDialog. See configuration documentation for more details. */ YAHOO.widget.SimpleDialog.prototype.init = function(el, userConfig) { YAHOO.widget.SimpleDialog.superclass.init.call(this, el/*, userConfig*/); // Note that we don't pass the user config in here yet because we only want it executed once, at the lowest subclass level this.beforeInitEvent.fire(YAHOO.widget.SimpleDialog); YAHOO.util.Dom.addClass(this.element, YAHOO.widget.SimpleDialog.CSS_SIMPLEDIALOG); this.cfg.queueProperty("postmethod", "manual"); if (userConfig) { this.cfg.applyConfig(userConfig, true); } this.beforeRenderEvent.subscribe(function() { if (! this.body) { this.setBody(""); } }, this, true); this.initEvent.fire(YAHOO.widget.SimpleDialog); }; /** * Prepares the SimpleDialog's internal FORM object, creating one if one is not currently present, and adding the value hidden field. * @method registerForm */ YAHOO.widget.SimpleDialog.prototype.registerForm = function() { YAHOO.widget.SimpleDialog.superclass.registerForm.call(this); this.form.innerHTML += ""; }; // BEGIN BUILT-IN PROPERTY EVENT HANDLERS // /** * Fired when the "icon" property is set. * @method configIcon * @param {String} type The CustomEvent type (usually the property name) * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. */ YAHOO.widget.SimpleDialog.prototype.configIcon = function(type,args,obj) { var icon = args[0]; if (icon && icon != "none") { var iconHTML = ""; this.body.innerHTML = iconHTML + this.body.innerHTML; } }; /** * Fired when the "text" property is set. * @method configText * @param {String} type The CustomEvent type (usually the property name) * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. */ YAHOO.widget.SimpleDialog.prototype.configText = function(type,args,obj) { var text = args[0]; if (text) { this.setBody(text); this.cfg.refireEvent("icon"); } }; // END BUILT-IN PROPERTY EVENT HANDLERS // /** * Returns a string representation of the object. * @method toString * @return {String} The string representation of the SimpleDialog */ YAHOO.widget.SimpleDialog.prototype.toString = function() { return "SimpleDialog " + this.id; }; /** * ContainerEffect encapsulates animation transitions that are executed when an Overlay is shown or hidden. * @namespace YAHOO.widget * @class ContainerEffect * @constructor * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation should be associated with * @param {Object} attrIn The object literal representing the animation arguments to be used for the animate-in transition. The arguments for this literal are: attributes(object, see YAHOO.util.Anim for description), duration(Number), and method(i.e. YAHOO.util.Easing.easeIn). * @param {Object} attrOut The object literal representing the animation arguments to be used for the animate-out transition. The arguments for this literal are: attributes(object, see YAHOO.util.Anim for description), duration(Number), and method(i.e. YAHOO.util.Easing.easeIn). * @param {HTMLElement} targetElement Optional. The target element that should be animated during the transition. Defaults to overlay.element. * @param {class} Optional. The animation class to instantiate. Defaults to YAHOO.util.Anim. Other options include YAHOO.util.Motion. */ YAHOO.widget.ContainerEffect = function(overlay, attrIn, attrOut, targetElement, animClass) { if (! animClass) { animClass = YAHOO.util.Anim; } /** * The overlay to animate * @property overlay * @type YAHOO.widget.Overlay */ this.overlay = overlay; /** * The animation attributes to use when transitioning into view * @property attrIn * @type Object */ this.attrIn = attrIn; /** * The animation attributes to use when transitioning out of view * @property attrOut * @type Object */ this.attrOut = attrOut; /** * The target element to be animated * @property targetElement * @type HTMLElement */ this.targetElement = targetElement || overlay.element; /** * The animation class to use for animating the overlay * @property animClass * @type class */ this.animClass = animClass; }; /** * Initializes the animation classes and events. * @method init */ YAHOO.widget.ContainerEffect.prototype.init = function() { this.beforeAnimateInEvent = new YAHOO.util.CustomEvent("beforeAnimateIn"); this.beforeAnimateOutEvent = new YAHOO.util.CustomEvent("beforeAnimateOut"); this.animateInCompleteEvent = new YAHOO.util.CustomEvent("animateInComplete"); this.animateOutCompleteEvent = new YAHOO.util.CustomEvent("animateOutComplete"); this.animIn = new this.animClass(this.targetElement, this.attrIn.attributes, this.attrIn.duration, this.attrIn.method); this.animIn.onStart.subscribe(this.handleStartAnimateIn, this); this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this); this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn, this); this.animOut = new this.animClass(this.targetElement, this.attrOut.attributes, this.attrOut.duration, this.attrOut.method); this.animOut.onStart.subscribe(this.handleStartAnimateOut, this); this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this); this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut, this); }; /** * Triggers the in-animation. * @method animateIn */ YAHOO.widget.ContainerEffect.prototype.animateIn = function() { this.beforeAnimateInEvent.fire(); this.animIn.animate(); }; /** * Triggers the out-animation. * @method animateOut */ YAHOO.widget.ContainerEffect.prototype.animateOut = function() { this.beforeAnimateOutEvent.fire(); this.animOut.animate(); }; /** * The default onStart handler for the in-animation. * @method handleStartAnimateIn * @param {String} type The CustomEvent type * @param {Object[]} args The CustomEvent arguments * @param {Object} obj The scope object */ YAHOO.widget.ContainerEffect.prototype.handleStartAnimateIn = function(type, args, obj) { }; /** * The default onTween handler for the in-animation. * @method handleTweenAnimateIn * @param {String} type The CustomEvent type * @param {Object[]} args The CustomEvent arguments * @param {Object} obj The scope object */ YAHOO.widget.ContainerEffect.prototype.handleTweenAnimateIn = function(type, args, obj) { }; /** * The default onComplete handler for the in-animation. * @method handleCompleteAnimateIn * @param {String} type The CustomEvent type * @param {Object[]} args The CustomEvent arguments * @param {Object} obj The scope object */ YAHOO.widget.ContainerEffect.prototype.handleCompleteAnimateIn = function(type, args, obj) { }; /** * The default onStart handler for the out-animation. * @method handleStartAnimateOut * @param {String} type The CustomEvent type * @param {Object[]} args The CustomEvent arguments * @param {Object} obj The scope object */ YAHOO.widget.ContainerEffect.prototype.handleStartAnimateOut = function(type, args, obj) { }; /** * The default onTween handler for the out-animation. * @method handleTweenAnimateOut * @param {String} type The CustomEvent type * @param {Object[]} args The CustomEvent arguments * @param {Object} obj The scope object */ YAHOO.widget.ContainerEffect.prototype.handleTweenAnimateOut = function(type, args, obj) { }; /** * The default onComplete handler for the out-animation. * @method handleCompleteAnimateOut * @param {String} type The CustomEvent type * @param {Object[]} args The CustomEvent arguments * @param {Object} obj The scope object */ YAHOO.widget.ContainerEffect.prototype.handleCompleteAnimateOut = function(type, args, obj) { }; /** * Returns a string representation of the object. * @method toString * @return {String} The string representation of the ContainerEffect */ YAHOO.widget.ContainerEffect.prototype.toString = function() { var output = "ContainerEffect"; if (this.overlay) { output += " [" + this.overlay.toString() + "]"; } return output; }; /** * A pre-configured ContainerEffect instance that can be used for fading an overlay in and out. * @method FADE * @static * @param {Overlay} The Overlay object to animate * @param {Number} The duration of the animation * @return {ContainerEffect} The configured ContainerEffect object */ YAHOO.widget.ContainerEffect.FADE = function(overlay, dur) { var fade = new YAHOO.widget.ContainerEffect(overlay, { attributes:{opacity: {from:0, to:1}}, duration:dur, method:YAHOO.util.Easing.easeIn }, { attributes:{opacity: {to:0}}, duration:dur, method:YAHOO.util.Easing.easeOut}, overlay.element ); fade.handleStartAnimateIn = function(type,args,obj) { YAHOO.util.Dom.addClass(obj.overlay.element, "hide-select"); if (! obj.overlay.underlay) { obj.overlay.cfg.refireEvent("underlay"); } if (obj.overlay.underlay) { obj.initialUnderlayOpacity = YAHOO.util.Dom.getStyle(obj.overlay.underlay, "opacity"); obj.overlay.underlay.style.filter = null; } YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "visible"); YAHOO.util.Dom.setStyle(obj.overlay.element, "opacity", 0); }; fade.handleCompleteAnimateIn = function(type,args,obj) { YAHOO.util.Dom.removeClass(obj.overlay.element, "hide-select"); if (obj.overlay.element.style.filter) { obj.overlay.element.style.filter = null; } if (obj.overlay.underlay) { YAHOO.util.Dom.setStyle(obj.overlay.underlay, "opacity", obj.initialUnderlayOpacity); } obj.overlay.cfg.refireEvent("iframe"); obj.animateInCompleteEvent.fire(); }; fade.handleStartAnimateOut = function(type, args, obj) { YAHOO.util.Dom.addClass(obj.overlay.element, "hide-select"); if (obj.overlay.underlay) { obj.overlay.underlay.style.filter = null; } }; fade.handleCompleteAnimateOut = function(type, args, obj) { YAHOO.util.Dom.removeClass(obj.overlay.element, "hide-select"); if (obj.overlay.element.style.filter) { obj.overlay.element.style.filter = null; } YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "hidden"); YAHOO.util.Dom.setStyle(obj.overlay.element, "opacity", 1); obj.overlay.cfg.refireEvent("iframe"); obj.animateOutCompleteEvent.fire(); }; fade.init(); return fade; }; /** * A pre-configured ContainerEffect instance that can be used for sliding an overlay in and out. * @method SLIDE * @static * @param {Overlay} The Overlay object to animate * @param {Number} The duration of the animation * @return {ContainerEffect} The configured ContainerEffect object */ YAHOO.widget.ContainerEffect.SLIDE = function(overlay, dur) { var x = overlay.cfg.getProperty("x") || YAHOO.util.Dom.getX(overlay.element); var y = overlay.cfg.getProperty("y") || YAHOO.util.Dom.getY(overlay.element); var clientWidth = YAHOO.util.Dom.getClientWidth(); var offsetWidth = overlay.element.offsetWidth; var slide = new YAHOO.widget.ContainerEffect(overlay, { attributes:{ points: { to:[x, y] } }, duration:dur, method:YAHOO.util.Easing.easeIn }, { attributes:{ points: { to:[(clientWidth+25), y] } }, duration:dur, method:YAHOO.util.Easing.easeOut }, overlay.element, YAHOO.util.Motion); slide.handleStartAnimateIn = function(type,args,obj) { obj.overlay.element.style.left = (-25-offsetWidth) + "px"; obj.overlay.element.style.top = y + "px"; }; slide.handleTweenAnimateIn = function(type, args, obj) { var pos = YAHOO.util.Dom.getXY(obj.overlay.element); var currentX = pos[0]; var currentY = pos[1]; if (YAHOO.util.Dom.getStyle(obj.overlay.element, "visibility") == "hidden" && currentX < x) { YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "visible"); } obj.overlay.cfg.setProperty("xy", [currentX,currentY], true); obj.overlay.cfg.refireEvent("iframe"); }; slide.handleCompleteAnimateIn = function(type, args, obj) { obj.overlay.cfg.setProperty("xy", [x,y], true); obj.startX = x; obj.startY = y; obj.overlay.cfg.refireEvent("iframe"); obj.animateInCompleteEvent.fire(); }; slide.handleStartAnimateOut = function(type, args, obj) { var vw = YAHOO.util.Dom.getViewportWidth(); var pos = YAHOO.util.Dom.getXY(obj.overlay.element); var yso = pos[1]; var currentTo = obj.animOut.attributes.points.to; obj.animOut.attributes.points.to = [(vw+25), yso]; }; slide.handleTweenAnimateOut = function(type, args, obj) { var pos = YAHOO.util.Dom.getXY(obj.overlay.element); var xto = pos[0]; var yto = pos[1]; obj.overlay.cfg.setProperty("xy", [xto,yto], true); obj.overlay.cfg.refireEvent("iframe"); }; slide.handleCompleteAnimateOut = function(type, args, obj) { YAHOO.util.Dom.setStyle(obj.overlay.element, "visibility", "hidden"); obj.overlay.cfg.setProperty("xy", [x,y]); obj.animateOutCompleteEvent.fire(); }; slide.init(); return slide; }; /* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 0.12.0 */ /** * @description * The Connection Manager provides a simplified interface to the XMLHttpRequest * object. It handles cross-browser instantiantion of XMLHttpRequest, negotiates the * interactive states and server response, returning the results to a pre-defined * callback you create. * * @namespace YAHOO.util * @module Connection * @Class Connect */ YAHOO.util.Connect = { /** * @description Array of MSFT ActiveX ids for XMLHttpRequest. * @property _msxml_progid * @private * @static * @type array */ _msxml_progid:[ 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ], /** * @description Object literal of HTTP header(s) * @property _http_header * @private * @static * @type object */ _http_header:{}, /** * @description Determines if HTTP headers are set. * @property _has_http_headers * @private * @static * @type boolean */ _has_http_headers:false, /** * @description Determines if a default header of * Content-Type of 'application/x-www-form-urlencoded' * will be added to any client HTTP headers sent for POST * transactions. * @property _use_default_post_header * @private * @static * @type boolean */ _use_default_post_header:true, /** * @description Determines if a default header of * Content-Type of 'application/x-www-form-urlencoded' * will be added to any client HTTP headers sent for POST * transactions. * @property _default_post_header * @private * @static * @type boolean */ _default_post_header:'application/x-www-form-urlencoded', /** * @description Property modified by setForm() to determine if the data * should be submitted as an HTML form. * @property _isFormSubmit * @private * @static * @type boolean */ _isFormSubmit:false, /** * @description Property modified by setForm() to determine if a file(s) * upload is expected. * @property _isFileUpload * @private * @static * @type boolean */ _isFileUpload:false, /** * @description Property modified by setForm() to set a reference to the HTML * form node if the desired action is file upload. * @property _formNode * @private * @static * @type object */ _formNode:null, /** * @description Property modified by setForm() to set the HTML form data * for each transaction. * @property _sFormData * @private * @static * @type string */ _sFormData:null, /** * @description Collection of polling references to the polling mechanism in handleReadyState. * @property _poll * @private * @static * @type object */ _poll:{}, /** * @description Queue of timeout values for each transaction callback with a defined timeout value. * @property _timeOut * @private * @static * @type object */ _timeOut:{}, /** * @description The polling frequency, in milliseconds, for HandleReadyState. * when attempting to determine a transaction's XHR readyState. * The default is 50 milliseconds. * @property _polling_interval * @private * @static * @type int */ _polling_interval:50, /** * @description A transaction counter that increments the transaction id for each transaction. * @property _transaction_id * @private * @static * @type int */ _transaction_id:0, /** * @description Member to add an ActiveX id to the existing xml_progid array. * In the event(unlikely) a new ActiveX id is introduced, it can be added * without internal code modifications. * @method setProgId * @public * @static * @param {string} id The ActiveX id to be added to initialize the XHR object. * @return void */ setProgId:function(id) { this._msxml_progid.unshift(id); }, /** * @description Member to enable or disable the default POST header. * @method setDefaultPostHeader * @public * @static * @param {boolean} b Set and use default header - true or false . * @return void */ setDefaultPostHeader:function(b) { this._use_default_post_header = b; }, /** * @description Member to modify the default polling interval. * @method setPollingInterval * @public * @static * @param {int} i The polling interval in milliseconds. * @return void */ setPollingInterval:function(i) { if(typeof i == 'number' && isFinite(i)){ this._polling_interval = i; } }, /** * @description Instantiates a XMLHttpRequest object and returns an object with two properties: * the XMLHttpRequest instance and the transaction id. * @method createXhrObject * @private * @static * @param {int} transactionId Property containing the transaction id for this transaction. * @return object */ createXhrObject:function(transactionId) { var obj,http; try { // Instantiates XMLHttpRequest in non-IE browsers and assigns to http. http = new XMLHttpRequest(); // Object literal with http and tId properties obj = { conn:http, tId:transactionId }; } catch(e) { for(var i=0; i = 200 && httpStatus < 300){ try { responseObject = this.createResponseObject(o, callback.argument); if(callback.success){ if(!callback.scope){ callback.success(responseObject); } else{ // If a scope property is defined, the callback will be fired from // the context of the object. callback.success.apply(callback.scope, [responseObject]); } } } catch(e){} } else{ try { switch(httpStatus){ // The following cases are wininet.dll error codes that may be encountered. case 12002: // Server timeout case 12029: // 12029 to 12031 correspond to dropped connections. case 12030: case 12031: case 12152: // Connection closed by server. case 13030: // See above comments for variable status. responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort?isAbort:false)); if(callback.failure){ if(!callback.scope){ callback.failure(responseObject); } else{ callback.failure.apply(callback.scope, [responseObject]); } } break; default: responseObject = this.createResponseObject(o, callback.argument); if(callback.failure){ if(!callback.scope){ callback.failure(responseObject); } else{ callback.failure.apply(callback.scope, [responseObject]); } } } } catch(e){} } this.releaseObject(o); responseObject = null; }, /** * @description This method evaluates the server response, creates and returns the results via * its properties. Success and failure cases will differ in the response * object's property values. * @method createResponseObject * @private * @static * @param {object} o The connection object * @param {callbackArg} callbackArg The user-defined argument or arguments to be passed to the callback * @return {object} */ createResponseObject:function(o, callbackArg) { var obj = {}; var headerObj = {}; try { var headerStr = o.conn.getAllResponseHeaders(); var header = headerStr.split('\n'); for(var i=0; i '); // IE will throw a security exception in an SSL environment if the // iframe source is undefined. if(typeof secureUri == 'boolean'){ io.src = 'javascript:false'; } else if(typeof secureURI == 'string'){ // Deprecated io.src = secureUri; } } else{ var io = document.createElement('iframe'); io.id = frameId; io.name = frameId; } io.style.position = 'absolute'; io.style.top = '-1000px'; io.style.left = '-1000px'; document.body.appendChild(io); }, /** * @description Parses the POST data and creates hidden form elements * for each key-value, and appends them to the HTML form object. * @method appendPostData * @private * @static * @param {string} postData The HTTP POST data * @return {array} formElements Collection of hidden fields. */ appendPostData:function(postData) { var formElements = new Array(); var postMessage = postData.split('&'); for(var i=0; i < postMessage.length; i++){ var delimitPos = postMessage[i].indexOf('='); if(delimitPos != -1){ formElements[i] = document.createElement('input'); formElements[i].type = 'hidden'; formElements[i].name = postMessage[i].substring(0,delimitPos); formElements[i].value = postMessage[i].substring(delimitPos+1); this._formNode.appendChild(formElements[i]); } } return formElements; }, /** * @description Uploads HTML form, including files/attachments, to the * iframe created in createFrame. * @method uploadFile * @private * @static * @param {int} id The transaction id. * @param {object} callback - User-defined callback object. * @param {string} uri Fully qualified path of resource. * @return {void} */ uploadFile:function(id, callback, uri, postData){ // Each iframe has an id prefix of "yuiIO" followed // by the unique transaction id. var frameId = 'yuiIO' + id; var io = document.getElementById(frameId); // Initialize the HTML form properties in case they are // not defined in the HTML form. this._formNode.action = uri; this._formNode.method = 'POST'; this._formNode.target = frameId; if(this._formNode.encoding){ // IE does not respect property enctype for HTML forms. // Instead use property encoding. this._formNode.encoding = 'multipart/form-data'; } else{ this._formNode.enctype = 'multipart/form-data'; } if(postData){ var oElements = this.appendPostData(postData); } this._formNode.submit(); if(oElements && oElements.length > 0){ try { for(var i=0; i < oElements.length; i++){ this._formNode.removeChild(oElements[i]); } } catch(e){} } // Reset HTML form status properties. this.resetFormState(); // Create the upload callback handler that fires when the iframe // receives the load event. Subsequently, the event handler is detached // and the iframe removed from the document. var uploadCallback = function() { var obj = {}; obj.tId = id; obj.argument = callback.argument; try { obj.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null; obj.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document; } catch(e){} if(callback.upload){ if(!callback.scope){ callback.upload(obj); } else{ callback.upload.apply(callback.scope, [obj]); } } if(YAHOO.util.Event){ YAHOO.util.Event.removeListener(io, "load", uploadCallback); } else if(window.detachEvent){ io.detachEvent('onload', uploadCallback); } else{ io.removeEventListener('load', uploadCallback, false); } setTimeout(function(){ document.body.removeChild(io); }, 100); }; // Bind the onload handler to the iframe to detect the file upload response. if(YAHOO.util.Event){ YAHOO.util.Event.addListener(io, "load", uploadCallback); } else if(window.attachEvent){ io.attachEvent('onload', uploadCallback); } else{ io.addEventListener('load', uploadCallback, false); } }, /** * @description Method to terminate a transaction, if it has not reached readyState 4. * @method abort * @public * @static * @param {object} o The connection object returned by asyncRequest. * @param {object} callback User-defined callback object. * @param {string} isTimeout boolean to indicate if abort was a timeout. * @return {boolean} */ abort:function(o, callback, isTimeout) { if(this.isCallInProgress(o)){ o.conn.abort(); window.clearInterval(this._poll[o.tId]); delete this._poll[o.tId]; if(isTimeout){ delete this._timeOut[o.tId]; } this.handleTransactionResponse(o, callback, true); return true; } else{ return false; } }, /** * Public method to check if the transaction is still being processed. * * @method isCallInProgress * @public * @static * @param {object} o The connection object returned by asyncRequest * @return {boolean} */ isCallInProgress:function(o) { // if the XHR object assigned to the transaction has not been dereferenced, // then check its readyState status. Otherwise, return false. if(o.conn){ return o.conn.readyState != 4 && o.conn.readyState != 0; } else{ //The XHR object has been destroyed. return false; } }, /** * @description Dereference the XHR instance and the connection object after the transaction is completed. * @method releaseObject * @private * @static * @param {object} o The connection object * @return {void} */ releaseObject:function(o) { //dereference the XHR instance. o.conn = null; //dereference the connection object. o = null; } }; /* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 0.12.0 */ (function() { YAHOO.util.Lang = { isArray: function(val) { // frames lose type, so test constructor string if (val.constructor && val.constructor.toString().indexOf('Array') > -1) { return true; } else { return YAHOO.util.Lang.isObject(val) && val.constructor == Array; } }, isBoolean: function(val) { return typeof val == 'boolean'; }, isFunction: function(val) { return typeof val == 'function'; }, isNull: function(val) { return val === null; }, isNumber: function(val) { return !isNaN(val); }, isObject: function(val) { return typeof val == 'object' || YAHOO.util.Lang.isFunction(val); }, isString: function(val) { return typeof val == 'string'; }, isUndefined: function(val) { return typeof val == 'undefined'; } }; })();/** * Provides Attribute configurations. * @namespace YAHOO.util * @class Attribute * @constructor * @param hash {Object} The intial Attribute. * @param {YAHOO.util.AttributeProvider} The owner of the Attribute instance. */ YAHOO.util.Attribute = function(hash, owner) { if (owner) { this.owner = owner; this.configure(hash, true); } }; YAHOO.util.Attribute.prototype = { /** * The name of the attribute. * @property name * @type String */ name: undefined, /** * The value of the attribute. * @property value * @type String */ value: null, /** * The owner of the attribute. * @property owner * @type YAHOO.util.AttributeProvider */ owner: null, /** * Whether or not the attribute is read only. * @property readOnly * @type Boolean */ readOnly: false, /** * Whether or not the attribute can only be written once. * @property writeOnce * @type Boolean */ writeOnce: false, /** * The attribute's initial configuration. * @private * @property _initialConfig * @type Object */ _initialConfig: null, /** * Whether or not the attribute's value has been set. * @private * @property _written * @type Boolean */ _written: false, /** * The method to use when setting the attribute's value. * The method recieves the new value as the only argument. * @property method * @type Function */ method: null, /** * The validator to use when setting the attribute's value. * @property validator * @type Function * @return Boolean */ validator: null, /** * Retrieves the current value of the attribute. * @method getValue * @return {any} The current value of the attribute. */ getValue: function() { return this.value; }, /** * Sets the value of the attribute and fires beforeChange and change events. * @method setValue * @param {Any} value The value to apply to the attribute. * @param {Boolean} silent If true the change events will not be fired. * @return {Boolean} Whether or not the value was set. */ setValue: function(value, silent) { var beforeRetVal; var owner = this.owner; var name = this.name; var event = { type: name, prevValue: this.getValue(), newValue: value }; if (this.readOnly || ( this.writeOnce && this._written) ) { return false; // write not allowed } if (this.validator && !this.validator.call(owner, value) ) { return false; // invalid value } if (!silent) { beforeRetVal = owner.fireBeforeChangeEvent(event); if (beforeRetVal === false) { YAHOO.log('setValue ' + name + 'cancelled by beforeChange event', 'info', 'Attribute'); return false; } } if (this.method) { this.method.call(owner, value); } this.value = value; this._written = true; event.type = name; if (!silent) { this.owner.fireChangeEvent(event); } return true; }, /** * Allows for configuring the Attribute's properties. * @method configure * @param {Object} map A key-value map of Attribute properties. * @param {Boolean} init Whether or not this should become the initial config. */ configure: function(map, init) { map = map || {}; this._written = false; // reset writeOnce this._initialConfig = this._initialConfig || {}; for (var key in map) { if ( key && map.hasOwnProperty(key) ) { this[key] = map[key]; if (init) { this._initialConfig[key] = map[key]; } } } }, /** * Resets the value to the initial config value. * @method resetValue * @return {Boolean} Whether or not the value was set. */ resetValue: function() { return this.setValue(this._initialConfig.value); }, /** * Resets the attribute config to the initial config state. * @method resetConfig */ resetConfig: function() { this.configure(this._initialConfig); }, /** * Resets the value to the current value. * Useful when values may have gotten out of sync with actual properties. * @method refresh * @return {Boolean} Whether or not the value was set. */ refresh: function(silent) { this.setValue(this.value, silent); } };(function() { var Lang = YAHOO.util.Lang; /* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt */ /** * Provides and manages YAHOO.util.Attribute instances * @namespace YAHOO.util * @class AttributeProvider * @uses YAHOO.util.EventProvider */ YAHOO.util.AttributeProvider = function() {}; YAHOO.util.AttributeProvider.prototype = { /** * A key-value map of Attribute configurations * @property _configs * @protected (may be used by subclasses and augmentors) * @private * @type {Object} */ _configs: null, /** * Returns the current value of the attribute. * @method get * @param {String} key The attribute whose value will be returned. */ get: function(key){ var configs = this._configs || {}; var config = configs[key]; if (!config) { YAHOO.log(key + ' not found', 'error', 'AttributeProvider'); return undefined; } return config.value; }, /** * Sets the value of a config. * @method set * @param {String} key The name of the attribute * @param {Any} value The value to apply to the attribute * @param {Boolean} silent Whether or not to suppress change events * @return {Boolean} Whether or not the value was set. */ set: function(key, value, silent){ var configs = this._configs || {}; var config = configs[key]; if (!config) { YAHOO.log('set failed: ' + key + ' not found', 'error', 'AttributeProvider'); return false; } return config.setValue(value, silent); }, /** * Returns an array of attribute names. * @method getAttributeKeys * @return {Array} An array of attribute names. */ getAttributeKeys: function(){ var configs = this._configs; var keys = []; var config; for (var key in configs) { config = configs[key]; if ( configs.hasOwnProperty(key) && !Lang.isUndefined(config) ) { keys[keys.length] = key; } } return keys; }, /** * Sets multiple attribute values. * @method setAttributes * @param {Object} map A key-value map of attributes * @param {Boolean} silent Whether or not to suppress change events */ setAttributes: function(map, silent){ for (var key in map) { if ( map.hasOwnProperty(key) ) { this.set(key, map[key], silent); } } }, /** * Resets the specified attribute's value to its initial value. * @method resetValue * @param {String} key The name of the attribute * @param {Boolean} silent Whether or not to suppress change events * @return {Boolean} Whether or not the value was set */ resetValue: function(key, silent){ var configs = this._configs || {}; if (configs[key]) { this.set(key, configs[key]._initialConfig.value, silent); return true; } return false; }, /** * Sets the attribute's value to its current value. * @method refresh * @param {String | Array} key The attribute(s) to refresh * @param {Boolean} silent Whether or not to suppress change events */ refresh: function(key, silent){ var configs = this._configs; key = ( ( Lang.isString(key) ) ? [key] : key ) || this.getAttributeKeys(); for (var i = 0, len = key.length; i < len; ++i) { if ( // only set if there is a value and not null configs[key[i]] && ! Lang.isUndefined(configs[key[i]].value) && ! Lang.isNull(configs[key[i]].value) ) { configs[key[i]].refresh(silent); } } }, /** * Adds an Attribute to the AttributeProvider instance. * @method register * @param {String} key The attribute's name * @param {Object} map A key-value map containing the * attribute's properties. */ register: function(key, map) { this._configs = this._configs || {}; if (this._configs[key]) { // dont override return false; } map.name = key; this._configs[key] = new YAHOO.util.Attribute(map, this); return true; }, /** * Returns the attribute's properties. * @method getAttributeConfig * @param {String} key The attribute's name * @private * @return {object} A key-value map containing all of the * attribute's properties. */ getAttributeConfig: function(key) { var configs = this._configs || {}; var config = configs[key] || {}; var map = {}; // returning a copy to prevent overrides for (key in config) { if ( config.hasOwnProperty(key) ) { map[key] = config[key]; } } return map; }, /** * Sets or updates an Attribute instance's properties. * @method configureAttribute * @param {String} key The attribute's name. * @param {Object} map A key-value map of attribute properties * @param {Boolean} init Whether or not this should become the intial config. */ configureAttribute: function(key, map, init) { var configs = this._configs || {}; if (!configs[key]) { YAHOO.log('unable to configure, ' + key + ' not found', 'error', 'AttributeProvider'); return false; } configs[key].configure(map, init); }, /** * Resets an attribute to its intial configuration. * @method resetAttributeConfig * @param {String} key The attribute's name. * @private */ resetAttributeConfig: function(key){ var configs = this._configs || {}; configs[key].resetConfig(); }, /** * Fires the attribute's beforeChange event. * @method fireBeforeChangeEvent * @param {String} key The attribute's name. * @param {Obj} e The event object to pass to handlers. */ fireBeforeChangeEvent: function(e) { var type = 'before'; type += e.type.charAt(0).toUpperCase() + e.type.substr(1) + 'Change'; e.type = type; return this.fireEvent(e.type, e); }, /** * Fires the attribute's change event. * @method fireChangeEvent * @param {String} key The attribute's name. * @param {Obj} e The event object to pass to the handlers. */ fireChangeEvent: function(e) { e.type += 'Change'; return this.fireEvent(e.type, e); } }; YAHOO.augment(YAHOO.util.AttributeProvider, YAHOO.util.EventProvider); })();(function() { // internal shorthand var Dom = YAHOO.util.Dom, Lang = YAHOO.util.Lang, EventPublisher = YAHOO.util.EventPublisher, AttributeProvider = YAHOO.util.AttributeProvider; /** * Element provides an interface to an HTMLElement's attributes and common * methods. Other commonly used attributes are added as well. * @namespace YAHOO.util * @class Element * @uses YAHOO.util.AttributeProvider * @constructor * @param el {HTMLElement | String} The html element that * represents the Element. * @param {Object} map A key-value map of initial config names and values */ YAHOO.util.Element = function(el, map) { if (arguments.length) { this.init(el, map); } }; YAHOO.util.Element.prototype = { /** * Dom events supported by the Element instance. * @property DOM_EVENTS * @type Object */ DOM_EVENTS: null, /** * Wrapper for HTMLElement method. * @method appendChild * @param {Boolean} deep Whether or not to do a deep clone */ appendChild: function(child) { child = child.get ? child.get('element') : child; this.get('element').appendChild(child); }, /** * Wrapper for HTMLElement method. * @method getElementsByTagName * @param {String} tag The tagName to collect */ getElementsByTagName: function(tag) { return this.get('element').getElementsByTagName(tag); }, /** * Wrapper for HTMLElement method. * @method hasChildNodes * @return {Boolean} Whether or not the element has childNodes */ hasChildNodes: function() { return this.get('element').hasChildNodes(); }, /** * Wrapper for HTMLElement method. * @method insertBefore * @param {HTMLElement} element The HTMLElement to insert * @param {HTMLElement} before The HTMLElement to insert * the element before. */ insertBefore: function(element, before) { element = element.get ? element.get('element') : element; before = (before && before.get) ? before.get('element') : before; this.get('element').insertBefore(element, before); }, /** * Wrapper for HTMLElement method. * @method removeChild * @param {HTMLElement} child The HTMLElement to remove */ removeChild: function(child) { child = child.get ? child.get('element') : child; this.get('element').removeChild(child); return true; }, /** * Wrapper for HTMLElement method. * @method replaceChild * @param {HTMLElement} newNode The HTMLElement to insert * @param {HTMLElement} oldNode The HTMLElement to replace */ replaceChild: function(newNode, oldNode) { newNode = newNode.get ? newNode.get('element') : newNode; oldNode = oldNode.get ? oldNode.get('element') : oldNode; return this.get('element').replaceChild(newNode, oldNode); }, /** * Registers Element specific attributes. * @method initAttributes * @param {Object} map A key-value map of initial attribute configs */ initAttributes: function(map) { map = map || {}; var element = Dom.get(map.element) || null; /** * The HTMLElement the Element instance refers to. * @config element * @type HTMLElement */ this.register('element', { value: element, readOnly: true }); }, /** * Adds a listener for the given event. These may be DOM or * customEvent listeners. Any event that is fired via fireEvent * can be listened for. All handlers receive an event object. * @method addListener * @param {String} type The name of the event to listen for * @param {Function} fn The handler to call when the event fires * @param {Any} obj A variable to pass to the handler * @param {Object} scope The object to use for the scope of the handler */ addListener: function(type, fn, obj, scope) { var el = this.get('element'); var scope = scope || this; el = this.get('id') || el; if (!this._events[type]) { // create on the fly if ( this.DOM_EVENTS[type] ) { YAHOO.util.Event.addListener(el, type, function(e) { if (e.srcElement && !e.target) { // supplement IE with target e.target = e.srcElement; } this.fireEvent(type, e); }, obj, scope); } this.createEvent(type, this); this._events[type] = true; } this.subscribe.apply(this, arguments); // notify via customEvent }, /** * Alias for addListener * @method on * @param {String} type The name of the event to listen for * @param {Function} fn The function call when the event fires * @param {Any} obj A variable to pass to the handler * @param {Object} scope The object to use for the scope of the handler */ on: function() { this.addListener.apply(this, arguments); }, /** * Remove an event listener * @method removeListener * @param {String} type The name of the event to listen for * @param {Function} fn The function call when the event fires */ removeListener: function(type, fn) { this.unsubscribe.apply(this, arguments); }, /** * Wrapper for Dom method. * @method addClass * @param {String} className The className to add */ addClass: function(className) { Dom.addClass(this.get('element'), className); }, /** * Wrapper for Dom method. * @method getElementsByClassName * @param {String} className The className to collect * @param {String} tag (optional) The tag to use in * conjunction with class name * @return {Array} Array of HTMLElements */ getElementsByClassName: function(className, tag) { return Dom.getElementsByClassName(className, tag, this.get('element') ); }, /** * Wrapper for Dom method. * @method hasClass * @param {String} className The className to add * @return {Boolean} Whether or not the element has the class name */ hasClass: function(className) { return Dom.hasClass(this.get('element'), className); }, /** * Wrapper for Dom method. * @method removeClass * @param {String} className The className to remove */ removeClass: function(className) { return Dom.removeClass(this.get('element'), className); }, /** * Wrapper for Dom method. * @method replaceClass * @param {String} oldClassName The className to replace * @param {String} newClassName The className to add */ replaceClass: function(oldClassName, newClassName) { return Dom.replaceClass(this.get('element'), oldClassName, newClassName); }, /** * Wrapper for Dom method. * @method setStyle * @param {String} property The style property to set * @param {String} value The value to apply to the style property */ setStyle: function(property, value) { return Dom.setStyle(this.get('element'), property, value); }, /** * Wrapper for Dom method. * @method getStyle * @param {String} property The style property to retrieve * @return {String} The current value of the property */ getStyle: function(property) { return Dom.getStyle(this.get('element'), property); }, /** * Apply any queued set calls. * @method fireQueue */ fireQueue: function() { var queue = this._queue; for (var i = 0, len = queue.length; i < len; ++i) { this[queue[i][0]].apply(this, queue[i][1]); } }, /** * Appends the HTMLElement into either the supplied parentNode. * @method appendTo * @param {HTMLElement | Element} parentNode The node to append to * @param {HTMLElement | Element} before An optional node to insert before */ appendTo: function(parent, before) { parent = (parent.get) ? parent.get('element') : Dom.get(parent); before = (before && before.get) ? before.get('element') : Dom.get(before); var element = this.get('element'); var newAddition = !Dom.inDocument(element); if (!element) { YAHOO.log('appendTo failed: element not available', 'error', 'Element'); return false; } if (!parent) { YAHOO.log('appendTo failed: parent not available', 'error', 'Element'); return false; } if (element.parent != parent) { if (before) { parent.insertBefore(element, before); } else { parent.appendChild(element); } } YAHOO.log(element + 'appended to ' + parent); if (!newAddition) { return false; // note return; no refresh if in document } // if a new addition, refresh HTMLElement any applied attributes var keys = this.getAttributeKeys(); for (var key in keys) { // only refresh HTMLElement attributes if ( !Lang.isUndefined(element[key]) ) { this.refresh(key); } } }, get: function(key) { var configs = this._configs || {}; var el = configs.element; // avoid loop due to 'element' if (el && !configs[key] && !Lang.isUndefined(el.value[key]) ) { return el.value[key]; } return AttributeProvider.prototype.get.call(this, key); }, set: function(key, value, silent) { var el = this.get('element'); if (!el) { this._queue[key] = ['set', arguments]; return false; } // set it on the element if not a property if ( !this._configs[key] && !Lang.isUndefined(el[key]) ) { _registerHTMLAttr(this, key); } return AttributeProvider.prototype.set.apply(this, arguments); }, register: function(key) { // protect html attributes var configs = this._configs || {}; var element = this.get('element') || null; if ( element && !Lang.isUndefined(element[key]) ) { YAHOO.log(key + ' is reserved for ' + element, 'error', 'Element'); return false; } return AttributeProvider.prototype.register.apply(this, arguments); }, configureAttribute: function(property, map, init) { // protect html attributes if (!this._configs[property] && this._configs.element && !Lang.isUndefined(this._configs.element[property]) ) { _registerHTMLAttr(this, property, map); return false; } return AttributeProvider.prototype.configure.apply(this, arguments); }, getAttributeKeys: function() { var el = this.get('element'); var keys = AttributeProvider.prototype.getAttributeKeys.call(this); //add any unconfigured element keys for (var key in el) { if (!this._configs[key]) { keys[key] = keys[key] || el[key]; } } return keys; }, init: function(el, attr) { this._queue = this._queue || []; this._events = this._events || {}; this._configs = this._configs || {}; attr = attr || {}; attr.element = attr.element || el || null; this.DOM_EVENTS = { 'click': true, 'keydown': true, 'keypress': true, 'keyup': true, 'mousedown': true, 'mousemove': true, 'mouseout': true, 'mouseover': true, 'mouseup': true }; var readyHandler = function() { this.initAttributes(attr); this.setAttributes(attr, true); this.fireQueue(); this.fireEvent('contentReady', { type: 'contentReady', target: attr.element }); }; if ( Lang.isString(el) ) { _registerHTMLAttr(this, 'id', { value: el }); YAHOO.util.Event.onAvailable(el, function() { attr.element = Dom.get(el); this.fireEvent('available', { type: 'available', target: attr.element }); }, this, true); YAHOO.util.Event.onContentReady(el, function() { readyHandler.call(this); }, this, true); } else { readyHandler.call(this); } } }; /** * Sets the value of the property and fires beforeChange and change events. * @private * @method _registerHTMLAttr * @param {YAHOO.util.Element} element The Element instance to * register the config to. * @param {String} key The name of the config to register * @param {Object} map A key-value map of the config's params */ var _registerHTMLAttr = function(self, key, map) { var el = self.get('element'); map = map || {}; map.name = key; map.method = map.method || function(value) { el[key] = value; }; map.value = map.value || el[key]; self._configs[key] = new YAHOO.util.Attribute(map, self); }; /** * Fires when the Element's HTMLElement can be retrieved by Id. * See: Element.addListener
*Event fields:
*<String> type
available
*<HTMLElement> * target
the HTMLElement bound to this Element instance
*Usage:
* @event available */ /** * Fires when the Element's HTMLElement subtree is rendered. *
*var handler = function(e) {var target = e.target};
* myTabs.addListener('available', handler);See: Element.addListener
*Event fields:
*<String> type
contentReady
*<HTMLElement> * target
the HTMLElement bound to this Element instance
*Usage:
* @event contentReady */ YAHOO.augment(YAHOO.util.Element, AttributeProvider); })();(function() { var Dom = YAHOO.util.Dom, Event = YAHOO.util.Event, Lang = YAHOO.util.Lang; /** * A representation of a Tab's label and content. * @namespace YAHOO.widget * @class Tab * @extends YAHOO.util.Element * @constructor * @param element {HTMLElement | String} (optional) The html element that * represents the TabView. An element will be created if none provided. * @param {Object} properties A key map of initial properties */ Tab = function(el, attr) { attr = attr || {}; if (arguments.length == 1 && !Lang.isString(el) && !el.nodeName) { attr = el; el = attr.element; } if (!el && !attr.element) { el = _createTabElement.call(this, attr); } this.loadHandler = { success: function(o) { this.set('content', o.responseText); }, failure: function(o) { YAHOO.log('loading failed: ' + o.statusText, 'error', 'Tab'); } }; Tab.superclass.constructor.call(this, el, attr); this.DOM_EVENTS = {}; // delegating to tabView }; YAHOO.extend(Tab, YAHOO.util.Element); var proto = Tab.prototype; /** * The default tag name for a Tab's inner element. * @property LABEL_INNER_TAGNAME * @type String * @default "em" */ proto.LABEL_TAGNAME = 'em'; /** * The class name applied to active tabs. * @property ACTIVE_CLASSNAME * @type String * @default "on" */ proto.ACTIVE_CLASSNAME = 'selected'; /** * The class name applied to disabled tabs. * @property DISABLED_CLASSNAME * @type String * @default "disabled" */ proto.DISABLED_CLASSNAME = 'disabled'; /** * The class name applied to dynamic tabs while loading. * @property LOADING_CLASSNAME * @type String * @default "disabled" */ proto.LOADING_CLASSNAME = 'loading'; /** * Provides a reference to the connection request object when data is * loaded dynamically. * @property dataConnection * @type Object */ proto.dataConnection = null; /** * Object containing success and failure callbacks for loading data. * @property loadHandler * @type object */ proto.loadHandler = null; /** * Provides a readable name for the tab. * @method toString * @return String */ proto.toString = function() { var el = this.get('element'); var id = el.id || el.tagName; return "Tab " + id; }; /** * Registers TabView specific properties. * @method initAttributes * @param {Object} attr Hash of initial attributes */ proto.initAttributes = function(attr) { attr = attr || {}; Tab.superclass.initAttributes.call(this, attr); var el = this.get('element'); /** * The event that triggers the tab's activation. * @config activationEvent * @type String */ this.register('activationEvent', { value: attr.activationEvent || 'click' }); /** * The element that contains the tab's label. * @config labelEl * @type HTMLElement */ this.register('labelEl', { value: attr.labelEl || _getlabelEl.call(this), method: function(value) { var current = this.get('labelEl'); if (current) { if (current == value) { return false; // already set } this.replaceChild(value, current); } else if (el.firstChild) { // ensure label is firstChild by default this.insertBefore(value, el.firstChild); } else { this.appendChild(value); } } }); /** * The tab's label text (or innerHTML). * @config label * @type String */ this.register('label', { value: attr.label || _getLabel.call(this), method: function(value) { var labelEl = this.get('labelEl'); if (!labelEl) { // create if needed this.set('labelEl', _createlabelEl.call(this)); } _setLabel.call(this, value); } }); /** * The HTMLElement that contains the tab's content. * @config contentEl * @type HTMLElement */ this.register('contentEl', { // TODO: apply className? value: attr.contentEl || document.createElement('div'), method: function(value) { var current = this.get('contentEl'); if (current) { if (current == value) { return false; // already set } this.replaceChild(value, current); } } }); /** * The tab's content. * @config content * @type String */ this.register('content', { value: attr.content, // TODO: what about existing? method: function(value) { this.get('contentEl').innerHTML = value; } }); var _dataLoaded = false; /** * The tab's data source, used for loading content dynamically. * @config dataSrc * @type String */ this.register('dataSrc', { value: attr.dataSrc }); /** * Whether or not content should be reloaded for every view. * @config cacheData * @type Boolean * @default false */ this.register('cacheData', { value: attr.cacheData || false, validator: Lang.isBoolean }); /** * The method to use for the data request. * @config loadMethod * @type String * @default "GET" */ this.register('loadMethod', { value: attr.loadMethod || 'GET', validator: Lang.isString }); /** * Whether or not any data has been loaded from the server. * @config dataLoaded * @type Boolean */ this.register('dataLoaded', { value: false, validator: Lang.isBoolean, writeOnce: true }); /** * Number if milliseconds before aborting and calling failure handler. * @config dataTimeout * @type Number * @default null */ this.register('dataTimeout', { value: attr.dataTimeout || null, validator: Lang.isNumber }); /** * Whether or not the tab is currently active. * If a dataSrc is set for the tab, the content will be loaded from * the given source. * @config active * @type Boolean */ this.register('active', { value: attr.active || this.hasClass(this.ACTIVE_CLASSNAME), method: function(value) { if (value === true) { this.addClass(this.ACTIVE_CLASSNAME); this.set('title', 'active'); } else { this.removeClass(this.ACTIVE_CLASSNAME); this.set('title', ''); } }, validator: function(value) { return Lang.isBoolean(value) && !this.get('disabled') ; } }); /** * Whether or not the tab is disabled. * @config disabled * @type Boolean */ this.register('disabled', { value: attr.disabled || this.hasClass(this.DISABLED_CLASSNAME), method: function(value) { if (value === true) { Dom.addClass(this.get('element'), this.DISABLED_CLASSNAME); } else { Dom.removeClass(this.get('element'), this.DISABLED_CLASSNAME); } }, validator: Lang.isBoolean }); /** * The href of the tab's anchor element. * @config href * @type String * @default '#' */ this.register('href', { value: attr.href || '#', method: function(value) { this.getElementsByTagName('a')[0].href = value; }, validator: Lang.isString }); /** * The Whether or not the tab's content is visible. * @config contentVisible * @type Boolean * @default false */ this.register('contentVisible', { value: attr.contentVisible, method: function(value) { if (value == true) { this.get('contentEl').style.display = 'block'; if ( this.get('dataSrc') ) { // load dynamic content unless already loaded and caching if ( !this.get('dataLoaded') || !this.get('cacheData') ) { _dataConnect.call(this); } } } else { this.get('contentEl').style.display = 'none'; } }, validator: Lang.isBoolean }); }; var _createTabElement = function(attr) { var el = document.createElement('li'); var a = document.createElement('a'); a.href = attr.href || '#'; el.appendChild(a); var label = attr.label || null; var labelEl = attr.labelEl || null; if (labelEl) { // user supplied labelEl if (!label) { // user supplied label label = _getLabel.call(this, labelEl); } } else { labelEl = _createlabelEl.call(this); } a.appendChild(labelEl); return el; }; var _getlabelEl = function() { return this.getElementsByTagName(this.LABEL_TAGNAME)[0]; }; var _createlabelEl = function() { var el = document.createElement(this.LABEL_TAGNAME); return el; }; var _setLabel = function(label) { var el = this.get('labelEl'); el.innerHTML = label; }; var _getLabel = function() { var label, el = this.get('labelEl'); if (!el) { return undefined; } return el.innerHTML; }; var _dataConnect = function() { if (!YAHOO.util.Connect) { YAHOO.log('YAHOO.util.Connect dependency not met', 'error', 'Tab'); return false; } Dom.addClass(this.get('contentEl').parentNode, this.LOADING_CLASSNAME); this.dataConnection = YAHOO.util.Connect.asyncRequest( this.get('loadMethod'), this.get('dataSrc'), { success: function(o) { this.loadHandler.success.call(this, o); this.set('dataLoaded', true); this.dataConnection = null; Dom.removeClass(this.get('contentEl').parentNode, this.LOADING_CLASSNAME); }, failure: function(o) { this.loadHandler.failure.call(this, o); this.dataConnection = null; Dom.removeClass(this.get('contentEl').parentNode, this.LOADING_CLASSNAME); }, scope: this, timeout: this.get('dataTimeout') } ); }; YAHOO.widget.Tab = Tab; /** * Fires before the active state is changed. *
*var handler = function(e) {var target = e.target};
* myTabs.addListener('contentReady', handler);See: Element.addListener
*If handler returns false, the change will be cancelled, and the value will not * be set.
*Event fields:
*
*<String> type
beforeActiveChange
*<Boolean> * prevValue
the current value
*<Boolean> * newValue
the new valueUsage:
* @event beforeActiveChange */ /** * Fires after the active state is changed. *
*var handler = function(e) {var previous = e.prevValue};
* myTabs.addListener('beforeActiveChange', handler);See: Element.addListener
*Event fields:
*
*<String> type
activeChange
*<Boolean> * prevValue
the previous value
*<Boolean> * newValue
the updated valueUsage:
* @event activeChange */ /** * Fires before the tab label is changed. *
*var handler = function(e) {var previous = e.prevValue};
* myTabs.addListener('activeChange', handler);See: Element.addListener
*If handler returns false, the change will be cancelled, and the value will not * be set.
*Event fields:
*
*<String> type
beforeLabelChange
*<String> * prevValue
the current value
*<String> * newValue
the new valueUsage:
* @event beforeLabelChange */ /** * Fires after the tab label is changed. *
*var handler = function(e) {var previous = e.prevValue};
* myTabs.addListener('beforeLabelChange', handler);See: Element.addListener
*Event fields:
*
*<String> type
labelChange
*<String> * prevValue
the previous value
*<String> * newValue
the updated valueUsage:
* @event labelChange */ /** * Fires before the tab content is changed. *
*var handler = function(e) {var previous = e.prevValue};
* myTabs.addListener('labelChange', handler);See: Element.addListener
*If handler returns false, the change will be cancelled, and the value will not * be set.
*Event fields:
*
*<String> type
beforeContentChange
*<String> * prevValue
the current value
*<String> * newValue
the new valueUsage:
* @event beforeContentChange */ /** * Fires after the tab content is changed. *
*var handler = function(e) {var previous = e.prevValue};
* myTabs.addListener('beforeContentChange', handler);See: Element.addListener
*Event fields:
*
*<String> type
contentChange
*<String> * prevValue
the previous value
*<Boolean> * newValue
the updated valueUsage:
* @event contentChange */ })();(function() { /** * The tabview module provides a widget for managing content bound to tabs. * @module tabview * */ /** * A widget to control tabbed views. * @namespace YAHOO.widget * @class TabView * @extends YAHOO.util.Element * @constructor * @param {HTMLElement | String | Object} el(optional) The html * element that represents the TabView, or the attribute object to use. * An element will be created if none provided. * @param {Object} attr (optional) A key map of the tabView's * initial attributes. Ignored if first arg is attributes object. */ YAHOO.widget.TabView = function(el, attr) { attr = attr || {}; if (arguments.length == 1 && !Lang.isString(el) && !el.nodeName) { attr = el; // treat first arg as attr object el = attr.element || null; } if (!el && !attr.element) { // create if we dont have one el = _createTabViewElement.call(this, attr); } YAHOO.widget.TabView.superclass.constructor.call(this, el, attr); }; YAHOO.extend(YAHOO.widget.TabView, YAHOO.util.Element); var proto = YAHOO.widget.TabView.prototype; var Dom = YAHOO.util.Dom; var Lang = YAHOO.util.Lang; var Event = YAHOO.util.Event; var Tab = YAHOO.widget.Tab; /** * The className to add when building from scratch. * @property CLASSNAME * @default "navset" */ proto.CLASSNAME = 'yui-navset'; /** * The className of the HTMLElement containing the TabView's tab elements * to look for when building from existing markup, or to add when building * from scratch. * All childNodes of the tab container are treated as Tabs when building * from existing markup. * @property TAB_PARENT_CLASSNAME * @default "nav" */ proto.TAB_PARENT_CLASSNAME = 'yui-nav'; /** * The className of the HTMLElement containing the TabView's label elements * to look for when building from existing markup, or to add when building * from scratch. * All childNodes of the content container are treated as content elements when * building from existing markup. * @property CONTENT_PARENT_CLASSNAME * @default "nav-content" */ proto.CONTENT_PARENT_CLASSNAME = 'yui-content'; proto._tabParent = null; proto._contentParent = null; /** * Adds a Tab to the TabView instance. * If no index is specified, the tab is added to the end of the tab list. * @method addTab * @param {YAHOO.widget.Tab} tab A Tab instance to add. * @param {Integer} index The position to add the tab. * @return void */ proto.addTab = function(tab, index) { var tabs = this.get('tabs'); if (!tabs) { // not ready yet this._queue[this._queue.length] = ['addTab', arguments]; return false; } index = (index === undefined) ? tabs.length : index; var before = this.getTab(index); var self = this; var el = this.get('element'); var tabParent = this._tabParent; var contentParent = this._contentParent; var tabElement = tab.get('element'); var contentEl = tab.get('contentEl'); if ( before ) { tabParent.insertBefore(tabElement, before.get('element')); } else { tabParent.appendChild(tabElement); } if ( contentEl && !Dom.isAncestor(contentParent, contentEl) ) { contentParent.appendChild(contentEl); } if ( !tab.get('active') ) { tab.set('contentVisible', false, true); /* hide if not active */ } else { this.set('activeTab', tab, true); } var activate = function(e) { YAHOO.util.Event.preventDefault(e); self.set('activeTab', this); }; tab.addListener( tab.get('activationEvent'), activate); tab.addListener('activationEventChange', function(e) { if (e.prevValue != e.newValue) { tab.removeListener(e.prevValue, activate); tab.addListener(e.newValue, activate); } }); tabs.splice(index, 0, tab); }; /** * Routes childNode events. * @method DOMEventHandler * @param {event} e The Dom event that is being handled. * @return void */ proto.DOMEventHandler = function(e) { var el = this.get('element'); var target = YAHOO.util.Event.getTarget(e); var tabParent = this._tabParent; if (Dom.isAncestor(tabParent, target) ) { var tabEl; var tab = null; var contentEl; var tabs = this.get('tabs'); for (var i = 0, len = tabs.length; i < len; i++) { tabEl = tabs[i].get('element'); contentEl = tabs[i].get('contentEl'); if ( target == tabEl || Dom.isAncestor(tabEl, target) ) { tab = tabs[i]; break; // note break } } if (tab) { tab.fireEvent(e.type, e); } } }; /** * Returns the Tab instance at the specified index. * @method getTab * @param {Integer} index The position of the Tab. * @return YAHOO.widget.Tab */ proto.getTab = function(index) { return this.get('tabs')[index]; }; /** * Returns the index of given tab. * @method getTabIndex * @param {YAHOO.widget.Tab} tab The tab whose index will be returned. * @return int */ proto.getTabIndex = function(tab) { var index = null; var tabs = this.get('tabs'); for (var i = 0, len = tabs.length; i < len; ++i) { if (tab == tabs[i]) { index = i; break; } } return index; }; /** * Removes the specified Tab from the TabView. * @method removeTab * @param {YAHOO.widget.Tab} item The Tab instance to be removed. * @return void */ proto.removeTab = function(tab) { var tabCount = this.get('tabs').length; var index = this.getTabIndex(tab); var nextIndex = index + 1; if ( tab == this.get('activeTab') ) { // select next tab if (tabCount > 1) { if (index + 1 == tabCount) { this.set('activeIndex', index - 1); } else { this.set('activeIndex', index + 1); } } } this._tabParent.removeChild( tab.get('element') ); this._contentParent.removeChild( tab.get('contentEl') ); this._configs.tabs.value.splice(index, 1); }; /** * Provides a readable name for the TabView instance. * @method toString * @return String */ proto.toString = function() { var name = this.get('id') || this.get('tagName'); return "TabView " + name; }; /** * The transiton to use when switching between tabs. * @method contentTransition */ proto.contentTransition = function(newTab, oldTab) { newTab.set('contentVisible', true); oldTab.set('contentVisible', false); }; /** * Registers TabView specific properties. * @method initAttributes * @param {Object} attr Hash of initial attributes */ proto.initAttributes = function(attr) { YAHOO.widget.TabView.superclass.initAttributes.call(this, attr); if (!attr.orientation) { attr.orientation = 'top'; } var el = this.get('element'); /** * The Tabs belonging to the TabView instance. * @config tabs * @type Array */ this.register('tabs', { value: [], readOnly: true }); /** * The container of the tabView's label elements. * @property _tabParent * @private * @type HTMLElement */ this._tabParent = this.getElementsByClassName(this.TAB_PARENT_CLASSNAME, 'ul' )[0] || _createTabParent.call(this); /** * The container of the tabView's content elements. * @property _contentParent * @type HTMLElement * @private */ this._contentParent = this.getElementsByClassName(this.CONTENT_PARENT_CLASSNAME, 'div')[0] || _createContentParent.call(this); /** * How the Tabs should be oriented relative to the TabView. * @config orientation * @type String * @default "top" */ this.register('orientation', { value: attr.orientation, method: function(value) { var current = this.get('orientation'); this.addClass('yui-navset-' + value); if (current != value) { this.removeClass('yui-navset-' + current); } switch(value) { case 'bottom': this.appendChild(this._tabParent); break; } } }); /** * The index of the tab currently active. * @config activeIndex * @type Int */ this.register('activeIndex', { value: attr.activeIndex, method: function(value) { this.set('activeTab', this.getTab(value)); }, validator: function(value) { return !this.getTab(value).get('disabled'); // cannot activate if disabled } }); /** * The tab currently active. * @config activeTab * @type YAHOO.widget.Tab */ this.register('activeTab', { value: attr.activeTab, method: function(tab) { var activeTab = this.get('activeTab'); if (tab) { tab.set('active', true); } if (activeTab && activeTab != tab) { activeTab.set('active', false); } if (activeTab && tab != activeTab) { // no transition if only 1 this.contentTransition(tab, activeTab); } else if (tab) { tab.set('contentVisible', true); } }, validator: function(value) { return !value.get('disabled'); // cannot activate if disabled } }); if ( this._tabParent ) { _initTabs.call(this); } for (var type in this.DOM_EVENTS) { if ( this.DOM_EVENTS.hasOwnProperty(type) ) { this.addListener.call(this, type, this.DOMEventHandler); } } }; /** * Creates Tab instances from a collection of HTMLElements. * @method createTabs * @private * @param {Array|HTMLCollection} elements The elements to use for Tabs. * @return void */ var _initTabs = function() { var tab, attr, contentEl; var el = this.get('element'); var tabs = _getChildNodes(this._tabParent); var contentElements = _getChildNodes(this._contentParent); for (var i = 0, len = tabs.length; i < len; ++i) { attr = {}; if (contentElements[i]) { attr.contentEl = contentElements[i]; } tab = new YAHOO.widget.Tab(tabs[i], attr); this.addTab(tab); if (tab.hasClass(tab.ACTIVE_CLASSNAME) ) { this._configs.activeTab.value = tab; // dont invoke method } } }; var _createTabViewElement = function(attr) { var el = document.createElement('div'); if ( this.CLASSNAME ) { el.className = this.CLASSNAME; } return el; }; var _createTabParent = function(attr) { var el = document.createElement('ul'); if ( this.TAB_PARENT_CLASSNAME ) { el.className = this.TAB_PARENT_CLASSNAME; } this.get('element').appendChild(el); return el; }; var _createContentParent = function(attr) { var el = document.createElement('div'); if ( this.CONTENT_PARENT_CLASSNAME ) { el.className = this.CONTENT_PARENT_CLASSNAME; } this.get('element').appendChild(el); return el; }; var _getChildNodes = function(el) { var nodes = []; var childNodes = el.childNodes; for (var i = 0, len = childNodes.length; i < len; ++i) { if (childNodes[i].nodeType == 1) { nodes[nodes.length] = childNodes[i]; } } return nodes; }; /** * Fires before the activeTab is changed. *
*var handler = function(e) {var previous = e.prevValue};
* myTabs.addListener('contentChange', handler);See: Element.addListener
*If handler returns false, the change will be cancelled, and the value will not * be set.
*Event fields:
*
*<String> type
beforeActiveTabChange
*<YAHOO.widget.Tab> * prevValue
the currently active tab
*<YAHOO.widget.Tab> * newValue
the tab to be made activeUsage:
* @event beforeActiveTabChange */ /** * Fires after the activeTab is changed. *
*var handler = function(e) {var previous = e.prevValue};
* myTabs.addListener('beforeActiveTabChange', handler);See: Element.addListener
*Event fields:
*
*<String> type
activeTabChange
*<YAHOO.widget.Tab> * prevValue
the formerly active tab
*<YAHOO.widget.Tab> * newValue
the new active tabUsage:
* @event activeTabChange */ /** * Fires before the orientation is changed. *
*var handler = function(e) {var previous = e.prevValue};
* myTabs.addListener('activeTabChange', handler);See: Element.addListener
*If handler returns false, the change will be cancelled, and the value will not * be set.
*Event fields:
*
*<String> type
beforeOrientationChange
*<String> * prevValue
the current orientation
*<String> * newValue
the new orientation to be appliedUsage:
* @event beforeOrientationChange */ /** * Fires after the orientation is changed. *
*var handler = function(e) {var previous = e.prevValue};
* myTabs.addListener('beforeOrientationChange', handler);See: Element.addListener
*Event fields:
*
*<String> type
orientationChange
*<String> * prevValue
the former orientation
*<String> * newValue
the new orientationUsage:
* @event orientationChange */ })(); /* Copyright (c) 2006, Yahoo! Inc. All rights reserved.Code licensed under the BSD License:http://developer.yahoo.net/yui/license.txtversion: 0.12.0 */ if(typeof YAHOO=="undefined"){var YAHOO={};}YAHOO.namespace=function(){var a=arguments,o=null,i,j,d;for(i=0;i
*var handler = function(e) {var previous = e.prevValue};
* myTabs.addListener('orientationChange', handler);-1),isSafari=(ua.indexOf('safari')>-1),isGecko=(!isOpera&&!isSafari&&ua.indexOf('gecko')>-1),isIE=(!isOpera&&ua.indexOf('msie')>-1);var patterns={HYPHEN:/(-[a-z])/i};var toCamel=function(property){if(!patterns.HYPHEN.test(property)){return property;}if(propertyCache[property]){return propertyCache[property];}while(patterns.HYPHEN.exec(property)){property=property.replace(RegExp.$1,RegExp.$1.substr(1).toUpperCase());}propertyCache[property]=property;return property;};if(document.defaultView&&document.defaultView.getComputedStyle){getStyle=function(el,property){var value=null;var computed=document.defaultView.getComputedStyle(el,'');if(computed){value=computed[toCamel(property)];}return el.style[property]||value;};}else if(document.documentElement.currentStyle&&isIE){getStyle=function(el,property){switch(toCamel(property)){case'opacity':var val=100;try{val=el.filters['DXImageTransform.Microsoft.Alpha'].opacity;}catch(e){try{val=el.filters('alpha').opacity;}catch(e){}}return val/100;break;default:var value=el.currentStyle?el.currentStyle[property]:null;return(el.style[property]||value);}};}else{getStyle=function(el,property){return el.style[property];};}if(isIE){setStyle=function(el,property,val){switch(property){case'opacity':if(typeof el.style.filter=='string'){el.style.filter='alpha(opacity='+val*100+')';if(!el.currentStyle||!el.currentStyle.hasLayout){el.style.zoom=1;}}break;default:el.style[property]=val;}};}else{setStyle=function(el,property,val){el.style[property]=val;};}YAHOO.util.Dom={get:function(el){if(!el){return null;}if(typeof el!='string'&&!(el instanceof Array)){return el;}if(typeof el=='string'){return document.getElementById(el);}else{var collection=[];for(var i=0,len=el.length;i =this.left&®ion.right<=this.right&®ion.top>=this.top&®ion.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(region){var t=Math.max(this.top,region.top);var r=Math.min(this.right,region.right);var b=Math.min(this.bottom,region.bottom);var l=Math.max(this.left,region.left);if(b>=t&&r>=l){return new YAHOO.util.Region(t,r,b,l);}else{return null;}};YAHOO.util.Region.prototype.union=function(region){var t=Math.min(this.top,region.top);var r=Math.max(this.right,region.right);var b=Math.max(this.bottom,region.bottom);var l=Math.min(this.left,region.left);return new YAHOO.util.Region(t,r,b,l);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+"}");};YAHOO.util.Region.getRegion=function(el){var p=YAHOO.util.Dom.getXY(el);var t=p[1];var r=p[0]+el.offsetWidth;var b=p[1]+el.offsetHeight;var l=p[0];return new YAHOO.util.Region(t,r,b,l);};YAHOO.util.Point=function(x,y){if(x instanceof Array){y=x[1];x=x[0];}this.x=this.right=this.left=this[0]=x;this.y=this.top=this.bottom=this[1]=y;};YAHOO.util.Point.prototype=new YAHOO.util.Region();YAHOO.util.CustomEvent=function(_1,_2,_3,_4){this.type=_1;this.scope=_2||window;this.silent=_3;this.signature=_4||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var _5="_YUICEOnSubscribe";if(_1!==_5){this.subscribeEvent=new YAHOO.util.CustomEvent(_5,this,true);}};YAHOO.util.CustomEvent.LIST=0;YAHOO.util.CustomEvent.FLAT=1;YAHOO.util.CustomEvent.prototype={subscribe:function(fn,_7,_8){if(this.subscribeEvent){this.subscribeEvent.fire(fn,_7,_8);}this.subscribers.push(new YAHOO.util.Subscriber(fn,_7,_8));},unsubscribe:function(fn,_9){var _10=false;for(var i=0,len=this.subscribers.length;i 0){_17=_14[0];}ret=s.fn.call(_16,_17,s.obj);}else{ret=s.fn.call(_16,this.type,_14,s.obj);}if(false===ret){if(!this.silent){}return false;}}}return true;},unsubscribeAll:function(){for(var i=0,len=this.subscribers.length;i =0){_60=_23[_61];}if(!el||!_60){return false;}if(this.useLegacyEvent(el,_59)){var _62=this.getLegacyIndex(el,_59);var _63=_26[_62];if(_63){for(i=0,len=_63.length;i 0);}var _76=[];for(var i=0,len=_28.length;i 0){for(var i=0,len=_23.length;i 0){j=_23.length;while(j){index=j-1;l=_23[index];if(l){EU.removeListener(l[EU.EL],l[EU.TYPE],l[EU.FN],index);}j=j-1;}l=null;EU.clearCache();}for(i=0,len=_25.length;i =0;i--){oldListItems[oldi]=null;}} this._oContainer._oContent._oBody.innerHTML="";} var oList=document.createElement("ul");oList=this._oContainer._oContent._oBody.appendChild(oList);for(var i=0;i =18&&nKeyCode<=20)||(nKeyCode==27)||(nKeyCode>=33&&nKeyCode<=35)||(nKeyCode>=36&&nKeyCode<=38)||(nKeyCode==40)||(nKeyCode>=44&&nKeyCode<=45)){return true;} return false;};YAHOO.widget.AutoComplete.prototype._sendQuery=function(sQuery){if(this.minQueryLength==-1){this._toggleContainer(false);return;} var aDelimChar=(this.delimChar)?this.delimChar:null;if(aDelimChar){var nDelimIndex=-1;for(var i=aDelimChar.length-1;i>=0;i--){var nNewIndex=sQuery.lastIndexOf(aDelimChar[i]);if(nNewIndex>nDelimIndex){nDelimIndex=nNewIndex;}} if(aDelimChar[i]==" "){for(var j=aDelimChar.length-1;j>=0;j--){if(sQuery[nDelimIndex-1]==aDelimChar[j]){nDelimIndex--;break;}}} if(nDelimIndex>-1){var nQueryStart=nDelimIndex+1;while(sQuery.charAt(nQueryStart)==" "){nQueryStart+=1;} this._sSavedQuery=sQuery.substring(0,nQueryStart);sQuery=sQuery.substr(nQueryStart);} else if(sQuery.indexOf(this._sSavedQuery)<0){this._sSavedQuery=null;}} if(sQuery&&(sQuery.length 0)){if(this._nDelayID!=-1){clearTimeout(this._nDelayID);} this._toggleContainer(false);return;} sQuery=encodeURIComponent(sQuery);this._nDelayID=-1;this.dataRequestEvent.fire(this,sQuery);this.dataSource.getResults(this._populateList,sQuery,this);};YAHOO.widget.AutoComplete.prototype._populateList=function(sQuery,aResults,oSelf){if(aResults===null){oSelf.dataErrorEvent.fire(oSelf,sQuery);} if(!oSelf._bFocused||!aResults){return;} var isOpera=(navigator.userAgent.toLowerCase().indexOf("opera")!=-1);var contentStyle=oSelf._oContainer._oContent.style;contentStyle.width=(!isOpera)?null:"";contentStyle.height=(!isOpera)?null:"";var sCurQuery=decodeURIComponent(sQuery);oSelf._sCurQuery=sCurQuery;oSelf._bItemSelected=false;if(oSelf._maxResultsDisplayed!=oSelf.maxResultsDisplayed){oSelf._initList();} var nItems=Math.min(aResults.length,oSelf.maxResultsDisplayed);oSelf._nDisplayedItems=nItems;if(nItems>0){oSelf._initContainerHelpers();var aItems=oSelf._aListItems;for(var i=nItems-1;i>=0;i--){var oItemi=aItems[i];var oResultItemi=aResults[i];oItemi.innerHTML=oSelf.formatResult(oResultItemi,sCurQuery);oItemi.style.display="list-item";oItemi._sResultKey=oResultItemi[0];oItemi._oResultData=oResultItemi;} for(var j=aItems.length-1;j>=nItems;j--){var oItemj=aItems[j];oItemj.innerHTML=null;oItemj.style.display="none";oItemj._sResultKey=null;oItemj._oResultData=null;} if(oSelf.autoHighlight){var oFirstItem=aItems[0];oSelf._toggleHighlight(oFirstItem,"to");oSelf.itemArrowToEvent.fire(oSelf,oFirstItem);oSelf._typeAhead(oFirstItem,sQuery);} else{oSelf._oCurItem=null;} var ok=oSelf.doBeforeExpandContainer(oSelf._oTextbox,oSelf._oContainer,sQuery,aResults);oSelf._toggleContainer(ok);} else{oSelf._toggleContainer(false);} oSelf.dataReturnEvent.fire(oSelf,sQuery,aResults);};YAHOO.widget.AutoComplete.prototype._clearSelection=function(){var sValue=this._oTextbox.value;var sChar=(this.delimChar)?this.delimChar[0]:null;var nIndex=(sChar)?sValue.lastIndexOf(sChar,sValue.length-2):-1;if(nIndex>-1){this._oTextbox.value=sValue.substring(0,nIndex);} else{this._oTextbox.value="";} this._sSavedQuery=this._oTextbox.value;this.selectionEnforceEvent.fire(this);};YAHOO.widget.AutoComplete.prototype._textMatchesOption=function(){var foundMatch=false;for(var i=this._nDisplayedItems-1;i>=0;i--){var oItem=this._aListItems[i];var sMatch=oItem._sResultKey.toLowerCase();if(sMatch==this._sCurQuery.toLowerCase()){foundMatch=true;break;}} return(foundMatch);};YAHOO.widget.AutoComplete.prototype._typeAhead=function(oItem,sQuery){if(!this.typeAhead){return;} var oTextbox=this._oTextbox;var sValue=this._oTextbox.value;if(!oTextbox.setSelectionRange&&!oTextbox.createTextRange){return;} var nStart=sValue.length;this._updateValue(oItem);var nEnd=oTextbox.value.length;this._selectText(oTextbox,nStart,nEnd);var sPrefill=oTextbox.value.substr(nStart,nEnd);this.typeAheadEvent.fire(this,sQuery,sPrefill);};YAHOO.widget.AutoComplete.prototype._selectText=function(oTextbox,nStart,nEnd){if(oTextbox.setSelectionRange){oTextbox.setSelectionRange(nStart,nEnd);} else if(oTextbox.createTextRange){var oTextRange=oTextbox.createTextRange();oTextRange.moveStart("character",nStart);oTextRange.moveEnd("character",nEnd-oTextbox.value.length);oTextRange.select();} else{oTextbox.select();}};YAHOO.widget.AutoComplete.prototype._toggleContainerHelpers=function(bShow){var bFireEvent=false;var width=this._oContainer._oContent.offsetWidth+"px";var height=this._oContainer._oContent.offsetHeight+"px";if(this.useIFrame&&this._oContainer._oIFrame){bFireEvent=true;if(bShow){this._oContainer._oIFrame.style.width=width;this._oContainer._oIFrame.style.height=height;} else{this._oContainer._oIFrame.style.width=0;this._oContainer._oIFrame.style.height=0;}} if(this.useShadow&&this._oContainer._oShadow){bFireEvent=true;if(bShow){this._oContainer._oShadow.style.width=width;this._oContainer._oShadow.style.height=height;} else{this._oContainer._oShadow.style.width=0;this._oContainer._oShadow.style.height=0;}}};YAHOO.widget.AutoComplete.prototype._toggleContainer=function(bShow){var oContainer=this._oContainer;if(this.alwaysShowContainer&&this._bContainerOpen){return;} if(!bShow){this._oContainer._oContent.scrollTop=0;var aItems=this._aListItems;if(aItems&&(aItems.length>0)){for(var i=aItems.length-1;i>=0;i--){aItems[i].style.display="none";}} if(this._oCurItem){this._toggleHighlight(this._oCurItem,"from");} this._oCurItem=null;this._nDisplayedItems=0;this._sCurQuery=null;} if(!bShow&&!this._bContainerOpen){oContainer._oContent.style.display="none";return;} var oAnim=this._oAnim;if(oAnim&&oAnim.getEl()&&(this.animHoriz||this.animVert)){if(!bShow){this._toggleContainerHelpers(bShow);} if(oAnim.isAnimated()){oAnim.stop();} var oClone=oContainer._oContent.cloneNode(true);oContainer.appendChild(oClone);oClone.style.top="-9000px";oClone.style.display="block";var wExp=oClone.offsetWidth;var hExp=oClone.offsetHeight;var wColl=(this.animHoriz)?0:wExp;var hColl=(this.animVert)?0:hExp;oAnim.attributes=(bShow)?{width:{to:wExp},height:{to:hExp}}:{width:{to:wColl},height:{to:hColl}};if(bShow&&!this._bContainerOpen){oContainer._oContent.style.width=wColl+"px";oContainer._oContent.style.height=hColl+"px";} else{oContainer._oContent.style.width=wExp+"px";oContainer._oContent.style.height=hExp+"px";} oContainer.removeChild(oClone);oClone=null;var oSelf=this;var onAnimComplete=function(){oAnim.onComplete.unsubscribeAll();if(bShow){oSelf.containerExpandEvent.fire(oSelf);} else{oContainer._oContent.style.display="none";oSelf.containerCollapseEvent.fire(oSelf);} oSelf._toggleContainerHelpers(bShow);};oContainer._oContent.style.display="block";oAnim.onComplete.subscribe(onAnimComplete);oAnim.animate();this._bContainerOpen=bShow;} else{if(bShow){oContainer._oContent.style.display="block";this.containerExpandEvent.fire(this);} else{oContainer._oContent.style.display="none";this.containerCollapseEvent.fire(this);} this._toggleContainerHelpers(bShow);this._bContainerOpen=bShow;}};YAHOO.widget.AutoComplete.prototype._toggleHighlight=function(oNewItem,sType){var sHighlight=this.highlightClassName;if(this._oCurItem){YAHOO.util.Dom.removeClass(this._oCurItem,sHighlight);} if((sType=="to")&&sHighlight){YAHOO.util.Dom.addClass(oNewItem,sHighlight);this._oCurItem=oNewItem;}};YAHOO.widget.AutoComplete.prototype._togglePrehighlight=function(oNewItem,sType){if(oNewItem==this._oCurItem){return;} var sPrehighlight=this.prehighlightClassName;if((sType=="mouseover")&&sPrehighlight){YAHOO.util.Dom.addClass(oNewItem,sPrehighlight);} else{YAHOO.util.Dom.removeClass(oNewItem,sPrehighlight);}};YAHOO.widget.AutoComplete.prototype._updateValue=function(oItem){var oTextbox=this._oTextbox;var sDelimChar=(this.delimChar)?(this.delimChar[0]||this.delimChar):null;var sSavedQuery=this._sSavedQuery;var sResultKey=oItem._sResultKey;oTextbox.focus();oTextbox.value="";if(sDelimChar){if(sSavedQuery){oTextbox.value=sSavedQuery;} oTextbox.value+=sResultKey+sDelimChar;if(sDelimChar!=" "){oTextbox.value+=" ";}} else{oTextbox.value=sResultKey;} if(oTextbox.type=="textarea"){oTextbox.scrollTop=oTextbox.scrollHeight;} var end=oTextbox.value.length;this._selectText(oTextbox,end,end);this._oCurItem=oItem;};YAHOO.widget.AutoComplete.prototype._selectItem=function(oItem){this._bItemSelected=true;this._updateValue(oItem);this._cancelIntervalDetection(this);this.itemSelectEvent.fire(this,oItem,oItem._oResultData);this._toggleContainer(false);};YAHOO.widget.AutoComplete.prototype._jumpSelection=function(){if(!this.typeAhead){return;} else{this._toggleContainer(false);}};YAHOO.widget.AutoComplete.prototype._moveSelection=function(nKeyCode){if(this._bContainerOpen){var oCurItem=this._oCurItem;var nCurItemIndex=-1;if(oCurItem){nCurItemIndex=oCurItem._nItemIndex;} var nNewItemIndex=(nKeyCode==40)?(nCurItemIndex+1):(nCurItemIndex-1);if(nNewItemIndex<-2||nNewItemIndex>=this._nDisplayedItems){return;} if(oCurItem){this._toggleHighlight(oCurItem,"from");this.itemArrowFromEvent.fire(this,oCurItem);} if(nNewItemIndex==-1){if(this.delimChar&&this._sSavedQuery){if(!this._textMatchesOption()){this._oTextbox.value=this._sSavedQuery;} else{this._oTextbox.value=this._sSavedQuery+this._sCurQuery;}} else{this._oTextbox.value=this._sCurQuery;} this._oCurItem=null;return;} if(nNewItemIndex==-2){this._toggleContainer(false);return;} var oNewItem=this._aListItems[nNewItemIndex];var oContent=this._oContainer._oContent;var scrollOn=((YAHOO.util.Dom.getStyle(oContent,"overflow")=="auto")||(YAHOO.util.Dom.getStyle(oContent,"overflowY")=="auto"));if(scrollOn&&(nNewItemIndex>-1)&&(nNewItemIndex (oContent.scrollTop+oContent.offsetHeight)){oContent.scrollTop=(oNewItem.offsetTop+oNewItem.offsetHeight)-oContent.offsetHeight;} else if((oNewItem.offsetTop+oNewItem.offsetHeight) (oContent.scrollTop+oContent.offsetHeight)){this._oContainer._oContent.scrollTop=(oNewItem.offsetTop+oNewItem.offsetHeight)-oContent.offsetHeight;}}} this._toggleHighlight(oNewItem,"to");this.itemArrowToEvent.fire(this,oNewItem);if(this.typeAhead){this._updateValue(oNewItem);}}};YAHOO.widget.AutoComplete.prototype._onItemMouseover=function(v,oSelf){if(oSelf.prehighlightClassName){oSelf._togglePrehighlight(this,"mouseover");} else{oSelf._toggleHighlight(this,"to");} oSelf.itemMouseOverEvent.fire(oSelf,this);};YAHOO.widget.AutoComplete.prototype._onItemMouseout=function(v,oSelf){if(oSelf.prehighlightClassName){oSelf._togglePrehighlight(this,"mouseout");} else{oSelf._toggleHighlight(this,"from");} oSelf.itemMouseOutEvent.fire(oSelf,this);};YAHOO.widget.AutoComplete.prototype._onItemMouseclick=function(v,oSelf){oSelf._toggleHighlight(this,"to");oSelf._selectItem(this);};YAHOO.widget.AutoComplete.prototype._onContainerMouseover=function(v,oSelf){oSelf._bOverContainer=true;};YAHOO.widget.AutoComplete.prototype._onContainerMouseout=function(v,oSelf){oSelf._bOverContainer=false;if(oSelf._oCurItem){oSelf._toggleHighlight(oSelf._oCurItem,"to");}};YAHOO.widget.AutoComplete.prototype._onContainerScroll=function(v,oSelf){oSelf._oTextbox.focus();};YAHOO.widget.AutoComplete.prototype._onContainerResize=function(v,oSelf){oSelf._toggleContainerHelpers(oSelf._bContainerOpen);};YAHOO.widget.AutoComplete.prototype._onTextboxKeyDown=function(v,oSelf){var nKeyCode=v.keyCode;switch(nKeyCode){case 9:if(oSelf.delimChar&&(oSelf._nKeyCode!=nKeyCode)){if(oSelf._bContainerOpen){YAHOO.util.Event.stopEvent(v);}} if(oSelf._oCurItem){oSelf._selectItem(oSelf._oCurItem);} else{oSelf._toggleContainer(false);} break;case 13:if(oSelf._nKeyCode!=nKeyCode){if(oSelf._bContainerOpen){YAHOO.util.Event.stopEvent(v);}} if(oSelf._oCurItem){oSelf._selectItem(oSelf._oCurItem);} else{oSelf._toggleContainer(false);} break;case 27:oSelf._toggleContainer(false);return;case 39:oSelf._jumpSelection();break;case 38:YAHOO.util.Event.stopEvent(v);oSelf._moveSelection(nKeyCode);break;case 40:YAHOO.util.Event.stopEvent(v);oSelf._moveSelection(nKeyCode);break;default:break;}};YAHOO.widget.AutoComplete.prototype._onTextboxKeyPress=function(v,oSelf){var nKeyCode=v.keyCode;var isMac=(navigator.userAgent.toLowerCase().indexOf("mac")!=-1);if(isMac){switch(nKeyCode){case 9:if(oSelf.delimChar&&(oSelf._nKeyCode!=nKeyCode)){if(oSelf._bContainerOpen){YAHOO.util.Event.stopEvent(v);}} break;case 13:if(oSelf._nKeyCode!=nKeyCode){if(oSelf._bContainerOpen){YAHOO.util.Event.stopEvent(v);}} break;case 38:case 40:YAHOO.util.Event.stopEvent(v);break;default:break;}} else if(nKeyCode==229){oSelf._queryInterval=setInterval(function(){oSelf._onIMEDetected(oSelf);},500);}};YAHOO.widget.AutoComplete.prototype._onTextboxKeyUp=function(v,oSelf){oSelf._initProps();var nKeyCode=v.keyCode;oSelf._nKeyCode=nKeyCode;var sText=this.value;if(oSelf._isIgnoreKey(nKeyCode)||(sText.toLowerCase()==oSelf._sCurQuery)){return;} else{oSelf.textboxKeyEvent.fire(oSelf,nKeyCode);} if(oSelf.queryDelay>0){var nDelayID=setTimeout(function(){oSelf._sendQuery(sText);},(oSelf.queryDelay*1000));if(oSelf._nDelayID!=-1){clearTimeout(oSelf._nDelayID);} oSelf._nDelayID=nDelayID;} else{oSelf._sendQuery(sText);}};YAHOO.widget.AutoComplete.prototype._onTextboxFocus=function(v,oSelf){oSelf._oTextbox.setAttribute("autocomplete","off");oSelf._bFocused=true;oSelf.textboxFocusEvent.fire(oSelf);};YAHOO.widget.AutoComplete.prototype._onTextboxBlur=function(v,oSelf){if(!oSelf._bOverContainer||(oSelf._nKeyCode==9)){if(!oSelf._bItemSelected){if(!oSelf._bContainerOpen||(oSelf._bContainerOpen&&!oSelf._textMatchesOption())){if(oSelf.forceSelection){oSelf._clearSelection();} else{oSelf.unmatchedItemSelectEvent.fire(oSelf,oSelf._sCurQuery);}}} if(oSelf._bContainerOpen){oSelf._toggleContainer(false);} oSelf._cancelIntervalDetection(oSelf);oSelf._bFocused=false;oSelf.textboxBlurEvent.fire(oSelf);}};YAHOO.widget.AutoComplete.prototype._onFormSubmit=function(v,oSelf){if(oSelf.allowBrowserAutocomplete){oSelf._oTextbox.setAttribute("autocomplete","on");} else{oSelf._oTextbox.setAttribute("autocomplete","off");}};YAHOO.widget.DataSource=function(){};YAHOO.widget.DataSource.ERROR_DATANULL="Response data was null";YAHOO.widget.DataSource.ERROR_DATAPARSE="Response data could not be parsed";YAHOO.widget.DataSource.prototype.maxCacheEntries=15;YAHOO.widget.DataSource.prototype.queryMatchContains=false;YAHOO.widget.DataSource.prototype.queryMatchSubset=false;YAHOO.widget.DataSource.prototype.queryMatchCase=false;YAHOO.widget.DataSource.prototype.toString=function(){return"DataSource "+this._sName;};YAHOO.widget.DataSource.prototype.getResults=function(oCallbackFn,sQuery,oParent){var aResults=this._doQueryCache(oCallbackFn,sQuery,oParent);if(aResults.length===0){this.queryEvent.fire(this,oParent,sQuery);this.doQuery(oCallbackFn,sQuery,oParent);}};YAHOO.widget.DataSource.prototype.doQuery=function(oCallbackFn,sQuery,oParent){};YAHOO.widget.DataSource.prototype.flushCache=function(){if(this._aCache){this._aCache=[];} if(this._aCacheHelper){this._aCacheHelper=[];} this.cacheFlushEvent.fire(this);};YAHOO.widget.DataSource.prototype.queryEvent=null;YAHOO.widget.DataSource.prototype.cacheQueryEvent=null;YAHOO.widget.DataSource.prototype.getResultsEvent=null;YAHOO.widget.DataSource.prototype.getCachedResultsEvent=null;YAHOO.widget.DataSource.prototype.dataErrorEvent=null;YAHOO.widget.DataSource.prototype.cacheFlushEvent=null;YAHOO.widget.DataSource._nIndex=0;YAHOO.widget.DataSource.prototype._sName=null;YAHOO.widget.DataSource.prototype._aCache=null;YAHOO.widget.DataSource.prototype._init=function(){var maxCacheEntries=this.maxCacheEntries;if(isNaN(maxCacheEntries)||(maxCacheEntries<0)){maxCacheEntries=0;} if(maxCacheEntries>0&&!this._aCache){this._aCache=[];} this._sName="instance"+YAHOO.widget.DataSource._nIndex;YAHOO.widget.DataSource._nIndex++;this.queryEvent=new YAHOO.util.CustomEvent("query",this);this.cacheQueryEvent=new YAHOO.util.CustomEvent("cacheQuery",this);this.getResultsEvent=new YAHOO.util.CustomEvent("getResults",this);this.getCachedResultsEvent=new YAHOO.util.CustomEvent("getCachedResults",this);this.dataErrorEvent=new YAHOO.util.CustomEvent("dataError",this);this.cacheFlushEvent=new YAHOO.util.CustomEvent("cacheFlush",this);};YAHOO.widget.DataSource.prototype._addCacheElem=function(oResult){var aCache=this._aCache;if(!aCache||!oResult||!oResult.query||!oResult.results){return;} if(aCache.length>=this.maxCacheEntries){aCache.shift();} aCache.push(oResult);};YAHOO.widget.DataSource.prototype._doQueryCache=function(oCallbackFn,sQuery,oParent){var aResults=[];var bMatchFound=false;var aCache=this._aCache;var nCacheLength=(aCache)?aCache.length:0;var bMatchContains=this.queryMatchContains;if((this.maxCacheEntries>0)&&aCache&&(nCacheLength>0)){this.cacheQueryEvent.fire(this,oParent,sQuery);if(!this.queryMatchCase){var sOrigQuery=sQuery;sQuery=sQuery.toLowerCase();} for(var i=nCacheLength-1;i>=0;i--){var resultObj=aCache[i];var aAllResultItems=resultObj.results;var matchKey=(!this.queryMatchCase)?encodeURIComponent(resultObj.query).toLowerCase():encodeURIComponent(resultObj.query);if(matchKey==sQuery){bMatchFound=true;aResults=aAllResultItems;if(i!=nCacheLength-1){aCache.splice(i,1);this._addCacheElem(resultObj);} break;} else if(this.queryMatchSubset){for(var j=sQuery.length-1;j>=0;j--){var subQuery=sQuery.substr(0,j);if(matchKey==subQuery){bMatchFound=true;for(var k=aAllResultItems.length-1;k>=0;k--){var aRecord=aAllResultItems[k];var sKeyIndex=(this.queryMatchCase)?encodeURIComponent(aRecord[0]).indexOf(sQuery):encodeURIComponent(aRecord[0]).toLowerCase().indexOf(sQuery);if((!bMatchContains&&(sKeyIndex===0))||(bMatchContains&&(sKeyIndex>-1))){aResults.unshift(aRecord);}} resultObj={};resultObj.query=sQuery;resultObj.results=aResults;this._addCacheElem(resultObj);break;}} if(bMatchFound){break;}}} if(bMatchFound){this.getCachedResultsEvent.fire(this,oParent,sOrigQuery,aResults);oCallbackFn(sOrigQuery,aResults,oParent);}} return aResults;};YAHOO.widget.DS_XHR=function(sScriptURI,aSchema,oConfigs){if(typeof oConfigs=="object"){for(var sConfig in oConfigs){this[sConfig]=oConfigs[sConfig];}} if(!aSchema||(aSchema.constructor!=Array)){return;} else{this.schema=aSchema;} this.scriptURI=sScriptURI;this._init();};YAHOO.widget.DS_XHR.prototype=new YAHOO.widget.DataSource();YAHOO.widget.DS_XHR.TYPE_JSON=0;YAHOO.widget.DS_XHR.TYPE_XML=1;YAHOO.widget.DS_XHR.TYPE_FLAT=2;YAHOO.widget.DS_XHR.ERROR_DATAXHR="XHR response failed";YAHOO.widget.DS_XHR.prototype.connMgr=YAHOO.util.Connect;YAHOO.widget.DS_XHR.prototype.connTimeout=0;YAHOO.widget.DS_XHR.prototype.scriptURI=null;YAHOO.widget.DS_XHR.prototype.scriptQueryParam="query";YAHOO.widget.DS_XHR.prototype.scriptQueryAppend="";YAHOO.widget.DS_XHR.prototype.responseType=YAHOO.widget.DS_XHR.TYPE_JSON;YAHOO.widget.DS_XHR.prototype.responseStripAfter="\n0){sUri+="&"+this.scriptQueryAppend;} var oResponse=null;var oSelf=this;var responseSuccess=function(oResp){if(!oSelf._oConn||(oResp.tId!=oSelf._oConn.tId)){oSelf.dataErrorEvent.fire(oSelf,oParent,sQuery,YAHOO.widget.DataSource.ERROR_DATANULL);return;} for(var foo in oResp){} if(!isXML){oResp=oResp.responseText;} else{oResp=oResp.responseXML;} if(oResp===null){oSelf.dataErrorEvent.fire(oSelf,oParent,sQuery,YAHOO.widget.DataSource.ERROR_DATANULL);return;} var aResults=oSelf.parseResponse(sQuery,oResp,oParent);var resultObj={};resultObj.query=decodeURIComponent(sQuery);resultObj.results=aResults;if(aResults===null){oSelf.dataErrorEvent.fire(oSelf,oParent,sQuery,YAHOO.widget.DataSource.ERROR_DATAPARSE);aResults=[];} else{oSelf.getResultsEvent.fire(oSelf,oParent,sQuery,aResults);oSelf._addCacheElem(resultObj);} oCallbackFn(sQuery,aResults,oParent);};var responseFailure=function(oResp){oSelf.dataErrorEvent.fire(oSelf,oParent,sQuery,YAHOO.widget.DS_XHR.ERROR_DATAXHR);return;};var oCallback={success:responseSuccess,failure:responseFailure};if(!isNaN(this.connTimeout)&&this.connTimeout>0){oCallback.timeout=this.connTimeout;} if(this._oConn){this.connMgr.abort(this._oConn);} oSelf._oConn=this.connMgr.asyncRequest("GET",sUri,oCallback,null);};YAHOO.widget.DS_XHR.prototype.parseResponse=function(sQuery,oResponse,oParent){var aSchema=this.schema;var aResults=[];var bError=false;var nEnd=((this.responseStripAfter!=="")&&(oResponse.indexOf))?oResponse.indexOf(this.responseStripAfter):-1;if(nEnd!=-1){oResponse=oResponse.substring(0,nEnd);} switch(this.responseType){case YAHOO.widget.DS_XHR.TYPE_JSON:var jsonList;if(window.JSON&&(navigator.userAgent.toLowerCase().indexOf('khtml')==-1)){var jsonObjParsed=JSON.parse(oResponse);if(!jsonObjParsed){bError=true;break;} else{try{jsonList=eval("jsonObjParsed."+aSchema[0]);} catch(e){bError=true;break;}}} else{try{while(oResponse.substring(0,1)==" "){oResponse=oResponse.substring(1,oResponse.length);} if(oResponse.indexOf("{")<0){bError=true;break;} if(oResponse.indexOf("{}")===0){break;} var jsonObjRaw=eval("("+oResponse+")");if(!jsonObjRaw){bError=true;break;} jsonList=eval("(jsonObjRaw."+aSchema[0]+")");} catch(e){bError=true;break;}} if(!jsonList){bError=true;break;} if(jsonList.constructor!=Array){jsonList=[jsonList];} for(var i=jsonList.length-1;i>=0;i--){var aResultItem=[];var jsonResult=jsonList[i];for(var j=aSchema.length-1;j>=1;j--){var dataFieldValue=jsonResult[aSchema[j]];if(!dataFieldValue){dataFieldValue="";} aResultItem.unshift(dataFieldValue);} if(aResultItem.length==1){aResultItem.push(jsonResult);} aResults.unshift(aResultItem);} break;case YAHOO.widget.DS_XHR.TYPE_XML:var xmlList=oResponse.getElementsByTagName(aSchema[0]);if(!xmlList){bError=true;break;} for(var k=xmlList.length-1;k>=0;k--){var result=xmlList.item(k);var aFieldSet=[];for(var m=aSchema.length-1;m>=1;m--){var sValue=null;var xmlAttr=result.attributes.getNamedItem(aSchema[m]);if(xmlAttr){sValue=xmlAttr.value;} else{var xmlNode=result.getElementsByTagName(aSchema[m]);if(xmlNode&&xmlNode.item(0)&&xmlNode.item(0).firstChild){sValue=xmlNode.item(0).firstChild.nodeValue;} else{sValue="";}} aFieldSet.unshift(sValue);} aResults.unshift(aFieldSet);} break;case YAHOO.widget.DS_XHR.TYPE_FLAT:if(oResponse.length>0){var newLength=oResponse.length-aSchema[0].length;if(oResponse.substr(newLength)==aSchema[0]){oResponse=oResponse.substr(0,newLength);} var aRecords=oResponse.split(aSchema[0]);for(var n=aRecords.length-1;n>=0;n--){aResults[n]=aRecords[n].split(aSchema[1]);}} break;default:break;} sQuery=null;oResponse=null;oParent=null;if(bError){return null;} else{return aResults;}};YAHOO.widget.DS_XHR.prototype._oConn=null;YAHOO.widget.DS_JSFunction=function(oFunction,oConfigs){if(typeof oConfigs=="object"){for(var sConfig in oConfigs){this[sConfig]=oConfigs[sConfig];}} if(!oFunction||(oFunction.constructor!=Function)){return;} else{this.dataFunction=oFunction;this._init();}};YAHOO.widget.DS_JSFunction.prototype=new YAHOO.widget.DataSource();YAHOO.widget.DS_JSFunction.prototype.dataFunction=null;YAHOO.widget.DS_JSFunction.prototype.doQuery=function(oCallbackFn,sQuery,oParent){var oFunction=this.dataFunction;var aResults=[];aResults=oFunction(sQuery);if(aResults===null){this.dataErrorEvent.fire(this,oParent,sQuery,YAHOO.widget.DataSource.ERROR_DATANULL);return;} var resultObj={};resultObj.query=decodeURIComponent(sQuery);resultObj.results=aResults;this._addCacheElem(resultObj);this.getResultsEvent.fire(this,oParent,sQuery,aResults);oCallbackFn(sQuery,aResults,oParent);return;};YAHOO.widget.DS_JSArray=function(aData,oConfigs){if(typeof oConfigs=="object"){for(var sConfig in oConfigs){this[sConfig]=oConfigs[sConfig];}} if(!aData||(aData.constructor!=Array)){return;} else{this.data=aData;this._init();}};YAHOO.widget.DS_JSArray.prototype=new YAHOO.widget.DataSource();YAHOO.widget.DS_JSArray.prototype.data=null;YAHOO.widget.DS_JSArray.prototype.doQuery=function(oCallbackFn,sQuery,oParent){var aData=this.data;var aResults=[];var bMatchFound=false;var bMatchContains=this.queryMatchContains;if(sQuery){if(!this.queryMatchCase){sQuery=sQuery.toLowerCase();} for(var i=aData.length-1;i>=0;i--){var aDataset=[];if(aData[i]){if(aData[i].constructor==String){aDataset[0]=aData[i];} else if(aData[i].constructor==Array){aDataset=aData[i];}} if(aDataset[0]&&(aDataset[0].constructor==String)){var sKeyIndex=(this.queryMatchCase)?encodeURIComponent(aDataset[0]).indexOf(sQuery):encodeURIComponent(aDataset[0]).toLowerCase().indexOf(sQuery);if((!bMatchContains&&(sKeyIndex===0))||(bMatchContains&&(sKeyIndex>-1))){aResults.unshift(aDataset);}}}} this.getResultsEvent.fire(this,oParent,sQuery,aResults);oCallbackFn(sQuery,aResults,oParent);}; //\///// //\ overLIB 4.21 - You may not remove or change this notice. //\ Copyright Erik Bosrup 1998-2004. All rights reserved. //\ //\ Contributors are listed on the homepage. //\ This file might be old, always check for the latest version at: //\ http://www.bosrup.com/web/overlib/ //\ //\ Please read the license agreement (available through the link above) //\ before using overLIB. Direct any licensing questions to erik@bosrup.com. //\ //\ Do not sell this as your own work or remove this copyright notice. //\ For full details on copying or changing this script please read the //\ license agreement at the link above. Please give credit on sites that //\ use overLIB and submit changes of the script so other people can use //\ them as well. // $Revision: 1.1 $ $Date: 2006-02-14 15:40:45 $ //\///// //\mini //////// // PRE-INIT // Ignore these lines, configuration is below. //////// var olLoaded = 0;var pmStart = 10000000; var pmUpper = 10001000; var pmCount = pmStart+1; var pmt=''; var pms = new Array(); var olInfo = new Info('4.21', 1); var FREPLACE = 0; var FBEFORE = 1; var FAFTER = 2; var FALTERNATE = 3; var FCHAIN=4; var olHideForm=0; // parameter for hiding SELECT and ActiveX elements in IE5.5+ var olHautoFlag = 0; // flags for over-riding VAUTO and HAUTO if corresponding var olVautoFlag = 0; // positioning commands are used on the command line var hookPts = new Array(), postParse = new Array(), cmdLine = new Array(), runTime = new Array(); // for plugins registerCommands('donothing,inarray,caparray,sticky,background,noclose,caption,left,right,center,offsetx,offsety,fgcolor,bgcolor,textcolor,capcolor,closecolor,width,border,cellpad,status,autostatus,autostatuscap,height,closetext,snapx,snapy,fixx,fixy,relx,rely,fgbackground,bgbackground,padx,pady,fullhtml,above,below,capicon,textfont,captionfont,closefont,textsize,captionsize,closesize,timeout,function,delay,hauto,vauto,closeclick,wrap,followmouse,mouseoff,closetitle,cssoff,compatmode,cssclass,fgclass,bgclass,textfontclass,captionfontclass,closefontclass'); //////// // DEFAULT CONFIGURATION // Settings you want everywhere are set here. All of this can also be // changed on your html page or through an overLIB call. //////// if (typeof ol_fgcolor=='undefined') var ol_fgcolor="#CCCCFF"; if (typeof ol_bgcolor=='undefined') var ol_bgcolor="#333399"; if (typeof ol_textcolor=='undefined') var ol_textcolor="#000000"; if (typeof ol_capcolor=='undefined') var ol_capcolor="#FFFFFF"; if (typeof ol_closecolor=='undefined') var ol_closecolor="#9999FF"; if (typeof ol_textfont=='undefined') var ol_textfont="Verdana,Arial,Helvetica"; if (typeof ol_captionfont=='undefined') var ol_captionfont="Verdana,Arial,Helvetica"; if (typeof ol_closefont=='undefined') var ol_closefont="Verdana,Arial,Helvetica"; if (typeof ol_textsize=='undefined') var ol_textsize="1"; if (typeof ol_captionsize=='undefined') var ol_captionsize="1"; if (typeof ol_closesize=='undefined') var ol_closesize="1"; if (typeof ol_width=='undefined') var ol_width="200"; if (typeof ol_border=='undefined') var ol_border="1"; if (typeof ol_cellpad=='undefined') var ol_cellpad=2; if (typeof ol_offsetx=='undefined') var ol_offsetx=10; if (typeof ol_offsety=='undefined') var ol_offsety=10; if (typeof ol_text=='undefined') var ol_text="Default Text"; if (typeof ol_cap=='undefined') var ol_cap=""; if (typeof ol_sticky=='undefined') var ol_sticky=0; if (typeof ol_background=='undefined') var ol_background=""; if (typeof ol_close=='undefined') var ol_close="Close"; if (typeof ol_hpos=='undefined') var ol_hpos=RIGHT; if (typeof ol_status=='undefined') var ol_status=""; if (typeof ol_autostatus=='undefined') var ol_autostatus=0; if (typeof ol_height=='undefined') var ol_height=-1; if (typeof ol_snapx=='undefined') var ol_snapx=0; if (typeof ol_snapy=='undefined') var ol_snapy=0; if (typeof ol_fixx=='undefined') var ol_fixx=-1; if (typeof ol_fixy=='undefined') var ol_fixy=-1; if (typeof ol_relx=='undefined') var ol_relx=null; if (typeof ol_rely=='undefined') var ol_rely=null; if (typeof ol_fgbackground=='undefined') var ol_fgbackground=""; if (typeof ol_bgbackground=='undefined') var ol_bgbackground=""; if (typeof ol_padxl=='undefined') var ol_padxl=1; if (typeof ol_padxr=='undefined') var ol_padxr=1; if (typeof ol_padyt=='undefined') var ol_padyt=1; if (typeof ol_padyb=='undefined') var ol_padyb=1; if (typeof ol_fullhtml=='undefined') var ol_fullhtml=0; if (typeof ol_vpos=='undefined') var ol_vpos=BELOW; if (typeof ol_aboveheight=='undefined') var ol_aboveheight=0; if (typeof ol_capicon=='undefined') var ol_capicon=""; if (typeof ol_frame=='undefined') var ol_frame=self; if (typeof ol_timeout=='undefined') var ol_timeout=0; if (typeof ol_function=='undefined') var ol_function=null; if (typeof ol_delay=='undefined') var ol_delay=0; if (typeof ol_hauto=='undefined') var ol_hauto=0; if (typeof ol_vauto=='undefined') var ol_vauto=0; if (typeof ol_closeclick=='undefined') var ol_closeclick=0; if (typeof ol_wrap=='undefined') var ol_wrap=0; if (typeof ol_followmouse=='undefined') var ol_followmouse=1; if (typeof ol_mouseoff=='undefined') var ol_mouseoff=0; if (typeof ol_closetitle=='undefined') var ol_closetitle='Close'; if (typeof ol_compatmode=='undefined') var ol_compatmode=0; if (typeof ol_css=='undefined') var ol_css=CSSOFF; if (typeof ol_fgclass=='undefined') var ol_fgclass=""; if (typeof ol_bgclass=='undefined') var ol_bgclass=""; if (typeof ol_textfontclass=='undefined') var ol_textfontclass=""; if (typeof ol_captionfontclass=='undefined') var ol_captionfontclass=""; if (typeof ol_closefontclass=='undefined') var ol_closefontclass=""; //////// // ARRAY CONFIGURATION //////// // You can use these arrays to store popup text here instead of in the html. if (typeof ol_texts=='undefined') var ol_texts = new Array("Text 0", "Text 1"); if (typeof ol_caps=='undefined') var ol_caps = new Array("Caption 0", "Caption 1"); //////// // END OF CONFIGURATION // Don't change anything below this line, all configuration is above. //////// //////// // INIT //////// // Runtime variables init. Don't change for config! var o3_text=""; var o3_cap=""; var o3_sticky=0; var o3_background=""; var o3_close="Close"; var o3_hpos=RIGHT; var o3_offsetx=2; var o3_offsety=2; var o3_fgcolor=""; var o3_bgcolor=""; var o3_textcolor=""; var o3_capcolor=""; var o3_closecolor=""; var o3_width=100; var o3_border=1; var o3_cellpad=2; var o3_status=""; var o3_autostatus=0; var o3_height=-1; var o3_snapx=0; var o3_snapy=0; var o3_fixx=-1; var o3_fixy=-1; var o3_relx=null; var o3_rely=null; var o3_fgbackground=""; var o3_bgbackground=""; var o3_padxl=0; var o3_padxr=0; var o3_padyt=0; var o3_padyb=0; var o3_fullhtml=0; var o3_vpos=BELOW; var o3_aboveheight=0; var o3_capicon=""; var o3_textfont="Verdana,Arial,Helvetica"; var o3_captionfont="Verdana,Arial,Helvetica"; var o3_closefont="Verdana,Arial,Helvetica"; var o3_textsize="1"; var o3_captionsize="1"; var o3_closesize="1"; var o3_frame=self; var o3_timeout=0; var o3_timerid=0; var o3_allowmove=0; var o3_function=null; var o3_delay=0; var o3_delayid=0; var o3_hauto=0; var o3_vauto=0; var o3_closeclick=0; var o3_wrap=0; var o3_followmouse=1; var o3_mouseoff=0; var o3_closetitle=''; var o3_compatmode=0; var o3_css=CSSOFF; var o3_fgclass=""; var o3_bgclass=""; var o3_textfontclass=""; var o3_captionfontclass=""; var o3_closefontclass=""; // Display state variables var o3_x = 0; var o3_y = 0; var o3_showingsticky = 0; var o3_removecounter = 0; // Our layer var over = null; var fnRef, hoveringSwitch = false; var olHideDelay; // Decide browser version var isMac = (navigator.userAgent.indexOf("Mac") != -1); var olOp = (navigator.userAgent.toLowerCase().indexOf('opera') > -1 && document.createTextNode); // Opera 7 var olNs4 = (navigator.appName=='Netscape' && parseInt(navigator.appVersion) == 4); var olNs6 = (document.getElementById) ? true : false; var olKq = (olNs6 && /konqueror/i.test(navigator.userAgent)); var olIe4 = (document.all) ? true : false; var olIe5 = false; var olIe55 = false; // Added additional variable to identify IE5.5+ var docRoot = 'document.body'; // Resize fix for NS4.x to keep track of layer if (olNs4) { var oW = window.innerWidth; var oH = window.innerHeight; window.onresize = function() { if (oW != window.innerWidth || oH != window.innerHeight) location.reload(); } } // Microsoft Stupidity Check(tm). if (olIe4) { var agent = navigator.userAgent; if (/MSIE/.test(agent)) { var versNum = parseFloat(agent.match(/MSIE[ ](\d\.\d+)\.*/i)[1]); if (versNum >= 5){ olIe5=true; olIe55=(versNum>=5.5&&!olOp) ? true : false; if (olNs6) olNs6=false; } } if (olNs6) olIe4 = false; } // Check for compatability mode. if (document.compatMode && document.compatMode == 'CSS1Compat') { docRoot= ((olIe4 && !olOp) ? 'document.documentElement' : docRoot); } // Add window onload handlers to indicate when all modules have been loaded // For Netscape 6+ and Mozilla, uses addEventListener method on the window object // For IE it uses the attachEvent method of the window object and for Netscape 4.x // it sets the window.onload handler to the OLonload_handler function for Bubbling if(window.addEventListener) window.addEventListener("load",OLonLoad_handler,false); else if (window.attachEvent) window.attachEvent("onload",OLonLoad_handler); var capExtent; //////// // PUBLIC FUNCTIONS //////// // overlib(arg0,...,argN) // Loads parameters into global runtime variables. function overlib() { if (!olLoaded || isExclusive(overlib.arguments)) return true; if (olCheckMouseCapture) olMouseCapture(); if (over) { over = (typeof over.id != 'string') ? o3_frame.document.all['overDiv'] : over; cClick(); } // Load defaults to runtime. olHideDelay=0; o3_text=ol_text; o3_cap=ol_cap; o3_sticky=ol_sticky; o3_background=ol_background; o3_close=ol_close; o3_hpos=ol_hpos; o3_offsetx=ol_offsetx; o3_offsety=ol_offsety; o3_fgcolor=ol_fgcolor; o3_bgcolor=ol_bgcolor; o3_textcolor=ol_textcolor; o3_capcolor=ol_capcolor; o3_closecolor=ol_closecolor; o3_width=ol_width; o3_border=ol_border; o3_cellpad=ol_cellpad; o3_status=ol_status; o3_autostatus=ol_autostatus; o3_height=ol_height; o3_snapx=ol_snapx; o3_snapy=ol_snapy; o3_fixx=ol_fixx; o3_fixy=ol_fixy; o3_relx=ol_relx; o3_rely=ol_rely; o3_fgbackground=ol_fgbackground; o3_bgbackground=ol_bgbackground; o3_padxl=ol_padxl; o3_padxr=ol_padxr; o3_padyt=ol_padyt; o3_padyb=ol_padyb; o3_fullhtml=ol_fullhtml; o3_vpos=ol_vpos; o3_aboveheight=ol_aboveheight; o3_capicon=ol_capicon; o3_textfont=ol_textfont; o3_captionfont=ol_captionfont; o3_closefont=ol_closefont; o3_textsize=ol_textsize; o3_captionsize=ol_captionsize; o3_closesize=ol_closesize; o3_timeout=ol_timeout; o3_function=ol_function; o3_delay=ol_delay; o3_hauto=ol_hauto; o3_vauto=ol_vauto; o3_closeclick=ol_closeclick; o3_wrap=ol_wrap; o3_followmouse=ol_followmouse; o3_mouseoff=ol_mouseoff; o3_closetitle=ol_closetitle; o3_css=ol_css; o3_compatmode=ol_compatmode; o3_fgclass=ol_fgclass; o3_bgclass=ol_bgclass; o3_textfontclass=ol_textfontclass; o3_captionfontclass=ol_captionfontclass; o3_closefontclass=ol_closefontclass; setRunTimeVariables(); fnRef = ''; // Special for frame support, over must be reset... o3_frame = ol_frame; if(!(over=createDivContainer())) return false; parseTokens('o3_', overlib.arguments); if (!postParseChecks()) return false; if (o3_delay == 0) { return runHook("olMain", FREPLACE); } else { o3_delayid = setTimeout("runHook('olMain', FREPLACE)", o3_delay); return false; } } // Clears popups if appropriate function nd(time) { if (olLoaded && !isExclusive()) { hideDelay(time); // delay popup close if time specified if (o3_removecounter >= 1) { o3_showingsticky = 0 }; if (o3_showingsticky == 0) { o3_allowmove = 0; if (over != null && o3_timerid == 0) runHook("hideObject", FREPLACE, over); } else { o3_removecounter++; } } return true; } // The Close onMouseOver function for stickies function cClick() { if (olLoaded) { runHook("hideObject", FREPLACE, over); o3_showingsticky = 0; } return false; } // Method for setting page specific defaults. function overlib_pagedefaults() { parseTokens('ol_', overlib_pagedefaults.arguments); } //////// // OVERLIB MAIN FUNCTION //////// // This function decides what it is we want to display and how we want it done. function olMain() { var layerhtml, styleType; runHook("olMain", FBEFORE); if (o3_background!="" || o3_fullhtml) { // Use background instead of box. layerhtml = runHook('ol_content_background', FALTERNATE, o3_css, o3_text, o3_background, o3_fullhtml); } else { // They want a popup box. styleType = (pms[o3_css-1-pmStart] == "cssoff" || pms[o3_css-1-pmStart] == "cssclass"); // Prepare popup background if (o3_fgbackground != "") o3_fgbackground = "background=\""+o3_fgbackground+"\""; if (o3_bgbackground != "") o3_bgbackground = (styleType ? "background=\""+o3_bgbackground+"\"" : o3_bgbackground); // Prepare popup colors if (o3_fgcolor != "") o3_fgcolor = (styleType ? "bgcolor=\""+o3_fgcolor+"\"" : o3_fgcolor); if (o3_bgcolor != "") o3_bgcolor = (styleType ? "bgcolor=\""+o3_bgcolor+"\"" : o3_bgcolor); // Prepare popup height if (o3_height > 0) o3_height = (styleType ? "height=\""+o3_height+"\"" : o3_height); else o3_height = ""; // Decide which kinda box. if (o3_cap=="") { // Plain layerhtml = runHook('ol_content_simple', FALTERNATE, o3_css, o3_text); } else { // With caption if (o3_sticky) { // Show close text layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, o3_close); } else { // No close text layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, ""); } } } // We want it to stick! if (o3_sticky) { if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid = 0; } o3_showingsticky = 1; o3_removecounter = 0; } // Created a separate routine to generate the popup to make it easier // to implement a plugin capability if (!runHook("createPopup", FREPLACE, layerhtml)) return false; // Prepare status bar if (o3_autostatus > 0) { o3_status = o3_text; if (o3_autostatus > 1) o3_status = o3_cap; } // When placing the layer the first time, even stickies may be moved. o3_allowmove = 0; // Initiate a timer for timeout if (o3_timeout > 0) { if (o3_timerid > 0) clearTimeout(o3_timerid); o3_timerid = setTimeout("cClick()", o3_timeout); } // Show layer runHook("disp", FREPLACE, o3_status); runHook("olMain", FAFTER); return (olOp && event && event.type == 'mouseover' && !o3_status) ? '' : (o3_status != ''); } //////// // LAYER GENERATION FUNCTIONS //////// // These functions just handle popup content with tags that should adhere to the W3C standards specification. // Makes simple table without caption function ol_content_simple(text) { var cpIsMultiple = /,/.test(o3_cellpad); var txt = ' '; set_background(""); return txt; } // Makes table with caption and optional close link function ol_content_caption(text,title,close) { var nameId, txt, cpIsMultiple = /,/.test(o3_cellpad); var closing, closeevent; closing = ""; closeevent = "onmouseover"; if (o3_closeclick == 1) closeevent = (o3_closetitle ? "title='" + o3_closetitle +"'" : "") + " onclick"; if (o3_capicon != "") { nameId = ' hspace = \"5\"'+' align = \"middle\" alt = \"\"'; if (typeof o3_dragimg != 'undefined' && o3_dragimg) nameId =' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"'; o3_capicon = ''; } if (close != "") closing = '
' : ((!olNs4&&cpIsMultiple) ? ' style="'+setCellPadStr(o3_cellpad)+'">' : '>'))+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize))+' '+(o3_closefontclass ? '' : wrapStr(0,o3_closesize,'close'))+close+(o3_closefontclass ? '' : wrapStr(1,o3_closesize,'close'))+' '; txt = ''; set_background(""); return txt; } // Sets the background picture,padding and lots more. :) function ol_content_background(text,picture,hasfullhtml) { if (hasfullhtml) { txt=text; } else { txt='
' : '>')+(o3_captionfontclass ? '' : ''+wrapStr(0,o3_captionsize,'caption'))+o3_capicon+title+(o3_captionfontclass ? '' : wrapStr(1,o3_captionsize)+'')+' '+closing+'
' :((!olNs4&&cpIsMultiple) ? ' style="'+setCellPadStr(o3_cellpad)+'">' : '>'))+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize)) + ' '; } set_background(picture); return txt; } // Loads a picture into the div. function set_background(pic) { if (pic == "") { if (olNs4) { over.background.src = null; } else if (over.style) { over.style.backgroundImage = "none"; } } else { if (olNs4) { over.background.src = pic; } else if (over.style) { over.style.width=o3_width + 'px'; over.style.backgroundImage = "url("+pic+")"; } } } //////// // HANDLING FUNCTIONS //////// var olShowId=-1; // Displays the popup function disp(statustext) { runHook("disp", FBEFORE); if (o3_allowmove == 0) { runHook("placeLayer", FREPLACE); (olNs6&&olShowId<0) ? olShowId=setTimeout("runHook('showObject', FREPLACE, over)", 1) : runHook("showObject", FREPLACE, over); o3_allowmove = (o3_sticky || o3_followmouse==0) ? 0 : 1; } runHook("disp", FAFTER); if (statustext != "") self.status = statustext; } // Creates the actual popup structure function createPopup(lyrContent){ runHook("createPopup", FBEFORE); if (o3_wrap) { var wd,ww,theObj = (olNs4 ? over : over.style); theObj.top = theObj.left = ((olIe4&&!olOp) ? 0 : -10000) + (!olNs4 ? 'px' : 0); layerWrite(lyrContent); wd = (olNs4 ? over.clip.width : over.offsetWidth); if (wd > (ww=windowWidth())) { lyrContent=lyrContent.replace(/\ /g, ' '); o3_width=ww; o3_wrap=0; } } layerWrite(lyrContent); // Have to set o3_width for placeLayer() routine if o3_wrap is turned on if (o3_wrap) o3_width=(olNs4 ? over.clip.width : over.offsetWidth); runHook("createPopup", FAFTER, lyrContent); return true; } // Decides where we want the popup. function placeLayer() { var placeX, placeY, widthFix = 0; // HORIZONTAL PLACEMENT, re-arranged to work in Safari if (o3_frame.innerWidth) widthFix=18; iwidth = windowWidth(); // Horizontal scroll offset winoffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollLeft') : o3_frame.pageXOffset; placeX = runHook('horizontalPlacement',FCHAIN,iwidth,winoffset,widthFix); // VERTICAL PLACEMENT, re-arranged to work in Safari if (o3_frame.innerHeight) { iheight=o3_frame.innerHeight; } else if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientHeight=='number'")&&eval('o3_frame.'+docRoot+'.clientHeight')) { iheight=eval('o3_frame.'+docRoot+'.clientHeight'); } // Vertical scroll offset scrolloffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollTop') : o3_frame.pageYOffset; placeY = runHook('verticalPlacement',FCHAIN,iheight,scrolloffset); // Actually move the object. repositionTo(over, placeX, placeY); } // Moves the layer function olMouseMove(e) { var e = (e) ? e : event; if (e.pageX) { o3_x = e.pageX; o3_y = e.pageY; } else if (e.clientX) { o3_x = eval('e.clientX+o3_frame.'+docRoot+'.scrollLeft'); o3_y = eval('e.clientY+o3_frame.'+docRoot+'.scrollTop'); } if (o3_allowmove == 1) runHook("placeLayer", FREPLACE); // MouseOut handler if (hoveringSwitch && !olNs4 && runHook("cursorOff", FREPLACE)) { (olHideDelay ? hideDelay(olHideDelay) : cClick()); hoveringSwitch = !hoveringSwitch; } } // Fake function for 3.0 users. function no_overlib() { return ver3fix; } // Capture the mouse and chain other scripts. function olMouseCapture() { capExtent = document; var fN, str = '', l, k, f, wMv, sS, mseHandler = olMouseMove; var re = /function[ ]*(\w*)\(/; wMv = (!olIe4 && window.onmousemove); if (document.onmousemove || wMv) { if (wMv) capExtent = window; f = capExtent.onmousemove.toString(); fN = f.match(re); if (fN == null) { str = f+'(e); '; } else if (fN[1] == 'anonymous' || fN[1] == 'olMouseMove' || (wMv && fN[1] == 'onmousemove')) { if (!olOp && wMv) { l = f.indexOf('{')+1; k = f.lastIndexOf('}'); sS = f.substring(l,k); if ((l = sS.indexOf('(')) != -1) { sS = sS.substring(0,l).replace(/^\s+/,'').replace(/\s+$/,''); if (eval("typeof " + sS + " == 'undefined'")) window.onmousemove = null; else str = sS + '(e);'; } } if (!str) { olCheckMouseCapture = false; return; } } else { if (fN[1]) str = fN[1]+'(e); '; else { l = f.indexOf('{')+1; k = f.lastIndexOf('}'); str = f.substring(l,k) + '\n'; } } str += 'olMouseMove(e); '; mseHandler = new Function('e', str); } capExtent.onmousemove = mseHandler; if (olNs4) capExtent.captureEvents(Event.MOUSEMOVE); } //////// // PARSING FUNCTIONS //////// // Does the actual command parsing. function parseTokens(pf, ar) { // What the next argument is expected to be. var v, i, mode=-1, par = (pf != 'ol_'); var fnMark = (par && !ar.length ? 1 : 0); for (i = 0; i < ar.length; i++) { if (mode < 0) { // Arg is maintext,unless its a number between pmStart and pmUpper // then its a command. if (typeof ar[i] == 'number' && ar[i] > pmStart && ar[i] < pmUpper) { fnMark = (par ? 1 : 0); i--; // backup one so that the next block can parse it } else { switch(pf) { case 'ol_': ol_text = ar[i].toString(); break; default: o3_text=ar[i].toString(); } } mode = 0; } else { // Note: NS4 doesn't like switch cases with vars. if (ar[i] >= pmCount || ar[i]==DONOTHING) { continue; } if (ar[i]==INARRAY) { fnMark = 0; eval(pf+'text=ol_texts['+ar[++i]+'].toString()'); continue; } if (ar[i]==CAPARRAY) { eval(pf+'cap=ol_caps['+ar[++i]+'].toString()'); continue; } if (ar[i]==STICKY) { if (pf!='ol_') eval(pf+'sticky=1'); continue; } if (ar[i]==BACKGROUND) { eval(pf+'background="'+ar[++i]+'"'); continue; } if (ar[i]==NOCLOSE) { if (pf!='ol_') opt_NOCLOSE(); continue; } if (ar[i]==CAPTION) { eval(pf+"cap='"+escSglQuote(ar[++i])+"'"); continue; } if (ar[i]==CENTER || ar[i]==LEFT || ar[i]==RIGHT) { eval(pf+'hpos='+ar[i]); if(pf!='ol_') olHautoFlag=1; continue; } if (ar[i]==OFFSETX) { eval(pf+'offsetx='+ar[++i]); continue; } if (ar[i]==OFFSETY) { eval(pf+'offsety='+ar[++i]); continue; } if (ar[i]==FGCOLOR) { eval(pf+'fgcolor="'+ar[++i]+'"'); continue; } if (ar[i]==BGCOLOR) { eval(pf+'bgcolor="'+ar[++i]+'"'); continue; } if (ar[i]==TEXTCOLOR) { eval(pf+'textcolor="'+ar[++i]+'"'); continue; } if (ar[i]==CAPCOLOR) { eval(pf+'capcolor="'+ar[++i]+'"'); continue; } if (ar[i]==CLOSECOLOR) { eval(pf+'closecolor="'+ar[++i]+'"'); continue; } if (ar[i]==WIDTH) { eval(pf+'width='+ar[++i]); continue; } if (ar[i]==BORDER) { eval(pf+'border='+ar[++i]); continue; } if (ar[i]==CELLPAD) { i=opt_MULTIPLEARGS(++i,ar,(pf+'cellpad')); continue; } if (ar[i]==STATUS) { eval(pf+"status='"+escSglQuote(ar[++i])+"'"); continue; } if (ar[i]==AUTOSTATUS) { eval(pf +'autostatus=('+pf+'autostatus == 1) ? 0 : 1'); continue; } if (ar[i]==AUTOSTATUSCAP) { eval(pf +'autostatus=('+pf+'autostatus == 2) ? 0 : 2'); continue; } if (ar[i]==HEIGHT) { eval(pf+'height='+pf+'aboveheight='+ar[++i]); continue; } // Same param again. if (ar[i]==CLOSETEXT) { eval(pf+"close='"+escSglQuote(ar[++i])+"'"); continue; } if (ar[i]==SNAPX) { eval(pf+'snapx='+ar[++i]); continue; } if (ar[i]==SNAPY) { eval(pf+'snapy='+ar[++i]); continue; } if (ar[i]==FIXX) { eval(pf+'fixx='+ar[++i]); continue; } if (ar[i]==FIXY) { eval(pf+'fixy='+ar[++i]); continue; } if (ar[i]==RELX) { eval(pf+'relx='+ar[++i]); continue; } if (ar[i]==RELY) { eval(pf+'rely='+ar[++i]); continue; } if (ar[i]==FGBACKGROUND) { eval(pf+'fgbackground="'+ar[++i]+'"'); continue; } if (ar[i]==BGBACKGROUND) { eval(pf+'bgbackground="'+ar[++i]+'"'); continue; } if (ar[i]==PADX) { eval(pf+'padxl='+ar[++i]); eval(pf+'padxr='+ar[++i]); continue; } if (ar[i]==PADY) { eval(pf+'padyt='+ar[++i]); eval(pf+'padyb='+ar[++i]); continue; } if (ar[i]==FULLHTML) { if (pf!='ol_') eval(pf+'fullhtml=1'); continue; } if (ar[i]==BELOW || ar[i]==ABOVE) { eval(pf+'vpos='+ar[i]); if (pf!='ol_') olVautoFlag=1; continue; } if (ar[i]==CAPICON) { eval(pf+'capicon="'+ar[++i]+'"'); continue; } if (ar[i]==TEXTFONT) { eval(pf+"textfont='"+escSglQuote(ar[++i])+"'"); continue; } if (ar[i]==CAPTIONFONT) { eval(pf+"captionfont='"+escSglQuote(ar[++i])+"'"); continue; } if (ar[i]==CLOSEFONT) { eval(pf+"closefont='"+escSglQuote(ar[++i])+"'"); continue; } if (ar[i]==TEXTSIZE) { eval(pf+'textsize="'+ar[++i]+'"'); continue; } if (ar[i]==CAPTIONSIZE) { eval(pf+'captionsize="'+ar[++i]+'"'); continue; } if (ar[i]==CLOSESIZE) { eval(pf+'closesize="'+ar[++i]+'"'); continue; } if (ar[i]==TIMEOUT) { eval(pf+'timeout='+ar[++i]); continue; } if (ar[i]==FUNCTION) { if (pf=='ol_') { if (typeof ar[i+1]!='number') { v=ar[++i]; ol_function=(typeof v=='function' ? v : null); }} else {fnMark = 0; v = null; if (typeof ar[i+1]!='number') v = ar[++i]; opt_FUNCTION(v); } continue; } if (ar[i]==DELAY) { eval(pf+'delay='+ar[++i]); continue; } if (ar[i]==HAUTO) { eval(pf+'hauto=('+pf+'hauto == 0) ? 1 : 0'); continue; } if (ar[i]==VAUTO) { eval(pf+'vauto=('+pf+'vauto == 0) ? 1 : 0'); continue; } if (ar[i]==CLOSECLICK) { eval(pf +'closeclick=('+pf+'closeclick == 0) ? 1 : 0'); continue; } if (ar[i]==WRAP) { eval(pf +'wrap=('+pf+'wrap == 0) ? 1 : 0'); continue; } if (ar[i]==FOLLOWMOUSE) { eval(pf +'followmouse=('+pf+'followmouse == 1) ? 0 : 1'); continue; } if (ar[i]==MOUSEOFF) { eval(pf +'mouseoff=('+pf+'mouseoff==0) ? 1 : 0'); v=ar[i+1]; if (pf != 'ol_' && eval(pf+'mouseoff') && typeof v == 'number' && (v < pmStart || v > pmUpper)) olHideDelay=ar[++i]; continue; } if (ar[i]==CLOSETITLE) { eval(pf+"closetitle='"+escSglQuote(ar[++i])+"'"); continue; } if (ar[i]==CSSOFF||ar[i]==CSSCLASS) { eval(pf+'css='+ar[i]); continue; } if (ar[i]==COMPATMODE) { eval(pf+'compatmode=('+pf+'compatmode==0) ? 1 : 0'); continue; } if (ar[i]==FGCLASS) { eval(pf+'fgclass="'+ar[++i]+'"'); continue; } if (ar[i]==BGCLASS) { eval(pf+'bgclass="'+ar[++i]+'"'); continue; } if (ar[i]==TEXTFONTCLASS) { eval(pf+'textfontclass="'+ar[++i]+'"'); continue; } if (ar[i]==CAPTIONFONTCLASS) { eval(pf+'captionfontclass="'+ar[++i]+'"'); continue; } if (ar[i]==CLOSEFONTCLASS) { eval(pf+'closefontclass="'+ar[++i]+'"'); continue; } i = parseCmdLine(pf, i, ar); } } if (fnMark && o3_function) o3_text = o3_function(); if ((pf == 'o3_') && o3_wrap) { o3_width = 0; var tReg=/<.*\n*>/ig; if (!tReg.test(o3_text)) o3_text = o3_text.replace(/[ ]+/g, ' '); if (!tReg.test(o3_cap))o3_cap = o3_cap.replace(/[ ]+/g, ' '); } if ((pf == 'o3_') && o3_sticky) { if (!o3_close && (o3_frame != ol_frame)) o3_close = ol_close; if (o3_mouseoff && (o3_frame == ol_frame)) opt_NOCLOSE(' '); } } //////// // LAYER FUNCTIONS //////// // Writes to a layer function layerWrite(txt) { txt += "\n"; if (olNs4) { var lyr = o3_frame.document.layers['overDiv'].document lyr.write(txt) lyr.close() } else if (typeof over.innerHTML != 'undefined') { if (olIe5 && isMac) over.innerHTML = ''; over.innerHTML = txt; } else { range = o3_frame.document.createRange(); range.setStartAfter(over); domfrag = range.createContextualFragment(txt); while (over.hasChildNodes()) { over.removeChild(over.lastChild); } over.appendChild(domfrag); } } // Make an object visible function showObject(obj) { runHook("showObject", FBEFORE); var theObj=(olNs4 ? obj : obj.style); theObj.visibility = 'visible'; runHook("showObject", FAFTER); } // Hides an object function hideObject(obj) { runHook("hideObject", FBEFORE); var theObj=(olNs4 ? obj : obj.style); if (olNs6 && olShowId>0) { clearTimeout(olShowId); olShowId=0; } theObj.visibility = 'hidden'; theObj.top = theObj.left = ((olIe4&&!olOp) ? 0 : -10000) + (!olNs4 ? 'px' : 0); if (o3_timerid > 0) clearTimeout(o3_timerid); if (o3_delayid > 0) clearTimeout(o3_delayid); o3_timerid = 0; o3_delayid = 0; self.status = ""; if (obj.onmouseout||obj.onmouseover) { if (olNs4) obj.releaseEvents(Event.MOUSEOUT || Event.MOUSEOVER); obj.onmouseout = obj.onmouseover = null; } runHook("hideObject", FAFTER); } // Move a layer function repositionTo(obj, xL, yL) { var theObj=(olNs4 ? obj : obj.style); theObj.left = xL + (!olNs4 ? 'px' : 0); theObj.top = yL + (!olNs4 ? 'px' : 0); } // Check position of cursor relative to overDiv DIVision; mouseOut function function cursorOff() { var left = parseInt(over.style.left); var top = parseInt(over.style.top); var right = left + (over.offsetWidth >= parseInt(o3_width) ? over.offsetWidth : parseInt(o3_width)); var bottom = top + (over.offsetHeight >= o3_aboveheight ? over.offsetHeight : o3_aboveheight); if (o3_x < left || o3_x > right || o3_y < top || o3_y > bottom) return true; return false; } //////// // COMMAND FUNCTIONS //////// // Calls callme or the default function. function opt_FUNCTION(callme) { o3_text = (callme ? (typeof callme=='string' ? (/.+\(.*\)/.test(callme) ? eval(callme) : callme) : callme()) : (o3_function ? o3_function() : 'No Function')); return 0; } // Handle hovering function opt_NOCLOSE(unused) { if (!unused) o3_close = ""; if (olNs4) { over.captureEvents(Event.MOUSEOUT || Event.MOUSEOVER); over.onmouseover = function () { if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid = 0; } } over.onmouseout = function (e) { if (olHideDelay) hideDelay(olHideDelay); else cClick(e); } } else { over.onmouseover = function () {hoveringSwitch = true; if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid =0; } } } return 0; } // Function to scan command line arguments for multiples function opt_MULTIPLEARGS(i, args, parameter) { var k=i, re, pV, str=''; for(k=i; k
'+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize))+' pmStart) break; str += args[k] + ','; } if (str) str = str.substring(0,--str.length); k--; // reduce by one so the for loop this is in works correctly pV=(olNs4 && /cellpad/i.test(parameter)) ? str.split(',')[0] : str; eval(parameter + '="' + pV + '"'); return k; } // Remove in texts when done. function nbspCleanup() { if (o3_wrap) { o3_text = o3_text.replace(/\ /g, ' '); o3_cap = o3_cap.replace(/\ /g, ' '); } } // Escape embedded single quotes in text strings function escSglQuote(str) { return str.toString().replace(/'/g,"\\'"); } // Onload handler for window onload event function OLonLoad_handler(e) { var re = /\w+\(.*\)[;\s]+/g, olre = /overlib\(|nd\(|cClick\(/, fn, l, i; if(!olLoaded) olLoaded=1; // Remove it for Gecko based browsers if(window.removeEventListener && e.eventPhase == 3) window.removeEventListener("load",OLonLoad_handler,false); else if(window.detachEvent) { // and for IE and Opera 4.x but execute calls to overlib, nd, or cClick() window.detachEvent("onload",OLonLoad_handler); var fN = document.body.getAttribute('onload'); if (fN) { fN=fN.toString().match(re); if (fN && fN.length) { for (i=0; i ' : '') : ''; else { fontStr='o3_'+whichString+'font'; fontColor='o3_'+((whichString=='caption')? 'cap' : whichString)+'color'; return (hasDims&&!olNs4) ? (isClose ? '' : ' ') : ''; } } // Quotes Multi word font names; needed for CSS Standards adherence in font-family function quoteMultiNameFonts(theFont) { var v, pM=theFont.split(','); for (var i=0; i0) clearTimeout(o3_timerid); o3_timerid=setTimeout("cClick()",(o3_timeout=time)); } } // Was originally in the placeLayer() routine; separated out for future ease function horizontalPlacement(browserWidth, horizontalScrollAmount, widthFix) { var placeX, iwidth=browserWidth, winoffset=horizontalScrollAmount; var parsedWidth = parseInt(o3_width); if (o3_fixx > -1 || o3_relx != null) { // Fixed position placeX=(o3_relx != null ? ( o3_relx < 0 ? winoffset +o3_relx+ iwidth - parsedWidth - widthFix : winoffset+o3_relx) : o3_fixx); } else { // If HAUTO, decide what to use. if (o3_hauto == 1) { if ((o3_x - winoffset) > (iwidth / 2)) { o3_hpos = LEFT; } else { o3_hpos = RIGHT; } } // From mouse if (o3_hpos == CENTER) { // Center placeX = o3_x+o3_offsetx-(parsedWidth/2); if (placeX < winoffset) placeX = winoffset; } if (o3_hpos == RIGHT) { // Right placeX = o3_x+o3_offsetx; if ((placeX+parsedWidth) > (winoffset+iwidth - widthFix)) { placeX = iwidth+winoffset - parsedWidth - widthFix; if (placeX < 0) placeX = 0; } } if (o3_hpos == LEFT) { // Left placeX = o3_x-o3_offsetx-parsedWidth; if (placeX < winoffset) placeX = winoffset; } // Snapping! if (o3_snapx > 1) { var snapping = placeX % o3_snapx; if (o3_hpos == LEFT) { placeX = placeX - (o3_snapx+snapping); } else { // CENTER and RIGHT placeX = placeX+(o3_snapx - snapping); } if (placeX < winoffset) placeX = winoffset; } } return placeX; } // was originally in the placeLayer() routine; separated out for future ease function verticalPlacement(browserHeight,verticalScrollAmount) { var placeY, iheight=browserHeight, scrolloffset=verticalScrollAmount; var parsedHeight=(o3_aboveheight ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight)); if (o3_fixy > -1 || o3_rely != null) { // Fixed position placeY=(o3_rely != null ? (o3_rely < 0 ? scrolloffset+o3_rely+iheight - parsedHeight : scrolloffset+o3_rely) : o3_fixy); } else { // If VAUTO, decide what to use. if (o3_vauto == 1) { if ((o3_y - scrolloffset) > (iheight / 2) && o3_vpos == BELOW && (o3_y + parsedHeight + o3_offsety - (scrolloffset + iheight) > 0)) { o3_vpos = ABOVE; } else if (o3_vpos == ABOVE && (o3_y - (parsedHeight + o3_offsety) - scrolloffset < 0)) { o3_vpos = BELOW; } } // From mouse if (o3_vpos == ABOVE) { if (o3_aboveheight == 0) o3_aboveheight = parsedHeight; placeY = o3_y - (o3_aboveheight+o3_offsety); if (placeY < scrolloffset) placeY = scrolloffset; } else { // BELOW placeY = o3_y+o3_offsety; } // Snapping! if (o3_snapy > 1) { var snapping = placeY % o3_snapy; if (o3_aboveheight > 0 && o3_vpos == ABOVE) { placeY = placeY - (o3_snapy+snapping); } else { placeY = placeY+(o3_snapy - snapping); } if (placeY < scrolloffset) placeY = scrolloffset; } } return placeY; } // checks positioning flags function checkPositionFlags() { if (olHautoFlag) olHautoFlag = o3_hauto=0; if (olVautoFlag) olVautoFlag = o3_vauto=0; return true; } // get Browser window width function windowWidth() { var w; if (o3_frame.innerWidth) w=o3_frame.innerWidth; else if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientWidth=='number'")&&eval('o3_frame.'+docRoot+'.clientWidth')) w=eval('o3_frame.'+docRoot+'.clientWidth'); return w; } // create the div container for popup content if it doesn't exist function createDivContainer(id,frm,zValue) { id = (id || 'overDiv'), frm = (frm || o3_frame), zValue = (zValue || 1000); var objRef, divContainer = layerReference(id); if (divContainer == null) { if (olNs4) { divContainer = frm.document.layers[id] = new Layer(window.innerWidth, frm); objRef = divContainer; } else { var body = (olIe4 ? frm.document.all.tags('BODY')[0] : frm.document.getElementsByTagName("BODY")[0]); if (olIe4&&!document.getElementById) { body.insertAdjacentHTML("beforeEnd",''); divContainer=layerReference(id); } else { divContainer = frm.document.createElement("DIV"); divContainer.id = id; body.appendChild(divContainer); } objRef = divContainer.style; } objRef.position = 'absolute'; objRef.visibility = 'hidden'; objRef.zIndex = zValue; if (olIe4&&!olOp) objRef.left = objRef.top = '0px'; else objRef.left = objRef.top = -10000 + (!olNs4 ? 'px' : 0); } return divContainer; } // get reference to a layer with ID=id function layerReference(id) { return (olNs4 ? o3_frame.document.layers[id] : (document.all ? o3_frame.document.all[id] : o3_frame.document.getElementById(id))); } //////// // UTILITY FUNCTIONS //////// // Checks if something is a function. function isFunction(fnRef) { var rtn = true; if (typeof fnRef == 'object') { for (var i = 0; i < fnRef.length; i++) { if (typeof fnRef[i]=='function') continue; rtn = false; break; } } else if (typeof fnRef != 'function') { rtn = false; } return rtn; } // Converts an array into an argument string for use in eval. function argToString(array, strtInd, argName) { var jS = strtInd, aS = '', ar = array; argName=(argName ? argName : 'ar'); if (ar.length > jS) { for (var k = jS; k < ar.length; k++) aS += argName+'['+k+'], '; aS = aS.substring(0, aS.length-2); } return aS; } // Places a hook in the correct position in a hook point. function reOrder(hookPt, fnRef, order) { var newPt = new Array(), match, i, j; if (!order || typeof order == 'undefined' || typeof order == 'number') return hookPt; if (typeof order=='function') { if (typeof fnRef=='object') { newPt = newPt.concat(fnRef); } else { newPt[newPt.length++]=fnRef; } for (i = 0; i < hookPt.length; i++) { match = false; if (typeof fnRef == 'function' && hookPt[i] == fnRef) { continue; } else { for(j = 0; j < fnRef.length; j++) if (hookPt[i] == fnRef[j]) { match = true; break; } } if (!match) newPt[newPt.length++] = hookPt[i]; } newPt[newPt.length++] = order; } else if (typeof order == 'object') { if (typeof fnRef == 'object') { newPt = newPt.concat(fnRef); } else { newPt[newPt.length++] = fnRef; } for (j = 0; j < hookPt.length; j++) { match = false; if (typeof fnRef == 'function' && hookPt[j] == fnRef) { continue; } else { for (i = 0; i < fnRef.length; i++) if (hookPt[j] == fnRef[i]) { match = true; break; } } if (!match) newPt[newPt.length++]=hookPt[j]; } for (i = 0; i < newPt.length; i++) hookPt[i] = newPt[i]; newPt.length = 0; for (j = 0; j < hookPt.length; j++) { match = false; for (i = 0; i < order.length; i++) { if (hookPt[j] == order[i]) { match = true; break; } } if (!match) newPt[newPt.length++] = hookPt[j]; } newPt = newPt.concat(order); } hookPt = newPt; return hookPt; } //////// // PLUGIN ACTIVATION FUNCTIONS //////// // Runs plugin functions to set runtime variables. function setRunTimeVariables(){ if (typeof runTime != 'undefined' && runTime.length) { for (var k = 0; k < runTime.length; k++) { runTime[k](); } } } // Runs plugin functions to parse commands. function parseCmdLine(pf, i, args) { if (typeof cmdLine != 'undefined' && cmdLine.length) { for (var k = 0; k < cmdLine.length; k++) { var j = cmdLine[k](pf, i, args); if (j >- 1) { i = j; break; } } } return i; } // Runs plugin functions to do things after parse. function postParseChecks(pf,args){ if (typeof postParse != 'undefined' && postParse.length) { for (var k = 0; k < postParse.length; k++) { if (postParse[k](pf,args)) continue; return false; // end now since have an error } } return true; } //////// // PLUGIN REGISTRATION FUNCTIONS //////// // Registers commands and creates constants. function registerCommands(cmdStr) { if (typeof cmdStr!='string') return; var pM = cmdStr.split(','); pms = pms.concat(pM); for (var i = 0; i< pM.length; i++) { eval(pM[i].toUpperCase()+'='+pmCount++); } } // Registers no-parameter commands function registerNoParameterCommands(cmdStr) { if (!cmdStr && typeof cmdStr != 'string') return; pmt=(!pmt) ? cmdStr : pmt + ',' + cmdStr; } // Register a function to hook at a certain point. function registerHook(fnHookTo, fnRef, hookType, optPm) { var hookPt, last = typeof optPm; if (fnHookTo == 'plgIn'||fnHookTo == 'postParse') return; if (typeof hookPts[fnHookTo] == 'undefined') hookPts[fnHookTo] = new FunctionReference(); hookPt = hookPts[fnHookTo]; if (hookType != null) { if (hookType == FREPLACE) { hookPt.ovload = fnRef; // replace normal overlib routine if (fnHookTo.indexOf('ol_content_') > -1) hookPt.alt[pms[CSSOFF-1-pmStart]]=fnRef; } else if (hookType == FBEFORE || hookType == FAFTER) { var hookPt=(hookType == 1 ? hookPt.before : hookPt.after); if (typeof fnRef == 'object') { hookPt = hookPt.concat(fnRef); } else { hookPt[hookPt.length++] = fnRef; } if (optPm) hookPt = reOrder(hookPt, fnRef, optPm); } else if (hookType == FALTERNATE) { if (last=='number') hookPt.alt[pms[optPm-1-pmStart]] = fnRef; } else if (hookType == FCHAIN) { hookPt = hookPt.chain; if (typeof fnRef=='object') hookPt=hookPt.concat(fnRef); // add other functions else hookPt[hookPt.length++]=fnRef; } return; } } // Register a function that will set runtime variables. function registerRunTimeFunction(fn) { if (isFunction(fn)) { if (typeof fn == 'object') { runTime = runTime.concat(fn); } else { runTime[runTime.length++] = fn; } } } // Register a function that will handle command parsing. function registerCmdLineFunction(fn){ if (isFunction(fn)) { if (typeof fn == 'object') { cmdLine = cmdLine.concat(fn); } else { cmdLine[cmdLine.length++] = fn; } } } // Register a function that does things after command parsing. function registerPostParseFunction(fn){ if (isFunction(fn)) { if (typeof fn == 'object') { postParse = postParse.concat(fn); } else { postParse[postParse.length++] = fn; } } } //////// // PLUGIN REGISTRATION FUNCTIONS //////// // Runs any hooks registered. function runHook(fnHookTo, hookType) { var l = hookPts[fnHookTo], k, rtnVal = null, optPm, arS, ar = runHook.arguments; if (hookType == FREPLACE) { arS = argToString(ar, 2); if (typeof l == 'undefined' || !(l = l.ovload)) rtnVal = eval(fnHookTo+'('+arS+')'); else rtnVal = eval('l('+arS+')'); } else if (hookType == FBEFORE || hookType == FAFTER) { if (typeof l != 'undefined') { l=(hookType == 1 ? l.before : l.after); if (l.length) { arS = argToString(ar, 2); for (var k = 0; k < l.length; k++) eval('l[k]('+arS+')'); } } } else if (hookType == FALTERNATE) { optPm = ar[2]; arS = argToString(ar, 3); if (typeof l == 'undefined' || (l = l.alt[pms[optPm-1-pmStart]]) == 'undefined') { rtnVal = eval(fnHookTo+'('+arS+')'); } else { rtnVal = eval('l('+arS+')'); } } else if (hookType == FCHAIN) { arS=argToString(ar,2); l=l.chain; for (k=l.length; k > 0; k--) if((rtnVal=eval('l[k-1]('+arS+')'))!=void(0)) break; } return rtnVal; } //////// // OBJECT CONSTRUCTORS //////// // Object for handling hooks. function FunctionReference() { this.ovload = null; this.before = new Array(); this.after = new Array(); this.alt = new Array(); this.chain = new Array(); } // Object for simple access to the overLIB version used. // Examples: simpleversion:351 major:3 minor:5 revision:1 function Info(version, prerelease) { this.version = version; this.prerelease = prerelease; this.simpleversion = Math.round(this.version*100); this.major = parseInt(this.simpleversion / 100); this.minor = parseInt(this.simpleversion / 10) - this.major * 10; this.revision = parseInt(this.simpleversion) - this.major * 100 - this.minor * 10; this.meets = meets; } // checks for Core Version required function meets(reqdVersion) { return (!reqdVersion) ? false : this.simpleversion >= Math.round(100*parseFloat(reqdVersion)); } //////// // STANDARD REGISTRATIONS //////// registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSOFF); registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSOFF); registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSOFF); registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSCLASS); registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSCLASS); registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSCLASS); registerPostParseFunction(checkPositionFlags); registerHook("hideObject", nbspCleanup, FAFTER); registerHook("horizontalPlacement", horizontalPlacement, FCHAIN); registerHook("verticalPlacement", verticalPlacement, FCHAIN); if (olNs4||(olIe5&&isMac)||olKq) olLoaded=1; registerNoParameterCommands('sticky,autostatus,autostatuscap,fullhtml,hauto,vauto,closeclick,wrap,followmouse,mouseoff,compatmode'); /////// // ESTABLISH MOUSECAPTURING /////// // Capture events, alt. diffuses the overlib function. var olCheckMouseCapture=true; if ((olNs4 || olNs6 || olIe4)) { olMouseCapture(); } else { overlib = no_overlib; nd = no_overlib; ver3fix = true; } // $Id: webstart.js,v 1.13 2008-01-14 15:05:28 grossben Exp $ //------------------------------------------------------------------------------ /** Copyright (c) 2007 Memorial Sloan-Kettering Cancer Center. ** ** Code written by: Ethan Cerami, Benjamin Gross ** Authors: Ethan Cerami, Gary Bader, Chris Sander, Benjamin Gross ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the GNU Lesser General Public License as published ** by the Free Software Foundation; either version 2.1 of the License, or ** any later version. ** ** This library is distributed in the hope that it will be useful, but ** WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF ** MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. The software and ** documentation provided hereunder is on an "as is" basis, and ** Memorial Sloan-Kettering Cancer Center ** has no obligations to provide maintenance, support, ** updates, enhancements or modifications. In no event shall ** Memorial Sloan-Kettering Cancer Center ** be liable to any party for direct, indirect, special, ** incidental or consequential damages, including lost profits, arising ** out of the use of this software and its documentation, even if ** Memorial Sloan-Kettering Cancer Center ** has been advised of the possibility of such damage. See ** the GNU Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this library; if not, write to the Free Software Foundation, ** Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. **/ /* * Javascript library to communication with java webstart application */ // globals var SCRIPT_ELEMENT_ID = "cytoscape"; var timoutVar; // used to set/unset timeout handlers var requestedID; // used to store record id link pressed var requestedCommand; // used to store web services command of link pressed var requestedNetworkViewTitle; // used to store web services title of link pressed - encoded from pc var requestedDataSources; // used to store web services data source filter - encoded from pc //var toolTip = "' To view this record in Cytoscape, click on this link. If Cytoscape is already running, the network will be loaded into Cytoscape straightaway. If Cytoscape is not running, Pathway Commons will attempt to load Cytoscape via Java Webstart. Click on the 'help' link for more information."; /* * Function to determine webstart version - taken from sun site */ function webstartVersionCheck(versionString) { // Mozilla may not recognize new plugins without this refresh navigator.plugins.refresh(true); // First, determine if Web Start is available if (navigator.mimeTypes['application/x-java-jnlp-file']) { // Next, check for appropriate version family for (var i = 0; i < navigator.mimeTypes.length; ++i) { var pluginType = navigator.mimeTypes[i].type; if (pluginType == "application/x-java-applet;version=" + versionString) { return true; } } } return true; } /* * Called when we haven't heard back webstart application */ function timeoutHandler() { var answer = confirm ("Press the 'OK' button to launch Cytoscape via Web Start. Depending on your network connection, this may take a minute or two."); if (answer) { // construct webstart url var hostname = window.location.hostname; var port = window.location.port; if (port) { hostname += (":" + port); } // note: context_path is set in stylesAndScripts.jsp var webstart_url = "http://" + hostname + context_path + "/cytoscape.jnlp?id=" + requestedID + "&command=" + requestedCommand; if (requestedNetworkViewTitle != "empty_title") { webstart_url += "&network_view_title=" + requestedNetworkViewTitle; } webstart_url += "&data_source=" + requestedDataSources; // determine if webstart is available - code taken from sun site var userAgent = navigator.userAgent.toLowerCase(); // user is running windows if (userAgent.indexOf("msie") != -1 && userAgent.indexOf("win") != -1){ document.write(""); } // user is not running windows else if (webstartVersionCheck("1.5")) { window.location = webstart_url; } // user does not have jre installed or lacks appropriate version - direct them to sun download site else { window.open("http://jdl.sun.com/webapps/getjava/BrowserRedirect?locale=en&host=java.com", "needdownload"); } } // outta here return false; } /* * Called when webstart program has returned with a response. */ function callBack() { clearTimeout(timeoutVar); } /* * Called to disable a link to the webstart. */ function disableLink(linkID) { var link = document.getElementById(linkID); if (link) { link.onclick = function() { return false; }; link.style.cursor = "default"; link.style.color = "#000000"; } } /** * Called to make a webstart app request */ function appRequest(url, linkID, command, networkViewTitle, dataSources) { // be good and remove the previous cytoscape script element // although, based on debugging, i'm not sure this really does anything var oldScript = document.getElementById(SCRIPT_ELEMENT_ID); if (oldScript) { oldScript.parentNode.removeChild(oldScript); } // create new script var newScript = document.createElement("script"); newScript.id = SCRIPT_ELEMENT_ID; newScript.setAttribute("type", "text/javascript"); newScript.setAttribute("src", url); // add new script to document (head section) var head = document.getElementsByTagName("head")[0]; head.appendChild(newScript); // disable link // we do this because some browsers // will not fetch data if the url has been fetched in the past disableLink(linkID); // save record id in case we have to pass to webstart requestedID = linkID; // save command in case we have to pass to webstart requestedCommand = command; // save title in case we have to pass to webstart requestedNetworkViewTitle = networkViewTitle; // save requested data sources requestedDataSources = dataSources; // set timeout - handler for when cytoscape is not running timeoutVar = setTimeout("timeoutHandler()", 1000); } /* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 0.12.0 */ (function() { var Event=YAHOO.util.Event; var Dom=YAHOO.util.Dom; /** * Defines the interface and base operation of items that that can be * dragged or can be drop targets. It was designed to be extended, overriding * the event handlers for startDrag, onDrag, onDragOver, onDragOut. * Up to three html elements can be associated with a DragDrop instance: **
* This class should not be instantiated until the onload event to ensure that * the associated elements are available. * The following would define a DragDrop obj that would interact with any * other DragDrop obj in the "group1" group: *- linked element: the element that is passed into the constructor. * This is the element which defines the boundaries for interaction with * other DragDrop objects.
*- handle element(s): The drag operation only occurs if the element that * was clicked matches a handle element. By default this is the linked * element, but there are times that you will want only a portion of the * linked element to initiate the drag operation, and the setHandleElId() * method provides a way to define this.
*- drag element: this represents an the element that would be moved along * with the cursor during a drag operation. By default, this is the linked * element itself as in {@link YAHOO.util.DD}. setDragElId() lets you define * a separate element that would be moved, as in {@link YAHOO.util.DDProxy} *
** dd = new YAHOO.util.DragDrop("div1", "group1"); ** Since none of the event handlers have been implemented, nothing would * actually happen if you were to run the code above. Normally you would * override this class or one of the default implementations, but you can * also override the methods you want on an instance of the class... ** dd.onDragDrop = function(e, id) { * alert("dd was dropped on " + id); * } ** @namespace YAHOO.util * @class DragDrop * @constructor * @param {String} id of the element that is linked to this instance * @param {String} sGroup the group of related DragDrop objects * @param {object} config an object containing configurable attributes * Valid properties for DragDrop: * padding, isTarget, maintainOffset, primaryButtonOnly */ YAHOO.util.DragDrop = function(id, sGroup, config) { if (id) { this.init(id, sGroup, config); } }; YAHOO.util.DragDrop.prototype = { /** * The id of the element associated with this object. This is what we * refer to as the "linked element" because the size and position of * this element is used to determine when the drag and drop objects have * interacted. * @property id * @type String */ id: null, /** * Configuration attributes passed into the constructor * @property config * @type object */ config: null, /** * The id of the element that will be dragged. By default this is same * as the linked element , but could be changed to another element. Ex: * YAHOO.util.DDProxy * @property dragElId * @type String * @private */ dragElId: null, /** * the id of the element that initiates the drag operation. By default * this is the linked element, but could be changed to be a child of this * element. This lets us do things like only starting the drag when the * header element within the linked html element is clicked. * @property handleElId * @type String * @private */ handleElId: null, /** * An associative array of HTML tags that will be ignored if clicked. * @property invalidHandleTypes * @type {string: string} */ invalidHandleTypes: null, /** * An associative array of ids for elements that will be ignored if clicked * @property invalidHandleIds * @type {string: string} */ invalidHandleIds: null, /** * An indexted array of css class names for elements that will be ignored * if clicked. * @property invalidHandleClasses * @type string[] */ invalidHandleClasses: null, /** * The linked element's absolute X position at the time the drag was * started * @property startPageX * @type int * @private */ startPageX: 0, /** * The linked element's absolute X position at the time the drag was * started * @property startPageY * @type int * @private */ startPageY: 0, /** * The group defines a logical collection of DragDrop objects that are * related. Instances only get events when interacting with other * DragDrop object in the same group. This lets us define multiple * groups using a single DragDrop subclass if we want. * @property groups * @type {string: string} */ groups: null, /** * Individual drag/drop instances can be locked. This will prevent * onmousedown start drag. * @property locked * @type boolean * @private */ locked: false, /** * Lock this instance * @method lock */ lock: function() { this.locked = true; }, /** * Unlock this instace * @method unlock */ unlock: function() { this.locked = false; }, /** * By default, all insances can be a drop target. This can be disabled by * setting isTarget to false. * @method isTarget * @type boolean */ isTarget: true, /** * The padding configured for this drag and drop object for calculating * the drop zone intersection with this object. * @method padding * @type int[] */ padding: null, /** * Cached reference to the linked element * @property _domRef * @private */ _domRef: null, /** * Internal typeof flag * @property __ygDragDrop * @private */ __ygDragDrop: true, /** * Set to true when horizontal contraints are applied * @property constrainX * @type boolean * @private */ constrainX: false, /** * Set to true when vertical contraints are applied * @property constrainY * @type boolean * @private */ constrainY: false, /** * The left constraint * @property minX * @type int * @private */ minX: 0, /** * The right constraint * @property maxX * @type int * @private */ maxX: 0, /** * The up constraint * @property minY * @type int * @type int * @private */ minY: 0, /** * The down constraint * @property maxY * @type int * @private */ maxY: 0, /** * Maintain offsets when we resetconstraints. Set to true when you want * the position of the element relative to its parent to stay the same * when the page changes * * @property maintainOffset * @type boolean */ maintainOffset: false, /** * Array of pixel locations the element will snap to if we specified a * horizontal graduation/interval. This array is generated automatically * when you define a tick interval. * @property xTicks * @type int[] */ xTicks: null, /** * Array of pixel locations the element will snap to if we specified a * vertical graduation/interval. This array is generated automatically * when you define a tick interval. * @property yTicks * @type int[] */ yTicks: null, /** * By default the drag and drop instance will only respond to the primary * button click (left button for a right-handed mouse). Set to true to * allow drag and drop to start with any mouse click that is propogated * by the browser * @property primaryButtonOnly * @type boolean */ primaryButtonOnly: true, /** * The availabe property is false until the linked dom element is accessible. * @property available * @type boolean */ available: false, /** * By default, drags can only be initiated if the mousedown occurs in the * region the linked element is. This is done in part to work around a * bug in some browsers that mis-report the mousedown if the previous * mouseup happened outside of the window. This property is set to true * if outer handles are defined. * * @property hasOuterHandles * @type boolean * @default false */ hasOuterHandles: false, /** * Code that executes immediately before the startDrag event * @method b4StartDrag * @private */ b4StartDrag: function(x, y) { }, /** * Abstract method called after a drag/drop object is clicked * and the drag or mousedown time thresholds have beeen met. * @method startDrag * @param {int} X click location * @param {int} Y click location */ startDrag: function(x, y) { /* override this */ }, /** * Code that executes immediately before the onDrag event * @method b4Drag * @private */ b4Drag: function(e) { }, /** * Abstract method called during the onMouseMove event while dragging an * object. * @method onDrag * @param {Event} e the mousemove event */ onDrag: function(e) { /* override this */ }, /** * Abstract method called when this element fist begins hovering over * another DragDrop obj * @method onDragEnter * @param {Event} e the mousemove event * @param {String|DragDrop[]} id In POINT mode, the element * id this is hovering over. In INTERSECT mode, an array of one or more * dragdrop items being hovered over. */ onDragEnter: function(e, id) { /* override this */ }, /** * Code that executes immediately before the onDragOver event * @method b4DragOver * @private */ b4DragOver: function(e) { }, /** * Abstract method called when this element is hovering over another * DragDrop obj * @method onDragOver * @param {Event} e the mousemove event * @param {String|DragDrop[]} id In POINT mode, the element * id this is hovering over. In INTERSECT mode, an array of dd items * being hovered over. */ onDragOver: function(e, id) { /* override this */ }, /** * Code that executes immediately before the onDragOut event * @method b4DragOut * @private */ b4DragOut: function(e) { }, /** * Abstract method called when we are no longer hovering over an element * @method onDragOut * @param {Event} e the mousemove event * @param {String|DragDrop[]} id In POINT mode, the element * id this was hovering over. In INTERSECT mode, an array of dd items * that the mouse is no longer over. */ onDragOut: function(e, id) { /* override this */ }, /** * Code that executes immediately before the onDragDrop event * @method b4DragDrop * @private */ b4DragDrop: function(e) { }, /** * Abstract method called when this item is dropped on another DragDrop * obj * @method onDragDrop * @param {Event} e the mouseup event * @param {String|DragDrop[]} id In POINT mode, the element * id this was dropped on. In INTERSECT mode, an array of dd items this * was dropped on. */ onDragDrop: function(e, id) { /* override this */ }, /** * Abstract method called when this item is dropped on an area with no * drop target * @method onInvalidDrop * @param {Event} e the mouseup event */ onInvalidDrop: function(e) { /* override this */ }, /** * Code that executes immediately before the endDrag event * @method b4EndDrag * @private */ b4EndDrag: function(e) { }, /** * Fired when we are done dragging the object * @method endDrag * @param {Event} e the mouseup event */ endDrag: function(e) { /* override this */ }, /** * Code executed immediately before the onMouseDown event * @method b4MouseDown * @param {Event} e the mousedown event * @private */ b4MouseDown: function(e) { }, /** * Event handler that fires when a drag/drop obj gets a mousedown * @method onMouseDown * @param {Event} e the mousedown event */ onMouseDown: function(e) { /* override this */ }, /** * Event handler that fires when a drag/drop obj gets a mouseup * @method onMouseUp * @param {Event} e the mouseup event */ onMouseUp: function(e) { /* override this */ }, /** * Override the onAvailable method to do what is needed after the initial * position was determined. * @method onAvailable */ onAvailable: function () { }, /** * Returns a reference to the linked element * @method getEl * @return {HTMLElement} the html element */ getEl: function() { if (!this._domRef) { this._domRef = Dom.get(this.id); } return this._domRef; }, /** * Returns a reference to the actual element to drag. By default this is * the same as the html element, but it can be assigned to another * element. An example of this can be found in YAHOO.util.DDProxy * @method getDragEl * @return {HTMLElement} the html element */ getDragEl: function() { return Dom.get(this.dragElId); }, /** * Sets up the DragDrop object. Must be called in the constructor of any * YAHOO.util.DragDrop subclass * @method init * @param id the id of the linked element * @param {String} sGroup the group of related items * @param {object} config configuration attributes */ init: function(id, sGroup, config) { this.initTarget(id, sGroup, config); Event.on(this.id, "mousedown", this.handleMouseDown, this, true); // Event.on(this.id, "selectstart", Event.preventDefault); }, /** * Initializes Targeting functionality only... the object does not * get a mousedown handler. * @method initTarget * @param id the id of the linked element * @param {String} sGroup the group of related items * @param {object} config configuration attributes */ initTarget: function(id, sGroup, config) { // configuration attributes this.config = config || {}; // create a local reference to the drag and drop manager this.DDM = YAHOO.util.DDM; // initialize the groups array this.groups = {}; // assume that we have an element reference instead of an id if the // parameter is not a string if (typeof id !== "string") { YAHOO.log("id is not a string, assuming it is an HTMLElement"); id = Dom.generateId(id); } // set the id this.id = id; // add to an interaction group this.addToGroup((sGroup) ? sGroup : "default"); // We don't want to register this as the handle with the manager // so we just set the id rather than calling the setter. this.handleElId = id; Event.onAvailable(id, this.handleOnAvailable, this, true); // the linked element is the element that gets dragged by default this.setDragElId(id); // by default, clicked anchors will not start drag operations. // @TODO what else should be here? Probably form fields. this.invalidHandleTypes = { A: "A" }; this.invalidHandleIds = {}; this.invalidHandleClasses = []; this.applyConfig(); }, /** * Applies the configuration parameters that were passed into the constructor. * This is supposed to happen at each level through the inheritance chain. So * a DDProxy implentation will execute apply config on DDProxy, DD, and * DragDrop in order to get all of the parameters that are available in * each object. * @method applyConfig */ applyConfig: function() { // configurable properties: // padding, isTarget, maintainOffset, primaryButtonOnly this.padding = this.config.padding || [0, 0, 0, 0]; this.isTarget = (this.config.isTarget !== false); this.maintainOffset = (this.config.maintainOffset); this.primaryButtonOnly = (this.config.primaryButtonOnly !== false); }, /** * Executed when the linked element is available * @method handleOnAvailable * @private */ handleOnAvailable: function() { this.available = true; this.resetConstraints(); this.onAvailable(); }, /** * Configures the padding for the target zone in px. Effectively expands * (or reduces) the virtual object size for targeting calculations. * Supports css-style shorthand; if only one parameter is passed, all sides * will have that padding, and if only two are passed, the top and bottom * will have the first param, the left and right the second. * @method setPadding * @param {int} iTop Top pad * @param {int} iRight Right pad * @param {int} iBot Bot pad * @param {int} iLeft Left pad */ setPadding: function(iTop, iRight, iBot, iLeft) { // this.padding = [iLeft, iRight, iTop, iBot]; if (!iRight && 0 !== iRight) { this.padding = [iTop, iTop, iTop, iTop]; } else if (!iBot && 0 !== iBot) { this.padding = [iTop, iRight, iTop, iRight]; } else { this.padding = [iTop, iRight, iBot, iLeft]; } }, /** * Stores the initial placement of the linked element. * @method setInitialPosition * @param {int} diffX the X offset, default 0 * @param {int} diffY the Y offset, default 0 */ setInitPosition: function(diffX, diffY) { var el = this.getEl(); if (!this.DDM.verifyEl(el)) { return; } var dx = diffX || 0; var dy = diffY || 0; var p = Dom.getXY( el ); this.initPageX = p[0] - dx; this.initPageY = p[1] - dy; this.lastPageX = p[0]; this.lastPageY = p[1]; this.setStartPosition(p); }, /** * Sets the start position of the element. This is set when the obj * is initialized, the reset when a drag is started. * @method setStartPosition * @param pos current position (from previous lookup) * @private */ setStartPosition: function(pos) { var p = pos || Dom.getXY( this.getEl() ); this.deltaSetXY = null; this.startPageX = p[0]; this.startPageY = p[1]; }, /** * Add this instance to a group of related drag/drop objects. All * instances belong to at least one group, and can belong to as many * groups as needed. * @method addToGroup * @param sGroup {string} the name of the group */ addToGroup: function(sGroup) { this.groups[sGroup] = true; this.DDM.regDragDrop(this, sGroup); }, /** * Remove's this instance from the supplied interaction group * @method removeFromGroup * @param {string} sGroup The group to drop */ removeFromGroup: function(sGroup) { if (this.groups[sGroup]) { delete this.groups[sGroup]; } this.DDM.removeDDFromGroup(this, sGroup); }, /** * Allows you to specify that an element other than the linked element * will be moved with the cursor during a drag * @method setDragElId * @param id {string} the id of the element that will be used to initiate the drag */ setDragElId: function(id) { this.dragElId = id; }, /** * Allows you to specify a child of the linked element that should be * used to initiate the drag operation. An example of this would be if * you have a content div with text and links. Clicking anywhere in the * content area would normally start the drag operation. Use this method * to specify that an element inside of the content div is the element * that starts the drag operation. * @method setHandleElId * @param id {string} the id of the element that will be used to * initiate the drag. */ setHandleElId: function(id) { if (typeof id !== "string") { YAHOO.log("id is not a string, assuming it is an HTMLElement"); id = Dom.generateId(id); } this.handleElId = id; this.DDM.regHandle(this.id, id); }, /** * Allows you to set an element outside of the linked element as a drag * handle * @method setOuterHandleElId * @param id the id of the element that will be used to initiate the drag */ setOuterHandleElId: function(id) { if (typeof id !== "string") { YAHOO.log("id is not a string, assuming it is an HTMLElement"); id = Dom.generateId(id); } Event.on(id, "mousedown", this.handleMouseDown, this, true); this.setHandleElId(id); this.hasOuterHandles = true; }, /** * Remove all drag and drop hooks for this element * @method unreg */ unreg: function() { Event.removeListener(this.id, "mousedown", this.handleMouseDown); this._domRef = null; this.DDM._remove(this); }, /** * Returns true if this instance is locked, or the drag drop mgr is locked * (meaning that all drag/drop is disabled on the page.) * @method isLocked * @return {boolean} true if this obj or all drag/drop is locked, else * false */ isLocked: function() { return (this.DDM.isLocked() || this.locked); }, /** * Fired when this object is clicked * @method handleMouseDown * @param {Event} e * @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj) * @private */ handleMouseDown: function(e, oDD) { var button = e.which || e.button; if (this.primaryButtonOnly && button > 1) { return; } if (this.isLocked()) { return; } this.DDM.refreshCache(this.groups); // var self = this; // setTimeout( function() { self.DDM.refreshCache(self.groups); }, 0); // Only process the event if we really clicked within the linked // element. The reason we make this check is that in the case that // another element was moved between the clicked element and the // cursor in the time between the mousedown and mouseup events. When // this happens, the element gets the next mousedown event // regardless of where on the screen it happened. var pt = new YAHOO.util.Point(Event.getPageX(e), Event.getPageY(e)); if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) { } else { if (this.clickValidator(e)) { // set the initial element position this.setStartPosition(); this.b4MouseDown(e); this.onMouseDown(e); this.DDM.handleMouseDown(e, this); this.DDM.stopEvent(e); } else { } } }, clickValidator: function(e) { var target = Event.getTarget(e); return ( this.isValidHandleChild(target) && (this.id == this.handleElId || this.DDM.handleWasClicked(target, this.id)) ); }, /** * Allows you to specify a tag name that should not start a drag operation * when clicked. This is designed to facilitate embedding links within a * drag handle that do something other than start the drag. * @method addInvalidHandleType * @param {string} tagName the type of element to exclude */ addInvalidHandleType: function(tagName) { var type = tagName.toUpperCase(); this.invalidHandleTypes[type] = type; }, /** * Lets you to specify an element id for a child of a drag handle * that should not initiate a drag * @method addInvalidHandleId * @param {string} id the element id of the element you wish to ignore */ addInvalidHandleId: function(id) { if (typeof id !== "string") { YAHOO.log("id is not a string, assuming it is an HTMLElement"); id = Dom.generateId(id); } this.invalidHandleIds[id] = id; }, /** * Lets you specify a css class of elements that will not initiate a drag * @method addInvalidHandleClass * @param {string} cssClass the class of the elements you wish to ignore */ addInvalidHandleClass: function(cssClass) { this.invalidHandleClasses.push(cssClass); }, /** * Unsets an excluded tag name set by addInvalidHandleType * @method removeInvalidHandleType * @param {string} tagName the type of element to unexclude */ removeInvalidHandleType: function(tagName) { var type = tagName.toUpperCase(); // this.invalidHandleTypes[type] = null; delete this.invalidHandleTypes[type]; }, /** * Unsets an invalid handle id * @method removeInvalidHandleId * @param {string} id the id of the element to re-enable */ removeInvalidHandleId: function(id) { if (typeof id !== "string") { YAHOO.log("id is not a string, assuming it is an HTMLElement"); id = Dom.generateId(id); } delete this.invalidHandleIds[id]; }, /** * Unsets an invalid css class * @method removeInvalidHandleClass * @param {string} cssClass the class of the element(s) you wish to * re-enable */ removeInvalidHandleClass: function(cssClass) { for (var i=0, len=this.invalidHandleClasses.length; i= this.minX; i = i - iTickSize) { if (!tickMap[i]) { this.xTicks[this.xTicks.length] = i; tickMap[i] = true; } } for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) { if (!tickMap[i]) { this.xTicks[this.xTicks.length] = i; tickMap[i] = true; } } this.xTicks.sort(this.DDM.numericSort) ; }, /** * Create the array of vertical tick marks if an interval was specified in * setYConstraint(). * @method setYTicks * @private */ setYTicks: function(iStartY, iTickSize) { this.yTicks = []; this.yTickSize = iTickSize; var tickMap = {}; for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) { if (!tickMap[i]) { this.yTicks[this.yTicks.length] = i; tickMap[i] = true; } } for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) { if (!tickMap[i]) { this.yTicks[this.yTicks.length] = i; tickMap[i] = true; } } this.yTicks.sort(this.DDM.numericSort) ; }, /** * By default, the element can be dragged any place on the screen. Use * this method to limit the horizontal travel of the element. Pass in * 0,0 for the parameters if you want to lock the drag to the y axis. * @method setXConstraint * @param {int} iLeft the number of pixels the element can move to the left * @param {int} iRight the number of pixels the element can move to the * right * @param {int} iTickSize optional parameter for specifying that the * element * should move iTickSize pixels at a time. */ setXConstraint: function(iLeft, iRight, iTickSize) { this.leftConstraint = iLeft; this.rightConstraint = iRight; this.minX = this.initPageX - iLeft; this.maxX = this.initPageX + iRight; if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); } this.constrainX = true; }, /** * Clears any constraints applied to this instance. Also clears ticks * since they can't exist independent of a constraint at this time. * @method clearConstraints */ clearConstraints: function() { this.constrainX = false; this.constrainY = false; this.clearTicks(); }, /** * Clears any tick interval defined for this instance * @method clearTicks */ clearTicks: function() { this.xTicks = null; this.yTicks = null; this.xTickSize = 0; this.yTickSize = 0; }, /** * By default, the element can be dragged any place on the screen. Set * this to limit the vertical travel of the element. Pass in 0,0 for the * parameters if you want to lock the drag to the x axis. * @method setYConstraint * @param {int} iUp the number of pixels the element can move up * @param {int} iDown the number of pixels the element can move down * @param {int} iTickSize optional parameter for specifying that the * element should move iTickSize pixels at a time. */ setYConstraint: function(iUp, iDown, iTickSize) { this.topConstraint = iUp; this.bottomConstraint = iDown; this.minY = this.initPageY - iUp; this.maxY = this.initPageY + iDown; if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); } this.constrainY = true; }, /** * resetConstraints must be called if you manually reposition a dd element. * @method resetConstraints * @param {boolean} maintainOffset */ resetConstraints: function() { // Maintain offsets if necessary if (this.initPageX || this.initPageX === 0) { // figure out how much this thing has moved var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0; var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0; this.setInitPosition(dx, dy); // This is the first time we have detected the element's position } else { this.setInitPosition(); } if (this.constrainX) { this.setXConstraint( this.leftConstraint, this.rightConstraint, this.xTickSize ); } if (this.constrainY) { this.setYConstraint( this.topConstraint, this.bottomConstraint, this.yTickSize ); } }, /** * Normally the drag element is moved pixel by pixel, but we can specify * that it move a number of pixels at a time. This method resolves the * location when we have it set up like this. * @method getTick * @param {int} val where we want to place the object * @param {int[]} tickArray sorted array of valid points * @return {int} the closest tick * @private */ getTick: function(val, tickArray) { if (!tickArray) { // If tick interval is not defined, it is effectively 1 pixel, // so we return the value passed to us. return val; } else if (tickArray[0] >= val) { // The value is lower than the first tick, so we return the first // tick. return tickArray[0]; } else { for (var i=0, len=tickArray.length; i = val) { var diff1 = val - tickArray[i]; var diff2 = tickArray[next] - val; return (diff2 > diff1) ? tickArray[i] : tickArray[next]; } } // The value is larger than the last tick, so we return the last // tick. return tickArray[tickArray.length - 1]; } }, /** * toString method * @method toString * @return {string} string representation of the dd obj */ toString: function() { return ("DragDrop " + this.id); } }; })(); /** * The drag and drop utility provides a framework for building drag and drop * applications. In addition to enabling drag and drop for specific elements, * the drag and drop elements are tracked by the manager class, and the * interactions between the various elements are tracked during the drag and * the implementing code is notified about these important moments. * @module dragdrop * @title Drag and Drop * @requires yahoo,dom,event * @namespace YAHOO.util */ // Only load the library once. Rewriting the manager class would orphan // existing drag and drop instances. if (!YAHOO.util.DragDropMgr) { /** * DragDropMgr is a singleton that tracks the element interaction for * all DragDrop items in the window. Generally, you will not call * this class directly, but it does have helper methods that could * be useful in your DragDrop implementations. * @class DragDropMgr * @static */ YAHOO.util.DragDropMgr = function() { var Event = YAHOO.util.Event; return { /** * Two dimensional Array of registered DragDrop objects. The first * dimension is the DragDrop item group, the second the DragDrop * object. * @property ids * @type {string: string} * @private * @static */ ids: {}, /** * Array of element ids defined as drag handles. Used to determine * if the element that generated the mousedown event is actually the * handle and not the html element itself. * @property handleIds * @type {string: string} * @private * @static */ handleIds: {}, /** * the DragDrop object that is currently being dragged * @property dragCurrent * @type DragDrop * @private * @static **/ dragCurrent: null, /** * the DragDrop object(s) that are being hovered over * @property dragOvers * @type Array * @private * @static */ dragOvers: {}, /** * the X distance between the cursor and the object being dragged * @property deltaX * @type int * @private * @static */ deltaX: 0, /** * the Y distance between the cursor and the object being dragged * @property deltaY * @type int * @private * @static */ deltaY: 0, /** * Flag to determine if we should prevent the default behavior of the * events we define. By default this is true, but this can be set to * false if you need the default behavior (not recommended) * @property preventDefault * @type boolean * @static */ preventDefault: true, /** * Flag to determine if we should stop the propagation of the events * we generate. This is true by default but you may want to set it to * false if the html element contains other features that require the * mouse click. * @property stopPropagation * @type boolean * @static */ stopPropagation: true, /** * Internal flag that is set to true when drag and drop has been * intialized * @property initialized * @private * @static */ initalized: false, /** * All drag and drop can be disabled. * @property locked * @private * @static */ locked: false, /** * Called the first time an element is registered. * @method init * @private * @static */ init: function() { this.initialized = true; }, /** * In point mode, drag and drop interaction is defined by the * location of the cursor during the drag/drop * @property POINT * @type int * @static */ POINT: 0, /** * In intersect mode, drag and drop interactio nis defined by the * overlap of two or more drag and drop objects. * @property INTERSECT * @type int * @static */ INTERSECT: 1, /** * The current drag and drop mode. Default: POINT * @property mode * @type int * @static */ mode: 0, /** * Runs method on all drag and drop objects * @method _execOnAll * @private * @static */ _execOnAll: function(sMethod, args) { for (var i in this.ids) { for (var j in this.ids[i]) { var oDD = this.ids[i][j]; if (! this.isTypeOfDD(oDD)) { continue; } oDD[sMethod].apply(oDD, args); } } }, /** * Drag and drop initialization. Sets up the global event handlers * @method _onLoad * @private * @static */ _onLoad: function() { this.init(); Event.on(document, "mouseup", this.handleMouseUp, this, true); Event.on(document, "mousemove", this.handleMouseMove, this, true); Event.on(window, "unload", this._onUnload, this, true); Event.on(window, "resize", this._onResize, this, true); // Event.on(window, "mouseout", this._test); }, /** * Reset constraints on all drag and drop objs * @method _onResize * @private * @static */ _onResize: function(e) { this._execOnAll("resetConstraints", []); }, /** * Lock all drag and drop functionality * @method lock * @static */ lock: function() { this.locked = true; }, /** * Unlock all drag and drop functionality * @method unlock * @static */ unlock: function() { this.locked = false; }, /** * Is drag and drop locked? * @method isLocked * @return {boolean} True if drag and drop is locked, false otherwise. * @static */ isLocked: function() { return this.locked; }, /** * Location cache that is set for all drag drop objects when a drag is * initiated, cleared when the drag is finished. * @property locationCache * @private * @static */ locationCache: {}, /** * Set useCache to false if you want to force object the lookup of each * drag and drop linked element constantly during a drag. * @property useCache * @type boolean * @static */ useCache: true, /** * The number of pixels that the mouse needs to move after the * mousedown before the drag is initiated. Default=3; * @property clickPixelThresh * @type int * @static */ clickPixelThresh: 3, /** * The number of milliseconds after the mousedown event to initiate the * drag if we don't get a mouseup event. Default=1000 * @property clickTimeThresh * @type int * @static */ clickTimeThresh: 1000, /** * Flag that indicates that either the drag pixel threshold or the * mousdown time threshold has been met * @property dragThreshMet * @type boolean * @private * @static */ dragThreshMet: false, /** * Timeout used for the click time threshold * @property clickTimeout * @type Object * @private * @static */ clickTimeout: null, /** * The X position of the mousedown event stored for later use when a * drag threshold is met. * @property startX * @type int * @private * @static */ startX: 0, /** * The Y position of the mousedown event stored for later use when a * drag threshold is met. * @property startY * @type int * @private * @static */ startY: 0, /** * Each DragDrop instance must be registered with the DragDropMgr. * This is executed in DragDrop.init() * @method regDragDrop * @param {DragDrop} oDD the DragDrop object to register * @param {String} sGroup the name of the group this element belongs to * @static */ regDragDrop: function(oDD, sGroup) { if (!this.initialized) { this.init(); } if (!this.ids[sGroup]) { this.ids[sGroup] = {}; } this.ids[sGroup][oDD.id] = oDD; }, /** * Removes the supplied dd instance from the supplied group. Executed * by DragDrop.removeFromGroup, so don't call this function directly. * @method removeDDFromGroup * @private * @static */ removeDDFromGroup: function(oDD, sGroup) { if (!this.ids[sGroup]) { this.ids[sGroup] = {}; } var obj = this.ids[sGroup]; if (obj && obj[oDD.id]) { delete obj[oDD.id]; } }, /** * Unregisters a drag and drop item. This is executed in * DragDrop.unreg, use that method instead of calling this directly. * @method _remove * @private * @static */ _remove: function(oDD) { for (var g in oDD.groups) { if (g && this.ids[g][oDD.id]) { delete this.ids[g][oDD.id]; } } delete this.handleIds[oDD.id]; }, /** * Each DragDrop handle element must be registered. This is done * automatically when executing DragDrop.setHandleElId() * @method regHandle * @param {String} sDDId the DragDrop id this element is a handle for * @param {String} sHandleId the id of the element that is the drag * handle * @static */ regHandle: function(sDDId, sHandleId) { if (!this.handleIds[sDDId]) { this.handleIds[sDDId] = {}; } this.handleIds[sDDId][sHandleId] = sHandleId; }, /** * Utility function to determine if a given element has been * registered as a drag drop item. * @method isDragDrop * @param {String} id the element id to check * @return {boolean} true if this element is a DragDrop item, * false otherwise * @static */ isDragDrop: function(id) { return ( this.getDDById(id) ) ? true : false; }, /** * Returns the drag and drop instances that are in all groups the * passed in instance belongs to. * @method getRelated * @param {DragDrop} p_oDD the obj to get related data for * @param {boolean} bTargetsOnly if true, only return targetable objs * @return {DragDrop[]} the related instances * @static */ getRelated: function(p_oDD, bTargetsOnly) { var oDDs = []; for (var i in p_oDD.groups) { for (j in this.ids[i]) { var dd = this.ids[i][j]; if (! this.isTypeOfDD(dd)) { continue; } if (!bTargetsOnly || dd.isTarget) { oDDs[oDDs.length] = dd; } } } return oDDs; }, /** * Returns true if the specified dd target is a legal target for * the specifice drag obj * @method isLegalTarget * @param {DragDrop} the drag obj * @param {DragDrop} the target * @return {boolean} true if the target is a legal target for the * dd obj * @static */ isLegalTarget: function (oDD, oTargetDD) { var targets = this.getRelated(oDD, true); for (var i=0, len=targets.length;i this.clickPixelThresh || diffY > this.clickPixelThresh) { this.startDrag(this.startX, this.startY); } } if (this.dragThreshMet) { this.dragCurrent.b4Drag(e); this.dragCurrent.onDrag(e); this.fireEvents(e, false); } this.stopEvent(e); return true; }, /** * Iterates over all of the DragDrop elements to find ones we are * hovering over or dropping on * @method fireEvents * @param {Event} e the event * @param {boolean} isDrop is this a drop op or a mouseover op? * @private * @static */ fireEvents: function(e, isDrop) { var dc = this.dragCurrent; // If the user did the mouse up outside of the window, we could // get here even though we have ended the drag. if (!dc || dc.isLocked()) { return; } var x = YAHOO.util.Event.getPageX(e); var y = YAHOO.util.Event.getPageY(e); var pt = new YAHOO.util.Point(x,y); // cache the previous dragOver array var oldOvers = []; var outEvts = []; var overEvts = []; var dropEvts = []; var enterEvts = []; // Check to see if the object(s) we were hovering over is no longer // being hovered over so we can fire the onDragOut event for (var i in this.dragOvers) { var ddo = this.dragOvers[i]; if (! this.isTypeOfDD(ddo)) { continue; } if (! this.isOverTarget(pt, ddo, this.mode)) { outEvts.push( ddo ); } oldOvers[i] = true; delete this.dragOvers[i]; } for (var sGroup in dc.groups) { if ("string" != typeof sGroup) { continue; } for (i in this.ids[sGroup]) { var oDD = this.ids[sGroup][i]; if (! this.isTypeOfDD(oDD)) { continue; } if (oDD.isTarget && !oDD.isLocked() && oDD != dc) { if (this.isOverTarget(pt, oDD, this.mode)) { // look for drop interactions if (isDrop) { dropEvts.push( oDD ); // look for drag enter and drag over interactions } else { // initial drag over: dragEnter fires if (!oldOvers[oDD.id]) { enterEvts.push( oDD ); // subsequent drag overs: dragOver fires } else { overEvts.push( oDD ); } this.dragOvers[oDD.id] = oDD; } } } } } if (this.mode) { if (outEvts.length) { dc.b4DragOut(e, outEvts); dc.onDragOut(e, outEvts); } if (enterEvts.length) { dc.onDragEnter(e, enterEvts); } if (overEvts.length) { dc.b4DragOver(e, overEvts); dc.onDragOver(e, overEvts); } if (dropEvts.length) { dc.b4DragDrop(e, dropEvts); dc.onDragDrop(e, dropEvts); } } else { // fire dragout events var len = 0; for (i=0, len=outEvts.length; i * YAHOO.util.DragDropMgr.refreshCache(ddinstance.groups); * * Alternatively: * * YAHOO.util.DragDropMgr.refreshCache({group1:true, group2:true}); *
* @TODO this really should be an indexed array. Alternatively this * method could accept both. * @method refreshCache * @param {Object} groups an associative array of groups to refresh * @static */ refreshCache: function(groups) { for (var sGroup in groups) { if ("string" != typeof sGroup) { continue; } for (var i in this.ids[sGroup]) { var oDD = this.ids[sGroup][i]; if (this.isTypeOfDD(oDD)) { // if (this.isTypeOfDD(oDD) && oDD.isTarget) { var loc = this.getLocation(oDD); if (loc) { this.locationCache[oDD.id] = loc; } else { delete this.locationCache[oDD.id]; // this will unregister the drag and drop object if // the element is not in a usable state // oDD.unreg(); } } } } }, /** * This checks to make sure an element exists and is in the DOM. The * main purpose is to handle cases where innerHTML is used to remove * drag and drop objects from the DOM. IE provides an 'unspecified * error' when trying to access the offsetParent of such an element * @method verifyEl * @param {HTMLElement} el the element to check * @return {boolean} true if the element looks usable * @static */ verifyEl: function(el) { try { if (el) { var parent = el.offsetParent; if (parent) { return true; } } } catch(e) { } return false; }, /** * Returns a Region object containing the drag and drop element's position * and size, including the padding configured for it * @method getLocation * @param {DragDrop} oDD the drag and drop object to get the * location for * @return {YAHOO.util.Region} a Region object representing the total area * the element occupies, including any padding * the instance is configured for. * @static */ getLocation: function(oDD) { if (! this.isTypeOfDD(oDD)) { return null; } var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l; try { pos= YAHOO.util.Dom.getXY(el); } catch (e) { } if (!pos) { return null; } x1 = pos[0]; x2 = x1 + el.offsetWidth; y1 = pos[1]; y2 = y1 + el.offsetHeight; t = y1 - oDD.padding[0]; r = x2 + oDD.padding[1]; b = y2 + oDD.padding[2]; l = x1 - oDD.padding[3]; return new YAHOO.util.Region( t, r, b, l ); }, /** * Checks the cursor location to see if it over the target * @method isOverTarget * @param {YAHOO.util.Point} pt The point to evaluate * @param {DragDrop} oTarget the DragDrop object we are inspecting * @return {boolean} true if the mouse is over the target * @private * @static */ isOverTarget: function(pt, oTarget, intersect) { // use cache if available var loc = this.locationCache[oTarget.id]; if (!loc || !this.useCache) { loc = this.getLocation(oTarget); this.locationCache[oTarget.id] = loc; } if (!loc) { return false; } oTarget.cursorIsOver = loc.contains( pt ); // DragDrop is using this as a sanity check for the initial mousedown // in this case we are done. In POINT mode, if the drag obj has no // contraints, we are also done. Otherwise we need to evaluate the // location of the target as related to the actual location of the // dragged element. var dc = this.dragCurrent; if (!dc || !dc.getTargetCoord || (!intersect && !dc.constrainX && !dc.constrainY)) { return oTarget.cursorIsOver; } oTarget.overlap = null; // Get the current location of the drag element, this is the // location of the mouse event less the delta that represents // where the original mousedown happened on the element. We // need to consider constraints and ticks as well. var pos = dc.getTargetCoord(pt.x, pt.y); var el = dc.getDragEl(); var curRegion = new YAHOO.util.Region( pos.y, pos.x + el.offsetWidth, pos.y + el.offsetHeight, pos.x ); var overlap = curRegion.intersect(loc); if (overlap) { oTarget.overlap = overlap; return (intersect) ? true : oTarget.cursorIsOver; } else { return false; } }, /** * unload event handler * @method _onUnload * @private * @static */ _onUnload: function(e, me) { this.unregAll(); }, /** * Cleans up the drag and drop events and objects. * @method unregAll * @private * @static */ unregAll: function() { if (this.dragCurrent) { this.stopDrag(); this.dragCurrent = null; } this._execOnAll("unreg", []); for (i in this.elementCache) { delete this.elementCache[i]; } this.elementCache = {}; this.ids = {}; }, /** * A cache of DOM elements * @property elementCache * @private * @static */ elementCache: {}, /** * Get the wrapper for the DOM element specified * @method getElWrapper * @param {String} id the id of the element to get * @return {YAHOO.util.DDM.ElementWrapper} the wrapped element * @private * @deprecated This wrapper isn't that useful * @static */ getElWrapper: function(id) { var oWrapper = this.elementCache[id]; if (!oWrapper || !oWrapper.el) { oWrapper = this.elementCache[id] = new this.ElementWrapper(YAHOO.util.Dom.get(id)); } return oWrapper; }, /** * Returns the actual DOM element * @method getElement * @param {String} id the id of the elment to get * @return {Object} The element * @deprecated use YAHOO.util.Dom.get instead * @static */ getElement: function(id) { return YAHOO.util.Dom.get(id); }, /** * Returns the style property for the DOM element (i.e., * document.getElById(id).style) * @method getCss * @param {String} id the id of the elment to get * @return {Object} The style property of the element * @deprecated use YAHOO.util.Dom instead * @static */ getCss: function(id) { var el = YAHOO.util.Dom.get(id); return (el) ? el.style : null; }, /** * Inner class for cached elements * @class DragDropMgr.ElementWrapper * @for DragDropMgr * @private * @deprecated */ ElementWrapper: function(el) { /** * The element * @property el */ this.el = el || null; /** * The element id * @property id */ this.id = this.el && el.id; /** * A reference to the style property * @property css */ this.css = this.el && el.style; }, /** * Returns the X position of an html element * @method getPosX * @param el the element for which to get the position * @return {int} the X coordinate * @for DragDropMgr * @deprecated use YAHOO.util.Dom.getX instead * @static */ getPosX: function(el) { return YAHOO.util.Dom.getX(el); }, /** * Returns the Y position of an html element * @method getPosY * @param el the element for which to get the position * @return {int} the Y coordinate * @deprecated use YAHOO.util.Dom.getY instead * @static */ getPosY: function(el) { return YAHOO.util.Dom.getY(el); }, /** * Swap two nodes. In IE, we use the native method, for others we * emulate the IE behavior * @method swapNode * @param n1 the first node to swap * @param n2 the other node to swap * @static */ swapNode: function(n1, n2) { if (n1.swapNode) { n1.swapNode(n2); } else { var p = n2.parentNode; var s = n2.nextSibling; if (s == n1) { p.insertBefore(n1, n2); } else if (n2 == n1.nextSibling) { p.insertBefore(n2, n1); } else { n1.parentNode.replaceChild(n2, n1); p.insertBefore(n1, s); } } }, /** * Returns the current scroll position * @method getScroll * @private * @static */ getScroll: function () { var t, l, dde=document.documentElement, db=document.body; if (dde && (dde.scrollTop || dde.scrollLeft)) { t = dde.scrollTop; l = dde.scrollLeft; } else if (db) { t = db.scrollTop; l = db.scrollLeft; } else { YAHOO.log("could not get scroll property"); } return { top: t, left: l }; }, /** * Returns the specified element style property * @method getStyle * @param {HTMLElement} el the element * @param {string} styleProp the style property * @return {string} The value of the style property * @deprecated use YAHOO.util.Dom.getStyle * @static */ getStyle: function(el, styleProp) { return YAHOO.util.Dom.getStyle(el, styleProp); }, /** * Gets the scrollTop * @method getScrollTop * @return {int} the document's scrollTop * @static */ getScrollTop: function () { return this.getScroll().top; }, /** * Gets the scrollLeft * @method getScrollLeft * @return {int} the document's scrollTop * @static */ getScrollLeft: function () { return this.getScroll().left; }, /** * Sets the x/y position of an element to the location of the * target element. * @method moveToEl * @param {HTMLElement} moveEl The element to move * @param {HTMLElement} targetEl The position reference element * @static */ moveToEl: function (moveEl, targetEl) { var aCoord = YAHOO.util.Dom.getXY(targetEl); YAHOO.util.Dom.setXY(moveEl, aCoord); }, /** * Gets the client height * @method getClientHeight * @return {int} client height in px * @deprecated use YAHOO.util.Dom.getViewportHeight instead * @static */ getClientHeight: function() { return YAHOO.util.Dom.getViewportHeight(); }, /** * Gets the client width * @method getClientWidth * @return {int} client width in px * @deprecated use YAHOO.util.Dom.getViewportWidth instead * @static */ getClientWidth: function() { return YAHOO.util.Dom.getViewportWidth(); }, /** * Numeric array sort function * @method numericSort * @static */ numericSort: function(a, b) { return (a - b); }, /** * Internal counter * @property _timeoutCount * @private * @static */ _timeoutCount: 0, /** * Trying to make the load order less important. Without this we get * an error if this file is loaded before the Event Utility. * @method _addListeners * @private * @static */ _addListeners: function() { var DDM = YAHOO.util.DDM; if ( YAHOO.util.Event && document ) { DDM._onLoad(); } else { if (DDM._timeoutCount > 2000) { } else { setTimeout(DDM._addListeners, 10); if (document && document.body) { DDM._timeoutCount += 1; } } } }, /** * Recursively searches the immediate parent and all child nodes for * the handle element in order to determine wheter or not it was * clicked. * @method handleWasClicked * @param node the html element to inspect * @static */ handleWasClicked: function(node, id) { if (this.isHandle(id, node.id)) { return true; } else { // check to see if this is a text node child of the one we want var p = node.parentNode; while (p) { if (this.isHandle(id, p.id)) { return true; } else { p = p.parentNode; } } } return false; } }; }(); // shorter alias, save a few bytes YAHOO.util.DDM = YAHOO.util.DragDropMgr; YAHOO.util.DDM._addListeners(); } /** * A DragDrop implementation where the linked element follows the * mouse cursor during a drag. * @class DD * @extends YAHOO.util.DragDrop * @constructor * @param {String} id the id of the linked element * @param {String} sGroup the group of related DragDrop items * @param {object} config an object containing configurable attributes * Valid properties for DD: * scroll */ YAHOO.util.DD = function(id, sGroup, config) { if (id) { this.init(id, sGroup, config); } }; YAHOO.extend(YAHOO.util.DD, YAHOO.util.DragDrop, { /** * When set to true, the utility automatically tries to scroll the browser * window wehn a drag and drop element is dragged near the viewport boundary. * Defaults to true. * @property scroll * @type boolean */ scroll: true, /** * Sets the pointer offset to the distance between the linked element's top * left corner and the location the element was clicked * @method autoOffset * @param {int} iPageX the X coordinate of the click * @param {int} iPageY the Y coordinate of the click */ autoOffset: function(iPageX, iPageY) { var x = iPageX - this.startPageX; var y = iPageY - this.startPageY; this.setDelta(x, y); }, /** * Sets the pointer offset. You can call this directly to force the * offset to be in a particular location (e.g., pass in 0,0 to set it * to the center of the object, as done in YAHOO.widget.Slider) * @method setDelta * @param {int} iDeltaX the distance from the left * @param {int} iDeltaY the distance from the top */ setDelta: function(iDeltaX, iDeltaY) { this.deltaX = iDeltaX; this.deltaY = iDeltaY; }, /** * Sets the drag element to the location of the mousedown or click event, * maintaining the cursor location relative to the location on the element * that was clicked. Override this if you want to place the element in a * location other than where the cursor is. * @method setDragElPos * @param {int} iPageX the X coordinate of the mousedown or drag event * @param {int} iPageY the Y coordinate of the mousedown or drag event */ setDragElPos: function(iPageX, iPageY) { // the first time we do this, we are going to check to make sure // the element has css positioning var el = this.getDragEl(); this.alignElWithMouse(el, iPageX, iPageY); }, /** * Sets the element to the location of the mousedown or click event, * maintaining the cursor location relative to the location on the element * that was clicked. Override this if you want to place the element in a * location other than where the cursor is. * @method alignElWithMouse * @param {HTMLElement} el the element to move * @param {int} iPageX the X coordinate of the mousedown or drag event * @param {int} iPageY the Y coordinate of the mousedown or drag event */ alignElWithMouse: function(el, iPageX, iPageY) { var oCoord = this.getTargetCoord(iPageX, iPageY); if (!this.deltaSetXY) { var aCoord = [oCoord.x, oCoord.y]; YAHOO.util.Dom.setXY(el, aCoord); var newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 ); var newTop = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 ); this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ]; } else { YAHOO.util.Dom.setStyle(el, "left", (oCoord.x + this.deltaSetXY[0]) + "px"); YAHOO.util.Dom.setStyle(el, "top", (oCoord.y + this.deltaSetXY[1]) + "px"); } this.cachePosition(oCoord.x, oCoord.y); this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth); }, /** * Saves the most recent position so that we can reset the constraints and * tick marks on-demand. We need to know this so that we can calculate the * number of pixels the element is offset from its original position. * @method cachePosition * @param iPageX the current x position (optional, this just makes it so we * don't have to look it up again) * @param iPageY the current y position (optional, this just makes it so we * don't have to look it up again) */ cachePosition: function(iPageX, iPageY) { if (iPageX) { this.lastPageX = iPageX; this.lastPageY = iPageY; } else { var aCoord = YAHOO.util.Dom.getXY(this.getEl()); this.lastPageX = aCoord[0]; this.lastPageY = aCoord[1]; } }, /** * Auto-scroll the window if the dragged object has been moved beyond the * visible window boundary. * @method autoScroll * @param {int} x the drag element's x position * @param {int} y the drag element's y position * @param {int} h the height of the drag element * @param {int} w the width of the drag element * @private */ autoScroll: function(x, y, h, w) { if (this.scroll) { // The client height var clientH = this.DDM.getClientHeight(); // The client width var clientW = this.DDM.getClientWidth(); // The amt scrolled down var st = this.DDM.getScrollTop(); // The amt scrolled right var sl = this.DDM.getScrollLeft(); // Location of the bottom of the element var bot = h + y; // Location of the right of the element var right = w + x; // The distance from the cursor to the bottom of the visible area, // adjusted so that we don't scroll if the cursor is beyond the // element drag constraints var toBot = (clientH + st - y - this.deltaY); // The distance from the cursor to the right of the visible area var toRight = (clientW + sl - x - this.deltaX); // How close to the edge the cursor must be before we scroll // var thresh = (document.all) ? 100 : 40; var thresh = 40; // How many pixels to scroll per autoscroll op. This helps to reduce // clunky scrolling. IE is more sensitive about this ... it needs this // value to be higher. var scrAmt = (document.all) ? 80 : 30; // Scroll down if we are near the bottom of the visible page and the // obj extends below the crease if ( bot > clientH && toBot < thresh ) { window.scrollTo(sl, st + scrAmt); } // Scroll up if the window is scrolled down and the top of the object // goes above the top border if ( y < st && st > 0 && y - st < thresh ) { window.scrollTo(sl, st - scrAmt); } // Scroll right if the obj is beyond the right border and the cursor is // near the border. if ( right > clientW && toRight < thresh ) { window.scrollTo(sl + scrAmt, st); } // Scroll left if the window has been scrolled to the right and the obj // extends past the left border if ( x < sl && sl > 0 && x - sl < thresh ) { window.scrollTo(sl - scrAmt, st); } } }, /** * Finds the location the element should be placed if we want to move * it to where the mouse location less the click offset would place us. * @method getTargetCoord * @param {int} iPageX the X coordinate of the click * @param {int} iPageY the Y coordinate of the click * @return an object that contains the coordinates (Object.x and Object.y) * @private */ getTargetCoord: function(iPageX, iPageY) { var x = iPageX - this.deltaX; var y = iPageY - this.deltaY; if (this.constrainX) { if (x < this.minX) { x = this.minX; } if (x > this.maxX) { x = this.maxX; } } if (this.constrainY) { if (y < this.minY) { y = this.minY; } if (y > this.maxY) { y = this.maxY; } } x = this.getTick(x, this.xTicks); y = this.getTick(y, this.yTicks); return {x:x, y:y}; }, /* * Sets up config options specific to this class. Overrides * YAHOO.util.DragDrop, but all versions of this method through the * inheritance chain are called */ applyConfig: function() { YAHOO.util.DD.superclass.applyConfig.call(this); this.scroll = (this.config.scroll !== false); }, /* * Event that fires prior to the onMouseDown event. Overrides * YAHOO.util.DragDrop. */ b4MouseDown: function(e) { // this.resetConstraints(); this.autoOffset(YAHOO.util.Event.getPageX(e), YAHOO.util.Event.getPageY(e)); }, /* * Event that fires prior to the onDrag event. Overrides * YAHOO.util.DragDrop. */ b4Drag: function(e) { this.setDragElPos(YAHOO.util.Event.getPageX(e), YAHOO.util.Event.getPageY(e)); }, toString: function() { return ("DD " + this.id); } ////////////////////////////////////////////////////////////////////////// // Debugging ygDragDrop events that can be overridden ////////////////////////////////////////////////////////////////////////// /* startDrag: function(x, y) { }, onDrag: function(e) { }, onDragEnter: function(e, id) { }, onDragOver: function(e, id) { }, onDragOut: function(e, id) { }, onDragDrop: function(e, id) { }, endDrag: function(e) { } */ }); /** * A DragDrop implementation that inserts an empty, bordered div into * the document that follows the cursor during drag operations. At the time of * the click, the frame div is resized to the dimensions of the linked html * element, and moved to the exact location of the linked element. * * References to the "frame" element refer to the single proxy element that * was created to be dragged in place of all DDProxy elements on the * page. * * @class DDProxy * @extends YAHOO.util.DD * @constructor * @param {String} id the id of the linked html element * @param {String} sGroup the group of related DragDrop objects * @param {object} config an object containing configurable attributes * Valid properties for DDProxy in addition to those in DragDrop: * resizeFrame, centerFrame, dragElId */ YAHOO.util.DDProxy = function(id, sGroup, config) { if (id) { this.init(id, sGroup, config); this.initFrame(); } }; /** * The default drag frame div id * @property YAHOO.util.DDProxy.dragElId * @type String * @static */ YAHOO.util.DDProxy.dragElId = "ygddfdiv"; YAHOO.extend(YAHOO.util.DDProxy, YAHOO.util.DD, { /** * By default we resize the drag frame to be the same size as the element * we want to drag (this is to get the frame effect). We can turn it off * if we want a different behavior. * @property resizeFrame * @type boolean */ resizeFrame: true, /** * By default the frame is positioned exactly where the drag element is, so * we use the cursor offset provided by YAHOO.util.DD. Another option that works only if * you do not have constraints on the obj is to have the drag frame centered * around the cursor. Set centerFrame to true for this effect. * @property centerFrame * @type boolean */ centerFrame: false, /** * Creates the proxy element if it does not yet exist * @method createFrame */ createFrame: function() { var self = this; var body = document.body; if (!body || !body.firstChild) { setTimeout( function() { self.createFrame(); }, 50 ); return; } var div = this.getDragEl(); if (!div) { div = document.createElement("div"); div.id = this.dragElId; var s = div.style; s.position = "absolute"; s.visibility = "hidden"; s.cursor = "move"; s.border = "2px solid #aaa"; s.zIndex = 999; // appendChild can blow up IE if invoked prior to the window load event // while rendering a table. It is possible there are other scenarios // that would cause this to happen as well. body.insertBefore(div, body.firstChild); } }, /** * Initialization for the drag frame element. Must be called in the * constructor of all subclasses * @method initFrame */ initFrame: function() { this.createFrame(); }, applyConfig: function() { YAHOO.util.DDProxy.superclass.applyConfig.call(this); this.resizeFrame = (this.config.resizeFrame !== false); this.centerFrame = (this.config.centerFrame); this.setDragElId(this.config.dragElId || YAHOO.util.DDProxy.dragElId); }, /** * Resizes the drag frame to the dimensions of the clicked object, positions * it over the object, and finally displays it * @method showFrame * @param {int} iPageX X click position * @param {int} iPageY Y click position * @private */ showFrame: function(iPageX, iPageY) { var el = this.getEl(); var dragEl = this.getDragEl(); var s = dragEl.style; this._resizeProxy(); if (this.centerFrame) { this.setDelta( Math.round(parseInt(s.width, 10)/2), Math.round(parseInt(s.height, 10)/2) ); } this.setDragElPos(iPageX, iPageY); YAHOO.util.Dom.setStyle(dragEl, "visibility", "visible"); }, /** * The proxy is automatically resized to the dimensions of the linked * element when a drag is initiated, unless resizeFrame is set to false * @method _resizeProxy * @private */ _resizeProxy: function() { if (this.resizeFrame) { var DOM = YAHOO.util.Dom; var el = this.getEl(); var dragEl = this.getDragEl(); var bt = parseInt( DOM.getStyle(dragEl, "borderTopWidth" ), 10); var br = parseInt( DOM.getStyle(dragEl, "borderRightWidth" ), 10); var bb = parseInt( DOM.getStyle(dragEl, "borderBottomWidth" ), 10); var bl = parseInt( DOM.getStyle(dragEl, "borderLeftWidth" ), 10); if (isNaN(bt)) { bt = 0; } if (isNaN(br)) { br = 0; } if (isNaN(bb)) { bb = 0; } if (isNaN(bl)) { bl = 0; } var newWidth = Math.max(0, el.offsetWidth - br - bl); var newHeight = Math.max(0, el.offsetHeight - bt - bb); DOM.setStyle( dragEl, "width", newWidth + "px" ); DOM.setStyle( dragEl, "height", newHeight + "px" ); } }, // overrides YAHOO.util.DragDrop b4MouseDown: function(e) { var x = YAHOO.util.Event.getPageX(e); var y = YAHOO.util.Event.getPageY(e); this.autoOffset(x, y); this.setDragElPos(x, y); }, // overrides YAHOO.util.DragDrop b4StartDrag: function(x, y) { // show the drag frame this.showFrame(x, y); }, // overrides YAHOO.util.DragDrop b4EndDrag: function(e) { YAHOO.util.Dom.setStyle(this.getDragEl(), "visibility", "hidden"); }, // overrides YAHOO.util.DragDrop // By default we try to move the element to the last location of the frame. // This is so that the default behavior mirrors that of YAHOO.util.DD. endDrag: function(e) { var DOM = YAHOO.util.Dom; var lel = this.getEl(); var del = this.getDragEl(); // Show the drag frame briefly so we can get its position // del.style.visibility = ""; DOM.setStyle(del, "visibility", ""); // Hide the linked element before the move to get around a Safari // rendering bug. //lel.style.visibility = "hidden"; DOM.setStyle(lel, "visibility", "hidden"); YAHOO.util.DDM.moveToEl(lel, del); //del.style.visibility = "hidden"; DOM.setStyle(del, "visibility", "hidden"); //lel.style.visibility = ""; DOM.setStyle(lel, "visibility", ""); }, toString: function() { return ("DDProxy " + this.id); } }); /** * A DragDrop implementation that does not move, but can be a drop * target. You would get the same result by simply omitting implementation * for the event callbacks, but this way we reduce the processing cost of the * event listener and the callbacks. * @class DDTarget * @extends YAHOO.util.DragDrop * @constructor * @param {String} id the id of the element that is a drop target * @param {String} sGroup the group of related DragDrop objects * @param {object} config an object containing configurable attributes * Valid properties for DDTarget in addition to those in * DragDrop: * none */ YAHOO.util.DDTarget = function(id, sGroup, config) { if (id) { this.initTarget(id, sGroup, config); } }; // YAHOO.util.DDTarget.prototype = new YAHOO.util.DragDrop(); YAHOO.extend(YAHOO.util.DDTarget, YAHOO.util.DragDrop, { toString: function() { return ("DDTarget " + this.id); } }); /****************************************************************************** Name: Highslide JS Version: 4.0.7 (Oct 9 2008) Config: default +events +unobtrusive +imagemap +slideshow +positioning +transitions +inline +ajax +iframe +flash Author: Torstein H?nsi Support: http://highslide.com/support Licence: Highslide JS is licensed under a Creative Commons Attribution-NonCommercial 2.5 License (http://creativecommons.org/licenses/by-nc/2.5/). You are free: * to copy, distribute, display, and perform the work * to make derivative works Under the following conditions: * Attribution. You must attribute the work in the manner specified by the author or licensor. * Noncommercial. You may not use this work for commercial purposes. * For any reuse or distribution, you must make clear to others the license terms of this work. * Any of these conditions can be waived if you get permission from the copyright holder. Your fair use and other rights are in no way affected by the above. ******************************************************************************/ var hs = { // Language strings lang : { loadingText : 'Loading...', loadingTitle : 'Click to cancel', focusTitle : 'Click to bring to front', fullExpandTitle : 'Expand to actual size', creditsText : 'Powered by Highslide JS', creditsTitle : 'Go to the Highslide JS homepage', previousText : 'Previous', nextText : 'Next', moveText : 'Move', closeText : 'Close', closeTitle : 'Close (esc)', resizeTitle : 'Resize', playText : 'Play', playTitle : 'Play slideshow (spacebar)', pauseText : 'Pause', pauseTitle : 'Pause slideshow (spacebar)', previousTitle : 'Previous (arrow left)', nextTitle : 'Next (arrow right)', moveTitle : 'Move', fullExpandText : 'Full size', number: 'Image %1 of %2', restoreTitle : 'Click to close image, click and drag to move. Use arrow keys for next and previous.' }, // See http://highslide.com/ref for examples of settings graphicsDir : 'highslide/graphics/', restoreCursor : 'zoomout.cur', // necessary for preload expandSteps : 10, // number of steps in zoom. Each step lasts for duration/step milliseconds. expandDuration : 250, // milliseconds restoreSteps : 10, restoreDuration : 250, marginLeft : 15, marginRight : 15, marginTop : 15, marginBottom : 15, zIndexCounter : 1001, // adjust to other absolutely positioned elements loadingOpacity : 0.75, allowMultipleInstances: true, numberOfImagesToPreload : 5, outlineWhileAnimating : 2, // 0 = never, 1 = always, 2 = HTML only outlineStartOffset : 3, // ends at 10 fullExpandPosition : 'bottom right', fullExpandOpacity : 1, padToMinWidth : false, // pad the popup width to make room for wide caption showCredits : true, // you can set this to false if you want creditsHref : 'http://highslide.com', enableKeyListener : true, transitions : [], transitionDuration: 500, dimmingOpacity: 0, // Lightbox style dimming background dimmingDuration: 50, // 0 for instant dimming allowWidthReduction : false, allowHeightReduction : true, preserveContent : true, // Preserve changes made to the content and position of HTML popups. objectLoadTime : 'before', // Load iframes 'before' or 'after' expansion. cacheAjax : true, // Cache ajax popups for instant display. Can be overridden for each popup. anchor : 'auto', // where the image expands from align : 'auto', // position in the client (overrides anchor) targetX: null, // the id of a target element targetY: null, dragByHeading: true, minWidth: 200, minHeight: 200, allowSizeReduction: true, // allow the image to reduce to fit client size. If false, this overrides minWidth and minHeight outlineType : 'drop-shadow', // set null to disable outlines wrapperClassName : 'highslide-wrapper', // for enhanced css-control skin : { controls: ' ', contentWrapper: ' '+ ''+ ' ' }, // END OF YOUR SETTINGS // declare internal properties preloadTheseImages : [], continuePreloading: true, expanders : [], overrides : [ 'allowSizeReduction', 'anchor', 'align', 'targetX', 'targetY', 'outlineType', 'outlineWhileAnimating', 'captionId', 'captionText', 'captionEval', 'captionOverlay', 'headingId', 'headingText', 'headingEval', 'headingOverlay', 'dragByHeading', 'autoplay', 'numberPosition', 'transitions', 'dimmingOpacity', 'contentId', 'width', 'height', 'allowWidthReduction', 'allowHeightReduction', 'preserveContent', 'maincontentId', 'maincontentText', 'maincontentEval', 'objectType', 'cacheAjax', 'objectWidth', 'objectHeight', 'objectLoadTime', 'swfOptions', 'wrapperClassName', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight', 'slideshowGroup', 'easing', 'easingClose', 'fadeInOut', 'src' ], overlays : [], idCounter : 0, oPos : { x: ['leftpanel', 'left', 'center', 'right', 'rightpanel'], y: ['above', 'top', 'middle', 'bottom', 'below'] }, mouse: {}, headingOverlay: {}, captionOverlay: {}, swfOptions: { flashvars: {}, params: {}, attributes: {} }, faders : [], slideshows : [], pendingOutlines : {}, sleeping : [], preloadTheseAjax : [], cacheBindings : [], cachedGets : {}, clones : {}, ie : (document.all && !window.opera), safari : /Safari/.test(navigator.userAgent), geckoMac : /Macintosh.+rv:1\.[0-8].+Gecko/.test(navigator.userAgent), $ : function (id) { return document.getElementById(id); }, push : function (arr, val) { arr[arr.length] = val; }, createElement : function (tag, attribs, styles, parent, nopad) { var el = document.createElement(tag); if (attribs) hs.setAttribs(el, attribs); if (nopad) hs.setStyles(el, {padding: 0, border: 'none', margin: 0}); if (styles) hs.setStyles(el, styles); if (parent) parent.appendChild(el); return el; }, setAttribs : function (el, attribs) { for (var x in attribs) el[x] = attribs[x]; }, setStyles : function (el, styles) { for (var x in styles) { if (hs.ie && x == 'opacity') { if (styles[x] > 0.99) el.style.removeAttribute('filter'); else el.style.filter = 'alpha(opacity='+ (styles[x] * 100) +')'; } else el.style[x] = styles[x]; } }, ieVersion : function () { var arr = navigator.appVersion.split("MSIE"); return arr[1] ? parseFloat(arr[1]) : null; }, getPageSize : function () { var d = document, w = window, iebody = d.compatMode && d.compatMode != 'BackCompat' ? d.documentElement : d.body; var b = d.body; var xScroll = (w.innerWidth && w.scrollMaxX) ? w.innerWidth + w.scrollMaxX : Math.max(b.scrollWidth, b.offsetWidth), yScroll = (w.innerHeight && window.scrollMaxY) ? w.innerHeight + w.scrollMaxY : Math.max(b.scrollHeight, b.offsetHeight), pageWidth = hs.ie ? iebody.scrollWidth : (d.documentElement.clientWidth || self.innerWidth), pageHeight = hs.ie ? Math.max(iebody.scrollHeight, iebody.clientHeight) : (d.documentElement.clientHeight || self.innerHeight); var width = hs.ie ? iebody.clientWidth : (d.documentElement.clientWidth || self.innerWidth), height = hs.ie ? iebody.clientHeight : self.innerHeight; return { pageWidth: Math.max(pageWidth, xScroll), pageHeight: Math.max(pageHeight, yScroll), width: width, height: height, scrollLeft: hs.ie ? iebody.scrollLeft : pageXOffset, scrollTop: hs.ie ? iebody.scrollTop : pageYOffset } }, getPosition : function(el) { if (/area/i.test(el.tagName)) { var imgs = document.getElementsByTagName('img'); for (var i = 0; i < imgs.length; i++) { var u = imgs[i].useMap; if (u && u.replace(/^.*?#/, '') == el.parentNode.name) { el = imgs[i]; break; } } } var p = { x: el.offsetLeft, y: el.offsetTop }; while (el.offsetParent) { el = el.offsetParent; p.x += el.offsetLeft; p.y += el.offsetTop; if (el != document.body && el != document.documentElement) { p.x -= el.scrollLeft; p.y -= el.scrollTop; } } return p; }, expand : function(a, params, custom, type) { if (!a) a = hs.createElement('a', null, { display: 'none' }, hs.container); if (typeof a.getParams == 'function') return params; if (type == 'html') { for (var i = 0; i < hs.sleeping.length; i++) { if (hs.sleeping[i] && hs.sleeping[i].a == a) { hs.sleeping[i].awake(); hs.sleeping[i] = null; return false; } } hs.hasHtmlExpanders = true; } try { new hs.Expander(a, params, custom, type); return false; } catch (e) { return true; } }, htmlExpand : function(a, params, custom) { return hs.expand(a, params, custom, 'html'); }, getSelfRendered : function() { return hs.createElement('div', { className: 'highslide-html-content', innerHTML: hs.replaceLang(hs.skin.contentWrapper) }); }, getElementByClass : function (el, tagName, className) { var els = el.getElementsByTagName(tagName); for (var i = 0; i < els.length; i++) { if ((new RegExp(className)).test(els[i].className)) { return els[i]; } } return null; }, replaceLang : function(s) { s = s.replace(/\s/g, ' '); var re = /{hs\.lang\.([^}]+)\}/g, matches = s.match(re), lang; for (var i = 0; i < matches.length; i++) { lang = matches[i].replace(re, "$1"); if (typeof hs.lang[lang] != 'undefined') s = s.replace(matches[i], hs.lang[lang]); } return s; }, setClickEvents : function () { var els = document.getElementsByTagName('a'); for (var i = 0; i < els.length; i++) { var type = hs.isUnobtrusiveAnchor(els[i]); if (type && !els[i].hsHasSetClick) { (function(){ var t = type; if (hs.fireEvent(hs, 'onSetClickEvent', { element: els[i], type: t })) { els[i].onclick =(type == 'image') ?function() { return hs.expand(this) }: function() { return hs.htmlExpand(this, { objectType: t } );}; } })(); els[i].hsHasSetClick = true; } } if (!hs.pageLoaded) setTimeout( hs.setClickEvents, 50); else hs.updateAnchors(); }, isUnobtrusiveAnchor: function(el) { if (el.rel == 'highslide') return 'image'; else if (el.rel == 'highslide-ajax') return 'ajax'; else if (el.rel == 'highslide-iframe') return 'iframe'; else if (el.rel == 'highslide-swf') return 'swf'; }, getCacheBinding : function (a) { for (var i = 0; i < hs.cacheBindings.length; i++) { if (hs.cacheBindings[i][0] == a) { var c = hs.cacheBindings[i][1]; hs.cacheBindings[i][1] = c.cloneNode(1); return c; } } return null; }, preloadAjax : function (e) { var arr = hs.getAnchors(); for (var i = 0; i < arr.htmls.length; i++) { var a = arr.htmls[i]; if (hs.getParam(a, 'objectType') == 'ajax' && hs.getParam(a, 'cacheAjax')) hs.push(hs.preloadTheseAjax, a); } hs.preloadAjaxElement(0); }, preloadAjaxElement : function (i) { if (!hs.preloadTheseAjax[i]) return; var a = hs.preloadTheseAjax[i]; var cache = hs.getNode(hs.getParam(a, 'contentId')); if (!cache) cache = hs.getSelfRendered(); var ajax = new hs.Ajax(a, cache, 1); ajax.onError = function () { }; ajax.onLoad = function () { hs.push(hs.cacheBindings, [a, cache]); hs.preloadAjaxElement(i + 1); }; ajax.run(); }, focusTopmost : function() { var topZ = 0, topmostKey = -1; for (var i = 0; i < hs.expanders.length; i++) { if (hs.expanders[i]) { if (hs.expanders[i].wrapper.style.zIndex && hs.expanders[i].wrapper.style.zIndex > topZ) { topZ = hs.expanders[i].wrapper.style.zIndex; topmostKey = i; } } } if (topmostKey == -1) hs.focusKey = -1; else hs.expanders[topmostKey].focus(); }, getParam : function (a, param) { a.getParams = a.onclick; var p = a.getParams ? a.getParams() : null; a.getParams = null; return (p && typeof p[param] != 'undefined') ? p[param] : (typeof hs[param] != 'undefined' ? hs[param] : null); }, getSrc : function (a) { var src = hs.getParam(a, 'src'); if (src) return src; return a.href; }, getNode : function (id) { var node = hs.$(id), clone = hs.clones[id], a = {}; if (!node && !clone) return null; if (!clone) { clone = node.cloneNode(true); clone.id = ''; hs.clones[id] = clone; return node; } else { return clone.cloneNode(true); } }, discardElement : function(d) { hs.garbageBin.appendChild(d); hs.garbageBin.innerHTML = ''; }, dim : function(exp) { if (!hs.dimmer) { hs.dimmer = hs.createElement ('div', { className: 'highslide-dimming', owner: '', onclick: function() { if (hs.fireEvent(hs, 'onDimmerClick')) hs.close(); } }, { position: 'absolute', left: 0 }, hs.container, true); hs.addEventListener(window, 'resize', hs.setDimmerSize); } hs.dimmer.style.display = ''; hs.setDimmerSize(); hs.dimmer.owner += '|'+ exp.key; if (hs.geckoMac && hs.dimmingGeckoFix) hs.dimmer.style.background = 'url('+ hs.graphicsDir + 'geckodimmer.png)'; else hs.fade(hs.dimmer, 0, exp.dimmingOpacity, hs.dimmingDuration); }, undim : function(key) { if (!hs.dimmer) return; if (typeof key != 'undefined') hs.dimmer.owner = hs.dimmer.owner.replace('|'+ key, ''); if ( (typeof key != 'undefined' && hs.dimmer.owner != '') || (hs.upcoming && hs.getParam(hs.upcoming, 'dimmingOpacity')) ) return; if (hs.geckoMac && hs.dimmingGeckoFix) hs.dimmer.style.background = 'none'; else hs.fade(hs.dimmer, hs.dimmingOpacity, 0, hs.dimmingDuration); setTimeout( function() { hs.setStyles(hs.dimmer, { display: 'none', width: 0, height: 0 }); }, hs.dimmingDuration); }, setDimmerSize : function(exp) { if (!hs.dimmer) return; var page = hs.getPageSize(); var h = (hs.ie && exp && exp.wrapper) ? parseInt(exp.wrapper.style.top) + parseInt(exp.wrapper.style.height)+ (exp.outline ? exp.outline.offset : 0) : 0; hs.setStyles(hs.dimmer, { width: page.pageWidth +'px', height: Math.max(page.pageHeight, h) +'px' }); }, previousOrNext : function (el, op) { hs.updateAnchors(); var exp = hs.last = hs.getExpander(el); try { var adj = hs.upcoming = exp.getAdjacentAnchor(op); adj.onclick(); } catch (e){ hs.last = hs.upcoming = null; } try { exp.close(); } catch (e) {} return false; }, previous : function (el) { return hs.previousOrNext(el, -1); }, next : function (el) { return hs.previousOrNext(el, 1); }, keyHandler : function(e) { if (!e) e = window.event; if (!e.target) e.target = e.srcElement; // ie if (e.target.form) return true; // form element has focus if (!hs.fireEvent(hs, 'onKeyDown', e)) return true; var op = null; switch (e.keyCode) { case 32: // Space op = 2; break; case 34: // Page Down case 39: // Arrow right case 40: // Arrow down op = 1; break; case 8: // Backspace case 33: // Page Up case 37: // Arrow left case 38: // Arrow up op = -1; break; case 27: // Escape case 13: // Enter op = 0; } if (op !== null) {if (op != 2)hs.removeEventListener(document, window.opera ? 'keypress' : 'keydown', hs.keyHandler); if (!hs.enableKeyListener) return true; if (e.preventDefault) e.preventDefault(); else e.returnValue = false; var exp = hs.getExpander(); if (exp) { if (op == 0) { exp.close(); } else if (op == 2) { if (exp.slideshow) exp.slideshow.hitSpace(); } else { if (exp.slideshow) exp.slideshow.pause(); hs.previousOrNext(exp.key, op); } return false; } } return true; }, registerOverlay : function (overlay) { hs.push(hs.overlays, overlay); }, addSlideshow : function (options) { var sg = options.slideshowGroup; if (typeof sg == 'object') { for (var i = 0; i < sg.length; i++) { var o = {}; for (var x in options) o[x] = options[x]; o.slideshowGroup = sg[i]; hs.push(hs.slideshows, o); } } else { hs.push(hs.slideshows, options); } }, getWrapperKey : function (element, expOnly) { var el, re = /^highslide-wrapper-([0-9]+)$/; // 1. look in open expanders el = element; while (el.parentNode) { if (el.id && re.test(el.id)) return el.id.replace(re, "$1"); el = el.parentNode; } // 2. look in thumbnail if (!expOnly) { el = element; while (el.parentNode) { if (el.tagName && hs.isHsAnchor(el)) { for (var key = 0; key < hs.expanders.length; key++) { var exp = hs.expanders[key]; if (exp && exp.a == el) return key; } } el = el.parentNode; } } return null; }, getExpander : function (el, expOnly) { if (typeof el == 'undefined') return hs.expanders[hs.focusKey] || null; if (typeof el == 'number') return hs.expanders[el] || null; if (typeof el == 'string') el = hs.$(el); return hs.expanders[hs.getWrapperKey(el, expOnly)] || null; }, isHsAnchor : function (a) { return (a.onclick && a.onclick.toString().replace(/\s/g, ' ').match(/hs.(htmlE|e)xpand/)); }, reOrder : function () { for (var i = 0; i < hs.expanders.length; i++) if (hs.expanders[i] && hs.expanders[i].isExpanded) hs.focusTopmost(); }, fireEvent : function (obj, evt, args) { return obj && obj[evt] ? (obj[evt](obj, args) !== false) : true; }, mouseClickHandler : function(e) { if (!e) e = window.event; if (e.button > 1) return true; if (!e.target) e.target = e.srcElement; var el = e.target; while (el.parentNode && !(/highslide-(image|move|html|resize)/.test(el.className))) { el = el.parentNode; } var exp = hs.getExpander(el); if (exp && (exp.isClosing || !exp.isExpanded)) return true; if (exp && e.type == 'mousedown') { if (e.target.form) return true; var match = el.className.match(/highslide-(image|move|resize)/); if (match) { hs.dragArgs = { exp: exp , type: match[1], left: exp.x.min, width: exp.x.span, top: exp.y.min, height: exp.y.span, clickX: e.clientX, clickY: e.clientY }; hs.addEventListener(document, 'mousemove', hs.dragHandler); if (e.preventDefault) e.preventDefault(); // FF if (/highslide-(image|html)-blur/.test(exp.content.className)) { exp.focus(); hs.hasFocused = true; } return false; } else if (/highslide-html/.test(el.className) && hs.focusKey != exp.key) { exp.focus(); exp.redoShowHide(); } } else if (e.type == 'mouseup') { hs.removeEventListener(document, 'mousemove', hs.dragHandler); if (hs.dragArgs) { if (hs.dragArgs.type == 'image') hs.dragArgs.exp.content.style.cursor = hs.styleRestoreCursor; var hasDragged = hs.dragArgs.hasDragged; if (!hasDragged &&!hs.hasFocused && !/(move|resize)/.test(hs.dragArgs.type)) { if (hs.fireEvent(exp, 'onImageClick')) exp.close(); } else if (hasDragged || (!hasDragged && hs.hasHtmlExpanders)) { hs.dragArgs.exp.redoShowHide(); } if (hs.dragArgs.exp.releaseMask) hs.dragArgs.exp.releaseMask.style.display = 'none'; if (hasDragged) hs.fireEvent(hs.dragArgs.exp, 'onDrop', hs.dragArgs); if (hasDragged) hs.setDimmerSize(exp); hs.hasFocused = false; hs.dragArgs = null; } else if (/highslide-image-blur/.test(el.className)) { el.style.cursor = hs.styleRestoreCursor; } } return false; }, dragHandler : function(e) { if (!hs.dragArgs) return true; if (!e) e = window.event; var a = hs.dragArgs, exp = a.exp; if (exp.iframe) { if (!exp.releaseMask) exp.releaseMask = hs.createElement('div', null, { position: 'absolute', width: exp.x.span+'px', height: exp.y.span+'px', left: 0, top: 0, zIndex: 4, background: (hs.ie ? 'white' : 'none'), opacity: 0.01 }, exp.wrapper, true); if (exp.releaseMask.style.display == 'none') exp.releaseMask.style.display = ''; } a.dX = e.clientX - a.clickX; a.dY = e.clientY - a.clickY; var distance = Math.sqrt(Math.pow(a.dX, 2) + Math.pow(a.dY, 2)); if (!a.hasDragged) a.hasDragged = (a.type != 'image' && distance > 0) || (distance > (hs.dragSensitivity || 5)); if (a.hasDragged && e.clientX > 5 && e.clientY > 5) { if (!hs.fireEvent(exp, 'onDrag', a)) return false; if (a.type == 'resize') exp.resize(a); else exp.move(a); } return false; }, wrapperMouseHandler : function (e) { try { if (!e) e = window.event; var over = /mouseover/i.test(e.type); if (!e.target) e.target = e.srcElement; // ie if (hs.ie) e.relatedTarget = over ? e.fromElement : e.toElement; // ie var exp = hs.getExpander(e.target); if (!exp.isExpanded) return; if (!exp || !e.relatedTarget || hs.getExpander(e.relatedTarget, true) == exp || hs.dragArgs) return; hs.fireEvent(exp, over ? 'onMouseOver' : 'onMouseOut', e); for (var i = 0; i < exp.overlays.length; i++) { var o = hs.$('hsId'+ exp.overlays[i]); if (o && o.hideOnMouseOut) { var from = over ? 0 : o.opacity, to = over ? o.opacity : 0; hs.fade(o, from, to); } } } catch (e) {} }, addEventListener : function (el, event, func) { try { el.addEventListener(event, func, false); } catch (e) { try { el.detachEvent('on'+ event, func); el.attachEvent('on'+ event, func); } catch (e) { el['on'+ event] = func; } } }, removeEventListener : function (el, event, func) { try { el.removeEventListener(event, func, false); } catch (e) { try { el.detachEvent('on'+ event, func); } catch (e) { el['on'+ event] = null; } } }, preloadFullImage : function (i) { if (hs.continuePreloading && hs.preloadTheseImages[i] && hs.preloadTheseImages[i] != 'undefined') { var img = document.createElement('img'); img.onload = function() { img = null; hs.preloadFullImage(i + 1); }; img.src = hs.preloadTheseImages[i]; } }, preloadImages : function (number) { if (number && typeof number != 'object') hs.numberOfImagesToPreload = number; var arr = hs.getAnchors(); for (var i = 0; i < arr.images.length && i < hs.numberOfImagesToPreload; i++) { hs.push(hs.preloadTheseImages, hs.getSrc(arr.images[i])); } // preload outlines if (hs.outlineType) new hs.Outline(hs.outlineType, function () { hs.preloadFullImage(0)} ); else hs.preloadFullImage(0); // preload cursor var cur = hs.createElement('img', { src: hs.graphicsDir + hs.restoreCursor }); }, init : function () { if (!hs.container) { hs.container = hs.createElement('div', { className: 'highslide-container' }, { position: 'absolute', left: 0, top: 0, width: '100%', zIndex: hs.zIndexCounter, direction: 'ltr' }, document.body, true ); hs.loading = hs.createElement('a', { className: 'highslide-loading', title: hs.lang.loadingTitle, innerHTML: hs.lang.loadingText, href: 'javascript:;' }, { position: 'absolute', top: '-9999px', opacity: hs.loadingOpacity, zIndex: 1 }, hs.container ); hs.garbageBin = hs.createElement('div', null, { display: 'none' }, hs.container); hs.clearing = hs.createElement('div', null, { clear: 'both', paddingTop: '1px' }, null, true); // http://www.robertpenner.com/easing/ Math.linearTween = function (t, b, c, d) { return c*t/d + b; }; Math.easeInQuad = function (t, b, c, d) { return c*(t/=d)*t + b; }; Math.easeInOutQuad = function (t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t + b; return -c/2 * ((--t)*(t-2) - 1) + b; }; for (var x in hs.langDefaults) { if (typeof hs[x] != 'undefined') hs.lang[x] = hs[x]; else if (typeof hs.lang[x] == 'undefined' && typeof hs.langDefaults[x] != 'undefined') hs.lang[x] = hs.langDefaults[x]; } hs.ie6SSL = (hs.ie && hs.ieVersion() <= 6 && location.protocol == 'https:'); hs.fireEvent(this, 'onActivate'); } }, domReady : function() { hs.isDomReady = true; if (hs.onDomReady) hs.onDomReady(); }, updateAnchors : function() { var els = document.getElementsByTagName('*'), all = [], images = [], htmls = [],groups = {}, re; for (var i = 0; i < els.length; i++) { re = hs.isHsAnchor(els[i]); if (re) { hs.push(all, els[i]); if (re[0] == 'hs.expand') hs.push(images, els[i]); else if (re[0] == 'hs.htmlExpand') hs.push(htmls, els[i]); var g = hs.getParam(els[i], 'slideshowGroup') || 'none'; if (!groups[g]) groups[g] = []; hs.push(groups[g], els[i]); } } hs.anchors = { all: all, groups: groups, images: images, htmls: htmls }; return hs.anchors; }, getAnchors : function() { return hs.anchors || hs.updateAnchors(); }, fade : function (el, o, oFinal, dur, i, dir) { if (typeof i == 'undefined') { // new fader if (typeof dur != 'number') dur = 250; if (dur < 25) { // instant hs.setStyles( el, { opacity: oFinal }); return; } i = hs.faders.length; dir = oFinal > o ? 1 : -1; var step = (25 / (dur - dur % 25)) * Math.abs(o - oFinal); } o = parseFloat(o); var skip = (el.fade === 0 || el.fade === false || (el.fade == 2 && hs.ie)); el.style.visibility = ((skip ? oFinal : o) <= 0) ? 'hidden' : 'visible'; if (skip || o < 0 || (dir == 1 && o > oFinal)) return; if (el.fading && el.fading.i != i) { // reverse clearTimeout(hs.faders[el.fading.i]); o = el.fading.o; } el.fading = {i: i, o: o, step: (step || el.fading.step)}; el.style.visibility = (o <= 0) ? 'hidden' : 'visible'; hs.setStyles(el, { opacity: o }); hs.faders[i] = setTimeout(function() { hs.fade(el, o + el.fading.step * dir, oFinal, null, i, dir); }, 25); }, close : function(el) { var exp = hs.getExpander(el); if (exp) exp.close(); return false; } }; // end hs object //----------------------------------------------------------------------------- hs.Outline = function (outlineType, onLoad) { this.onLoad = onLoad; this.outlineType = outlineType; var v = hs.ieVersion(), tr; this.hasAlphaImageLoader = hs.ie && v >= 5.5 && v < 7; if (!outlineType) { if (onLoad) onLoad(); return; } hs.init(); this.table = hs.createElement( 'table', { cellSpacing: 0 }, { visibility: 'hidden', position: 'absolute', borderCollapse: 'collapse', width: 0 }, hs.container, true ); var tbody = hs.createElement('tbody', null, null, this.table, 1); this.td = []; for (var i = 0; i <= 8; i++) { if (i % 3 == 0) tr = hs.createElement('tr', null, { height: 'auto' }, tbody, true); this.td[i] = hs.createElement('td', null, null, tr, true); var style = i != 4 ? { lineHeight: 0, fontSize: 0} : { position : 'relative' }; hs.setStyles(this.td[i], style); } this.td[4].className = outlineType; this.preloadGraphic(); }; hs.Outline.prototype = { preloadGraphic : function () { var src = hs.graphicsDir + (hs.outlinesDir || "outlines/")+ this.outlineType +".png"; var appendTo = hs.safari ? hs.container : null; this.graphic = hs.createElement('img', null, { position: 'absolute', left: '-9999px', top: '-9999px' }, appendTo, true); // for onload trigger var pThis = this; this.graphic.onload = function() { pThis.onGraphicLoad(); }; this.graphic.src = src; }, onGraphicLoad : function () { var o = this.offset = this.graphic.width / 4, pos = [[0,0],[0,-4],[-2,0],[0,-8],0,[-2,-8],[0,-2],[0,-6],[-2,-2]], dim = { height: (2*o) +'px', width: (2*o) +'px' }; hs.discardElement(this.graphic); for (var i = 0; i <= 8; i++) { if (pos[i]) { if (this.hasAlphaImageLoader) { var w = (i == 1 || i == 7) ? '100%' : this.graphic.width +'px'; var div = hs.createElement('div', null, { width: '100%', height: '100%', position: 'relative', overflow: 'hidden'}, this.td[i], true); hs.createElement ('div', null, { filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale, src='"+ this.graphic.src + "')", position: 'absolute', width: w, height: this.graphic.height +'px', left: (pos[i][0]*o)+'px', top: (pos[i][1]*o)+'px' }, div, true); } else { hs.setStyles(this.td[i], { background: 'url('+ this.graphic.src +') '+ (pos[i][0]*o)+'px '+(pos[i][1]*o)+'px'}); } if (window.opera && (i == 3 || i ==5)) hs.createElement('div', null, dim, this.td[i], true); hs.setStyles (this.td[i], dim); } } if (hs.pendingOutlines[this.outlineType]) hs.pendingOutlines[this.outlineType].destroy(); hs.pendingOutlines[this.outlineType] = this; if (this.onLoad) this.onLoad(); }, setPosition : function (exp, pos, vis) { pos = pos || { x: exp.x.min, y: exp.y.min, w: exp.x.span + exp.x.p1 + exp.x.p2, h: exp.y.span + exp.y.p1 + exp.y.p2 }; if (vis) this.table.style.visibility = (pos.h >= 4 * this.offset) ? 'visible' : 'hidden'; hs.setStyles(this.table, { left: (pos.x - this.offset) +'px', top: (pos.y - this.offset) +'px', width: (pos.w + 2 * (exp.x.cb + this.offset)) +'px' }); pos.w += 2 * (exp.x.cb - this.offset); pos.h += + 2 * (exp.y.cb - this.offset); hs.setStyles (this.td[4], { width: pos.w >= 0 ? pos.w +'px' : 0, height: pos.h >= 0 ? pos.h +'px' : 0 }); if (this.hasAlphaImageLoader) this.td[3].style.height = this.td[5].style.height = this.td[4].style.height; }, destroy : function(hide) { if (hide) this.table.style.visibility = 'hidden'; else hs.discardElement(this.table); } }; //----------------------------------------------------------------------------- // The expander object hs.Expander = function(a, params, custom, contentType) { if (document.readyState && hs.ie && !hs.isDomReady) { hs.onDomReady = function() { new hs.Expander(a, params, custom, contentType); }; return; } this.a = a; this.custom = custom; this.contentType = contentType || 'image'; this.isHtml = (contentType == 'html'); this.isImage = !this.isHtml; hs.continuePreloading = false; this.overlays = []; this.last = hs.last; hs.last = null; hs.init(); var key = this.key = hs.expanders.length; // override inline parameters for (var i = 0; i < hs.overrides.length; i++) { var name = hs.overrides[i]; this[name] = params && typeof params[name] != 'undefined' ? params[name] : hs[name]; } if (!this.src) this.src = a.href; // get thumb var el = (params && params.thumbnailId) ? hs.$(params.thumbnailId) : a; el = this.thumb = el.getElementsByTagName('img')[0] || el; this.thumbsUserSetId = el.id || a.id; if (!hs.fireEvent(this, 'onInit')) return true; // check if already open for (var i = 0; i < hs.expanders.length; i++) { if (hs.expanders[i] && hs.expanders[i].a == a && !(this.last && this.transitions[1] == 'crossfade')) { hs.expanders[i].focus(); return false; } } // cancel other for (var i = 0; i < hs.expanders.length; i++) { if (hs.expanders[i] && hs.expanders[i].thumb != el && !hs.expanders[i].onLoadStarted) { hs.expanders[i].cancelLoading(); } } hs.expanders[this.key] = this; if (!hs.allowMultipleInstances) { if (hs.expanders[key-1]) hs.expanders[key-1].close(); if (typeof hs.focusKey != 'undefined' && hs.expanders[hs.focusKey]) hs.expanders[hs.focusKey].close(); } var pos = hs.getPosition(el); // initiate metrics var x = this.x = {}; x.t = el.width ? parseInt(el.width) : el.offsetWidth; x.tpos = pos.x; x.tb = (el.offsetWidth - x.t) / 2; var y = this.y = {}; y.t = el.height ? parseInt(el.height) : el.offsetHeight; y.tpos = pos.y; y.tb = (el.offsetHeight - y.t) / 2; x.p1 = x.p2 = y.p1 = y.p2 = 0; hs.page = hs.getPageSize(); if (x.t == 0 && x.tpos == 0) { x.tpos = (hs.page.width / 2) + hs.page.scrollLeft; y.tpos = (hs.page.height / 2) + hs.page.scrollTop; }; if (/area/i.test(el.tagName)) this.getImageMapAreaCorrection(el); // instanciate the wrapper this.wrapper = hs.createElement( 'div', { id: 'highslide-wrapper-'+ this.key, className: this.wrapperClassName }, { visibility: 'hidden', position: 'absolute', zIndex: hs.zIndexCounter++ }, null, true ); this.wrapper.onmouseover = this.wrapper.onmouseout = hs.wrapperMouseHandler; if (this.contentType == 'image' && this.outlineWhileAnimating == 2) this.outlineWhileAnimating = 0; // get the outline if (!this.outlineType || (this.last && this.isImage && this.transitions[1] == 'crossfade')) { this[this.contentType +'Create'](); } else if (hs.pendingOutlines[this.outlineType]) { this.connectOutline(); this[this.contentType +'Create'](); } else { this.showLoading(); var exp = this; new hs.Outline(this.outlineType, function () { exp.connectOutline(); exp[exp.contentType +'Create'](); } ); } return true; }; hs.Expander.prototype = { connectOutline : function(x, y) { var o = this.outline = hs.pendingOutlines[this.outlineType]; o.table.style.zIndex = this.wrapper.style.zIndex; hs.pendingOutlines[this.outlineType] = null; }, showLoading : function() { if (this.onLoadStarted || this.loading) return; this.loading = hs.loading; var exp = this; this.loading.onclick = function() { exp.cancelLoading(); }; if (!hs.fireEvent(this, 'onShowLoading')) return; var exp = this, l = (this.x.tpos + this.x.tb + (this.x.t - this.loading.offsetWidth) / 2) +'px', t = (this.y.tpos + (this.y.t - this.loading.offsetHeight) / 2) +'px'; if (!tgt && this.last && this.transitions[1] == 'crossfade') var tgt = this.last; if (tgt) { l = (tgt.x.min + tgt.x.cb + tgt.x.p1 + (tgt.x.span - this.loading.offsetWidth) / 2) +'px'; t = (tgt.y.min + tgt.y.cb + tgt.y.p1 + (tgt.y.span - this.loading.offsetHeight) / 2) +'px'; this.loading.style.zIndex = hs.zIndexCounter++; } setTimeout(function () { if (exp.loading) hs.setStyles(exp.loading, { left: l, top: t, zIndex: hs.zIndexCounter++ })} , 100); }, imageCreate : function() { var exp = this; var img = document.createElement('img'); this.content = img; img.onload = function () { if (hs.expanders[exp.key]) exp.contentLoaded(); }; if (hs.blockRightClick) img.oncontextmenu = function() { return false; }; img.className = 'highslide-image'; hs.setStyles(img, { visibility: 'hidden', display: 'block', position: 'absolute', maxWidth: '9999px', zIndex: 3 }); img.title = hs.lang.restoreTitle; if (hs.safari) hs.container.appendChild(img); if (hs.ie && hs.flushImgSize) img.src = null; img.src = this.src; this.showLoading(); }, htmlCreate : function () { if (!hs.fireEvent(this, 'onBeforeGetContent')) return; this.content = hs.getCacheBinding(this.a); if (!this.content) this.content = hs.getNode(this.contentId); if (!this.content) this.content = hs.getSelfRendered(); this.getInline(['maincontent']); if (this.maincontent) { var body = hs.getElementByClass(this.content, 'div', 'highslide-body'); if (body) body.appendChild(this.maincontent); this.maincontent.style.display = 'block'; } hs.fireEvent(this, 'onAfterGetContent'); this.innerContent = this.content; if (/(swf|iframe)/.test(this.objectType)) this.setObjContainerSize(this.innerContent); // the content tree hs.container.appendChild(this.wrapper); hs.setStyles( this.wrapper, { position: 'static', padding: '0 '+ hs.marginRight +'px 0 '+ hs.marginLeft +'px' }); this.content = hs.createElement( 'div', { className: 'highslide-html' }, { position: 'relative', zIndex: 3, overflow: 'hidden' }, this.wrapper ); this.mediumContent = hs.createElement('div', null, null, this.content, 1); this.mediumContent.appendChild(this.innerContent); hs.setStyles (this.innerContent, { position: 'relative', display: 'block' }); if (this.width) this.innerContent.style.width = this.width+'px'; if (this.height) this.innerContent.style.height = this.height+'px'; if (this.innerContent.offsetWidth < this.minWidth) this.innerContent.style.width = this.minWidth +'px'; if (this.objectType == 'ajax' && !hs.getCacheBinding(this.a)) { this.showLoading(); var ajax = new hs.Ajax(this.a, this.innerContent); var exp = this; ajax.onLoad = function () { if (hs.expanders[exp.key]) exp.contentLoaded(); }; ajax.onError = function () { location.href = exp.src; }; ajax.run(); } else if (this.objectType == 'iframe' && this.objectLoadTime == 'before') { this.writeExtendedContent(); } else this.contentLoaded(); }, contentLoaded : function() { try { if (!this.content) return; this.content.onload = null; if (this.onLoadStarted) return; else this.onLoadStarted = true; var x = this.x, y = this.y; if (this.loading) { hs.setStyles(this.loading, { top: '-9999px' }); this.loading = null; hs.fireEvent(this, 'onHideLoading'); } this.marginBottom = hs.marginBottom; if (this.isImage) { x.full = this.content.width; y.full = this.content.height; hs.setStyles(this.content, { width: this.x.t +'px', height: this.y.t +'px' }); } else if (this.htmlGetSize) this.htmlGetSize(); this.wrapper.appendChild(this.content); hs.setStyles (this.wrapper, { left: this.x.tpos +'px', top: this.y.tpos +'px' }); hs.container.appendChild(this.wrapper); // correct for borders x.cb = (this.content.offsetWidth - this.x.t) / 2; y.cb = (this.content.offsetHeight - this.y.t) / 2; var modMarginRight = hs.marginRight + 2 * x.cb; this.marginBottom += 2 * y.cb; this.initSlideshow(); this.getOverlays(); var ratio = x.full / y.full; var minWidth = this.allowSizeReduction ? this.minWidth : x.full; var minHeight = this.allowSizeReduction ? this.minHeight : y.full; var justify = { x: 'auto', y: 'auto' }; if (this.align == 'center') { justify.x = justify.y = 'center'; } else { if (this.anchor.match(/^top/)) justify.y = null; if (this.anchor.match(/right$/)) justify.x = 'max'; if (this.anchor.match(/^bottom/)) justify.y = 'max'; if (this.anchor.match(/left$/)) justify.x = null; } // justify x.min = x.tpos - x.cb + x.tb; x.span = Math.min(x.full, this.maxWidth || x.full); x.minSpan = Math.min(x.full, minWidth); x.justify = justify.x; x.target = this.targetX; x.marginMin = hs.marginLeft; x.marginMax = modMarginRight; x.scroll = hs.page.scrollLeft; x.clientSpan = hs.page.width; this.justify(x); y.min = y.tpos - y.cb + y.tb; y.span = Math.min(y.full, this.maxHeight || y.full); y.minSpan = Math.min(y.full, minHeight); y.justify = justify.y; y.target = this.targetY; y.marginMin = hs.marginTop; y.marginMax = this.marginBottom; y.scroll = hs.page.scrollTop; y.clientSpan = hs.page.height; this.justify(y); if (this.isHtml) this.htmlSizeOperations(); if (this.overlayBox) this.sizeOverlayBox(0, 1); if (this.allowSizeReduction) { if (this.isImage) this.correctRatio(ratio); else this.fitOverlayBox(); var ss = this.slideshow; if (ss && this.last && ss.controls && ss.fixedControls) { var pos = ss.overlayOptions.position || '', p; for (var dim in hs.oPos) for (var i = 0; i < 5; i++) { p = this[dim]; if (pos.match(hs.oPos[dim][i])) { p.min = this.last[dim].min + (this.last[dim].p1 - p.p1) + (this.last[dim].span - p.span) * [0, 0, .5, 1, 1][i]; if (ss.fixedControls == 'fit') { if (p.min + p.span + p.p1 + p.p2 > p.scroll + p.clientSpan - p.marginMax) p.min = p.scroll + p.clientSpan - p.span - p.marginMin - p.marginMax - p.p1 - p.p2; if (p.min < p.scroll + p.marginMin) p.min = p.scroll + p.marginMin; } } } } if (this.isImage && this.x.full > this.x.span) { this.createFullExpand(); if (this.overlays.length == 1) this.sizeOverlayBox(); } } this.show(); } catch (e) { window.location.href = this.src; } }, setObjContainerSize : function(parent, auto) { var c = hs.getElementByClass(parent, 'DIV', 'highslide-body'); if (/(iframe|swf)/.test(this.objectType)) { if (this.objectWidth) c.style.width = this.objectWidth +'px'; if (this.objectHeight) c.style.height = this.objectHeight +'px'; } }, writeExtendedContent : function () { if (this.hasExtendedContent) return; var exp = this; this.body = hs.getElementByClass(this.innerContent, 'DIV', 'highslide-body'); if (this.objectType == 'iframe') { this.showLoading(); var ruler = hs.clearing.cloneNode(1); this.body.appendChild(ruler); this.newWidth = this.innerContent.offsetWidth; if (!this.objectWidth) this.objectWidth = ruler.offsetWidth; var hDiff = this.innerContent.offsetHeight - this.body.offsetHeight, h = this.objectHeight || (hs.getPageSize()).height - hDiff - hs.marginTop - hs.marginBottom, onload = this.objectLoadTime == 'before' ? ' onload="if (hs.expanders['+ this.key +']) hs.expanders['+ this.key +'].contentLoaded()" ' : ''; this.body.innerHTML += ''; this.ruler = this.body.getElementsByTagName('div')[0]; this.iframe = this.body.getElementsByTagName('iframe')[0]; if (this.objectLoadTime == 'after') this.correctIframeSize(); } if (this.objectType == 'swf') { this.body.id = this.body.id || 'hs-flash-id-' + this.key; var a = this.swfOptions; if (typeof a.params.wmode == 'undefined') a.params.wmode = 'transparent'; if (swfobject) swfobject.embedSWF(this.src, this.body.id, this.objectWidth, this.objectHeight, a.version || '7', a.expressInstallSwfurl, a.flashvars, a.params, a.attributes); } this.hasExtendedContent = true; }, htmlGetSize : function() { if (this.iframe && !this.objectHeight) { // loadtime before this.iframe.style.height = this.body.style.height = this.getIframePageHeight() +'px'; } this.innerContent.appendChild(hs.clearing); if (!this.x.full) this.x.full = this.innerContent.offsetWidth; this.y.full = this.innerContent.offsetHeight; this.innerContent.removeChild(hs.clearing); if (hs.ie && this.newHeight > parseInt(this.innerContent.currentStyle.height)) { // ie css bug this.newHeight = parseInt(this.innerContent.currentStyle.height); } hs.setStyles( this.wrapper, { position: 'absolute', padding: '0'}); hs.setStyles( this.content, { width: this.x.t +'px', height: this.y.t +'px'}); }, getIframePageHeight : function() { var h; try { var doc = this.iframe.contentDocument || this.iframe.contentWindow.document; var clearing = doc.createElement('div'); clearing.style.clear = 'both'; doc.body.appendChild(clearing); h = clearing.offsetTop; if (hs.ie) h += parseInt(doc.body.currentStyle.marginTop) + parseInt(doc.body.currentStyle.marginBottom) - 1; } catch (e) { // other domain h = 300; } return h; }, correctIframeSize : function () { var wDiff = this.innerContent.offsetWidth - this.ruler.offsetWidth; if (wDiff < 0) wDiff = 0; var hDiff = this.innerContent.offsetHeight - this.body.offsetHeight; hs.setStyles(this.iframe, { width: (this.x.span - wDiff) +'px', height: (this.y.span - hDiff) +'px' }); hs.setStyles(this.body, { width: this.iframe.style.width, height: this.iframe.style.height }); this.scrollingContent = this.iframe; this.scrollerDiv = this.scrollingContent; }, htmlSizeOperations : function () { this.setObjContainerSize(this.innerContent); if (this.objectType == 'swf' && this.objectLoadTime == 'before') this.writeExtendedContent(); // handle minimum size if (this.x.span < this.x.full && !this.allowWidthReduction) this.x.span = this.x.full; if (this.y.span < this.y.full && !this.allowHeightReduction) this.y.span = this.y.full; this.scrollerDiv = this.innerContent; hs.setStyles(this.mediumContent, { width: this.x.span +'px', position: 'relative', left: (this.x.min - this.x.tpos) +'px', top: (this.y.min - this.y.tpos) +'px' }); hs.setStyles(this.innerContent, { border: 'none', width: 'auto', height: 'auto' }); var node = hs.getElementByClass(this.innerContent, 'DIV', 'highslide-body'); if (node && !/(iframe|swf)/.test(this.objectType)) { var cNode = node; // wrap to get true size node = hs.createElement(cNode.nodeName, null, {overflow: 'hidden'}, null, true); cNode.parentNode.insertBefore(node, cNode); node.appendChild(hs.clearing); // IE6 node.appendChild(cNode); var wDiff = this.innerContent.offsetWidth - node.offsetWidth; var hDiff = this.innerContent.offsetHeight - node.offsetHeight; node.removeChild(hs.clearing); var kdeBugCorr = hs.safari || navigator.vendor == 'KDE' ? 1 : 0; // KDE repainting bug hs.setStyles(node, { width: (this.x.span - wDiff - kdeBugCorr) +'px', height: (this.y.span - hDiff) +'px', overflow: 'auto', position: 'relative' } ); if (kdeBugCorr && cNode.offsetHeight > node.offsetHeight) { node.style.width = (parseInt(node.style.width) + kdeBugCorr) + 'px'; } this.scrollingContent = node; this.scrollerDiv = this.scrollingContent; } if (this.iframe && this.objectLoadTime == 'before') this.correctIframeSize(); if (!this.scrollingContent && this.y.span < this.mediumContent.offsetHeight) this.scrollerDiv = this.content; if (this.scrollerDiv == this.content && !this.allowWidthReduction && !/(iframe|swf)/.test(this.objectType)) { this.x.span += 17; // room for scrollbars } if (this.scrollerDiv && this.scrollerDiv.offsetHeight > this.scrollerDiv.parentNode.offsetHeight) { setTimeout("try { hs.expanders["+ this.key +"].scrollerDiv.style.overflow = 'auto'; } catch(e) {}", hs.expandDuration); } }, getImageMapAreaCorrection : function(area) { var c = area.coords.split(','); for (var i = 0; i < c.length; i++) c[i] = parseInt(c[i]); if (area.shape.toLowerCase() == 'circle') { this.x.tpos += c[0] - c[2]; this.y.tpos += c[1] - c[2]; this.x.t = this.y.t = 2 * c[2]; } else { var maxX, maxY, minX = maxX = c[0], minY = maxY = c[1]; for (var i = 0; i < c.length; i++) { if (i % 2 == 0) { minX = Math.min(minX, c[i]); maxX = Math.max(maxX, c[i]); } else { minY = Math.min(minY, c[i]); maxY = Math.max(maxY, c[i]); } } this.x.tpos += minX; this.x.t = maxX - minX; this.y.tpos += minY; this.y.t = maxY - minY; } }, justify : function (p, moveOnly) { var tgtArr, tgt = p.target, dim = p == this.x ? 'x' : 'y'; if (tgt && tgt.match(/ /)) { tgtArr = tgt.split(' '); tgt = tgtArr[0]; } if (tgt && hs.$(tgt)) { p.min = hs.getPosition(hs.$(tgt))[dim]; if (tgtArr && tgtArr[1] && tgtArr[1].match(/^[-]?[0-9]+px$/)) p.min += parseInt(tgtArr[1]); } else if (p.justify == 'auto' || p.justify == 'center') { var hasMovedMin = false; var allowReduce = hs.allowSizeReduction; if (p.justify == 'center') p.min = Math.round(p.scroll + (p.clientSpan - p.span - p.marginMax - p.p1 - p.p2) / 2); else p.min = Math.round(p.min - ((p.span + p.p1 + p.p2 - p.t) / 2)); if (p.min < p.scroll + p.marginMin) { p.min = p.scroll + p.marginMin; hasMovedMin = true; } if (!moveOnly && p.span < p.minSpan) { p.span = p.minSpan; allowReduce = false; } if (p.min + p.span + p.p1 + p.p2 > p.scroll + p.clientSpan - p.marginMax) { if (!moveOnly && hasMovedMin && allowReduce) { p.span = p.clientSpan - p.marginMin - p.marginMax; // can't expand more } else if (p.span + p.p1 + p.p2 < p.clientSpan - p.marginMin - p.marginMax) { p.min = p.scroll + p.clientSpan - p.span - p.marginMax - p.p1 - p.p2; } else { // image larger than viewport p.min = p.scroll + p.marginMin; if (!moveOnly && allowReduce) p.span = p.clientSpan - p.marginMin - p.marginMax; } } if (!moveOnly && p.span < p.minSpan) { p.span = p.minSpan; allowReduce = false; } } else if (p.justify == 'max') { p.min = Math.floor(p.min - p.span + p.t); } if (p.min < p.marginMin) { var tmpMin = p.min; p.min = p.marginMin; if (allowReduce && !moveOnly) p.span = p.span - (p.min - tmpMin); } }, correctRatio : function(ratio) { var x = this.x, y = this.y; var changed = false; if (x.span / y.span > ratio) { // width greater x.span = y.span * ratio; if (x.span < x.minSpan) { // below minWidth x.span = x.minSpan; y.span = x.span / ratio; } changed = true; } else if (x.span / y.span < ratio) { // height greater var tmpHeight = y.span; y.span = x.span / ratio; changed = true; } this.fitOverlayBox(ratio); if (changed) { x.min = x.tpos - x.cb + x.tb; x.minSpan = x.span; this.justify(x, true); y.min = y.tpos - y.cb + y.tb; y.minSpan = y.span; this.justify(y, true); if (this.overlayBox) this.sizeOverlayBox(); } }, fitOverlayBox : function(ratio) { var x = this.x, y = this.y; if (this.overlayBox) { while (y.span > this.minHeight && x.span > this.minWidth && y.marginMin + y.p1 + y.span + y.p2 + y.marginMax > y.clientSpan) { y.span -= 10; if (ratio) x.span = y.span * ratio; this.sizeOverlayBox(0, 1); } } }, reflow : function () { var h = /iframe/i.test(this.scrollerDiv.tagName) ? this.getIframePageHeight() + 1 +'px' : 'auto'; if (this.body) this.body.style.height = h; this.scrollerDiv.style.height = h; this.y.span = this.innerContent.offsetHeight; this.content.style.height = this.y.span +'px'; if (this.outline) this.outline.setPosition(this); }, show : function () { // Selectbox bug var imgPos = { x: this.x.min - 20, y: this.y.min - 20, w: this.x.span + 40 + this.x.p1 + this.x.p2, h: this.y.span + 40 + this.y.p1 + this.y.p2 }; hs.hideSelects = (hs.ie && hs.ieVersion() < 7); if (hs.hideSelects) this.showHideElements('SELECT', 'hidden', imgPos); // Iframes bug hs.hideIframes = ((window.opera && navigator.appVersion < 9) || navigator.vendor == 'KDE' || (hs.ie && hs.ieVersion() < 5.5)); if (hs.hideIframes) this.showHideElements('IFRAME', 'hidden', imgPos); // Scrollbars bug if (hs.geckoMac) this.showHideElements('*', 'hidden', imgPos); hs.fireEvent(this, 'onBeforeExpand'); // Apply size change this.changeSize( 1, { xmin: this.x.tpos + this.x.tb - this.x.cb, ymin: this.y.tpos + this.y.tb - this.y.cb, xspan: this.x.t, yspan: this.y.t, xp1: 0, xp2: 0, yp1: 0, yp2: 0, o: hs.outlineStartOffset }, { xmin: this.x.min, ymin: this.y.min, xspan: this.x.span, yspan: this.y.span, xp1: this.x.p1, yp1: this.y.p1, xp2: this.x.p2, yp2: this.y.p2, o: this.outline ? this.outline.offset : 0 }, hs.expandDuration, hs.expandSteps ); }, changeSize : function(up, from, to, dur, steps) { // transition var trans = this.transitions, other = up ? (this.last ? this.last.a : null) : hs.upcoming, t = (trans[1] && other && hs.getParam(other, 'transitions')[1] == trans[1]) ? trans[1] : trans[0]; if (up && this.isHtml && trans[1] == 'crossfade') t = trans[1] = 'fade'; if (this[t] && t != 'expand') { this[t](up, from, to); return; } if (up) hs.setStyles(this.wrapper, { opacity: 1 }); if (this.outline && !this.outlineWhileAnimating) { if (up) this.outline.setPosition(this); else this.outline.destroy( (this.isHtml && this.preserveContent)); } if (!up && this.overlayBox) { if (this.slideshow) { var c = this.slideshow.controls; if (c && hs.getExpander(c) == this) c.parentNode.removeChild(c); } if (this.isHtml && this.preserveContent) { this.overlayBox.style.top = '-9999px'; hs.container.appendChild(this.overlayBox); } else hs.discardElement(this.overlayBox); } if (this.fadeInOut) { from.op = up ? 0 : 1; to.op = up; } var t, exp = this, easing = Math[this.easing] || Math.easeInQuad; if (!up) easing = Math[this.easingClose] || easing; for (var i = 1; i <= steps; i++) { t = Math.round(i * (dur / steps)); (function(){ var pI = i, size = {}; for (var x in from) { size[x] = easing(t, from[x], to[x] - from[x], dur); if (!/^op$/.test(x)) size[x] = Math.round(size[x]); } setTimeout ( function() { if (up && pI == 1) { exp.content.style.visibility = 'visible'; exp.a.className += ' highslide-active-anchor'; } exp.setSize(size); }, t); })(); } if (up) { setTimeout(function() { if (exp.outline) exp.outline.table.style.visibility = "visible"; }, t); setTimeout(function() { exp.afterExpand(); }, t + 50); } else setTimeout(function() { exp.afterClose(); }, t); }, setSize : function (to) { try { if (to.op) hs.setStyles(this.wrapper, { opacity: to.op }); hs.setStyles ( this.wrapper, { width : (to.xspan +to.xp1 + to.xp2 + 2 * this.x.cb) +'px', height : (to.yspan +to.yp1 + to.yp2 + 2 * this.y.cb) +'px', left: to.xmin +'px', top: to.ymin +'px' }); hs.setStyles(this.content, { top: to.yp1 +'px', left: to.xp1 +'px', width: to.xspan +'px', height: to.yspan +'px' }); if (this.isHtml) { hs.setStyles(this.mediumContent, { left: (this.x.min - to.xmin + this.x.p1 - to.xp1) +'px', top: (this.y.min - to.ymin + this.y.p1 - to.yp1) +'px' }); this.innerContent.style.visibility = 'visible'; } if (this.outline && this.outlineWhileAnimating) { var o = this.outline.offset - to.o; this.outline.setPosition(this, { x: to.xmin + o, y: to.ymin + o, w: to.xspan + to.xp1 + to.xp2 + - 2 * o, h: to.yspan + to.yp1 + to.yp2 + - 2 * o }, 1); } this.wrapper.style.visibility = 'visible'; } catch (e) { window.location.href = this.src; } }, fade : function(up, from, to) { this.outlineWhileAnimating = false; var exp = this, t = up ? 250 : 0; if (up) { hs.setStyles(this.wrapper, { opacity: 0 }); this.setSize(to); this.content.style.visibility = 'visible'; hs.fade (this.wrapper, 0, 1); } if (this.outline) { this.outline.table.style.zIndex = this.wrapper.style.zIndex; var dir = up || -1; for (var i = from.o; dir * i <= dir * to.o; i += dir, t += 25) { (function() { var o = up ? to.o - i : from.o - i; setTimeout(function() { exp.outline.setPosition(exp, { x: (exp.x.min + o), y: (exp.y.min + o), w: (exp.x.span - 2 * o + exp.x.p1 + exp.x.p2), h: (exp.y.span - 2 * o + exp.y.p1 + exp.y.p2) }, 1); }, t); })(); } } if (up) setTimeout(function() { exp.afterExpand(); }, t+50); else { setTimeout( function() { if (exp.outline) exp.outline.destroy(exp.preserveContent); hs.fade (exp.wrapper, 1, 0); setTimeout( function() { exp.afterClose(); }, 250); }, t); } }, crossfade : function (up, from, to) { if (!up) return; var exp = this, steps = parseInt(hs.transitionDuration / 25), last = this.last; hs.removeEventListener(document, 'mousemove', hs.dragHandler); hs.setStyles(this.content, { width: to.xspan +'px', height: to.yspan +'px' }); this.outline = this.last.outline; this.last.outline = null; this.fadeBox = hs.createElement('div', { className: 'highslide-image' }, { position: 'absolute', zIndex: 4, overflow: 'hidden', display: 'none' } ); var names = { oldImg: last, newImg: this }; for (var x in names) { this[x] = names[x].content.cloneNode(1); hs.setStyles(this[x], { position: 'absolute', border: 0, visibility: 'visible' }); this.fadeBox.appendChild(this[x]); } this.wrapper.appendChild(this.fadeBox); from = { xmin: last.x.min, xspan: last.x.span, xp1: last.x.p1, xp2: last.x.p2, ymin: last.y.min, yspan: last.y.span, yp1: last.y.p1, yp2: last.y.p2, o: 1 / steps }; to.yspan = this.y.span; to.o = 1; var t, easing = Math.easeInOutQuad; this.crossfadeStep(from); function prep() { if (exp.overlayBox) { exp.wrapper.appendChild(exp.overlayBox); for (var i = 0; i < exp.last.overlays.length; i++) { var oDiv = hs.$('hsId'+ exp.last.overlays[i]); if (oDiv.reuse === exp.key) exp.overlayBox.appendChild(oDiv); else hs.fade(oDiv, oDiv.opacity, 0); } } exp.fadeBox.style.display = ''; exp.last.content.style.display = 'none'; }; if (/rv:1\.[0-8].+Gecko/.test(navigator.userAgent)) setTimeout(prep, 0); else prep(); if (hs.safari) { var match = navigator.userAgent.match(/Safari\/([0-9]{3})/); if (match && parseInt(match[1]) < 525) this.wrapper.style.visibility = 'visible'; } for (var i = 1; i <= steps; i++) { t = Math.round(i * (hs.transitionDuration / steps)); (function(){ var size = {}, pI = i; for (var x in from) { var val = easing(t, from[x], to[x] - from[x], hs.transitionDuration); size[x] = (x != 'o') ? Math.round(val) : val; } setTimeout ( function() { exp.crossfadeStep(size); }, t); })(); } setTimeout ( function () { exp.crossfadeEnd(); }, t + 100); }, crossfadeStep : function (size) { try { if (this.outline) this.outline.setPosition(this, { x: size.xmin, y: size.ymin, w: size.xspan + size.xp1 + size.xp2, h: size.yspan + size.yp1 + size.yp2 }, 1); this.last.wrapper.style.clip = 'rect(' + (size.ymin - this.last.y.min)+'px, ' + (size.xspan + size.xp1 + size.xp2 + 2 * this.last.x.cb + size.xmin - this.last.x.min) +'px, ' + (size.yspan + size.yp1 + size.yp2 + 2 * this.last.y.cb + size.ymin - this.last.y.min) +'px, ' + (size.xmin - this.last.x.min)+'px)'; hs.setStyles(this.content, { top: size.yp1 +'px', left: size.xp1 +'px', marginTop: (this.y.min - size.ymin) +'px', marginLeft: (this.x.min - size.xmin) +'px' }); hs.setStyles(this.wrapper, { top: size.ymin +'px', left: size.xmin +'px', width: (size.xp1 + size.xp2 + size.xspan + 2 * this.x.cb)+ 'px', height: (size.yp1 + size.yp2 + size.yspan + 2 * this.y.cb) + 'px' }); hs.setStyles(this.fadeBox, { width: size.xspan + 'px', height: size.yspan +'px', left: size.xp1 +'px', top: size.yp1 +'px', visibility: 'visible' }); hs.setStyles(this.oldImg, { top: (this.last.y.min - size.ymin + this.last.y.p1 - size.yp1)+'px', left: (this.last.x.min - size.xmin + this.last.x.p1 - size.xp1)+'px' }); hs.setStyles(this.newImg, { opacity: size.o, top: (this.y.min - size.ymin + this.y.p1 - size.yp1) +'px', left: (this.x.min - size.xmin + this.x.p1 - size.xp1) +'px' }); hs.setStyles(this.overlayBox, { width: size.xspan + 'px', height: size.yspan +'px', left: (size.xp1 + this.x.cb) +'px', top: (size.yp1 + this.y.cb) +'px' }); } catch (e) {} }, crossfadeEnd : function() { this.wrapper.style.background = this.wrapperBG || ''; this.wrapper.style.visibility = this.content.style.visibility = 'visible'; this.fadeBox.style.display = 'none'; this.a.className += ' highslide-active-anchor'; this.afterExpand(); this.last.afterClose(); }, reuseOverlay : function(o, el) { if (!this.last) return false; for (var i = 0; i < this.last.overlays.length; i++) { var oDiv = hs.$('hsId'+ this.last.overlays[i]); if (oDiv && oDiv.hsId == o.hsId) { this.genOverlayBox(); oDiv.reuse = this.key; hs.push(this.overlays, this.last.overlays[i]); return true; } } return false; }, afterExpand : function() { this.isExpanded = true; this.focus(); if (this.isHtml && this.objectLoadTime == 'after') this.writeExtendedContent(); if (this.isHtml) { if (this.iframe) { try { var exp = this, doc = this.iframe.contentDocument || this.iframe.contentWindow.document; hs.addEventListener(doc, 'mousedown', function () { if (hs.focusKey != exp.key) exp.focus(); }); } catch(e) {} if (hs.ie && typeof this.isClosing != 'boolean') // first open this.iframe.style.width = (this.objectWidth - 1) +'px'; // hasLayout } } if (this.dimmingOpacity) hs.dim(this); if (hs.upcoming && hs.upcoming == this.a) hs.upcoming = null; this.prepareNextOutline(); var p = hs.page, mX = hs.mouse.x + p.scrollLeft, mY = hs.mouse.y + p.scrollTop; this.mouseIsOver = this.x.min < mX && mX < this.x.min + this.x.p1 + this.x.span + this.x.p2 && this.y.min < mY && mY < this.y.min + this.y.p1 + this.y.span + this.y.p2; if (this.overlayBox) this.showOverlays(); hs.fireEvent(this, 'onAfterExpand'); }, prepareNextOutline : function() { var key = this.key; var outlineType = this.outlineType; new hs.Outline(outlineType, function () { try { hs.expanders[key].preloadNext(); } catch (e) {} }); }, preloadNext : function() { var next = this.getAdjacentAnchor(1); if (next && next.onclick.toString().match(/hs\.expand/)) var img = hs.createElement('img', { src: hs.getSrc(next) }); }, getAdjacentAnchor : function(op) { var current = this.getAnchorIndex(), as = hs.anchors.groups[this.slideshowGroup || 'none']; /*< ? if ($cfg->slideshow) : ?>s*/ if (!as[current + op] && this.slideshow && this.slideshow.repeat) { if (op == 1) return as[0]; else if (op == -1) return as[as.length-1]; } /*< ? endif ?>s*/ return as[current + op] || null; }, getAnchorIndex : function() { var arr = hs.anchors.groups[this.slideshowGroup || 'none']; for (var i = 0; i < arr.length; i++) { if (arr[i] == this.a) return i; } return null; }, getNumber : function() { if (this[this.numberPosition]) { var arr = hs.anchors.groups[this.slideshowGroup || 'none']; var s = hs.lang.number.replace('%1', this.getAnchorIndex() + 1).replace('%2', arr.length); this[this.numberPosition].innerHTML = ' '+ this[this.numberPosition].innerHTML; } }, initSlideshow : function() { if (this.slideshow) return; if (!this.last) { for (var i = 0; i < hs.slideshows.length; i++) { var ss = hs.slideshows[i], sg = ss.slideshowGroup; if (typeof sg == 'undefined' || sg === null || sg === this.slideshowGroup) this.slideshow = new hs.Slideshow(ss); } } else { this.slideshow = this.last.slideshow; } var ss = this.slideshow; if (!ss) return; var exp = ss.exp = this; ss.checkFirstAndLast(); if (ss.controls) { var o = ss.overlayOptions || {}; o.overlayId = ss.controls; o.hsId = 'controls'; this.createOverlay(o); } if (!this.last && this.autoplay) ss.play(true); if (ss.autoplay) { ss.autoplay = setTimeout(function() { hs.next(exp.key); }, (ss.interval || 500)); } }, cancelLoading : function() { hs.expanders[this.key] = null; if (hs.upcoming == this.a) hs.upcoming = null; hs.undim(); if (this.loading) hs.loading.style.left = '-9999px'; hs.fireEvent(this, 'onHideLoading'); }, writeCredits : function () { if (this.credits) return; this.credits = hs.createElement('a', { href: hs.creditsHref, className: 'highslide-credits', innerHTML: hs.lang.creditsText, title: hs.lang.creditsTitle } ); this.createOverlay({ overlayId: this.credits, position: 'top left', hsId: 'credits' }); }, getInline : function(types, addOverlay) { for (var i = 0; i < types.length; i++) { var type = types[i], s = null; if (type == 'caption' && !hs.fireEvent(this, 'onBeforeGetCaption')) return; else if (type == 'heading' && !hs.fireEvent(this, 'onBeforeGetHeading')) return; if (!this[type +'Id'] && this.thumbsUserSetId) this[type +'Id'] = type +'-for-'+ this.thumbsUserSetId; if (this[type +'Id']) this[type] = hs.getNode(this[type +'Id']); if (!this[type] && !this[type +'Text'] && this[type +'Eval']) try { s = eval(this[type +'Eval']); } catch (e) {} if (!this[type] && this[type +'Text']) { s = this[type +'Text']; } if (!this[type] && !s) { var next = this.a.nextSibling; while (next && !hs.isHsAnchor(next)) { if ((new RegExp('highslide-'+ type)).test(next.className || null)) { this[type] = next.cloneNode(1); break; } next = next.nextSibling; } } if (!this[type] && !s && this.numberPosition == type) s = '\n'; if (!this[type] && s) this[type] = hs.createElement('div', { className: 'highslide-'+ type, innerHTML: s } ); if (addOverlay && this[type]) { var o = { position: (type == 'heading') ? 'above' : 'below' }; for (var x in this[type+'Overlay']) o[x] = this[type+'Overlay'][x]; o.overlayId = this[type]; this.createOverlay(o); } } }, showHideElements : function (tagName, visibility, imgPos) { var els = document.getElementsByTagName(tagName); var prop = tagName == '*' ? 'overflow' : 'visibility'; for (var i = 0; i < els.length; i++) { if (prop == 'visibility' || (document.defaultView.getComputedStyle( els[i], "").getPropertyValue('overflow') == 'auto' || els[i].getAttribute('hidden-by') != null)) { var hiddenBy = els[i].getAttribute('hidden-by'); if (visibility == 'visible' && hiddenBy) { hiddenBy = hiddenBy.replace('['+ this.key +']', ''); els[i].setAttribute('hidden-by', hiddenBy); if (!hiddenBy) els[i].style[prop] = els[i].origProp; } else if (visibility == 'hidden') { // hide if behind var elPos = hs.getPosition(els[i]); elPos.w = els[i].offsetWidth; elPos.h = els[i].offsetHeight; if (!this.dimmingOpacity) { // hide all if dimming var clearsX = (elPos.x + elPos.w < imgPos.x || elPos.x > imgPos.x + imgPos.w); var clearsY = (elPos.y + elPos.h < imgPos.y || elPos.y > imgPos.y + imgPos.h); } var wrapperKey = hs.getWrapperKey(els[i]); if (!clearsX && !clearsY && wrapperKey != this.key) { // element falls behind image if (!hiddenBy) { els[i].setAttribute('hidden-by', '['+ this.key +']'); els[i].origProp = els[i].style[prop]; els[i].style[prop] = 'hidden'; } else if (!hiddenBy.match('['+ this.key +']')) { els[i].setAttribute('hidden-by', hiddenBy + '['+ this.key +']'); } } else if (hiddenBy == '['+ this.key +']' || hs.focusKey == wrapperKey) { // on move els[i].setAttribute('hidden-by', ''); els[i].style[prop] = els[i].origProp || ''; } else if (hiddenBy && hiddenBy.match('['+ this.key +']')) { els[i].setAttribute('hidden-by', hiddenBy.replace('['+ this.key +']', '')); } } } } }, focus : function() { this.wrapper.style.zIndex = hs.zIndexCounter++; // blur others for (var i = 0; i < hs.expanders.length; i++) { if (hs.expanders[i] && i == hs.focusKey) { var blurExp = hs.expanders[i]; blurExp.content.className += ' highslide-'+ blurExp.contentType +'-blur'; if (blurExp.isImage) { blurExp.content.style.cursor = hs.ie ? 'hand' : 'pointer'; blurExp.content.title = hs.lang.focusTitle; } hs.fireEvent(this, 'onBlur'); } } // focus this if (this.outline) this.outline.table.style.zIndex = this.wrapper.style.zIndex; this.content.className = 'highslide-'+ this.contentType; if (this.isImage) { this.content.title = hs.lang.restoreTitle; hs.styleRestoreCursor = window.opera ? 'pointer' : 'url('+ hs.graphicsDir + hs.restoreCursor +'), pointer'; if (hs.ie && hs.ieVersion() < 6) hs.styleRestoreCursor = 'hand'; this.content.style.cursor = hs.styleRestoreCursor; } hs.focusKey = this.key; hs.addEventListener(document, window.opera ? 'keypress' : 'keydown', hs.keyHandler); hs.fireEvent(this, 'onFocus'); }, move : function (e) { this.x.min = e.left + e.dX; this.y.min = e.top + e.dY; if (e.type == 'image') this.content.style.cursor = 'move'; hs.setStyles(this.wrapper, { left: this.x.min +'px', top: this.y.min +'px' }); if (this.outline) this.outline.setPosition(this); }, resize : function (e) { var w, h, r = e.width / e.height; w = Math.max(e.width + e.dX, Math.min(this.minWidth, this.x.full)); if (this.isImage && Math.abs(w - this.x.full) < 12) w = this.x.full; h = this.isHtml ? e.height + e.dY : w / r; if (h < Math.min(this.minHeight, this.y.full)) { h = Math.min(this.minHeight, this.y.full); if (this.isImage) w = h * r; } this.x.span = w; this.y.span = h; if (this.isHtml) { var d = this.scrollerDiv; if (typeof this.wDiff == 'undefined') { this.wDiff = this.innerContent.offsetWidth - d.offsetWidth; this.hDiff = this.innerContent.offsetHeight - d.offsetHeight; } hs.setStyles(d, { width: (this.x.span - this.wDiff) +'px', height: (this.y.span - this.hDiff) +'px' }); } var size = { width: this.x.span +'px', height: this.y.span +'px' }; hs.setStyles(this.content, size); if (this.releaseMask) hs.setStyles(this.releaseMask, size); if (this.isHtml) { this.mediumContent.style.width = 'auto'; if (this.body) hs.setStyles(this.body, { width: 'auto', height: 'auto' }); } if (this.overlayBox) this.sizeOverlayBox(true); hs.setStyles(this.wrapper, { width: (this.x.p1 + this.x.p2 +2 * this.x.cb + this.x.span) +'px', height: (this.y.p1 + this.y.p2 +2 * this.y.cb + this.y.span) +'px' }); if (this.slideshow && this.isImage) { if (w == this.x.full) this.slideshow.disable('full-expand'); else this.slideshow.enable('full-expand'); } if (this.outline) this.outline.setPosition(this); }, close : function() { if (this.isClosing || !this.isExpanded || (hs.upcoming && this.transitions[1] == 'crossfade') ) return; this.isClosing = true; if (!hs.fireEvent(this, 'onBeforeClose')) return; if (this.slideshow && !hs.upcoming) this.slideshow.pause(); hs.removeEventListener(document, window.opera ? 'keypress' : 'keydown', hs.keyHandler); try { if (this.isHtml) this.htmlPrepareClose(); this.content.style.cursor = 'default'; this.changeSize( 0, { xmin: this.x.min, ymin: this.y.min, xspan: this.x.span, yspan: parseInt(this.content.style.height), xp1: this.x.p1, yp1: this.y.p1, xp2: this.x.p2, yp2: this.y.p2, o: this.outline ? this.outline.offset : 0 }, { xmin: this.x.tpos - this.x.cb + this.x.tb, ymin: this.y.tpos - this.y.cb + this.y.tb, xspan: this.x.t, yspan: this.y.t, xp1: 0, yp1: 0, xp2: 0, yp2: 0, o: hs.outlineStartOffset }, hs.restoreDuration, hs.restoreSteps ); } catch (e) { this.afterClose(); } }, htmlPrepareClose : function() { if (hs.geckoMac) { // bad redraws if (!hs.mask) hs.mask = hs.createElement('div', null, { position: 'absolute' }, hs.container); hs.setStyles(hs.mask, { width: this.x.span +'px', height: this.y.span +'px', left: this.x.min +'px', top: this.y.min +'px', display: 'block' }); } if (this.objectType == 'swf') try { hs.$(this.body.id).StopPlay(); } catch (e) {} if (this.objectLoadTime == 'after' && !this.preserveContent) this.destroyObject(); if (this.scrollerDiv && this.scrollerDiv != this.scrollingContent) this.scrollerDiv.style.overflow = 'hidden'; }, destroyObject : function () { if (hs.ie && this.iframe) try { this.iframe.contentWindow.document.body.innerHTML = ''; } catch (e) {} if (this.objectType == 'swf') swfobject.removeSWF(this.body.id); this.body.innerHTML = ''; }, sleep : function() { if (this.outline) this.outline.table.style.display = 'none'; this.releaseMask = null; this.wrapper.style.display = 'none'; hs.push(hs.sleeping, this); }, awake : function() { hs.expanders[this.key] = this; if (!hs.allowMultipleInstances &&hs.focusKey != this.key) { try { hs.expanders[hs.focusKey].close(); } catch (e){} } var z = hs.zIndexCounter++, stl = { display: '', zIndex: z }; hs.setStyles (this.wrapper, stl); this.isClosing = false; var o = this.outline || 0; if (o) { if (!this.outlineWhileAnimating) stl.visibility = 'hidden'; hs.setStyles (o.table, stl); } this.show(); }, createOverlay : function (o) { var el = o.overlayId; if (typeof el == 'string') el = hs.getNode(el); if (!el || typeof el == 'string') return; if (!hs.fireEvent(this, 'onCreateOverlay', { overlay: el })) return; el.style.display = 'block'; o.hsId = o.hsId || o.overlayId; if (this.transitions[1] == 'crossfade' && this.reuseOverlay(o, el)) return; this.genOverlayBox(); var width = o.width && /^[0-9]+(px|%)$/.test(o.width) ? o.width : 'auto'; if (/^(left|right)panel$/.test(o.position) && !/^[0-9]+px$/.test(o.width)) width = '200px'; var overlay = hs.createElement( 'div', { id: 'hsId'+ hs.idCounter++, hsId: o.hsId }, { position: 'absolute', visibility: 'hidden', width: width }, this.overlayBox, true ); overlay.appendChild(el); hs.setAttribs(overlay, { hideOnMouseOut: o.hideOnMouseOut, opacity: o.opacity || 1, hsPos: o.position, fade: o.fade }); if (this.gotOverlays) { this.positionOverlay(overlay); if (!overlay.hideOnMouseOut || this.mouseIsOver) hs.fade(overlay, 0, overlay.opacity); } hs.push(this.overlays, hs.idCounter - 1); }, positionOverlay : function(overlay) { var p = overlay.hsPos || 'middle center'; if (/left$/.test(p)) overlay.style.left = 0; if (/center$/.test(p)) hs.setStyles (overlay, { left: '50%', marginLeft: '-'+ Math.round(overlay.offsetWidth / 2) +'px' }); if (/right$/.test(p)) overlay.style.right = 0; if (/^leftpanel$/.test(p)) { hs.setStyles(overlay, { right: '100%', marginRight: this.x.cb +'px', top: - this.y.cb +'px', bottom: - this.y.cb +'px', overflow: 'auto' }); this.x.p1 = overlay.offsetWidth; } else if (/^rightpanel$/.test(p)) { hs.setStyles(overlay, { left: '100%', marginLeft: this.x.cb +'px', top: - this.y.cb +'px', bottom: - this.y.cb +'px', overflow: 'auto' }); this.x.p2 = overlay.offsetWidth; } if (/^top/.test(p)) overlay.style.top = 0; if (/^middle/.test(p)) hs.setStyles (overlay, { top: '50%', marginTop: '-'+ Math.round(overlay.offsetHeight / 2) +'px' }); if (/^bottom/.test(p)) overlay.style.bottom = 0; if (/^above$/.test(p)) { hs.setStyles(overlay, { left: (- this.x.p1 - this.x.cb) +'px', right: (- this.x.p2 - this.x.cb) +'px', bottom: '100%', marginBottom: this.y.cb +'px', width: 'auto' }); this.y.p1 = overlay.offsetHeight; } else if (/^below$/.test(p)) { hs.setStyles(overlay, { position: 'relative', left: (- this.x.p1 - this.x.cb) +'px', right: (- this.x.p2 - this.x.cb) +'px', top: '100%', marginTop: this.y.cb +'px', width: 'auto' }); this.y.p2 = overlay.offsetHeight; overlay.style.position = 'absolute'; } }, getOverlays : function() { this.getInline(['heading', 'caption'], true); this.getNumber(); if (this.caption) hs.fireEvent(this, 'onAfterGetCaption'); if (this.heading) hs.fireEvent(this, 'onAfterGetHeading'); if (this.heading && this.dragByHeading) this.heading.className += ' highslide-move'; if (hs.showCredits) this.writeCredits(); for (var i = 0; i < hs.overlays.length; i++) { var o = hs.overlays[i], tId = o.thumbnailId, sg = o.slideshowGroup; if ((!tId && !sg) || (tId && tId == this.thumbsUserSetId) || (sg && sg === this.slideshowGroup)) { if (this.isImage || (this.isHtml && o.useOnHtml)) this.createOverlay(o); } } var os = []; for (var i = 0; i < this.overlays.length; i++) { var o = hs.$('hsId'+ this.overlays[i]); if (/panel$/.test(o.hsPos)) this.positionOverlay(o); else hs.push(os, o); } var curW = this.x.p1 + this.x.full + this.x.p2; if (hs.padToMinWidth && curW < hs.minWidth) { this.x.p1 += (hs.minWidth - curW) / 2; this.x.p2 += (hs.minWidth - curW) / 2; } for (var i = 0; i < os.length; i++) this.positionOverlay(os[i]); this.gotOverlays = true; }, genOverlayBox : function() { if (!this.overlayBox) this.overlayBox = hs.createElement ( 'div', null, { position : 'absolute', width: this.x.span ? this.x.span +'px' : this.x.full +'px', height: 0, visibility : 'hidden', overflow : 'hidden', zIndex : hs.ie ? 4 : null }, hs.container, true ); }, sizeOverlayBox : function(doWrapper, doPanels) { hs.setStyles( this.overlayBox, { width: this.x.span +'px', height: this.y.span +'px' }); if (doWrapper || doPanels) { for (var i = 0; i < this.overlays.length; i++) { var o = hs.$('hsId'+ this.overlays[i]); if (o && /^(above|below)$/.test(o.hsPos)) { if (hs.ie && (hs.ieVersion() <= 6 || document.compatMode == 'BackCompat')) { o.style.width = (this.overlayBox.offsetWidth + 2 * this.x.cb + this.x.p1 + this.x.p2) +'px'; } this.y[o.hsPos == 'above' ? 'p1' : 'p2'] = o.offsetHeight; } } } if (doWrapper) { hs.setStyles(this.content, { top: this.y.p1 +'px' }); hs.setStyles(this.overlayBox, { top: (this.y.p1 + this.y.cb) +'px' }); } }, showOverlays : function() { var b = this.overlayBox; hs.setStyles(b, { top: (this.y.p1 + this.y.cb) +'px', left: (this.x.p1 + this.x.cb) +'px', overflow : 'visible' }); if (hs.safari) b.style.visibility = 'visible'; this.wrapper.appendChild (b); for (var i = 0; i < this.overlays.length; i++) { var o = hs.$('hsId'+ this.overlays[i]); o.style.zIndex = o.hsId == 'controls' ? 5 : 4; if (!o.hideOnMouseOut || this.mouseIsOver) hs.fade(o, 0, o.opacity); } }, createFullExpand : function () { if (this.slideshow && this.slideshow.controls) { this.slideshow.enable('full-expand'); return; } this.fullExpandLabel = hs.createElement( 'a', { href: 'javascript:hs.expanders['+ this.key +'].doFullExpand();', title: hs.lang.fullExpandTitle, className: 'highslide-full-expand' } ); if (!hs.fireEvent(this, 'onCreateFullExpand')) return; this.createOverlay({ overlayId: this.fullExpandLabel, position: hs.fullExpandPosition, hideOnMouseOut: true, opacity: hs.fullExpandOpacity }); }, doFullExpand : function () { try { if (!hs.fireEvent(this, 'onDoFullExpand')) return; if (this.fullExpandLabel) hs.discardElement(this.fullExpandLabel); else if (this.slideshow) this.slideshow.disable('full-expand'); this.focus(); this.x.min = parseInt(this.wrapper.style.left) - (this.x.full - this.content.width) / 2; if (this.x.min < hs.marginLeft) this.x.min = hs.marginLeft; this.wrapper.style.left = this.x.min +'px'; hs.setStyles(this.content, { width: this.x.full +'px', height: this.y.full +'px'}); this.x.span = this.x.full; this.y.span = this.y.full; if (this.overlayBox) this.sizeOverlayBox(true); hs.setStyles(this.wrapper, { width: (this.x.p1 + 2 * this.x.cb + this.x.span + this.x.p2) +'px', height: (this.y.p1 + 2 * this.y.cb + this.y.span + this.y.p2) +'px' }); if (this.outline) this.outline.setPosition(this); this.redoShowHide(); hs.setDimmerSize(this); } catch (e) { window.location.href = this.content.src; } }, // on end move and resize redoShowHide : function() { var imgPos = { x: parseInt(this.wrapper.style.left) - 20, y: parseInt(this.wrapper.style.top) - 20, w: this.content.offsetWidth + 40 + this.x.p1 + this.x.p2, h: this.content.offsetHeight + 40 + this.y.p1 + this.y.p2 }; if (hs.hideSelects) this.showHideElements('SELECT', 'hidden', imgPos); if (hs.hideIframes) this.showHideElements('IFRAME', 'hidden', imgPos); if (hs.geckoMac) this.showHideElements('*', 'hidden', imgPos); }, afterClose : function () { this.a.className = this.a.className.replace('highslide-active-anchor', ''); if (hs.hideSelects) this.showHideElements('SELECT', 'visible'); if (hs.hideIframes) this.showHideElements('IFRAME', 'visible'); if (hs.geckoMac) this.showHideElements('*', 'visible'); if (this.isHtml && this.preserveContent) this.sleep(); else { if (this.outline && this.outlineWhileAnimating) this.outline.destroy(); hs.discardElement(this.wrapper); } if (hs.mask) hs.mask.style.display = 'none'; if (this.dimmingOpacity) hs.undim(this.key); hs.fireEvent(this, 'onAfterClose'); hs.expanders[this.key] = null; hs.reOrder(); } }; // hs.Ajax object prototype hs.Ajax = function (a, content, pre) { this.a = a; this.content = content; this.pre = pre; }; hs.Ajax.prototype = { run : function () { if (!this.src) this.src = hs.getSrc(this.a); if (this.src.match('#')) { var arr = this.src.split('#'); this.src = arr[0]; this.id = arr[1]; } if (hs.cachedGets[this.src]) { this.cachedGet = hs.cachedGets[this.src]; if (this.id) this.getElementContent(); else this.loadHTML(); return; } try { this.xmlHttp = new XMLHttpRequest(); } catch (e) { try { this.xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { this.xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { this.onError(); } } } var pThis = this; this.xmlHttp.onreadystatechange = function() { if(pThis.xmlHttp.readyState == 4) { if (pThis.id) pThis.getElementContent(); else pThis.loadHTML(); } }; this.xmlHttp.open("GET", this.src, true); this.xmlHttp.send(null); }, getElementContent : function() { hs.init(); var attribs = window.opera || hs.ie6SSL ? { src: 'about:blank' } : null; this.iframe = hs.createElement('iframe', attribs, { position: 'absolute', top: '-9999px' }, hs.container); this.loadHTML(); }, loadHTML : function() { var s = this.cachedGet || this.xmlHttp.responseText; if (this.pre) hs.cachedGets[this.src] = s; if (!hs.ie || hs.ieVersion() >= 5.5) { s = s.replace(/\s/g, ' ').replace( new RegExp(']*>', 'gi'), '').replace( new RegExp('', 'gi'), ''); if (this.iframe) { var doc = this.iframe.contentDocument; if (!doc && this.iframe.contentWindow) doc = this.iframe.contentWindow.document; if (!doc) { // Opera var pThis = this; setTimeout(function() { pThis.loadHTML(); }, 25); return; } doc.open(); doc.write(s); doc.close(); try { s = doc.getElementById(this.id).innerHTML; } catch (e) { try { s = this.iframe.document.getElementById(this.id).innerHTML; } catch (e) {} // opera } } else { s = s.replace(new RegExp('^.*?]*>(.*?).*?$', 'i'), '$1'); } } hs.getElementByClass(this.content, 'DIV', 'highslide-body').innerHTML = s; this.onLoad(); for (var x in this) this[x] = null; } }; hs.Slideshow = function (options) { hs.updateAnchors(); for (var x in options) this[x] = options[x]; if (this.useControls) this.getControls(); }; hs.Slideshow.prototype = { getControls: function() { this.controls = hs.createElement('div', { innerHTML: hs.replaceLang(hs.skin.controls) }, null, hs.container); var buttons = ['play', 'pause', 'previous', 'next', 'move', 'full-expand', 'close']; this.btn = {}; var pThis = this; for (var i = 0; i < buttons.length; i++) { this.btn[buttons[i]] = hs.getElementByClass(this.controls, 'li', 'highslide-'+ buttons[i]); this.enable(buttons[i]); } this.btn.pause.style.display = 'none'; this.disable('full-expand'); }, checkFirstAndLast: function() { if (this.repeat || !this.controls) return; var cur = this.exp.getAnchorIndex(), re = /disabled$/; if (cur == 0) this.disable('previous'); else if (re.test(this.btn.previous.getElementsByTagName('a')[0].className)) this.enable('previous'); if (cur + 1 == hs.anchors.groups[this.exp.slideshowGroup || 'none'].length) { this.disable('next'); this.disable('play'); } else if (re.test(this.btn.next.getElementsByTagName('a')[0].className)) { this.enable('next'); this.enable('play'); } }, enable: function(btn) { if (!this.btn) return; var sls = this, a = this.btn[btn].getElementsByTagName('a')[0], re = /disabled$/; a.onclick = function() { sls[btn](); return false; }; if (re.test(a.className)) a.className = a.className.replace(re, ''); }, disable: function(btn) { if (!this.btn) return; var a = this.btn[btn].getElementsByTagName('a')[0]; a.onclick = function() { return false; }; if (!/disabled$/.test(a.className)) a.className += ' disabled'; }, hitSpace: function() { if (this.autoplay) this.pause(); else this.play(); }, play: function(wait) { if (this.btn) { this.btn.play.style.display = 'none'; this.btn.pause.style.display = ''; } this.autoplay = true; if (!wait) hs.next(this.exp.key); }, pause: function() { if (this.btn) { this.btn.pause.style.display = 'none'; this.btn.play.style.display = ''; } clearTimeout(this.autoplay); this.autoplay = null; }, previous: function() { this.pause(); hs.previous(this.btn.previous); }, next: function() { this.pause(); hs.next(this.btn.next); }, move: function() {}, 'full-expand': function() { hs.getExpander().doFullExpand(); }, close: function() { hs.close(this.btn.close); } }; if (document.readyState && hs.ie) { (function () { try { document.documentElement.doScroll('left'); } catch (e) { setTimeout(arguments.callee, 50); return; } hs.domReady(); })(); } hs.langDefaults = hs.lang; // history var HsExpander = hs.Expander; // set handlers hs.addEventListener(document, 'mousemove', function(e) { hs.mouse = { x: e.clientX, y: e.clientY }; }); hs.addEventListener(document, 'mousedown', hs.mouseClickHandler); hs.addEventListener(document, 'mouseup', hs.mouseClickHandler); hs.addEventListener(window, 'load', hs.preloadImages); hs.addEventListener(window, 'load', hs.preloadAjax); hs.addEventListener(window, 'load', function() { hs.pageLoaded = true; }); hs.setClickEvents();