R33941 - in /trunk/phpgwapi/js/egw_action: egw_action.js test/js/jquery.js test/test_action.html

Author: igel457
New Revision: 33941

URL: http://www.egroupware.org/viewvc/egroupware?rev=33941&view=rev
Log:
Finished implementation of the abstract egwAction interface - now going to test it

Added:
trunk/phpgwapi/js/egw_action/test/js/jquery.js
trunk/phpgwapi/js/egw_action/test/test_action.html
Modified:
trunk/phpgwapi/js/egw_action/egw_action.js

Modified: trunk/phpgwapi/js/egw_action/egw_action.js
URL: http://www.egroupware.org/viewvc/egroupware/trunk/phpgwapi/js/egw_action/egw_action.js?rev=33941&r1=33940&r2=33941&view=diff

— trunk/phpgwapi/js/egw_action/egw_action.js (original)
+++ trunk/phpgwapi/js/egw_action/egw_action.js Thu Feb 24 20:00:47 2011
@@ -8,8 +8,6 @@

  • @package egw_action
  • @version $Id$
    */

-// XXX WARNING: UNTESTED, UNFINISHED, NOT (YET) WORKING CODE! XXX

/** egwActionHandler Interface **/

@@ -97,7 +95,7 @@

  • 1. A reference to this action
    
  • 2. The senders, an array of all objects (JS)/object ids (PHP) which evoked the event
    

*/
-egwAction.prototype.set_onExecute(_value)
+egwAction.prototype.set_onExecute = function(_value)
{
//Reset the onExecute handlers
this.execJSFnct = null;
@@ -130,17 +128,17 @@
}
}

-egwAction.prototype.set_caption(_value)
+egwAction.prototype.set_caption = function(_value)
{
this.caption = _value;
}

-egwAction.prototype.set_icon(_value)
+egwAction.prototype.set_icon = function(_value)
{
this.icon = _value;
}

-egwAction.prototype.set_allowOnMultiple(_value)
+egwAction.prototype.set_allowOnMultiple = function(_value)
{
this.allowOnMultiple = _value;
}
@@ -340,9 +338,12 @@
const EGW_AO_EVENT_DRAG_OVER_ENTER = 0x00;
const EGW_AO_EVENT_DRAG_OVER_LEAVE = 0x01;

+// No shift key is pressed
const EGW_AO_SHIFT_STATE_NONE = 0x00;
+// A shift key, which allows multiselection is pressed (usually CTRL on a PC keyboard)
const EGW_AO_SHIFT_STATE_MULTI = 0x01;
-const EGW_AO_SHIFT_STATE_LIST = 0x02;
+// A shift key is pressed, which forces blockwise selection (SHIFT on a PC keyboard)
+const EGW_AO_SHIFT_STATE_BLOCK = 0x02;

