You found a bug! We've classified it as a bug in our system. We encourage you to continue the discussion and to find an acceptable workaround while we work on a permanent fix.
  1. #1
    Ext User
    Join Date
    Jun 2010
    Posts
    9
    Vote Rating
    0
    Mphasize is on a distinguished road

      0  

    Default [FIXED-117] Animated Toolbars | Component.show(animation) does not work as expected

    [FIXED-117] Animated Toolbars | Component.show(animation) does not work as expected


    Hello,

    I just spent a lot of time trying to get this to work, so I thought I might share this. I expect that most of my problems are simply due to the library being a beta. Anyway.... a short summary of my findings is to be found a the bottom.

    What I'm trying to do: I want to have a nice semi-transparent toolbar on the top, which is able to fade in and out, or slide in and out whenever you tap the screen (say parent panel).

    As a side notice, the handler property does not seem to be supported in the config options of panels, so I set up a custom handler with panel.mon(ui.el, { tap: tapContent }) after creating the panel.

    So here's my setup....
    Code:
    Ext.Panel({
        id: 'toolbartxt',
        scroll:'vertical',
        html: 'Pick a button, any button.',
        fullscreen: true,            
        dockedItems: {
            xtype: 'toolbar',
            id : 'topBar',
            cls: 'visible',
            ui: 'dark',
            dock: 'top',
            overlay: true,
            items: buttonsGroup1.concat(buttonsGroup2).concat(buttonsGroup3)
        }
    });
    Using overlay makes it possible for the content to slide under the docked toolbar.

    Then I hacked the transparent toolbars in the css
    Code:
            .x-toolbar {             -webkit-opacity: 0.8;         }
    And now the trouble began....
    The event handler is supposed to toggle the toolbar based on it's visibility, but (probably) because of setting the toolbar to semi-transparent, the function Toolbar.isVisible() is broken.
    I fixed this by setting and checking for a custom class.

    Then I wanted to animate, but the .show() and .hide() functions don't support the Config-Objects for animations yet
    (I tried .hide({type: 'slide', direction: 'up'}), resulting in an error), so I had to setup custom animations in order to use the string identifier like .hide('slideUp'); ....

    When I tried the same thing with .show('slideDown'), I found that .show() is somehow ignoring the animation altogether. After venturing into ext-touch.js, the reason was apparently in the onShow, where there is a switch (this.isFloating) which determines if the animation should be run or not. I don't know if the switch is not working properly (maybe because of overlay:true?) or whatever the reason, but I could get the animation to work by changing to the following:

    Code:
         onShow : function(animation) {
            animation = animation || this.showAnimation;
            if (this.floating) {
                [...]
            }
            else {
                this.getVisibilityEl().show();
                /* new */
                if (animation) {
                    Ext.anims[animation].run(this.el, {
                        out: false
                    });
                    this.showAnimation = animation;
                }
                /* end of new */
            }
        }
    I am still working in a very simply example so I cannot yet say if my *fix* is not blowing up other parts.


    So, the summary:
    1) handler-property in config-object for Ext.Panel would be nice
    2) showAnimation-property, show(animation), hide(animation) with support for config-objects would be nice
    3) isVisible() should work, even if elements are semi-transparent
    4) show(animation) should work on docked toolbars with overlay-property enabled.


    Well, if I have missed something important to avoid all these issues, please enlighten me. Otherwise thanks for reading.

    Best!
    M

  2. #2
    Sencha User
    Join Date
    Mar 2007
    Location
    Haarlem, Netherlands
    Posts
    1,243
    Vote Rating
    9
    TommyMaintz will become famous soon enough TommyMaintz will become famous soon enough

      0  

    Default


    First of all I would like to say that this is one of the best bug reports I have ever seen. It was really informative and at the end I knew exactly what you were trying to do, and what the issues might be.

    While trying to implement the behavior you were trying to accomplish I ran into multiple bugs inside onShow and onHide related to animations. It was never really meant to hide and show components that are not floating using animations. Obviously this will all be fixed in the next release.

    Because I liked the concept of what you were trying to do I went ahead an created a temporary (and in some parts ugly) solution. It consists of three parts.

    The first thing we need to do is apply some overrides to Component. (Lets hope this doesnt break other parts of the library...)
    Code:
    Ext.override(Ext.Component, {
        // @private
        onShow : function(animation) {
            animation = animation || this.showAnimation;
    
            this.getVisibilityEl().show();
    
            if (animation) {
                this.el.setStyle('opacity', 0.01);
            }
                        
            if (this.floating) {
                this.el.appendTo(document.body);
                if (this.centered) {
                    this.setCentered(true, true);
                }
                else {
                    this.setPosition(this.x, this.y);
                }
                
                function preventDefault(e) {
                    e.preventDefault();
                };
                doc.on('click', preventDefault, this, {single: true});
    
                showConfig.after = function() {
                    (function() {
                        doc.un('click', preventDefault, this);
                    }).defer(50, this);
                };
                
                // Then we reset the size to the width and height given in the config
                // and if they were not given use the default css dimensions.
                // This will also relayout the item which is good since things might
                // change based on the styling we give to floating items
                delete this.lastSize;
                this.doComponentLayout(this.width, this.height);
    
                if (this.modal) {
                    if (this.ownerCt) {
                        this.ownerCt.el.mask();
                    }
                    else {
                        Ext.getBody().mask();
                    }
                }
                if (this.hideOnMaskTap) {
                    Ext.getDoc().on('touchstart', this.onFloatingTouchStart, this);
                }
            }
    
            if (animation) {
                var showConfig = {}, showAnim, doc = Ext.getDoc();
    
                if (Ext.isObject(animation) && !animation.run) {
                    showConfig = Ext.apply({}, animation || {});
                    showAnim = showConfig.type;
                }
                else if (Ext.isString(animation)) {
                    showAnim = animation;
                }
                else if (animation.run) {
                    animation.run(this.el, {
                        out: false
                    });
                    this.showAnimation = animation;
                    return;
                }
    
                showConfig.scope = this;
                showConfig.out = false;
                showConfig.autoClear = true;
    
                Ext.anims[showAnim].run(this.el, showConfig);
    
                this.showAnimation = showAnim;
            }
        },
        
        // @private
        onHide : function(animation) {
            animation = animation || this.showAnimation;
    
            if (this.hideOnMaskTap && this.floating) {
                Ext.getDoc().un('touchstart', this.onFloatingTouchStart, this);
            }
    
            if (this.floating && this.modal) {
                if (this.ownerCt) {
                    this.ownerCt.el.unmask();
                }
                else {
                    Ext.getBody().unmask();
                }
            }
    
            if (animation) {
                var hideConfig = {}, hideAnim;
    
                if (Ext.isObject(animation) && !animation.run) {
                    hideConfig = Ext.apply({}, animation || {});
                    hideAnim = hideConfig.type;
                }
                else if (Ext.isString(animation)) {
                    hideAnim = animation;
                }
                else if (animation.run) {
                    animation.run(this.el, {
                        out: false,
                        scope: this,
                        after: function() {
                            this.getVisibilityEl().hide();
                        }
                    });
                    return;
                }
    
                hideConfig.after = function() {
                    this.getVisibilityEl().hide();
                };
                hideConfig.scope = this;
                hideConfig.out = true;
                hideConfig.autoClear = true;
    
                Ext.anims[hideAnim].run(this.el, hideConfig);
            } else {
                this.getVisibilityEl().hide();
            }
        }
    });
    After that I created an extension to toolbar that implements our behavior. The code is not optimal especially dealing with componentLayouts of parents if you initially hide the bar is a nasty workaround for now.
    Code:
    Ext.ux.ToggleBar = Ext.extend(Ext.Toolbar, {
        cmpCls: 'x-togglebar',
        overlay: true,
    
        initComponent : function() {
            this.showAnim = new Ext.Anim({
                autoClear: false,
                to: {
                    opacity: 0.85
                }
            });
            
            this.hideAnim = new Ext.Anim({
                to: {
                    opacity: 0
                }
            });
            
            Ext.ux.ToggleBar.superclass.initComponent.call(this);
        },
        
        afterRender : function() {
            Ext.ux.ToggleBar.superclass.afterRender.call(this);
    
            if (this.ownerCt) {
                this.mon(this.ownerCt.getContentTarget(), {
                    tap: this.onOwnerTap,
                    scope: this
                });
            }
        },
        
        onOwnerTap : function() {
            if (this.hidden) {
                this.show(this.showAnim);
            }
            else {
                this.hide(this.hideAnim);
            }
        },
        
        onShow : function() {
            if (this.ownerCt) {
                this.getVisibilityEl().show();
                this.ownerCt.doComponentLayout();
            }
            Ext.ux.ToggleBar.superclass.onShow.apply(this, arguments);
        }
    });
    
    Ext.reg('togglebar', Ext.ux.ToggleBar);
    Last but not least we want to test our new extension out!
    Code:
    Ext.setup({
        onReady: function() {
            new Ext.Panel({
                fullscreen: true,
                html: 'Tap anywhere in this panel to toggle the toolbar',
                dockedItems: [{
                    xtype: 'togglebar',
                    dock: 'top',
                    hidden: true,
                    items: [{
                        text: 'Button'
                    }]
                }]
            });
        }
    });
    I like the concept and functionality and will consider putting this in as an actual component or configuration into the main library. Also in the next release we will make sure that onShow and onHide are better suited to do these types of things in general.

    Again I would like to say I really appreciate these well-written bug reports as they make our life a lot easier.

  3. #3
    Ext User
    Join Date
    Jun 2010
    Posts
    9
    Vote Rating
    0
    Mphasize is on a distinguished road

      0  

    Default


    Wow, thanks for the thoughts you put into this. I will try your solution as soon as I can and post some feedback.

Similar Threads

  1. Replies: 4
    Last Post: 15 Nov 2011, 8:30 AM
  2. Replies: 13
    Last Post: 9 Nov 2010, 6:08 AM
  3. Replies: 1
    Last Post: 18 Aug 2010, 7:57 PM
  4. [FIXED-117] TabPanel property tabPosition missing
    By feyyaz in forum Ext Designer: Bugs
    Replies: 1
    Last Post: 28 Apr 2010, 2:08 PM
  5. Replies: 6
    Last Post: 25 Aug 2009, 1:03 AM

Thread Participants: 1