javascript 如何动态更改悬停和按下的 extjs 按钮的背景
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12106952/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to change background of hovered and pressed extjs-button dynamically
提问by suamikim
Hy there,
你好,
i need the ability to change the background-color for the different states (normal, hover, pressed) of a button dynamically.
我需要能够动态更改按钮不同状态(正常、悬停、按下)的背景颜色。
What i've came up with so far is the following: http://jsfiddle.net/suamikim/c3eHh/
到目前为止我想出的是以下内容: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();
});
This works basically but there are some questions left to me:
这基本上有效,但还有一些问题留给我:
1)
1)
Is it ok to call the hover-function of jquery everytime the updateBackground-method is called?
According to the jquery-doc (http://api.jquery.com/hover/) this functions binds the 2 given functions to the mouse-enter- & mouse-leave-events of the given element.
Does this mean that it binds new functions everytime i call it or does it update the already bound ones or does it dispose the already bound ones automatically before binding the new ones...
In short: do i have to dispose anything before binding the new functions with $.hover?
每次调用 updateBackground-method 时都可以调用 jquery 的悬停函数吗?
根据 jquery-doc ( http://api.jquery.com/hover/),此函数将 2 个给定函数绑定到给定元素的鼠标输入和鼠标离开事件。
这是否意味着它每次我调用它时都会绑定新函数,或者它是否更新已经绑定的函数,或者它是否在绑定新函数之前自动处理已经绑定的函数......
简而言之:我是否必须在绑定新函数之前处理任何内容?使用 $.hover 函数?
2)
2)
I set the style for the pressed state as document-style which means that the document-header gets polluted if the updateBackground-function is called often (everytime one of the text-fields fires the blur-event in my test-case).
我将按下状态的样式设置为文档样式,这意味着如果经常调用 updateBackground 函数(每次文本字段之一在我的测试用例中触发模糊事件),文档标题就会被污染。
Is there any better way to achieve the same goal or can i remove the already set styles before adding new ones?
有没有更好的方法来实现相同的目标,或者我可以在添加新样式之前删除已经设置的样式吗?
3)
3)
The background for hover-state doesn't appear if the button is pressed because of the !important-flag in the pressed-style. I can't just remove this flag because the background of the pressed-state wouldn't show correctely without it...
Any solutions?
由于按下样式中的 !important-flag,如果按下按钮,则不会出现悬停状态的背景。我不能只是删除这个标志,因为没有它按下状态的背景不会正确显示......有任何解决方案吗?
In general i'd be open for every suggestion on how to solve this problem in a completely different way.
一般来说,我愿意接受关于如何以完全不同的方式解决这个问题的每一个建议。
Thanks,
谢谢,
mik
米克
Edit:
编辑:
The code above is just an example. Actually i need to be able to change the background-attribute for other ext-controls than buttons too (panels, checkboxes, ...) but i think that i can adopt a working solution for buttons to those other controls myself.
上面的代码只是一个例子。实际上,我也需要能够更改除按钮之外的其他 ext 控件的背景属性(面板、复选框等),但我认为我可以自己采用适用于其他控件的按钮的解决方案。
Please keep this in mind and don't specify the answer too much on buttons. It should be as generic as possible...
请记住这一点,不要在按钮上过多地指定答案。它应该尽可能通用...
回答by pllee
Using some more specific css selectors you can take advantage of Ext's pressedCls and overCls configs. http://docs.sencha.com/ext-js/4-1/#!/api/Ext.button.Button-cfg-pressedClshttp://docs.sencha.com/ext-js/4-1/source/Button2.html#Ext-button-Button-cfg-overCls
使用一些更具体的 css 选择器,您可以利用 Ext 的 pressCls 和 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(),
})
Edit for a more dynamic, generic solution
编辑以获得更动态的通用解决方案
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());
}
}
}
});
Since you want something that works on more than just button this should work on any component.
由于您想要的不仅仅是按钮,因此它应该适用于任何组件。
Here is an example usage:
这是一个示例用法:
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'
});
回答by suamikim
Ok, i just found a solution which should cover all the problems described above:
好的,我刚刚找到了一个解决方案,它应该涵盖上述所有问题:
I add both, the pressed
and hovered
style directly to the header.
我将pressed
和hovered
样式都直接添加到标题中。
To make sure that the header won't be polluted i just remove the style-elements dynamically with jQuery
's detach-function from the header before appending new ones.
为了确保标题不会被污染,我只是jQuery
在添加新元素之前使用的 detach-function 从标题中动态删除样式元素。
And the code for the dynamic changing of the background:
以及动态改变背景的代码:
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);
// Set the background for hovered and pressed button as document style
// Remove style-element if it already exists to not pollute the document-head
$('head style:contains("' + btn.id + ':hover")').detach();
$('<style type="text/css"> #' + btn.id + ':hover { background: ' + bckgrHover + ' !important } </style>').appendTo('head');
$('head style:contains("' + btn.id + '.x-btn-pressed")').detach();
$('<style type="text/css"> .x-body #' + btn.id + '.x-btn-pressed { background: ' + bckgrPressed + ' !important } </style>').appendTo('head');
};
Seems to work for me but I'm still open for any suggestions/improvements to this!
似乎对我有用,但我仍然愿意对此提出任何建议/改进!
Thanks.
谢谢。