嗨,
我需要能够动态更改按钮的不同状态(正常,悬停,按下)的背景颜色。
到目前为止,我想到的是以下内容:
http://jsfiddle.net/suamikim/c3eHh/
Ext.onReady(function() {
function updateBackground() {
var theWin = win || this, // neccessary because of the call from the afterrender-event
btn = theWin.down('#btnTest'),
bckgr = theWin.down('#btnBckgr').getValue(),
bckgrHover = theWin.down('#btnBckgrHover').getValue(),
bckgrPressed = theWin.down('#btnBckgrPressed').getValue();
// Set normal background as button-style
// Should be ok
$('#' + btn.id).css('background', bckgr);
// Toggle background when hover-state changes
// Are there any downsides if this function gets called everytime the updateBackground-method is called? Do i have to dispose anything before binding the functions again?
$('#' + btn.id).hover(function() {
$('#' + btn.id).css('background', bckgrHover);
}, function() {
$('#' + btn.id).css('background', bckgr);
}
);
// Set the background for pressed button as document style
// Problems:
// - Pollutes the document-header if called multiple times...
// - Background does not change anymore on hover for pressed button because of the !important, but without important it wouldn't show the pressed background at all...
$('<style type="text/css"> #' + btn.id + '.x-btn-pressed { background: ' + bckgrPressed + ' !important } </style>').appendTo('head');
};
// Create a window with the propertygrid
var win = Ext.create('Ext.window.Window', {
width: 800,
height: 200,
layout: 'fit',
tbar: {
defaultType: 'textfield',
defaults: {
listeners: {
blur: updateBackground
}
},
items: [
'Background (CSS):', { itemId: 'btnBckgr', value: '#77ABD8' },
'Background hover (CSS):', { itemId: 'btnBckgrHover', value: '#CC1C1C' },
'Background pressed (CSS):', { itemId: 'btnBckgrPressed', value: '#7D4FC6' }
]
},
items: [{
xtype: 'button',
itemId: 'btnTest',
text: 'test button',
enableToggle: true
}],
listeners: {
'afterrender': updateBackground
}
}).show();
});
这基本上可以工作,但是还有一些问题要问:
1)
每次调用updateBackground方法时都可以调用jquery的悬停功能吗?
根据jquery-doc(http://api.jquery.com/hover/),此函数将2个给定函数绑定(bind)到给定元素的mouse-enter和mouse-leave事件。
这是否意味着它每次我调用它都会绑定(bind)新功能,还是更新已绑定(bind)的功能,还是在绑定(bind)新功能之前自动处理已绑定(bind)的功能...
简而言之:在将新功能与$ .hover绑定(bind)之前,我是否必须处置任何东西?
2)
我将按下状态的样式设置为文档样式,这意味着如果经常调用updateBackground-function(每次文本字段之一在我的测试用例中触发模糊事件),文档头就会被污染。
有没有更好的方法可以实现相同的目标,还是可以在添加新样式之前删除已经设置的样式?
3)
如果由于按下样式中的!important标志,则如果按下按钮,则不会显示悬停状态的背景。我不能只删除该标志,因为没有它,按下状态的背景将无法正确显示...
有什么办法吗?
总的来说,我会接受所有关于如何以完全不同的方式解决此问题的建议。
谢谢,
k
编辑:
上面的代码仅是示例。实际上,除了按钮(面板,复选框,...)以外,我还需要能够更改其他ext控件的背景属性,但我认为我可以自己为其他控件采用按钮的有效解决方案。
请记住这一点,不要在按钮上指定太多答案。它应该尽可能通用。
最佳答案
使用一些更特定的css选择器,您可以利用Ext的pressedCls和overCls配置。 http://docs.sencha.com/ext-js/4-1/#!/api/Ext.button.Button-cfg-pressedCls http://docs.sencha.com/ext-js/4-1/source/Button2.html#Ext-button-Button-cfg-overCls
.x-btn.my-over {
background: blue;
}
/*Ext is not consistent */
.x-btn.x-btn-my-pressed {
background: red;
}
new Ext.button.Button({
overCls : 'my-over',
pressedCls : 'my-pressed',
//needs to be true to have the pressed cls show
enableToggle : true,
text : 'My button',
renderTo : Ext.getBody(),
})
编辑以获得更动态,更通用的解决方案
Ext.define('DynamicStyleState', {
alias : 'plugin.dynamicStyleState',
extend : Ext.AbstractPlugin,
/**
* @cfg
*/
elementProperty : 'el',
/**
* @property
*/
pressed : false,
init : function(component) {
this.component = component;
this.component.on('afterrender', this._onAfterrender, this);
},
/**
* @protected
*/
clearStyle : function() {
this.el.setStyle({
background : ''
});
},
/**
* @protected
* meant to be overriden
*/
getHoverStyle : function() {
return {
background : 'blue'
};
},
/**
* @protected
* meant to be overriden
*/
getPressedStyle : function() {
return {
background : 'red'
};
},
_onAfterrender : function() {
this.el = this.component[this.elementProperty];
this.el.hover(this._onElementMouseIn, this._onElementMouseOut, this);
this.el.on('click', this._onElementClick, this);
},
_onElementMouseIn : function() {
if(!this.pressed) {
this.el.setStyle(this.getHoverStyle());
}
},
_onElementMouseOut : function() {
if(!this.pressed) {
this.clearStyle();
}
},
_onElementClick : function(e) {
this.pressed = !this.pressed;
if(this.pressed) {
this.el.setStyle(this.getPressedStyle());
} else {
//mimic mouse in
if(e.within(this.el)) {
this.el.setStyle(this.getHoverStyle());
}
}
}
});
由于您想要的不仅仅是按钮,还可以在任何组件上使用。
这是一个示例用法:
var headerHoverColor = new Ext.form.field.Text({
fieldLabel : 'Header hover color',
value : 'orange',
renderTo : Ext.getBody()
});
var headerPressedColor = new Ext.form.field.Text({
fieldLabel : 'Header pressed color',
value : 'black',
renderTo : Ext.getBody()
})
new Ext.panel.Panel({
plugins : {
ptype : 'dynamicStyleState',
elementProperty : 'body'
},
header : {
plugins : {
ptype : 'dynamicStyleState',
getHoverStyle : function() {
return {
background : headerHoverColor.getValue()
}
},
getPressedStyle : function() {
return {
background : headerPressedColor.getValue()
}
}
}
},
height : 300,
width : 300,
renderTo : Ext.getBody(),
title : 'Panel'
});