티스토리 수익 글 보기
* 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
* Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7
* Firefox 1.5.0.9: 1.8.0.9 <-- Reports 1.8
* Firefox 2.0.0.3: 1.8.1.3 <-- Reports 1.8
* Firefox 3 alpha: 1.9a4 <-- Reports 1.9
*
* @property gecko
* @type float
*/
gecko:0,
/**
* AppleWebKit version. KHTML browsers that are not WebKit browsers
* will evaluate to 1, other browsers 0. Example: 418.9.1
*
* Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
* latest available for Mac OSX 10.3.
* Safari 2.0.2: 416 <-- hasOwnProperty introduced
* Safari 2.0.4: 418 <-- preventDefault fixed
* Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
* different versions of webkit
* Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been
* updated, but not updated
* to the latest patch.
* Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native SVG
* and many major issues fixed).
* 3.x yahoo.com, flickr:422 <-- Safari 3.x hacks the user agent
* string when hitting yahoo.com and
* flickr.com.
* Safari 3.0.4 (523.12):523.12 <-- First Tiger release - automatic update
* from 2.x via the 10.4.11 OS patch
* Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event.
* yahoo.com user agent hack removed.
*
*
* http://developer.apple.com/internet/safari/uamatrix.html
* @property webkit
* @type float
*/
webkit: 0,
/**
* The mobile property will be set to a string containing any relevant
* user agent information when a modern mobile browser is detected.
* Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
* devices with the WebKit-based browser, and Opera Mini.
* @property mobile
* @type string
*/
mobile: null,
/**
* Adobe AIR version number or 0. Only populated if webkit is detected.
* Example: 1.0
* @property air
* @type float
*/
air: 0
};
var ua=navigator.userAgent, m;
// Modern KHTML browsers should qualify as Safari X-Grade
if ((/KHTML/).test(ua)) {
o.webkit=1;
}
// Modern WebKit browsers are at least X-Grade
m=ua.match(/AppleWebKit\/([^\s]*)/);
if (m&&m[1]) {
o.webkit=parseFloat(m[1]);
// Mobile browser check
if (/ Mobile\//.test(ua)) {
o.mobile = "Apple"; // iPhone or iPod Touch
} else {
m=ua.match(/NokiaN[^\/]*/);
if (m) {
o.mobile = m[0]; // Nokia N-series, ex: NokiaN95
}
}
m=ua.match(/AdobeAIR\/([^\s]*)/);
if (m) {
o.air = m[0]; // Adobe AIR 1.0 or better
}
}
if (!o.webkit) { // not webkit
// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
m=ua.match(/Opera[\s\/]([^\s]*)/);
if (m&&m[1]) {
o.opera=parseFloat(m[1]);
m=ua.match(/Opera Mini[^;]*/);
if (m) {
o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
}
} else { // not opera or webkit
m=ua.match(/MSIE\s([^;]*)/);
if (m&&m[1]) {
o.ie=parseFloat(m[1]);
} else { // not opera, webkit, or ie
m=ua.match(/Gecko\/([^\s]*)/);
if (m) {
o.gecko=1; // Gecko detected, look for revision
m=ua.match(/rv:([^\s\)]*)/);
if (m&&m[1]) {
o.gecko=parseFloat(m[1]);
}
}
}
}
}
return o;
}();
/*
* Initializes the global by creating the default namespaces and applying
* any new configuration information that is detected. This is the setup
* for env.
* @method init
* @static
* @private
*/
(function() {
YAHOO.namespace("util", "widget", "example");
if ("undefined" !== typeof YAHOO_config) {
var l=YAHOO_config.listener,ls=YAHOO.env.listeners,unique=true,i;
if (l) {
// if YAHOO is loaded multiple times we need to check to see if
// this is a new config object. If it is, add the new component
// load listener to the stack
for (i=0;i-
*
- YAHOO.util.CustomEvent.LIST:
*
-
*
- param1: event name *
- param2: array of arguments sent to fire *
- param3:
a custom object supplied by the subscriber
*
* - YAHOO.util.CustomEvent.FLAT
*
-
*
- param1: the first argument passed to fire. If you need to * pass multiple parameters, use and array or object literal *
- param2:
a custom object supplied by the subscriber
*
*
The callback is executed with a single parameter: * the custom object parameter, if provided.
* * @method onAvailable * * @param {string||string[]} p_id the id of the element, or an array * of ids to look for. * @param {function} p_fn what to execute when the element is found. * @param {object} p_obj an optional object to be passed back as * a parameter to p_fn. * @param {boolean|object} p_override If set to true, p_fn will execute * in the scope of p_obj, if set to an object it * will execute in the scope of that object * @param checkContent {boolean} check child node readiness (onContentReady) * @static */ onAvailable: function(p_id, p_fn, p_obj, p_override, checkContent) { var a = (YAHOO.lang.isString(p_id)) ? [p_id] : p_id; for (var i=0; iThe callback is a CustomEvent, so the signature is:
*type <string>, args <array>, customobject <object>
*For DOMReady events, there are no fire argments, so the * signature is:
*"DOMReady", [], obj
* * * @method onDOMReady * * @param {function} p_fn what to execute when the element is found. * @param {object} p_obj an optional object to be passed back as * a parameter to p_fn. * @param {boolean|object} p_scope If set to true, p_fn will execute * in the scope of p_obj, if set to an object it * will execute in the scope of that object * * @static */ onDOMReady: function(p_fn, p_obj, p_override) { if (this.DOMReady) { setTimeout(function() { var s = window; if (p_override) { if (p_override === true) { s = p_obj; } else { s = p_override; } } p_fn.call(s, "DOMReady", [], p_obj); }, 0); } else { this.DOMReadyEvent.subscribe(p_fn, p_obj, p_override); } }, /** * Appends an event handler * * @method addListener * * @param {String|HTMLElement|Array|NodeList} el An id, an element * reference, or a collection of ids and/or elements to assign the * listener to. * @param {String} sType The type of event to append * @param {Function} fn The method the event invokes * @param {Object} obj An arbitrary object that will be * passed as a parameter to the handler * @param {Boolean|object} override If true, the obj passed in becomes * the execution scope of the listener. If an * object, this object becomes the execution * scope. * @return {Boolean} True if the action was successful or defered, * false if one or more of the elements * could not have the listener attached, * or if the operation throws an exception. * @static */ addListener: function(el, sType, fn, obj, override) { if (!fn || !fn.call) { return false; } // The el argument can be an array of elements or element ids. if ( this._isValidCollection(el)) { var ok = true; for (var i=0,len=el.length; i-
*
- * scope: defines the default execution scope. If not defined * the default scope will be this instance. * *
- * silent: if true, the custom event will not generate log messages. * This is false by default. * *
- * onSubscribeCallback: specifies a callback to execute when the * event has a new subscriber. This will fire immediately for * each queued subscriber if any exist prior to the creation of * the event. * *
* 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) {
// refresh everything if group array is not provided
var g = groups || this.ids;
for (var sGroup in g) {
if ("string" != typeof sGroup) {
continue;
}
for (var i in this.ids[sGroup]) {
var oDD = this.ids[sGroup][i];
if (this.isTypeOfDD(oDD)) {
var loc = this.getLocation(oDD);
if (loc) {
this.locationCache[oDD.id] = loc;
} else {
delete this.locationCache[oDD.id];
}
}
}
}
},
/**
* 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
* @param {boolean} intersect true if we are in intersect mode
* @param {YAHOO.util.Region} pre-cached location of the dragged element
* @return {boolean} true if the mouse is over the target
* @private
* @static
*/
isOverTarget: function(pt, oTarget, intersect, curRegion) {
// 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 done. Otherwise we need to evaluate the
// region the target as occupies to determine if the dragged element
// overlaps with it.
var dc = this.dragCurrent;
if (!dc || (!intersect && !dc.constrainX && !dc.constrainY)) {
//if (oTarget.cursorIsOver) {
//}
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.
if (!curRegion) {
var pos = dc.getTargetCoord(pt.x, pt.y);
var el = dc.getDragEl();
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 (var i in this.elementCache) {
//delete this.elementCache[i];
//}
//this.elementCache = {};
this.ids = {};
},
/**
* A cache of DOM elements
* @property elementCache
* @private
* @static
* @deprecated elements are not cached now
*/
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 {
}
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();
}
(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:
* -
*
- 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 = {
/**
* An Object Literal containing the events that we will be using: mouseDown, b4MouseDown, mouseUp, b4StartDrag, startDrag, b4EndDrag, endDrag, mouseUp, drag, b4Drag, invalidDrop, b4DragOut, dragOut, dragEnter, b4DragOver, dragOver, b4DragDrop, dragDrop
* By setting any of these to false, then event will not be fired.
* @property events
* @type object
*/
events: null,
/**
* @method on
* @description Shortcut for EventProvider.subscribe, see YAHOO.util.EventProvider.subscribe
*/
on: function() {
this.subscribe.apply(this, arguments);
},
/**
* 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 instances can be a drop target. This can be disabled by
* setting isTarget to false.
* @property isTarget
* @type boolean
*/
isTarget: true,
/**
* The padding configured for this drag and drop object for calculating
* the drop zone intersection with this object.
* @property padding
* @type int[]
*/
padding: null,
/**
* If this flag is true, do not fire drop events. The element is a drag only element (for movement not dropping)
* @property dragOnly
* @type Boolean
*/
dragOnly: false,
/**
* 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,
/**
* The difference between the click position and the source element's location
* @property deltaX
* @type int
* @private
*/
deltaX: 0,
/**
* The difference between the click position and the source element's location
* @property deltaY
* @type int
* @private
*/
deltaY: 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,
/**
* Property that is assigned to a drag and drop object when testing to
* see if it is being targeted by another dd object. This property
* can be used in intersect mode to help determine the focus of
* the mouse interaction. DDM.getBestMatch uses this property first to
* determine the closest match in INTERSECT mode when multiple targets
* are part of the same interaction.
* @property cursorIsOver
* @type boolean
*/
cursorIsOver: false,
/**
* Property that is assigned to a drag and drop object when testing to
* see if it is being targeted by another dd object. This is a region
* that represents the area the draggable element overlaps this target.
* DDM.getBestMatch uses this property to compare the size of the overlap
* to that of other targets in order to determine the closest match in
* INTERSECT mode when multiple targets are part of the same interaction.
* @property overlap
* @type YAHOO.util.Region
*/
overlap: null,
/**
* 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._domRef || this.id, "mousedown",
this.handleMouseDown, this, true);
// Event.on(this.id, "selectstart", Event.preventDefault);
for (var i in this.events) {
this.createEvent(i + 'Event');
}
},
/**
* 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 || {};
this.events = {};
// create a local reference to the drag and drop manager
this.DDM = YAHOO.util.DDM;
// initialize the groups object
this.groups = {};
// assume that we have an element reference instead of an id if the
// parameter is not a string
if (typeof id !== "string") {
this._domRef = id;
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() {
this.events = {
mouseDown: true,
b4MouseDown: true,
mouseUp: true,
b4StartDrag: true,
startDrag: true,
b4EndDrag: true,
endDrag: true,
drag: true,
b4Drag: true,
invalidDrop: true,
b4DragOut: true,
dragOut: true,
dragEnter: true,
b4DragOver: true,
dragOver: true,
b4DragDrop: true,
dragDrop: true
};
if (this.config.events) {
for (var i in this.config.events) {
if (this.config.events[i] === false) {
this.events[i] = false;
}
}
}
// 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);
this.dragOnly = ((this.config.dragOnly === true) ? true : 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
* @private
*/
setInitPosition: function(diffX, diffY) {
var el = this.getEl();
if (!this.DDM.verifyEl(el)) {
if (el && el.style && (el.style.display == 'none')) {
} else {
}
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") {
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") {
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;
}
// firing the mousedown events prior to calculating positions
var b4Return = this.b4MouseDown(e);
if (this.events.b4MouseDown) {
b4Return = this.fireEvent('b4MouseDownEvent', e);
}
var mDownReturn = this.onMouseDown(e);
if (this.events.mouseDown) {
mDownReturn = this.fireEvent('mouseDownEvent', e);
}
if ((b4Return === false) || (mDownReturn === false)) {
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();
// start tracking mousemove distance and mousedown time to
// determine when to start the actual drag
this.DDM.handleMouseDown(e, this);
// this mousedown is mine
this.DDM.stopEvent(e);
} else {
}
}
},
/**
* @method clickValidator
* @description Method validates that the clicked element
* was indeed the handle or a valid child of the handle
* @param {Event} e
*/
clickValidator: function(e) {
var target = YAHOO.util.Event.getTarget(e);
return ( this.isValidHandleChild(target) &&
(this.id == this.handleElId ||
this.DDM.handleWasClicked(target, this.id)) );
},
/**
* 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};
},
/**
* 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") {
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") {
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; iUsage: 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) */ var Anim = function(el, attributes, duration, method) { if (!el) { } this.init(el, attributes, duration, method); }; Anim.NAME = 'Anim'; 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 (this.constructor.NAME + ': ' + 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; } Y.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 = Y.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 || (Y.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. Should only be needed for subclass use. * @method setRuntimeAttribute * @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] * 1; // times 1 to cast "by" } } else { end = start + attributes[attr]['by'] * 1; } } 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); return true; }, /** * 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 = Y.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 = !YAHOO.lang.isUndefined(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 || Y.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 = Y.AnimMgr.fps; /** * Changes the animated element * @method setEl */ this.setEl = function(element) { el = Y.Dom.get(element); }; /** * 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(Y.AnimMgr.fps * this.duration) : this.duration; if (this.duration === 0 && this.useSeconds) { // jump to last frame if zero second duration this.totalFrames = 1; } Y.AnimMgr.registerElement(this); return true; }; /** * 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 (!this.isAnimated()) { // nothing to stop return false; } if (finish) { this.currentFrame = this.totalFrames; this._onTween.fire(); } Y.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 Y.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 Y.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 Y.CustomEvent('tween', this); /** * Custom event that fires after onTween * @private */ this._onTween = new Y.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 Y.CustomEvent('complete', this); /** * Custom event that fires after onComplete * @private */ this._onComplete = new Y.CustomEvent('_complete', this, true); this._onStart.subscribe(onStart); this._onTween.subscribe(onTween); this._onComplete.subscribe(onComplete); } }; Y.Anim = Anim; })(); /** * 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 = 1000; /** * 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) { index = index || getIndex(tween); if (!tween.isAnimated() || index == -1) { return false; } tween._onComplete.fire(); queue.splice(index, 1); tweenCount -= 1; if (tweenCount <= 0) { this.stop(); } return true; }; /** * 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) { this.unRegister(queue[0], 0); } 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] ]; }; }; (function() { /** * Anim subclass for color transitions. *Usage: 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: var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);
Usage: var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);
-
*
- onSuccess *
-
* callback to execute when the script(s) are finished loading
* The callback receives an object back with the following
* data:
*
-
*
- win *
- the window the script(s) were inserted into *
- data *
- the data object passed in when the request was made *
- nodes *
- An array containing references to the nodes that were * inserted *
- purge *
- A function that, when executed, will remove the nodes * that were inserted *
- *
* - onFailure *
-
* callback to execute when the script load operation fails
* The callback receives an object back with the following
* data:
*
-
*
- win *
- the window the script(s) were inserted into *
- data *
- the data object passed in when the request was made *
- nodes *
- An array containing references to the nodes that were * inserted successfully *
- purge *
- A function that, when executed, will remove any nodes * that were inserted *
- *
* - scope *
- the execution context for the callbacks *
- win *
- a window other than the one the utility occupies *
- autopurge *
- * setting to true will let the utilities cleanup routine purge * the script once loaded * *
- data *
- * data that is supplied to the callback when the script(s) are * loaded. * *
- varName *
- * variable that should be available when a script is finished * loading. Used to help Safari 2.x and below with script load * detection. The type of this property should match what was * passed into the url parameter: if loading a single url, a * string can be supplied. If loading multiple scripts, you * must supply an array that contains the variable name for * each script. * *
- insertBefore *
- node or node id that will become the new node's nextSibling *
* // assumes yahoo, dom, and event are already on the page
* YAHOO.util.Get.script(
* ["http://yui.yahooapis.com/2.3.1/build/dragdrop/dragdrop-min.js",
* "http://yui.yahooapis.com/2.3.1/build/animation/animation-min.js"], {
* onSuccess: function(o) {
* new YAHOO.util.DDProxy("dd1"); // also new o.reference("dd1"); would work
* this.log("won't cause error because YAHOO is the scope");
* this.log(o.nodes.length === 2) // true
* // o.purge(); // optionally remove the script nodes immediately
* },
* onFailure: function(o) {
* },
* data: "foo",
* scope: YAHOO,
* // win: otherframe // target another window/frame
* autopurge: true // allow the utility to choose when to remove the nodes
* });
*
* @return {tId: string} an object containing info about the transaction
*/
script: function(url, opts) { return _queue("script", url, opts); },
/**
* Fetches and inserts one or more css link nodes into the
* head of the current document or the document in a specified
* window.
* @method css
* @static
* @param url {string} the url or urls to the css file(s)
* @param opts Options:
* -
*
- onSuccess *
-
* callback to execute when the css file(s) are finished loading
* The callback receives an object back with the following
* data:
*
- win
- the window the link nodes(s) were inserted into
* - data *
- the data object passed in when the request was made *
- nodes *
- An array containing references to the nodes that were * inserted *
- purge *
- A function that, when executed, will remove the nodes * that were inserted *
- *
* YAHOO.util.Get.css("http://yui.yahooapis.com/2.3.1/build/menu/assets/skins/sam/menu.css");
*
*
* YAHOO.util.Get.css(["http://yui.yahooapis.com/2.3.1/build/menu/assets/skins/sam/menu.css",
*
* @return {tId: string} an object containing info about the transaction
*/
css: function(url, opts) {
return _queue("css", url, opts);
}
};
}();
YAHOO.register("get", YAHOO.util.Get, {version: "2.5.1", build: "984"});
var Y=YAHOO,snag=(Y.U=Y.util,Y.D=Y.util.Dom,Y.E=Y.util.Event,1);function woe_location_obj(ID,title,sub_title,relevance,bbox,precision,lat,lon,place_url,place_disambiguate){this.id=ID,this.title=title,this.sub_title=sub_title,this.relevance=relevance,this.bbox=bbox,this.precision=precision,this.lat=lat,this.lon=lon,this.place_url=place_url,this.place_disambiguate=place_disambiguate}function Currency(){var self=this;this.currencies={ARS:"AR $%.2f",AUD:"AU $%.2f",BRL:"BR R$%.2f",CAD:"CAD $%.2f",CHF:"SFr. %.2f",CLP:"CL $%d",CNY:"%.2f元",COP:"CO $%.2f",DKK:"kr %.2f",EUR:"€ %.2f","EUR-at":"%.2f €","EUR-be":"%.2f €","EUR-de":"%.2f €","EUR-fr":"%.2f €","EUR-pt":"%.2f €","EUR-es":"%.2f €",GBP:"UK £%.2f",HKD:"HK $%.2f",INR:"Rs. %.2f",JPY:"%d 円",KRW:"₩ %d",MXN:"Mex $%.2f",MYR:"RM %.2f",NOK:"kr %.2f",NZD:"NZ $%.2f",PEN:"S/ %.2f",PHP:"P %.2f",SEK:"%.2f kr",SGD:"SGD $%.2f",USD:"US $%.2f",VEF:"BsF %.2f"},this.currencies_sans_prefix={ARS:"$%.2f",AUD:"$%.2f",BRL:"$%.2f",CAD:"$%.2f",CHF:"SFr. %.2f",CLP:"$%d",CNY:"%.2f元",COP:"$%.2f",DKK:"kr %.2f",EUR:"€ %.2f","EUR-at":"%.2f €","EUR-be":"%.2f €","EUR-de":"%.2f €","EUR-fr":"%.2f €","EUR-pt":"%.2f €","EUR-es":"%.2f €",GBP:"£ %.2f",HKD:"$%.2f",INR:"Rs. %.2f",JPY:"%d 円",KRW:"₩ %d",MXN:"$%.2f",MYR:"RM %.2f",NOK:"kr %.2f",NZD:"$%.2f",PEN:"S/ %.2f",PHP:"P %.2f",SEK:"%.2f kr",SGD:"$%.2f",USD:"$%.2f",VEF:"BsF %.2f"},this.default_currency_type="USD",this.default_show_currency_prefix=!0,this.decimal_replacements={FRA:",",DKK:",",NOK:",",SEK:",","EUR-at":",","EUR-be":",","EUR-de":",","EUR-es":",","EUR-fr":",","EUR-it":",","EUR-nl":",","EUR-pt":","},this.format_decimal=function(n_amount,s_currency,s_country){s_country=s_currency+(s_country?"-"+s_country:"");return self.decimal_replacements[s_currency]||self.decimal_replacements[s_country]?n_amount.replace_global(".",self.decimal_replacements[s_country]||self.decimal_replacements[s_currency]):n_amount},this.format_currency=function(n_amount_in_dollars,o_options){var c,currency_type=self.default_currency_type,currency_country=null,currency_map=self.currencies;return o_options&&(currency_type=o_options.currency_type||self.default_currency_type,o_options.country&&(currency_country=currency_type+"-"+o_options.country),currency_map=void 0===o_options.show_prefix||o_options.show_prefix?self.currencies:self.currencies_sans_prefix),(currency_string=currency_country&¤cy_map[currency_country]||currency_map[currency_type])?(c=F.output.sprintf(currency_string,n_amount_in_dollars),self.format_decimal(c,currency_type,o_options.country)):(writeDebug("Warn: No matching currency type"),c=F.output.sprintf(currency_map[self.default_currency_type],n_amount_in_dollars),self.format_decimal(c,self.default_currency_type))}}F._eb={eb_go_go_go:function(){this._eb_listeners=[],F._ebA.push(this)},eb_broadcast:function(){for(var new_args=[],i=0;i"+F.output.get("loc_results_more")+""),_ge("loc_search_results_div").innerHTML=htmlA.join("")}this.div_show()},F._loc_search_div.div_go_to_map=function(i,ms){var location_woe_id;location_woe_id=!ms||ms<1?(location_woe_id=this.locations[i].id,location_woe_id="GeocodedBuilding"==this.locations[i].precision||"POI"==this.locations[i].precision?"/map?fLat="+this.locations[i].lat+"&fLon="+this.locations[i].lon+"&zl=2&place_id="+location_woe_id+"&woe_sub_title="+escape(this.locations[i].sub_title):"/map?place_id="+location_woe_id,document.location=location_woe_id,F.output.get("loc_results_take_you_there")):(setTimeout("_ge('"+this.id+"').div_go_to_map("+i+", "+(ms-1e3)+")",ms),0==ms?F.output.get("loc_results_zero_second"):1==_pi(ms/1e3)?F.output.get("loc_results_one_second"):F.output.get("loc_results_x_second",_pi(ms/1e3))),writeDebug(location_woe_id),_ge("loc_search_msg_div")&&(_ge("loc_search_msg_div").style.display="block",_ge("loc_search_msg_div").innerHTML=location_woe_id)},F._loc_search_div.div_go_to_place=function(i,ms){var location_woe_id;location_woe_id=!ms||ms<1?(location_woe_id=this.locations[i].id,location_woe_id=_ge("world_map")?_ge("user_places_is_go")?"/photos/"+_ge("user_places_is_go").innerHTML+"/places"+this.locations[i].place_url:"/places"+this.locations[i].place_url:"GeocodedBuilding"==this.locations[i].precision||"POI"==this.locations[i].precision?"/map?fLat="+this.locations[i].lat+"&fLon="+this.locations[i].lon+"&zl=2&place_id="+location_woe_id+"&woe_sub_title="+escape(this.locations[i].sub_title):"/map?place_id="+location_woe_id,document.location=location_woe_id,F.output.get("loc_results_take_you_there")):(setTimeout("_ge('"+this.id+"').div_go_to_place("+i+", "+(ms-1e3)+")",ms),0==ms?F.output.get("loc_results_zero_second"):1==_pi(ms/1e3)?F.output.get("loc_results_one_second"):F.output.get("loc_results_x_second",_pi(ms/1e3))),writeDebug(location_woe_id),_ge("loc_search_msg_div")&&(_ge("loc_search_msg_div").style.display="block",_ge("loc_search_msg_div").innerHTML=location_woe_id)},F._loc_search_div.div_on_result_click=function(i){("site"!=this.page_type&&"explore"!=this.page_type&&"places_home"!=this.page_type||_ge("div_force_header_location_search"))&&(this.current_location_index=i,this.focus_on_location(),this.div_update_results(),this.div_fade())},F._loc_search_div.div_do_loc_search=function(){var page_map_type=window.page_map_type,search_term=_ge(this.input_id).value.trim();search_term&&this.last_search_term!=search_term&&(this.last_search_term&&(this.div_log(0),this.logged_last)&&(this.logged_last=0),this.last_search_term=search_term,search_term=/^([-\.\d]+),\s*([-\.\d]+)$/i.exec(search_term),"org"==page_map_type&&search_term&&search_term.length?(this.locations=[new woe_location_obj(null,null,null,null,[search_term[2],search_term[1],search_term[2],search_term[1]].join(","),null,search_term[1],search_term[2],null,null)],this.current_location_index=0,_ge(this.id).focus_on_location(),F.API.callMethod("flickr.people.geo.setLocation",{lat:search_term[1],lon:search_term[2],accuracy:16,context:"last"},this,null,null,0)):(this.div_loading(),F.API.callMethod("flickr.geocode.translate",{location:this.last_search_term,provider_name:this.provider_name},this,null,null,null,0)))},F._loc_search_div.div_add_source_params=function(params){return null!=this.setLocation_geo_point&&_ge("map_controller").is_this_point_on_the_map(this.setLocation_geo_point)&&(writeDebug("adding source!"),params.source=this.setLocation_source_id,params.query=this.setLocation_search_term),params},F._loc_search_div.flickr_geocode_translate_onLoad=function(success,responseXML,responseText,params){if(success){var id,success=responseXML.documentElement.getElementsByTagName("ResultSet")[0],results=responseXML.documentElement.getElementsByTagName("Result");if(this.last_source_id=success.getAttribute("fl:source_id"),this.locations=[],0==results.length)this.div_update_results();else{for(i=0;i
'+F.output.get("nothing_to_print")+'