// If this flag is set, this object will not be returned as “focused”. If this
// flag is not applied to container objects, it may lead to some strange behaviour.
@@ -356,22 +357,124 @@
*

  • @param string _id is the identifier of the object which
  • @param object _parent is the parent object in the hirachy. This may be set to NULL
    • @param object _iface is the egwActionObjectInterface which connects the object
    • to the outer world.
      
    • @param object _manager is the action manager this object is connected to
    • @param object _iface is the egwActionObjectInterface which connects
    • this object to the DOM tree.
      
    • @param boolean _flags a set of additional flags being applied to the object
  • */
    -function egwActionObject(_id, _parent, _manager, _iface, _flagss)
    -{
    • this object to the DOM tree. If the _manager isn't supplied, the parent manager
      
    • is taken.
      
    • @param int _flags a set of additional flags being applied to the object,
    • defaults to 0
      
  • */
    +function egwActionObject(_id, _parent, _iface, _manager, _flags)
    +{
  • //Preset some parameters
  • if (typeof _manager == “undefined” && typeof _parent == “object” && _parent)
  •   _manager = _parent.manager;
    
  • if (typeof _flags == “undefined”)
  •   _flags = 0;
    
  • this.id = _id;
    this.parent = _parent;
    this.children = [];
    this.actionLinks = [];
    this.manager = _manager;
  • this.selectBehaviour = _selectBehaviour;
  • this.flags = _flags;

    this.iface = _iface;
    this.iface.setStateChangeCallback(this._ifaceCallback, this)
    +}

+/**

    • Returns the object from the tree with the given ID
  • */
    +//TODO: Add “ByID”-Suffix to all other of those functions.
    +//TODO: Add search function to egw_action_commons.js
    +egwActionObject.prototype.getObjectById = function(_id)
    +{
  • if (this.id == _id)
  • {
  •   return this;
    
  • }
  • for (var i = 0; i < this.children.length; i++)
  • {
  •   var obj = this.children[i].getObjectById(_id);
    
  •   if (obj)
    
  •   {
    
  •   	return obj;
    
  •   }
    
  • }
  • return null;
    +}

+/**

    • Adds an object as child to the actionObject and returns it - if the supplied
    • parameter is a object, the object will be added directly, otherwise an object
    • with the given id will be created.
    • @param string/object _id Id of the object which will be created or the object
    • that will be added.
      
    • @param object if _id was an string, _interface defines the interface which
    • will be connected to the newly generated object.
      
    • @param int _flags are the flags will which be supplied to the newly generated
    • object. May be omitted.
      
    • @returns object the generated object
  • */
    +egwActionObject.prototype.addObject = function(_id, _interface, _flags)
    +{
  • return this.insertObject(false, _id, _interface, _flags);
    +}

+/**

    • Inserts an object as child to the actionObject and returns it - if the supplied
    • parameter is a object, the object will be added directly, otherwise an object
    • with the given id will be created.
    • @param int _index Position where the object will be inserted, “false” will add it
    • to the end of the list.
      
    • @param string/object _id Id of the object which will be created or the object
    • that will be added.
      
    • @param object _iface if _id was an string, _iface defines the interface which
    • will be connected to the newly generated object.
      
    • @param int _flags are the flags will which be supplied to the newly generated
    • object. May be omitted.
      
    • @returns object the generated object
  • */
    +egwActionObject.prototype.insertObject = function(_index, _id, _iface, _flags)
    +{
  • if (_index === false)
  •   _index = this.children.length;
    
  • var obj = null;
  • if (typeof _id == “object”)
  • {
  •   obj = _id;
    
  •   // Set the parent to null and reset the focus of the object
    
  •   obj.parent = null;
    
  •   obj.setFocused(false);
    
  •   // Set the parent to this object
    
  •   obj.parent = this;
    
  • }
  • else if (typeof _id == “string”)
  • {
  •   obj = new egwActionObject(_id, this, _iface, this.manager, _flags)
    
  • }
  • if (obj)
  • {
  •   // Add the element to the children
    
  •   this.children.splice(_index, 0, obj);
    
  • }
  • else
  • {
  •   throw "Error while adding new element to the ActionObjects!"
    
  • }
  • return obj;
    }

/**
@@ -433,7 +536,7 @@
if (typeof(_obj) == “undefined”)
{
_obj = {

  •   	"elements": [];
    
  •   	"elements": []
      }
    
    }

@@ -518,6 +621,15 @@
return null;
}

+/**

    • Internal function which is connected to the ActionObjectInterface associated
    • with this object in the constructor. It gets called, whenever the object
    • gets (de)selected.
    • @param int _newState is the new state of the object
    • @param int _shiftState is the status of extra keys being pressed during the
    • selection process.
      
  • */
    egwActionObject.prototype._ifaceCallback = function(_newState, _shiftState)
    {
    // Remove the focus from all children on the same level
    @@ -547,7 +659,7 @@

      	// If the LIST state is active, get all objects inbetween this one and the focused one
      	// and set their select state.
    
  •   	if (egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_LIST))
    
  •   	if (egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_BLOCK))
      	{
      		var focused = this.getRootObject().getFocusedObject();
      		if (focused)
    

@@ -562,75 +674,101 @@

		// If the focused element didn't belong to this container, or the "list"
		// shift-state isn't active, set the focus to this element.
  •   	if (objs.length == 0 || !egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_LIST))
    
  •   	if (objs.length == 0 || !egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_BLOCK))
      	{
    
  •   		this.getRootObject().setFocused(false);
      		this.setFocused(true);
      	}
      }
    
    }
    }

+/**

    • Returns whether the object is currently selected.
  • */
    egwActionObject.prototype.getSelected = function()
    {
    return egwBitIsSet(this.getState(), EGW_AO_STATE_SELECTED);
    }

+/**

    • Returns whether the object is currently focused.
  • */
    egwActionObject.prototype.getFocused = function()
    {

-}

  • return egwBitIsSet(this.getState(), EGW_AO_STATE_FOCUSED);
    +}

+/**

    • Returns the complete state of the object.
  • */
    egwActionObject.prototype.getState = function()
    {
    -}

