YAHOO.namespace('ext', 'ext.util', 'ext.grid', 'ext.dd', 'ext.tree', 'ext.data', 'ext.form');
if(typeof Ext == 'undefined'){
Ext = YAHOO.ext;
}
YAHOO.ext.Strict = (document.compatMode == 'CSS1Compat');
YAHOO.ext.SSL_SECURE_URL = 'javascript:false';
YAHOO.ext.BLANK_IMAGE_URL = 'http:/'+'/www.yui-ext.com/blog/images/s.gif';
// for old browsers
window.undefined = undefined;
/**
* @class Function
* These functions are available on every Function object (any javascript function).
*/
//
/**
* Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
* Call directly on any function. Example: myFunction.createCallback(myarg, myarg2)
* Will create a function that is bound to those 2 args.
* @return {Function} The new function
*/
Function.prototype.createCallback = function(/*args...*/){
// make args available, in function below
var args = arguments;
var method = this;
return function() {
return method.apply(window, args);
};
};
/**
* Creates a delegate (callback) that sets the scope to obj.
* Call directly on any function. Example: this.myFunction.createDelegate(this)
* Will create a function that is automatically scoped to this.
* @param {Object} obj (optional) The object for which the scope is set
* @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
* @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
* if a number the args are inserted at the specified position
* @return {Function} The new function
*/
Function.prototype.createDelegate = function(obj, args, appendArgs){
var method = this;
return function() {
var callArgs = args || arguments;
if(appendArgs === true){
callArgs = Array.prototype.slice.call(arguments, 0);
callArgs = callArgs.concat(args);
}else if(typeof appendArgs == 'number'){
callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
var applyArgs = [appendArgs, 0].concat(args); // create method call params
Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
}
return method.apply(obj || window, callArgs);
};
};
/**
* Calls this function after the number of millseconds specified.
* @param {Number} millis The number of milliseconds for the setTimeout call
* @param {Object} obj (optional) The object for which the scope is set
* @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
* @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
* if a number the args are inserted at the specified position
* @return {Number} The timeout id that can be used with clearTimeout
*/
Function.prototype.defer = function(millis, obj, args, appendArgs){
return setTimeout(this.createDelegate(obj, args, appendArgs), millis);
};
/**
* Create a combined function call sequence of the original function + the passed function.
* The resulting function returns the results of the original function.
* The passed fcn is called with the parameters of the original function
* @param {Function} fcn The function to sequence
* @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
* @return {Function} The new function
*/
Function.prototype.createSequence = function(fcn, scope){
if(typeof fcn != 'function'){
return this;
}
var method = this;
return function() {
var retval = method.apply(this || window, arguments);
fcn.apply(scope || this || window, arguments);
return retval;
};
};
/*
* IE will leak if this isn't here
*/
YAHOO.util.Event.on(window, 'unload', function(){
var p = Function.prototype;
delete p.createSequence;
delete p.defer;
delete p.createDelegate;
delete p.createCallback;
delete p.createInterceptor;
});
/**
* Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
* The resulting function returns the results of the original function.
* The passed fcn is called with the parameters of the original function.
* @addon
* @param {Function} fcn The function to call before the original
* @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
* @return {Function} The new function
*/
Function.prototype.createInterceptor = function(fcn, scope){
if(typeof fcn != 'function'){
return this;
}
var method = this;
return function() {
fcn.target = this;
fcn.method = method;
if(fcn.apply(scope || this || window, arguments) === false){
return;
}
return method.apply(this || window, arguments);;
};
};
/**
* @class YAHOO.ext.util.Browser
* @singleton
*/
YAHOO.ext.util.Browser = new function(){
var ua = navigator.userAgent.toLowerCase();
/** @type Boolean */
this.isOpera = (ua.indexOf('opera') > -1);
/** @type Boolean */
this.isSafari = (ua.indexOf('webkit') > -1);
/** @type Boolean */
this.isIE = (window.ActiveXObject);
/** @type Boolean */
this.isIE7 = (ua.indexOf('msie 7') > -1);
/** @type Boolean */
this.isGecko = !this.isSafari && (ua.indexOf('gecko') > -1);
if(ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1){
/** @type Boolean */
this.isWindows = true;
}else if(ua.indexOf("macintosh") != -1){
/** @type Boolean */
this.isMac = true;
}
if(this.isIE && !this.isIE7){
try{
document.execCommand("BackgroundImageCache", false, true);
}catch(e){}
}
}();
/**
* Enable custom handler signature and event cancelling. Using fireDirect() instead of fire() calls the subscribed event handlers
* with the exact parameters passed to fireDirect, instead of the usual (eventType, args[], obj). IMO this is more intuitive
* and promotes cleaner code. Also, if an event handler returns false, it is returned by fireDirect and no other handlers will be called.
* Example:
* if(beforeUpdateEvent.fireDirect(myArg, myArg2) !== false){
* // do update
* }
*/
YAHOO.util.CustomEvent.prototype.fireDirect = function(){
var len=this.subscribers.length;
for (var i=0; i
var Employee = function(name){
this.name = name;
this.events = {
'fired' : new YAHOO.util.CustomEvent('fired'),
'quit' : true // lazy initialize the CustomEvent
}
}
YAHOO.extend(Employee, YAHOO.ext.util.Observable);
*/
YAHOO.ext.util.Observable = function(){};
YAHOO.ext.util.Observable.prototype = {
/**
* Fires the specified event with the passed parameters (minus the event name).
* @param {String} eventName
* @param {Object...} args Variable number of parameters are passed to handlers
* @return {Boolean} returns false if any of the handlers return false otherwise it returns true
*/
fireEvent : function(){
var ce = this.events[arguments[0].toLowerCase()];
if(typeof ce == 'object'){
return ce.fireDirect.apply(ce, Array.prototype.slice.call(arguments, 1));
}else{
return true;
}
},
/**
* Appends an event handler to this component
* @param {String} eventName The type of event to listen for
* @param {Function} handler The method the event invokes
* @param {Object} scope (optional) The scope (this object) for the handler
* @param {boolean} override (optional) If true, scope becomes the scope
*/
addListener : function(eventName, fn, scope, override){
eventName = eventName.toLowerCase();
var ce = this.events[eventName];
if(!ce){
// added for a better message when subscribing to wrong event
throw 'You are trying to listen for an event that does not exist: "' + eventName + '".';
}
if(typeof ce == 'boolean'){
ce = new YAHOO.util.CustomEvent(eventName);
this.events[eventName] = ce;
}
ce.subscribe(fn, scope, override);
},
/**
* Appends an event handler to this component that is delayed the specified number of milliseconds. This
* is useful for events that modify the DOM and need to wait for the browser to catch up.
* @param {String} eventName The type of event to listen for
* @param {Function} handler The method the event invokes
* @param {Object} scope (optional) The scope (this object) for the handler
* @param {Number} delay (optional) The number of milliseconds to delay (defaults to 1 millisecond)
* @return {Function} The wrapped function that was created (can be used to remove the listener)
*/
delayedListener : function(eventName, fn, scope, delay){
var newFn = function(){
setTimeout(fn.createDelegate(scope, arguments), delay || 1);
}
this.addListener(eventName, newFn);
return newFn;
},
/**
* Appends an event handler to this component that is buffered. If the event is triggered more than once
* in the specified time-frame, only the last one actually fires.
* @param {String} eventName The type of event to listen for
* @param {Function} handler The method the event invokes
* @param {Object} scope (optional) The scope (this object) for the handler
* @param {Number} millis (optional) The number of milliseconds to buffer (defaults to 250)
* @return {Function} The wrapped function that was created (can be used to remove the listener)
*/
bufferedListener : function(eventName, fn, scope, millis){
var task = new YAHOO.ext.util.DelayedTask();
var newFn = function(){
task.delay(millis || 250, fn, scope, Array.prototype.slice.call(arguments, 0));
}
this.addListener(eventName, newFn);
return newFn;
},
/**
* Removes a listener
* @param {String} eventName The type of event to listen for
* @param {Function} handler The handler to remove
* @param {Object} scope (optional) The scope (this object) for the handler
*/
removeListener : function(eventName, fn, scope){
var ce = this.events[eventName.toLowerCase()];
if(typeof ce == 'object'){
ce.unsubscribe(fn, scope);
}
},
/**
* Removes all listeners for this object
*/
purgeListeners : function(){
for(var evt in this.events){
if(typeof this.events[evt] == 'object'){
this.events[evt].unsubscribeAll();
}
}
}
};
/**
* Appends an event handler to this element (shorthand for addListener)
* @param {String} eventName The type of event to listen for
* @param {Function} handler The method the event invokes
* @param {Object} scope (optional) The scope (this object) for the handler
* @param {boolean} override (optional) If true, scope becomes the scope
* @method
*/
YAHOO.ext.util.Observable.prototype.on = YAHOO.ext.util.Observable.prototype.addListener;
/**
* Starts capture on the specified Observable. All events will be passed
* to the supplied function with the event name + standard signature of the event
* before the event is fired. If the supplied function returns false,
* the event will not fire.
* @param {Observable} o The Observable to capture
* @param {Function} fn The function to call
* @param {Object} scope (optional) The scope (this object) for the fn
* @static
*/
YAHOO.ext.util.Observable.capture = function(o, fn, scope){
o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
};
/**
* Removes all added captures from the Observable.
* @param {Observable} o The Observable to release
* @static
*/
YAHOO.ext.util.Observable.releaseCapture = function(o){
o.fireEvent = YAHOO.ext.util.Observable.prototype.fireEvent;
};
/**
* @class YAHOO.ext.util.Config
* Class with one useful method
* @singleton
*/
YAHOO.ext.util.Config = {
/**
* Copies all the properties of config to obj.
* @param {Object} obj The receiver of the properties
* @param {Object} config The source of the properties
* @param {Object} defaults A different object that will also be applied for default values
* @return {Object} returns obj
*/
apply : function(obj, config, defaults){
if(defaults){
this.apply(obj, defaults);
}
if(config){
for(var prop in config){
obj[prop] = config[prop];
}
}
return obj;
}
};
if(!String.escape){
String.escape = function(string) {
return string.replace(/('|\\)/g, "\\$1");
};
};
String.leftPad = function (val, size, ch) {
var result = new String(val);
if (ch == null) {
ch = " ";
}
while (result.length < size) {
result = ch + result;
}
return result;
};
// workaround for Safari anim duration speed problems
if(YAHOO.util.AnimMgr && YAHOO.ext.util.Browser.isSafari){
YAHOO.util.AnimMgr.fps = 500;
}
// add ability for callbacks instead of events for animations
if(YAHOO.util.Anim){
YAHOO.util.Anim.prototype.animateX = function(callback, scope){
var f = function(){
this.onComplete.unsubscribe(f);
if(typeof callback == 'function'){
callback.call(scope || this, this);
}
};
this.onComplete.subscribe(f, this, true);
this.animate();
};
}
// workaround for Safari 1.3 not supporting hasOwnProperty
if(YAHOO.util.Connect && YAHOO.ext.util.Browser.isSafari){
YAHOO.util.Connect.setHeader = function(o){
for(var prop in this._http_header){
// if(this._http_header.hasOwnProperty(prop)){
if(typeof this._http_header[prop] != 'function'){
o.conn.setRequestHeader(prop, this._http_header[prop]);
}
}
delete this._http_header;
this._http_header = {};
this._has_http_headers = false;
};
}
/**
* A simple enhancement to drag drop that allows you to constrain the movement of the
* DD or DDProxy object to a particular element.
var dd = new YAHOO.util.DDProxy("dragDiv1", "proxytest",
{ dragElId: "existingProxyDiv" });
dd.startDrag = function(){
this.constrainTo('parent-id');
};
* Or you can initalize it using the {@link YAHOO.ext.Element} object:
getEl('dragDiv1').initDDProxy('proxytest', {dragElId: "existingProxyDiv"}, {
startDrag : function(){
this.constrainTo('parent-id');
}
});
*/
if(YAHOO.util.DragDrop){
/**
* Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
* @type Object
*/
YAHOO.util.DragDrop.prototype.defaultPadding = {left:0, right:0, top:0, bottom:0};
/**
* Initializes the drag drop object's constraints to restrict movement to a certain element.
* @param {String/HTMLElement/Element} constrainTo The element to constrain to.
* @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
* and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
* an object containing the sides to pad. For example: {right:10, bottom:10}
* @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
*/
YAHOO.util.DragDrop.prototype.constrainTo = function(constrainTo, pad, inContent){
if(typeof pad == 'number'){
pad = {left: pad, right:pad, top:pad, bottom:pad};
}
pad = pad || this.defaultPadding;
var b = getEl(this.getEl()).getBox();
var ce = getEl(constrainTo);
var c = ce.dom == document.body ? { x: 0, y: 0,
width: YAHOO.util.Dom.getViewportWidth(),
height: YAHOO.util.Dom.getViewportHeight()} : ce.getBox(inContent || false);
var topSpace = b.y - c.y;
var leftSpace = b.x - c.x;
this.resetConstraints();
this.setXConstraint(leftSpace - (pad.left||0), // left
c.width - leftSpace - b.width - (pad.right||0) //right
);
this.setYConstraint(topSpace - (pad.top||0), //top
c.height - topSpace - b.height - (pad.bottom||0) //bottom
);
}
}