From 81bea17aefb26859f825b9293c7c99192874806e Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 8 Nov 2011 20:40:44 +0400 Subject: upgrade Dojo to 1.6.1 --- lib/dijit/_CssStateMixin.js | 395 ++++++++++++++++++++++++++++---------------- 1 file changed, 255 insertions(+), 140 deletions(-) (limited to 'lib/dijit/_CssStateMixin.js') diff --git a/lib/dijit/_CssStateMixin.js b/lib/dijit/_CssStateMixin.js index 53144804f..2fdecdcdf 100644 --- a/lib/dijit/_CssStateMixin.js +++ b/lib/dijit/_CssStateMixin.js @@ -1,149 +1,264 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._CssStateMixin"]){ -dojo._hasResource["dijit._CssStateMixin"]=true; +if(!dojo._hasResource["dijit._CssStateMixin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._CssStateMixin"] = true; dojo.provide("dijit._CssStateMixin"); -dojo.declare("dijit._CssStateMixin",[],{cssStateNodes:{},postCreate:function(){ -this.inherited(arguments); -dojo.forEach(["onmouseenter","onmouseleave","onmousedown"],function(e){ -this.connect(this.domNode,e,"_cssMouseEvent"); -},this); -this.connect(this,"set",function(_1,_2){ -if(arguments.length>=2&&{disabled:true,readOnly:true,checked:true,selected:true}[_1]){ -this._setStateClass(); -} -}); -dojo.forEach(["_onFocus","_onBlur"],function(ap){ -this.connect(this,ap,"_setStateClass"); -},this); -for(var ap in this.cssStateNodes){ -this._trackMouseState(this[ap],this.cssStateNodes[ap]); -} -this._setStateClass(); -},_cssMouseEvent:function(_3){ -if(!this.disabled){ -switch(_3.type){ -case "mouseenter": -case "mouseover": -this._hovering=true; -this._active=this._mouseDown; -break; -case "mouseleave": -case "mouseout": -this._hovering=false; -this._active=false; -break; -case "mousedown": -this._active=true; -this._mouseDown=true; -var _4=this.connect(dojo.body(),"onmouseup",function(){ -this._active=false; -this._mouseDown=false; -this._setStateClass(); -this.disconnect(_4); -}); -break; -} -this._setStateClass(); -} -},_setStateClass:function(){ -var _5=this.baseClass.split(" "); -function _6(_7){ -_5=_5.concat(dojo.map(_5,function(c){ -return c+_7; -}),"dijit"+_7); -}; -if(!this.isLeftToRight()){ -_6("Rtl"); -} -if(this.checked){ -_6("Checked"); -} -if(this.state){ -_6(this.state); -} -if(this.selected){ -_6("Selected"); -} -if(this.disabled){ -_6("Disabled"); -}else{ -if(this.readOnly){ -_6("ReadOnly"); -}else{ -if(this._active){ -_6("Active"); -}else{ -if(this._hovering){ -_6("Hover"); -} -} -} -} -if(this._focused){ -_6("Focused"); -} -var tn=this.stateNode||this.domNode,_8={}; -dojo.forEach(tn.className.split(" "),function(c){ -_8[c]=true; -}); -if("_stateClasses" in this){ -dojo.forEach(this._stateClasses,function(c){ -delete _8[c]; -}); -} -dojo.forEach(_5,function(c){ -_8[c]=true; -}); -var _9=[]; -for(var c in _8){ -_9.push(c); -} -tn.className=_9.join(" "); -this._stateClasses=_5; -},_trackMouseState:function(_a,_b){ -var _c=false,_d=false,_e=false; -var _f=this,cn=dojo.hitch(this,"connect",_a); -function _10(){ -var _11=("disabled" in _f&&_f.disabled)||("readonly" in _f&&_f.readonly); -dojo.toggleClass(_a,_b+"Hover",_c&&!_d&&!_11); -dojo.toggleClass(_a,_b+"Active",_d&&!_11); -dojo.toggleClass(_a,_b+"Focused",_e&&!_11); -}; -cn("onmouseenter",function(){ -_c=true; -_10(); -}); -cn("onmouseleave",function(){ -_c=false; -_d=false; -_10(); -}); -cn("onmousedown",function(){ -_d=true; -_10(); -}); -cn("onmouseup",function(){ -_d=false; -_10(); -}); -cn("onfocus",function(){ -_e=true; -_10(); -}); -cn("onblur",function(){ -_e=false; -_10(); -}); -this.connect(this,"set",function(_12,_13){ -if(_12=="disabled"||_12=="readOnly"){ -_10(); -} + + +dojo.declare("dijit._CssStateMixin", [], { + // summary: + // Mixin for widgets to set CSS classes on the widget DOM nodes depending on hover/mouse press/focus + // state changes, and also higher-level state changes such becoming disabled or selected. + // + // description: + // By mixing this class into your widget, and setting the this.baseClass attribute, it will automatically + // maintain CSS classes on the widget root node (this.domNode) depending on hover, + // active, focus, etc. state. Ex: with a baseClass of dijitButton, it will apply the classes + // dijitButtonHovered and dijitButtonActive, as the user moves the mouse over the widget and clicks it. + // + // It also sets CSS like dijitButtonDisabled based on widget semantic state. + // + // By setting the cssStateNodes attribute, a widget can also track events on subnodes (like buttons + // within the widget). + + // cssStateNodes: [protected] Object + // List of sub-nodes within the widget that need CSS classes applied on mouse hover/press and focus + //. + // Each entry in the hash is a an attachpoint names (like "upArrowButton") mapped to a CSS class names + // (like "dijitUpArrowButton"). Example: + // | { + // | "upArrowButton": "dijitUpArrowButton", + // | "downArrowButton": "dijitDownArrowButton" + // | } + // The above will set the CSS class dijitUpArrowButton to the this.upArrowButton DOMNode when it + // is hovered, etc. + cssStateNodes: {}, + + // hovering: [readonly] Boolean + // True if cursor is over this widget + hovering: false, + + // active: [readonly] Boolean + // True if mouse was pressed while over this widget, and hasn't been released yet + active: false, + + _applyAttributes: function(){ + // This code would typically be in postCreate(), but putting in _applyAttributes() for + // performance: so the class changes happen before DOM is inserted into the document. + // Change back to postCreate() in 2.0. See #11635. + + this.inherited(arguments); + + // Automatically monitor mouse events (essentially :hover and :active) on this.domNode + dojo.forEach(["onmouseenter", "onmouseleave", "onmousedown"], function(e){ + this.connect(this.domNode, e, "_cssMouseEvent"); + }, this); + + // Monitoring changes to disabled, readonly, etc. state, and update CSS class of root node + dojo.forEach(["disabled", "readOnly", "checked", "selected", "focused", "state", "hovering", "active"], function(attr){ + this.watch(attr, dojo.hitch(this, "_setStateClass")); + }, this); + + // Events on sub nodes within the widget + for(var ap in this.cssStateNodes){ + this._trackMouseState(this[ap], this.cssStateNodes[ap]); + } + // Set state initially; there's probably no hover/active/focus state but widget might be + // disabled/readonly/checked/selected so we want to set CSS classes for those conditions. + this._setStateClass(); + }, + + _cssMouseEvent: function(/*Event*/ event){ + // summary: + // Sets hovering and active properties depending on mouse state, + // which triggers _setStateClass() to set appropriate CSS classes for this.domNode. + + if(!this.disabled){ + switch(event.type){ + case "mouseenter": + case "mouseover": // generated on non-IE browsers even though we connected to mouseenter + this._set("hovering", true); + this._set("active", this._mouseDown); + break; + + case "mouseleave": + case "mouseout": // generated on non-IE browsers even though we connected to mouseleave + this._set("hovering", false); + this._set("active", false); + break; + + case "mousedown" : + this._set("active", true); + this._mouseDown = true; + // Set a global event to handle mouseup, so it fires properly + // even if the cursor leaves this.domNode before the mouse up event. + // Alternately could set active=false on mouseout. + var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){ + this._mouseDown = false; + this._set("active", false); + this.disconnect(mouseUpConnector); + }); + break; + } + } + }, + + _setStateClass: function(){ + // summary: + // Update the visual state of the widget by setting the css classes on this.domNode + // (or this.stateNode if defined) by combining this.baseClass with + // various suffixes that represent the current widget state(s). + // + // description: + // In the case where a widget has multiple + // states, it sets the class based on all possible + // combinations. For example, an invalid form widget that is being hovered + // will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover". + // + // The widget may have one or more of the following states, determined + // by this.state, this.checked, this.valid, and this.selected: + // - Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid + // - Incomplete - ValidationTextBox sets this.state to "Incomplete" if the current input value is not finished yet + // - Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true + // - Selected - ex: currently selected tab will have this.selected==true + // + // In addition, it may have one or more of the following states, + // based on this.disabled and flags set in _onMouse (this.active, this.hovering) and from focus manager (this.focused): + // - Disabled - if the widget is disabled + // - Active - if the mouse (or space/enter key?) is being pressed down + // - Focused - if the widget has focus + // - Hover - if the mouse is over the widget + + // Compute new set of classes + var newStateClasses = this.baseClass.split(" "); + + function multiply(modifier){ + newStateClasses = newStateClasses.concat(dojo.map(newStateClasses, function(c){ return c+modifier; }), "dijit"+modifier); + } + + if(!this.isLeftToRight()){ + // For RTL mode we need to set an addition class like dijitTextBoxRtl. + multiply("Rtl"); + } + + if(this.checked){ + multiply("Checked"); + } + if(this.state){ + multiply(this.state); + } + if(this.selected){ + multiply("Selected"); + } + + if(this.disabled){ + multiply("Disabled"); + }else if(this.readOnly){ + multiply("ReadOnly"); + }else{ + if(this.active){ + multiply("Active"); + }else if(this.hovering){ + multiply("Hover"); + } + } + + if(this._focused){ + multiply("Focused"); + } + + // Remove old state classes and add new ones. + // For performance concerns we only write into domNode.className once. + var tn = this.stateNode || this.domNode, + classHash = {}; // set of all classes (state and otherwise) for node + + dojo.forEach(tn.className.split(" "), function(c){ classHash[c] = true; }); + + if("_stateClasses" in this){ + dojo.forEach(this._stateClasses, function(c){ delete classHash[c]; }); + } + + dojo.forEach(newStateClasses, function(c){ classHash[c] = true; }); + + var newClasses = []; + for(var c in classHash){ + newClasses.push(c); + } + tn.className = newClasses.join(" "); + + this._stateClasses = newStateClasses; + }, + + _trackMouseState: function(/*DomNode*/ node, /*String*/ clazz){ + // summary: + // Track mouse/focus events on specified node and set CSS class on that node to indicate + // current state. Usually not called directly, but via cssStateNodes attribute. + // description: + // Given class=foo, will set the following CSS class on the node + // - fooActive: if the user is currently pressing down the mouse button while over the node + // - fooHover: if the user is hovering the mouse over the node, but not pressing down a button + // - fooFocus: if the node is focused + // + // Note that it won't set any classes if the widget is disabled. + // node: DomNode + // Should be a sub-node of the widget, not the top node (this.domNode), since the top node + // is handled specially and automatically just by mixing in this class. + // clazz: String + // CSS class name (ex: dijitSliderUpArrow). + + // Current state of node (initially false) + // NB: setting specifically to false because dojo.toggleClass() needs true boolean as third arg + var hovering=false, active=false, focused=false; + + var self = this, + cn = dojo.hitch(this, "connect", node); + + function setClass(){ + var disabled = ("disabled" in self && self.disabled) || ("readonly" in self && self.readonly); + dojo.toggleClass(node, clazz+"Hover", hovering && !active && !disabled); + dojo.toggleClass(node, clazz+"Active", active && !disabled); + dojo.toggleClass(node, clazz+"Focused", focused && !disabled); + } + + // Mouse + cn("onmouseenter", function(){ + hovering = true; + setClass(); + }); + cn("onmouseleave", function(){ + hovering = false; + active = false; + setClass(); + }); + cn("onmousedown", function(){ + active = true; + setClass(); + }); + cn("onmouseup", function(){ + active = false; + setClass(); + }); + + // Focus + cn("onfocus", function(){ + focused = true; + setClass(); + }); + cn("onblur", function(){ + focused = false; + setClass(); + }); + + // Just in case widget is enabled/disabled while it has focus/hover/active state. + // Maybe this is overkill. + this.watch("disabled", setClass); + this.watch("readOnly", setClass); + } }); -}}); + } -- cgit v1.2.3