-egwActionObject.prototype.setSelected = function(_selected, _applyToSelf,

  • _applyToChildren, _applyToParent)
    -{
  • if (typeof _applyToSelf == “undefined”)
  •   _applyToSelf = true;
    
  • if (typeof _applyToChildren == “undefined”)
  •   _applyToChildren = true;
    
  • if (typeof _applyToParent == “undefined”)
  •   _applyToParent = false;
    
  • if (_applyToSelf)
  • {
  •   var state = this.iface.getState();
    
  •   if (_selected)
    
  •   {
    
  •   	state &= ~EGW_AO_STATE_SELECTED;
    
  • return this.iface.getState();
    +}

+/**

    • Sets the focus of the element. The formerly focused element in the tree will
    • be de-focused.
    • @param boolean _focused - whether to remove or set the focus. Defaults to true
    • @param boolean _recPrev is internally used to prevent infinit recursion. Do not touch.
  • */
    +egwActionObject.prototype.setFocused = function(_focused, _recPrev)
    +{
  • if (typeof _focused == “undefined”)
  •   _focused = true;
    
  • //TODO: When deleting and moving objects is implemented, don’t forget to update
  • // the selection and the focused element!!
  • if (typeof _recPrev == “undefined”)
  •   _recPrev = false;
    
  • //Check whether the focused state has changed
  • if (_focused != this.getFocused())
  • {
  •   //Reset the focus of the formerly focused element
    
  •   if (!_recPrev)
    
  •   {
    
  •   	var focused = this.getRootObject.getFocusedObject();
    
  •   	if (focused)
    
  •   	{
    
  •   		focused.setFocused(false, true);
    
  •   	}
    
  •   }
    
  •   if (!_focused)
    
  •   {
    
  •   	//If the object is not focused, reset the focus state of all children
    
  •   	for (var i = 0; i < this.children.length; i++)
    
  •   	{
    
  •   		this.children[i].setFocused(false, true);
    
  •   	}
      }
      else
      {
    
  •   	state |=  EGW_AO_STATE_SELECTED;
    
  •   }
    
  •   this.iface.setState(state, true);
    
  • }
  • if (_applyToChildren)
  • {
  •   for (var i = 0; i < this.children.length; i++)
    
  •   {
    
  •   	this.children[i].setFocused(true, true, false);
    
  •   }
    
  • }
  • if (_applyToParent)
  • {
  •   for (var i = 0; i < this.children.length; i++)
    
  •   {
    
  •   	this.children[i].setFocused(true, false, true);
    
  •   }
    
  • }
    -}

-egwActionObject.prototype.setFocused = function(_focused, _applyToSelf,

  • _applyToChildren, _applyToParent)
    -{
  •   	//Otherwise set the focused state of the parent to true
    
  •   	if (this.parent)
    
  •   	{
    
  •   		this.parent.setFocused(true, true);
    
  •   	}
    
  •   }
    
  •   //No perform the actual change in the interface state.
    
  •   this.iface.setState(egwSetBit(this.iface.getState(), EGW_AO_STATE_FOCUSED,
    
  •   	_focused));
    
  • }
    +}

+/**

    • Sets the selected state of the element.
    • TODO: Callback
  • */
    +egwActionObject.prototype.setSelected = function(_selected)
    +{
  • this.iface.setState(egwSetBit(this.iface.getState(), EGW_AO_STATE_SELECTED,
  •   _selected));
    

}

/**
@@ -783,7 +921,7 @@

  • Sets the callback function which will be called when a user interaction changes
  • state of the object.
    */
    -egwActionObjectInterface.prototype.setStateChangeCallback(_callback, _context)
    +egwActionObjectInterface.prototype.setStateChangeCallback = function(_callback, _context)
    {
    this.stateChangeCallback = _callback;
    this.stateChangeContext = _context;
    @@ -796,7 +934,7 @@
  • @param boolean _selected Whether the object is selected or not.
    */
    -egwActionObjectInterface.prototype._selectChange(_selected)
    +egwActionObjectInterface.prototype._selectChange = function(_selected)
    {
    // Check whether the selected bit has actually changed - the callback may
    // perform expensive operations, and we don’t want those to happen without
    @@ -839,7 +977,6 @@
    }
    }

/**

  • Returns the current state of the object. The state is maintained by the
  • egwActionObjectInterface and implementations do not have to overwrite this
    @@ -850,3 +987,16 @@
    return this._state;
    }

+/** egwActionObjectManager Object /
+
+/

    • The egwActionObjectManager is a dummy class which only contains a dummy
    • AOI. It may be used as root object or as object containers.
  • */
    +function egwActionObjectManager(_id, _manager)
    +{
  • return new egwActionObject(_id, null, _manager,
  •   new egwActionObjectInterface(), EGW_AO_FLAG_IS_CONTAINER);
    

+}
+

Added: trunk/phpgwapi/js/egw_action/test/js/jquery.js
URL: http://www.egroupware.org/viewvc/egroupware/trunk/phpgwapi/js/egw_action/test/js/jquery.js?rev=33941&view=auto

