Subversion Repositories Applications.papyrus

Rev

Blame | Last modification | View Log | RSS feed

if(!dojo._hasResource["dijit._Container"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dijit._Container"] = true;
dojo.provide("dijit._Container");

dojo.declare("dijit._Contained",
        null,
        {
                // summary
                //              Mixin for widgets that are children of a container widget

                getParent: function(){
                        // summary:
                        //              returns the parent widget of this widget, assuming the parent
                        //              implements dijit._Container
                        for(var p=this.domNode.parentNode; p; p=p.parentNode){
                                var id = p.getAttribute && p.getAttribute("widgetId");
                                if(id){
                                        var parent = dijit.byId(id);
                                        return parent.isContainer ? parent : null;
                                }
                        }
                        return null;
                },

                _getSibling: function(which){
                        var node = this.domNode;
                        do{
                                node = node[which+"Sibling"];
                        }while(node && node.nodeType != 1);
                        if(!node){ return null; } // null
                        var id = node.getAttribute("widgetId");
                        return dijit.byId(id);
                },

                getPreviousSibling: function(){
                        // summary:
                        //              returns null if this is the first child of the parent,
                        //              otherwise returns the next element sibling to the "left".

                        return this._getSibling("previous");
                },

                getNextSibling: function(){
                        // summary:
                        //              returns null if this is the last child of the parent,
                        //              otherwise returns the next element sibling to the "right".

                        return this._getSibling("next");
                }
        }
);

dojo.declare("dijit._Container",
        null,
        {
                // summary
                //              Mixin for widgets that contain a list of children like SplitContainer

                isContainer: true,

                addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
                        // summary:
                        //              Process the given child widget, inserting it's dom node as
                        //              a child of our dom node

                        if(insertIndex === undefined){
                                insertIndex = "last";
                        }
                        var refNode = this.containerNode || this.domNode;
                        if(insertIndex && typeof insertIndex == "number"){
                                var children = dojo.query("> [widgetid]", refNode);
                                if(children && children.length >= insertIndex){
                                        refNode = children[insertIndex-1]; insertIndex = "after";
                                }
                        }
                        dojo.place(widget.domNode, refNode, insertIndex);

                        // If I've been started but the child widget hasn't been started,
                        // start it now.  Make sure to do this after widget has been
                        // inserted into the DOM tree, so it can see that it's being controlled by me,
                        // so it doesn't try to size itself.
                        if(this._started && !widget._started){
                                widget.startup();
                        }
                },

                removeChild: function(/*Widget*/ widget){
                        // summary:
                        //              removes the passed widget instance from this widget but does
                        //              not destroy it
                        var node = widget.domNode;
                        node.parentNode.removeChild(node);      // detach but don't destroy
                },

                _nextElement: function(node){
                        do{
                                node = node.nextSibling;
                        }while(node && node.nodeType != 1);
                        return node;
                },

                _firstElement: function(node){
                        node = node.firstChild;
                        if(node && node.nodeType != 1){
                                node = this._nextElement(node);
                        }
                        return node;
                },

                getChildren: function(){
                        // summary:
                        //              Returns array of children widgets
                        return dojo.query("> [widgetId]", this.containerNode || this.domNode).map(dijit.byNode); // Array
                },

                hasChildren: function(){
                        // summary:
                        //              Returns true if widget has children
                        var cn = this.containerNode || this.domNode;
                        return !!this._firstElement(cn); // Boolean
                },

                _getSiblingOfChild: function(/*Widget*/ child, /*int*/ dir){
                        // summary:
                        //              get the next or previous widget sibling of child
                        // dir:
                        //              if 1, get the next sibling
                        //              if -1, get the previous sibling
                        var node = child.domNode;
                        var which = (dir>0 ? "nextSibling" : "previousSibling");
                        do{
                                node = node[which];
                        }while(node && (node.nodeType != 1 || !dijit.byNode(node)));
                        return node ? dijit.byNode(node) : null;
                }
        }
);

dojo.declare("dijit._KeyNavContainer",
        [dijit._Container],
        {

                // summary:
                //              A _Container with keyboard navigation of its children.
                //              To use this mixin, call connectKeyNavHandlers() in
                //              postCreate() and call startupKeyNavChildren() in startup().

/*=====
                // focusedChild: Widget
                //              The currently focused child widget, or null if there isn't one
                focusedChild: null,
=====*/

                _keyNavCodes: {},

                connectKeyNavHandlers: function(/*Array*/ prevKeyCodes, /*Array*/ nextKeyCodes){
                        // summary:
                        //              Call in postCreate() to attach the keyboard handlers
                        //              to the container.
                        // preKeyCodes: Array
                        //              Key codes for navigating to the previous child.
                        // nextKeyCodes: Array
                        //              Key codes for navigating to the next child.

                        var keyCodes = this._keyNavCodes = {};
                        var prev = dojo.hitch(this, this.focusPrev);
                        var next = dojo.hitch(this, this.focusNext);
                        dojo.forEach(prevKeyCodes, function(code){ keyCodes[code] = prev });
                        dojo.forEach(nextKeyCodes, function(code){ keyCodes[code] = next });
                        this.connect(this.domNode, "onkeypress", "_onContainerKeypress");
                        if(dojo.isIE){
                                this.connect(this.domNode, "onactivate", "_onContainerFocus");
                                this.connect(this.domNode, "ondeactivate", "_onContainerBlur");
                        }else{
                                this.connect(this.domNode, "onfocus", "_onContainerFocus");
                                this.connect(this.domNode, "onblur", "_onContainerBlur");
                        }
                },

                startupKeyNavChildren: function(){
                        // summary:
                        //              Call in startup() to set child tabindexes to -1
                        dojo.forEach(this.getChildren(), dojo.hitch(this, "_setTabIndexMinusOne"));
                },

                addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
                        // summary: Add a child to our _Container
                        dijit._KeyNavContainer.superclass.addChild.apply(this, arguments);
                        this._setTabIndexMinusOne(widget);
                },

                focus: function(){
                        // summary: Default focus() implementation: focus the first child.
                        this.focusFirstChild();
                },

                focusFirstChild: function(){
                        // summary: Focus the first focusable child in the container.
                        this.focusChild(this._getFirstFocusableChild());
                },

                focusNext: function(){
                        // summary: Focus the next widget or focal node (for widgets
                        //              with multiple focal nodes) within this container.
                        if(this.focusedChild && this.focusedChild.hasNextFocalNode
                                        && this.focusedChild.hasNextFocalNode()){
                                this.focusedChild.focusNext();
                                return;
                        }
                        var child = this._getNextFocusableChild(this.focusedChild, 1);
                        if(child.getFocalNodes){
                                this.focusChild(child, child.getFocalNodes()[0]);
                        }else{
                                this.focusChild(child);
                        }
                },

                focusPrev: function(){
                        // summary: Focus the previous widget or focal node (for widgets
                        //              with multiple focal nodes) within this container.
                        if(this.focusedChild && this.focusedChild.hasPrevFocalNode
                                        && this.focusedChild.hasPrevFocalNode()){
                                this.focusedChild.focusPrev();
                                return;
                        }
                        var child = this._getNextFocusableChild(this.focusedChild, -1);
                        if(child.getFocalNodes){
                                var nodes = child.getFocalNodes();
                                this.focusChild(child, nodes[nodes.length-1]);
                        }else{
                                this.focusChild(child);
                        }
                },

                focusChild: function(/*Widget*/ widget, /*Node?*/ node){
                        // summary: Focus widget. Optionally focus 'node' within widget.
                        if(widget){
                                if(this.focusedChild && widget !== this.focusedChild){
                                        this._onChildBlur(this.focusedChild);
                                }
                                this.focusedChild = widget;
                                if(node && widget.focusFocalNode){
                                        widget.focusFocalNode(node);
                                }else{
                                        widget.focus();
                                }
                        }
                },

                _setTabIndexMinusOne: function(/*Widget*/ widget){
                        if(widget.getFocalNodes){
                                dojo.forEach(widget.getFocalNodes(), function(node){
                                        node.setAttribute("tabIndex", -1);
                                });
                        }else{
                                (widget.focusNode || widget.domNode).setAttribute("tabIndex", -1);
                        }
                },

                _onContainerFocus: function(evt){
                        this.domNode.setAttribute("tabIndex", -1);
                        if(evt.target === this.domNode){
                                this.focusFirstChild();
                        }else{
                                var widget = dijit.getEnclosingWidget(evt.target);
                                if(widget && widget.isFocusable()){
                                        this.focusedChild = widget;
                                }
                        }
                },

                _onContainerBlur: function(evt){
                        if(this.tabIndex){
                                this.domNode.setAttribute("tabIndex", this.tabIndex);
                        }
                },

                _onContainerKeypress: function(evt){
                        if(evt.ctrlKey || evt.altKey){ return; }
                        var func = this._keyNavCodes[evt.keyCode];
                        if(func){
                                func();
                                dojo.stopEvent(evt);
                        }
                },

                _onChildBlur: function(/*Widget*/ widget){
                        // summary:
                        //              Called when focus leaves a child widget to go
                        //              to a sibling widget.
                },

                _getFirstFocusableChild: function(){
                        return this._getNextFocusableChild(null, 1);
                },

                _getNextFocusableChild: function(child, dir){
                        if(child){
                                child = this._getSiblingOfChild(child, dir);
                        }
                        var children = this.getChildren();
                        for(var i=0; i < children.length; i++){
                                if(!child){
                                        child = children[(dir>0) ? 0 : (children.length-1)];
                                }
                                if(child.isFocusable()){
                                        return child;
                                }
                                child = this._getSiblingOfChild(child, dir);
                        }
                }
        }
);

}