Cómo cambiar el fondo del botón extjs sobrevolado y presionado dinámicamente
Frecuentes
Visto 20,708 veces
3
Hy allí,
Necesito la capacidad de cambiar el color de fondo para los diferentes estados (normal, flotante, presionado) de un botón dinámicamente.
Lo que se me ha ocurrido hasta ahora es lo siguiente: 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();
});
Esto funciona básicamente, pero me quedan algunas preguntas:
1)
¿Está bien llamar a la función de desplazamiento de jquery cada vez que se llama al método updateBackground?
De acuerdo con jquery-doc (http://api.jquery.com/hover/) esta función vincula las 2 funciones dadas a los eventos mouse-enter- & mouse-leave-events del elemento dado.
¿Significa esto que vincula nuevas funciones cada vez que lo llamo o actualiza las ya vinculadas o elimina las ya vinculadas automáticamente antes de vincular las nuevas...
En resumen: ¿tengo que desechar algo antes de vincular las nuevas funciones con $ .hover?
2)
Configuré el estilo para el estado presionado como estilo de documento, lo que significa que el encabezado del documento se contamina si se llama a menudo a la función de actualización de fondo (cada vez que uno de los campos de texto activa el evento de desenfoque en mi caso de prueba).
¿Hay alguna forma mejor de lograr el mismo objetivo o puedo eliminar los estilos ya establecidos antes de agregar otros nuevos?
3)
El fondo para el estado de desplazamiento no aparece si se presiona el botón debido a la bandera !importante en el estilo presionado. No puedo simplemente eliminar esta bandera porque el fondo del estado presionado no se mostraría correctamente sin ella... ¿Alguna solución?
En general, estaría abierto a cualquier sugerencia sobre cómo resolver este problema de una manera completamente diferente.
Gracias,
mik
Edit:
El código anterior es solo un ejemplo. En realidad, también necesito poder cambiar el atributo de fondo para otros controles externos además de los botones (paneles, casillas de verificación, ...), pero creo que puedo adoptar una solución funcional para los botones para esos otros controles.
Tenga esto en cuenta y no especifique demasiado la respuesta en los botones. Debe ser lo más genérico posible...
2 Respuestas
14
Usando algunos selectores css más específicos, puede aprovechar las configuraciones pressedCls y overCls de Ext. 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(),
})
Edite para una solución genérica más dinámica
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());
}
}
}
});
Dado que desea algo que funcione en algo más que un botón, esto debería funcionar en cualquier componente.
Aquí hay un ejemplo de uso:
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'
});
Respondido 28 ago 12, 01:08
1
Ok, acabo de encontrar una solución que debería cubrir todos los problemas descritos anteriormente:
Agrego ambos, el pressed
y hovered
estilo directamente al encabezado.
Para asegurarme de que el encabezado no se contamine, simplemente elimino los elementos de estilo dinámicamente con jQuery
La función de separación del encabezado antes de agregar otros nuevos.
Y el código para el cambio dinámico del fondo:
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');
};
¡Parece funcionar para mí, pero todavía estoy abierto a cualquier sugerencia/mejora a esto!
Gracias.
Respondido 27 ago 12, 20:08
No estoy realmente seguro de cómo esto es mejor que mi solución, supongo que para cada uno. Crear el css en javascript requiere mucho trabajo adicional y no aprovecha el almacenamiento en caché del navegador. Su solución utiliza identificadores codificados, lo que dificulta su mantenimiento. Su solución es realizar consultas de componentes para obtener referencias, lo cual es un trabajo adicional que no es necesario. Su solución es usar jQuery dentro de Ext, que es un no, no. Sus soluciones también salen de la Ext api provista para agregar clases css a los botones al presionar y pasar el mouse. - por favor
@pllee Como se dijo antes, necesito una solución que pueda cambiar el estilo DINÁMICAMENTE y no veo cómo podría lograrse esto con su solución porque usa clases css creadas y asignadas estáticamente. Agregue un comentario arriba y muéstreme cómo funcionaría dinámicamente su solución porque simplemente no la veo... Gracias. Suamikim
Lo siento, pensé en clases dinámicas de css en el botón como new Ext.Button({overCls: 'red-button'); new Button({overCls: 'yellow-button'});
hubiera sido suficiente. - por favor
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas javascript jquery css extjs extjs4 or haz tu propia pregunta.
Necesito poder cambiar el css dinámicamente durante el tiempo de ejecución para los controles creados dinámicamente (en realidad, no solo los botones como en el ejemplo anterior). - Suamikim
@suamikim su pregunta solicita específicamente ayuda con los estados de los botones. Si necesita más ayuda que los estados de los botones, actualice su pregunta o publique otra. - por favor
Ok, agregué una nota al final, pero lo más importante es que necesito poder cambiar el fondo dinámicamente. - Suamikim
Perfecto. La parte editada es exactamente lo que estaba buscando y parece ser mejor que mi solución, ya que solo usa herramientas estándar ext hasta donde puedo ver. Gracias - Suamikim