— trunk/phpgwapi/js/egw_action/test/js/jquery.js (added)
+++ trunk/phpgwapi/js/egw_action/test/js/jquery.js Thu Feb 24 20:00:47 2011
@@ -1,0 +1,8176 @@
+/*!

    • jQuery JavaScript Library v1.5
    • Copyright 2011, John Resig
    • Dual licensed under the MIT or GPL Version 2 licenses.
    • Includes Sizzle.js
    • Copyright 2011, The Dojo Foundation
    • Released under the MIT, BSD, and GPL Licenses.
    • Date: Mon Jan 31 08:31:29 2011 -0500
  • */
    +(function( window, undefined ) {

+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {

  •   // The jQuery object is actually just the init constructor 'enhanced'
    
  •   return new jQuery.fn.init( selector, context, rootjQuery );
    
  • },
  • // Map over jQuery in case of overwrite
  • _jQuery = window.jQuery,
  • // Map over the $ in case of overwrite
  • _$ = window.$,
  • // A central reference to the root jQuery(document)
  • rootjQuery,
  • // A simple way to check for HTML strings or ID strings
  • // (both of which we optimize for)
  • quickExpr = /^(?:[^<](<[\w\W]+>)[^>]$|#([\w-]+)$)/,
  • // Check if a string has a non-whitespace character in it
  • rnotwhite = /\S/,
  • // Used for trimming whitespace
  • trimLeft = /^\s+/,
  • trimRight = /\s+$/,
  • // Check for digits
  • rdigit = /\d/,
  • // Match a standalone tag
  • rsingleTag = /^<(\w+)\s*/?>(?:</\1>)?$/,
  • // JSON RegExp
  • rvalidchars = /^[],:{}\s]*$/,
  • rvalidescape = /\(?:["\/bfnrt]|u[0-9a-fA-F]{4})/g,
  • rvalidtokens = /"[^"\\n\r]"|true|false|null|-?\d+(?:.\d)?(?:[eE][+-]?\d+)?/g,
  • rvalidbraces = /(?:^|:|,)(?:\s*[)+/g,
  • // Useragent RegExp
  • rwebkit = /(webkit) //,
  • ropera = /(opera)(?:.*version)? //,
  • rmsie = /(msie) ([\w.]+)/,
  • rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
  • // Keep a UserAgent string for use with jQuery.browser
  • userAgent = navigator.userAgent,
  • // For matching the engine and version of the browser
  • browserMatch,
  • // Has the ready events already been bound?
  • readyBound = false,
  • // The deferred used on DOM ready
  • readyList,
  • // Promise methods
  • promiseMethods = “then done fail isResolved isRejected promise”.split( " " ),
  • // The ready event handler
  • DOMContentLoaded,
  • // Save a reference to some core methods
  • toString = Object.prototype.toString,
  • hasOwn = Object.prototype.hasOwnProperty,
  • push = Array.prototype.push,
  • slice = Array.prototype.slice,
  • trim = String.prototype.trim,
  • indexOf = Array.prototype.indexOf,
  • // [[Class]] -> type pairs
  • class2type = {};

+jQuery.fn = jQuery.prototype = {

  • constructor: jQuery,
  • init: function( selector, context, rootjQuery ) {
  •   var match, elem, ret, doc;
    
  •   // Handle $(""), $(null), or $(undefined)
    
  •   if ( !selector ) {
    
  •   	return this;
    
  •   }
    
  •   // Handle $(DOMElement)
    
  •   if ( selector.nodeType ) {
    
  •   	this.context = this[0] = selector;
    
  •   	this.length = 1;
    
  •   	return this;
    
  •   }
    
  •   // The body element only exists once, optimize finding it
    
  •   if ( selector === "body" && !context && document.body ) {
    
  •   	this.context = document;
    
  •   	this[0] = document.body;
    
  •   	this.selector = "body";
    
  •   	this.length = 1;
    
  •   	return this;
    
  •   }
    
  •   // Handle HTML strings
    
  •   if ( typeof selector === "string" ) {
    
  •   	// Are we dealing with HTML string or an ID?
    
  •   	match = quickExpr.exec( selector );
    
  •   	// Verify a match, and that no context was specified for #id
    
  •   	if ( match && (match[1] || !context) ) {
    
  •   		// HANDLE: $(html) -> $(array)
    
  •   		if ( match[1] ) {
    
  •   			context = context instanceof jQuery ? context[0] : context;
    
  •   			doc = (context ? context.ownerDocument || context : document);
    
  •   			// If a single string is passed in and it's a single tag
    
  •   			// just do a createElement and skip the rest
    
  •   			ret = rsingleTag.exec( selector );
    
  •   			if ( ret ) {
    
  •   				if ( jQuery.isPlainObject( context ) ) {
    
  •   					selector = [ document.createElement( ret[1] ) ];
    
  •   					jQuery.fn.attr.call( selector, context, true );
    
  •   				} else {
    
  •   					selector = [ doc.createElement( ret[1] ) ];
    
  •   				}
    
  •   			} else {
    
  •   				ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
    
  •   				selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
    
  •   			}
    
  •   			return jQuery.merge( this, selector );
    
  •   		// HANDLE: $("#id")
    
  •   		} else {
    
  •   			elem = document.getElementById( match[2] );
    
  •   			// Check parentNode to catch when Blackberry 4.6 returns
    
  •   			// nodes that are no longer in the document #6963
    
  •   			if ( elem && elem.parentNode ) {
    
  •   				// Handle the case where IE and Opera return items
    
  •   				// by name instead of ID
    
  •   				if ( elem.id !== match[2] ) {
    
  •   					return rootjQuery.find( selector );
    
  •   				}
    
  •   				// Otherwise, we inject the element directly into the jQuery object
    
  •   				this.length = 1;
    
  •   				this[0] = elem;
    
  •   			}
    
  •   			this.context = document;
    
  •   			this.selector = selector;
    
  •   			return this;
    
  •   		}
    
  •   	// HANDLE: $(expr, $(...))
    
  •   	} else if ( !context || context.jquery ) {
    
  •   		return (context || rootjQuery).find( selector );
    
  •   	// HANDLE: $(expr, context)
    
  •   	// (which is just equivalent to: $(context).find(expr)
    
  •   	} else {
    
  •   		return this.constructor( context ).find( selector );
    
  •   	}
    
  •   // HANDLE: $(function)
    
  •   // Shortcut for document ready
    
  •   } else if ( jQuery.isFunction( selector ) ) {
    
  •   	return rootjQuery.ready( selector );
    
  •   }
    
  •   if (selector.selector !== undefined) {
    
  •   	this.selector = selector.selector;
    
  •   	this.context = selector.context;
    
  •   }
    
  •   return jQuery.makeArray( selector, this );
    
  • },
  • // Start with an empty selector
  • selector: “”,
  • // The current version of jQuery being used
  • jquery: “1.5”,
  • // The default length of a jQuery object is 0
  • length: 0,
  • // The number of elements contained in the matched element set
  • size: function() {
  •   return this.length;
    
  • },
  • toArray: function() {
  •   return slice.call( this, 0 );
    
  • },
  • // Get the Nth element in the matched element set OR
  • // Get the whole matched element set as a clean array
  • get: function( num ) {
  •   return num == null ?
    
  •   	// Return a 'clean' array
    
  •   	this.toArray() :
    
  •   	// Return just the object
    
  •   	( num < 0 ? this[ this.length + num ] : this[ num ] );
    
  • },
  • // Take an array of elements and push it onto the stack
  • // (returning the new matched element set)
  • pushStack: function( elems, name, selector ) {
  •   // Build a new jQuery matched element set
    
  •   var ret = this.constructor();
    
  •   if ( jQuery.isArray( elems ) ) {
    
  •   	push.apply( ret, elems );
    
  •   } else {
    
  •   	jQuery.merge( ret, elems );
    
  •   }
    
  •   // Add the old object onto the stack (as a reference)
    
  •   ret.prevObject = this;
    
  •   ret.context = this.context;
    
  •   if ( name === "find" ) {
    
  •   	ret.selector = this.selector + (this.selector ? " " : "") + selector;
    
  •   } else if ( name ) {
    
  •   	ret.selector = this.selector + "." + name + "(" + selector + ")";
    
  •   }
    
  •   // Return the newly-formed element set
    
  •   return ret;
    
  • },
  • // Execute a callback for every element in the matched set.
  • // (You can seed the arguments with an array of args, but this is
  • // only used internally.)
  • each: function( callback, args ) {
  •   return jQuery.each( this, callback, args );
    
  • },
  • ready: function( fn ) {
  •   // Attach the listeners
    
  •   jQuery.bindReady();
    
  •   // Add the callback
    
  •   readyList.done( fn );
    
  •   return this;
    
  • },
  • eq: function( i ) {
  •   return i === -1 ?
    
  •   	this.slice( i ) :
    
  •   	this.slice( i, +i + 1 );
    
  • },
  • first: function() {
  •   return this.eq( 0 );
    
  • },
  • last: function() {
  •   return this.eq( -1 );
    
  • },
  • slice: function() {
  •   return this.pushStack( slice.apply( this, arguments ),
    
  •   	"slice", slice.call(arguments).join(",") );
    
  • },
  • map: function( callback ) {
  •   return this.pushStack( jQuery.map(this, function( elem, i ) {
    
  •   	return callback.call( elem, i, elem );
    
  •   }));
    
  • },
  • end: function() {
  •   return this.prevObject || this.constructor(null);
    
  • },
  • // For internal use only.
  • // Behaves like an Array’s method, not like a jQuery method.
  • push: push,
  • sort: [].sort,
  • splice: [].splice
    +};

+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {

  • var options, name, src, copy, copyIsArray, clone,
  •   target = arguments[0] || {},
    
  •   i = 1,
    
  •   length = arguments.length,
    
  •   deep = false;
    
  • // Handle a deep copy situation
  • if ( typeof target === “boolean” ) {
  •   deep = target;
    
  •   target = arguments[1] || {};
    
  •   // skip the boolean and the target
    
  •   i = 2;
    
  • }
  • // Handle case when target is a string or something (possible in deep copy)
  • if ( typeof target !== “object” && !jQuery.isFunction(target) ) {
  •   target = {};
    
  • }
  • // extend jQuery itself if only one argument is passed
  • if ( length === i ) {
  •   target = this;
    
  •   --i;
    
  • }
  • for ( ; i < length; i++ ) {
  •   // Only deal with non-null/undefined values
    
  •   if ( (options = arguments[ i ]) != null ) {
    
  •   	// Extend the base object
    
  •   	for ( name in options ) {
    
  •   		src = target[ name ];
    
  •   		copy = options[ name ];
    
  •   		// Prevent never-ending loop
    
  •   		if ( target === copy ) {
    
  •   			continue;
    
  •   		}
    
  •   		// Recurse if we're merging plain objects or arrays
    
  •   		if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
    
  •   			if ( copyIsArray ) {
    
  •   				copyIsArray = false;
    
  •   				clone = src && jQuery.isArray(src) ? src : [];
    
  •   			} else {
    
  •   				clone = src && jQuery.isPlainObject(src) ? src : {};
    
  •   			}
    
  •   			// Never move original objects, clone them
    
  •   			target[ name ] = jQuery.extend( deep, clone, copy );
    
  •   		// Don't bring in undefined values
    
  •   		} else if ( copy !== undefined ) {
    
  •   			target[ name ] = copy;
    
  •   		}
    
  •   	}
    
  •   }
    
  • }
  • // Return the modified object
  • return target;
    +};

+jQuery.extend({

  • noConflict: function( deep ) {
  •   window.$ = _$;
    
  •   if ( deep ) {
    
  •   	window.jQuery = _jQuery;
    
  •   }
    
  •   return jQuery;
    
  • },
  • // Is the DOM ready to be used? Set to true once it occurs.
  • isReady: false,
  • // A counter to track how many items to wait for before
  • // the ready event fires. See #6781
  • readyWait: 1,
  • // Handle when the DOM is ready
  • ready: function( wait ) {
  •   // A third-party is pushing the ready event forwards
    
  •   if ( wait === true ) {
    
  •   	jQuery.readyWait--;
    
  •   }
    
  •   // Make sure that the DOM is not already loaded
    
  •   if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
    
  •   	// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
    
  •   	if ( !document.body ) {
    
  •   		return setTimeout( jQuery.ready, 1 );
    
  •   	}
    
  •   	// Remember that the DOM is ready
    
  •   	jQuery.isReady = true;
    
  •   	// If a normal DOM Ready event fired, decrement, and wait if need be
    
  •   	if ( wait !== true && --jQuery.readyWait > 0 ) {
    
  •   		return;
    
  •   	}
    
  •   	// If there are functions bound, to execute
    
  •   	readyList.resolveWith( document, [ jQuery ] );
    
  •   	// Trigger any bound ready events
    
  •   	if ( jQuery.fn.trigger ) {
    
  •   		jQuery( document ).trigger( "ready" ).unbind( "ready" );
    
  •   	}
    
  •   }
    
  • },
  • bindReady: function() {
  •   if ( readyBound ) {
    
  •   	return;
    
  •   }
    
  •   readyBound = true;
    
  •   // Catch cases where $(document).ready() is called after the
    
  •   // browser event has already occurred.
    
  •   if ( document.readyState === "complete" ) {
    
  •   	// Handle it asynchronously to allow scripts the opportunity to delay ready
    
  •   	return setTimeout( jQuery.ready, 1 );
    
  •   }
    
  •   // Mozilla, Opera and webkit nightlies currently support this event
    
  •   if ( document.addEventListener ) {
    
  •   	// Use the handy event callback
    
  •   	document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
    
  •   	// A fallback to window.onload, that will always work
    
  •   	window.addEventListener( "load", jQuery.ready, false );
    
  •   // If IE event model is used
    
  •   } else if ( document.attachEvent ) {
    
  •   	// ensure firing before onload,
    
  •   	// maybe late but safe also for iframes
    
  •   	document.attachEvent("onreadystatechange", DOMContentLoaded);
    
  •   	// A fallback to window.onload, that will always work
    
  •   	window.attachEvent( "onload", jQuery.ready );
    
  •   	// If IE and not a frame
    
  •   	// continually check to see if the document is ready
    
  •   	var toplevel = false;
    
  •   	try {
    
  •   		toplevel = window.frameElement == null;
    
  •   	} catch(e) {}
    
  •   	if ( document.documentElement.doScroll && toplevel ) {
    
  •   		doScrollCheck();
    
  •   	}
    
  •   }
    
  • },
  • // See test/unit/core.js for details concerning isFunction.
  • // Since version 1.3, DOM methods and functions like alert
  • // aren’t supported. They return false on IE (#2968).
  • isFunction: function( obj ) {
  •   return jQuery.type(obj) === "function";
    
  • },
  • isArray: Array.isArray || function( obj ) {
  •   return jQuery.type(obj) === "array";
    
  • },
  • // A crude way of determining if an object is a window
  • isWindow: function( obj ) {
  •   return obj && typeof obj === "object" && "setInterval" in obj;
    
  • },
  • isNaN: function( obj ) {
  •   return obj == null || !rdigit.test( obj ) || isNaN( obj );
    
  • },
  • type: function( obj ) {
  •   return obj == null ?
    
  •   	String( obj ) :
    
  •   	class2type[ toString.call(obj) ] || "object";
    
  • },
  • isPlainObject: function( obj ) {
  •   // Must be an Object.
    
  •   // Because of IE, we also have to check the presence of the constructor property.
    
  •   // Make sure that DOM nodes and window objects don't pass through, as well
    
  •   if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
    
  •   	return false;
    
  •   }
    
  •   // Not own constructor property must be Object
    
  •   if ( obj.constructor &&
    
  •   	!hasOwn.call(obj, "constructor") &&
    
  •   	!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
    
  •   	return false;
    
  •   }
    
  •   // Own properties are enumerated firstly, so to speed up,
    
  •   // if last one is own, then all properties are own.
    
  •   var key;
    
  •   for ( key in obj ) {}
    
  •   return key === undefined || hasOwn.call( obj, key );
    
  • },
  • isEmptyObject: function( obj ) {
  •   for ( var name in obj ) {
    
  •   	return false;
    
  •   }
    
  •   return true;
    
  • },
  • error: function( msg ) {
  •   throw msg;
    
  • },
  • parseJSON: function( data ) {
  •   if ( typeof data !== "string" || !data ) {
    
  •   	return null;
    
  •   }
    
  •   // Make sure leading/trailing whitespace is removed (IE can't handle it)
    
  •   data = jQuery.trim( data );
    
  •   // Make sure the incoming data is actual JSON
    
  •   // Logic borrowed from http://json.org/json2.js
    
  •   if ( rvalidchars.test(data.replace(rvalidescape, "@")
    
  •   	.replace(rvalidtokens, "]")
    
  •   	.replace(rvalidbraces, "")) ) {
    
  •   	// Try to use the native JSON parser first
    
  •   	return window.JSON && window.JSON.parse ?
    
  •   		window.JSON.parse( data ) :
    
  •   		(new Function("return " + data))();
    
  •   } else {
    
  •   	jQuery.error( "Invalid JSON: " + data );
    
  •   }
    
  • },
  • // Cross-browser xml parsing
  • // (xml & tmp used internally)
  • parseXML: function( data , xml , tmp ) {
  •   if ( window.DOMParser ) { // Standard
    
  •   	tmp = new DOMParser();
    
  •   	xml = tmp.parseFromString( data , "text/xml" );
    
  •   } else { // IE
    
  •   	xml = new ActiveXObject( "Microsoft.XMLDOM" );
    
  •   	xml.async = "false";
    
  •   	xml.loadXML( data );
    
  •   }
    
  •   tmp = xml.documentElement;
    
  •   if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
    
  •   	jQuery.error( "Invalid XML: " + data );
    
  •   }
    
  •   return xml;
    
  • },
  • noop: function() {},
  • // Evalulates a script in a global context
  • globalEval: function( data ) {
  •   if ( data && rnotwhite.test(data) ) {
    
  •   	// Inspired by code by Andrea Giammarchi
    
  •   	// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
    
  •   	var head = document.getElementsByTagName("head")[0] || document.documentElement,
    
  •   		script = document.createElement("script");
    
  •   	script.type = "text/javascript";
    
  •   	if ( jQuery.support.scriptEval() ) {
    
  •   		script.appendChild( document.createTextNode( data ) );
    
  •   	} else {
    
  •   		script.text = data;
    
  •   	}
    
  •   	// Use insertBefore instead of appendChild to circumvent an IE6 bug.
    
  •   	// This arises when a base node is used (#2709).
    
  •   	head.insertBefore( script, head.firstChild );
    
  •   	head.removeChild( script );
    
  •   }
    
  • },
  • nodeName: function( elem, name ) {
  •   return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
    
  • },
  • // args is for internal usage only
  • each: function( object, callback, args ) {
  •   var name, i = 0,
    
  •   	length = object.length,
    
  •   	isObj = length === undefined || jQuery.isFunction(object);
    
  •   if ( args ) {
    
  •   	if ( isObj ) {
    
  •   		for ( name in object ) {
    
  •   			if ( callback.apply( object[ name ], args ) === false ) {
    
  •   				break;
    
  •   			}
    
  •   		}
    
  •   	} else {
    
  •   		for ( ; i < length; ) {
    
  •   			if ( callback.apply( object[ i++ ], args ) === false ) {
    
  •   				break;
    
  •   			}
    
  •   		}
    
  •   	}
    
  •   // A special, fast, case for the most common use of each
    
  •   } else {
    
  •   	if ( isObj ) {
    
  •   		for ( name in object ) {
    
  •   			if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
    
  •   				break;
    
  •   			}
    
  •   		}
    
  •   	} else {
    
  •   		for ( var value = object[0];
    
  •   			i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
    
  •   	}
    
  •   }
    
  •   return object;
    
  • },
  • // Use native String.trim function wherever possible
  • trim: trim ?
  •   function( text ) {
    
  •   	return text == null ?
    
  •   		"" :
    
  •   		trim.call( text );
    
  •   } :
    
  •   // Otherwise use our own trimming functionality
    
  •   function( text ) {
    
  •   	return text == null ?
    
  •   		"" :
    
  •   		text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
    
  •   },
    
  • // results is for internal usage only
  • makeArray: function( array, results ) {
  •   var ret = results || [];
    
  •   if ( array != null ) {
    
  •   	// The window, strings (and functions) also have 'length'
    
  •   	// The extra typeof function check is to prevent crashes
    
  •   	// in Safari 2 (See: #3039)
    
  •   	// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
    
  •   	var type = jQuery.type(array);
    
  •   	if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
    
  •   		push.call( ret, array );
    
  •   	} else {
    
  •   		jQuery.merge( ret, array );
    
  •   	}
    
  •   }
    
  •   return ret;
    
  • },
  • inArray: function( elem, array ) {
  •   if ( array.indexOf ) {
    
  •   	return array.indexOf( elem );
    
  •   }
    
  •   for ( var i = 0, length = array.length; i < length; i++ ) {
    
  •   	if ( array[ i ] === elem ) {
    
  •   		return i;
    
  •   	}
    
  •   }
    
  •   return -1;
    
  • },
  • merge: function( first, second ) {
  •   var i = first.length,
    
  •   	j = 0;
    
  •   if ( typeof second.length === "number" ) {
    
  •   	for ( var l = second.length; j < l; j++ ) {
    
  •   		first[ i++ ] = second[ j ];
    
  •   	}
    
  •   } else {
    
  •   	while ( second[j] !== undefined ) {
    
  •   		first[ i++ ] = second[ j++ ];
    
  •   	}
    
  •   }
    
  •   first.length = i;
    
  •   return first;
    
  • },
  • grep: function( elems, callback, inv ) {
  •   var ret = [], retVal;
    
  •   inv = !!inv;
    
  •   // Go through the array, only saving the items
    
  •   // that pass the validator function
    
  •   for ( var i = 0, length = elems.length; i < length; i++ ) {
    
  •   	retVal = !!callback( elems[ i ], i );
    
  •   	if ( inv !== retVal ) {
    
  •   		ret.push( elems[ i ] );
    
  •   	}
    
  •   }
    
  •   return ret;
    
  • },
  • // arg is for internal usage only
  • map: function( elems, callback, arg ) {
  •   var ret = [], value;
    
  •   // Go through the array, translating each of the items to their
    
  •   // new value (or values).
    
  •   for ( var i = 0, length = elems.length; i < length; i++ ) {
    
  •   	value = callback( elems[ i ], i, arg );
    
  •   	if ( value != null ) {
    
  •   		ret[ ret.length ] = value;
    
  •   	}
    
  •   }
    
  •   // Flatten any nested arrays
    
  •   return ret.concat.apply( [], ret );
    
  • },
  • // A global GUID counter for objects
  • guid: 1,
  • proxy: function( fn, proxy, thisObject ) {
  •   if ( arguments.length === 2 ) {
    
  •   	if ( typeof proxy === "string" ) {
    
  •   		thisObject = fn;
    
  •   		fn = thisObject[ proxy ];
    
  •   		proxy = undefined;
    
  •   	} else if ( proxy && !jQuery.isFunction( proxy ) ) {
    
  •   		thisObject = proxy;
    
  •   		proxy = undefined;
    
  •   	}
    
  •   }
    
  •   if ( !proxy && fn ) {
    
  •   	proxy = function() {
    
  •   		return fn.apply( thisObject || this, arguments );
    
  •   	};
    
  •   }
    
  •   // Set the guid of unique handler to the same of original handler, so it can be removed
    
  •   if ( fn ) {
    
  •   	proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
    
  •   }
    
  •   // So proxy can be declared as an argument
    
  •   return proxy;
    
  • },
  • // Mutifunctional method to get and set values to a collection
  • // The value/s can be optionally by executed if its a function
  • access: function( elems, key, value, exec, fn, pass ) {
  •   var length = elems.length;
    
  •   // Setting many attributes
    
  •   if ( typeof key === "object" ) {
    
  •   	for ( var k in key ) {
    
  •   		jQuery.access( elems, k, key[k], exec, fn, value );
    
  •   	}
    
  •   	return elems;
    
  •   }
    
  •   // Setting one attribute
    
  •   if ( value !== undefined ) {
    
  •   	// Optionally, function values get executed if exec is true
    
  •   	exec = !pass && exec && jQuery.isFunction(value);
    
  •   	for ( var i = 0; i < length; i++ ) {
    
  •   		fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
    
  •   	}
    
  •   	return elems;
    
  •   }
    
  •   // Getting an attribute
    
  •   return length ? fn( elems[0], key ) : undefined;
    
  • },
  • now: function() {
  •   return (new Date()).getTime();
    
  • },
  • // Create a simple deferred (one callbacks list)
  • _Deferred: function() {
  •   var // callbacks list
    
  •   	callbacks = [],
    
  •   	// stored [ context , args ]
    
  •   	fired,
    
  •   	// to avoid firing when already doing so
    
  •   	firing,
    
  •   	// flag to know if the deferred has been cancelled
    
  •   	cancelled,
    
  •   	// the deferred itself
    
  •   	deferred  = {