簡體   English   中英

如何動態更改懸停和按下的extjs按鈕的背景

[英]How to change background of hovered and pressed extjs-button dynamically

那里,

我需要能夠動態地改變按鈕的不同狀態(正常,懸停,按下)的背景顏色。

到目前為止我想出的是以下內容: 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-method時都可以調用jquery的hover-function嗎?

根據jquery-doc( http://api.jquery.com/hover/ ),這個函數將給定的兩個函數綁定到給定元素的mouse-enter-和mouse-leave-events。

這是否意味着它每次調用它時綁定新函數或更新已綁定的函數,或者在綁定新函數之前自動處理已綁定的函數...

簡而言之:在使用$ .hover綁定新函數之前,我是否必須處置任何內容?

2)

我將按下狀態的樣式設置為文檔樣式,這意味着如果經常調用updateBackground函數,文檔頭會被污染(每次其中一個文本字段在我的測試用例中觸發blur-event)。

有沒有更好的方法來實現相同的目標或者我可以在添加新的樣式之前刪除已設置的樣式?

3)

如果由於壓縮樣式中的!important-flag按下按鈕,則不會出現懸停狀態的背景。 我不能只是刪除這個標志,因為如果沒有它,壓制狀態的背景將無法正確顯示...任何解決方案?

總的來說,我會對如何以完全不同的方式解決這個問題的每一個建議持開放態度。

謝謝,

MIK


編輯:

上面的代碼只是一個例子。 實際上我需要能夠更改其他分機控制的背景屬性而不是按鈕(面板,復選框,......)但我認為我可以自己采用按鈕的工作解決方案到其他控件。

請記住這一點,不要在按鈕上指定過多的答案。 它應該盡可能通用......

使用一些更具體的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/源極/ Button2.html#分機鍵式按鈕-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'
});

好的,我剛剛找到了一個應該涵蓋上述所有問題的解決方案:

我將兩個, pressedhovered樣式直接添加到標題中。

為了確保標題不會被污染,我只需要在添加新標題之前使用jQuery的detach-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);

    // 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');
};

似乎為我工作,但我仍然願意接受任何建議/改進!

謝謝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM