/* Copyright (c) 2009, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 3.0.0 build: 1549 */ YUI.add('node-focusmanager',function(Y){var ACTIVE_DESCENDANT="activeDescendant",ID="id",DISABLED="disabled",TAB_INDEX="tabIndex",FOCUSED="focused",FOCUS_CLASS="focusClass",CIRCULAR="circular",UI="UI",KEY="key",ACTIVE_DESCENDANT_CHANGE=ACTIVE_DESCENDANT+"Change",HOST="host",scrollKeys={37:true,38:true,39:true,40:true},clickableElements={"a":true,"button":true,"input":true,"object":true},Lang=Y.Lang,UA=Y.UA,NodeFocusManager=function(){NodeFocusManager.superclass.constructor.apply(this,arguments);};NodeFocusManager.ATTRS={focused:{value:false,readOnly:true},descendants:{getter:function(value){return this.get(HOST).all(value);}},activeDescendant:{setter:function(value){var isNumber=Lang.isNumber,INVALID_VALUE=Y.Attribute.INVALID_VALUE,descendantsMap=this._descendantsMap,descendants=this._descendants,nodeIndex,returnValue,oNode;if(isNumber(value)){nodeIndex=value;returnValue=nodeIndex;} else if((value instanceof Y.Node)&&descendantsMap){nodeIndex=descendantsMap[value.get(ID)];if(isNumber(nodeIndex)){returnValue=nodeIndex;} else{returnValue=INVALID_VALUE;}} else{returnValue=INVALID_VALUE;} if(descendants){oNode=descendants.item(nodeIndex);if(oNode&&oNode.get("disabled")){returnValue=INVALID_VALUE;}} return returnValue;}},keys:{value:{next:null,previous:null}},focusClass:{},circular:{value:true}};Y.extend(NodeFocusManager,Y.Plugin.Base,{_stopped:true,_descendants:null,_descendantsMap:null,_focusedNode:null,_lastNodeIndex:0,_eventHandlers:null,_initDescendants:function(){var descendants=this.get("descendants"),descendantsMap={},nFirstEnabled=-1,nDescendants,nActiveDescendant=this.get(ACTIVE_DESCENDANT),oNode,sID,i=0;if(Lang.isUndefined(nActiveDescendant)){nActiveDescendant=-1;} if(descendants){nDescendants=descendants.size();if(nDescendants>1){for(i=0;i1){aHandlers=this._eventHandlers||[];oDocument=this.get(HOST).get("ownerDocument");if(aHandlers.length===0){aHandlers.push(oDocument.on("focus",this._onDocFocus,this));aHandlers.push(oDocument.on("mousedown",this._onDocMouseDown,this));aHandlers.push(this.after("keysChange",this._attachKeyHandler));aHandlers.push(this.after("descendantsChange",this._initDescendants));aHandlers.push(this.after(ACTIVE_DESCENDANT_CHANGE,this._afterActiveDescendantChange));handle=this.after("focusedChange",Y.bind(function(event){if(event.newVal){this._attachKeyHandler();handle.detach();}},this));aHandlers.push(handle);} this._eventHandlers=aHandlers;}},_onDocMouseDown:function(event){var oHost=this.get(HOST),oTarget=event.target,bChildNode=oHost.contains(oTarget),node,getFocusable=function(node){var returnVal=false;if(!node.compareTo(oHost)){returnVal=this._isDescendant(node)?node:getFocusable.call(this,node.get("parentNode"));} return returnVal;};if(bChildNode){node=getFocusable.call(this,oTarget);if(node){oTarget=node;} else if(!node&&this.get(FOCUSED)){this._set(FOCUSED,false);this._onDocFocus(event);}} if(bChildNode&&this._isDescendant(oTarget)){this.focus(oTarget);} else if(UA.webkit&&this.get(FOCUSED)&&(!bChildNode||(bChildNode&&!this._isDescendant(oTarget)))){this._set(FOCUSED,false);this._onDocFocus(event);}},_onDocFocus:function(event){var oTarget=this._focusTarget||event.target,bFocused=this.get(FOCUSED),focusClass=this.get(FOCUS_CLASS),oFocusedNode=this._focusedNode,bInCollection;if(this._focusTarget){this._focusTarget=null;} if(this.get(HOST).contains(oTarget)){bInCollection=this._isDescendant(oTarget);if(!bFocused&&bInCollection){bFocused=true;} else if(bFocused&&!bInCollection){bFocused=false;}} else{bFocused=false;} if(focusClass){if(oFocusedNode&&(!oFocusedNode.compareTo(oTarget)||!bFocused)){this._removeFocusClass();} if(bInCollection&&bFocused){if(focusClass.fn){oTarget=focusClass.fn(oTarget);oTarget.addClass(focusClass.className);} else{oTarget.addClass(focusClass);} this._focusedNode=oTarget;}} this._set(FOCUSED,bFocused);},_focusNext:function(event,activeDescendant){var nActiveDescendant=activeDescendant||this.get(ACTIVE_DESCENDANT),oNode;if(this._isDescendant(event.target)&&(nActiveDescendant<=this._lastNodeIndex)){nActiveDescendant=nActiveDescendant+1;if(nActiveDescendant===(this._lastNodeIndex+1)&&this.get(CIRCULAR)){nActiveDescendant=0;} oNode=this._descendants.item(nActiveDescendant);if(oNode.get(DISABLED)){this._focusNext(event,nActiveDescendant);} else{this.focus(nActiveDescendant);}} this._preventScroll(event);},_focusPrevious:function(event,activeDescendant){var nActiveDescendant=activeDescendant||this.get(ACTIVE_DESCENDANT),oNode;if(this._isDescendant(event.target)&&nActiveDescendant>=0){nActiveDescendant=nActiveDescendant-1;if(nActiveDescendant===-1&&this.get(CIRCULAR)){nActiveDescendant=this._lastNodeIndex;} oNode=this._descendants.item(nActiveDescendant);if(oNode.get(DISABLED)){this._focusPrevious(event,nActiveDescendant);} else{this.focus(nActiveDescendant);}} this._preventScroll(event);},_afterActiveDescendantChange:function(event){var oNode=this._descendants.item(event.prevVal);if(oNode){oNode.set(TAB_INDEX,-1);} oNode=this._descendants.item(event.newVal);if(oNode){oNode.set(TAB_INDEX,0);}},initializer:function(config){this.start();},destructor:function(){this.stop();this.get(HOST).focusManager=null;},focus:function(index){if(Lang.isUndefined(index)){index=this.get(ACTIVE_DESCENDANT);} this.set(ACTIVE_DESCENDANT,index,{src:UI});var oNode=this._descendants.item(this.get(ACTIVE_DESCENDANT));if(oNode){oNode.focus();if(UA.opera&&oNode.get("nodeName").toLowerCase()==="button"){this._focusTarget=oNode;}}},blur:function(){var oNode;if(this.get(FOCUSED)){oNode=this._descendants.item(this.get(ACTIVE_DESCENDANT));if(oNode){oNode.blur();this._removeFocusClass();} this._set(FOCUSED,false,{src:UI});}},start:function(){if(this._stopped){this._initDescendants();this._attachEventHandlers();this._stopped=false;}},stop:function(){if(!this._stopped){this._detachEventHandlers();this._descendants=null;this._focusedNode=null;this._lastNodeIndex=0;this._stopped=true;}},refresh:function(){this._initDescendants();}});NodeFocusManager.NAME="nodeFocusManager";NodeFocusManager.NS="focusManager";Y.namespace("Plugin");Y.Plugin.NodeFocusManager=NodeFocusManager;},'3.0.0',{requires:['attribute','node','plugin','node-event-simulate','event-key','event-focus']});