1. #1
    Sencha Premium Member
    Join Date
    Dec 2011
    Location
    London, UK
    Posts
    260
    Vote Rating
    8
    bseddon will become famous soon enough

      0  

    Default Floating window issue in various beta versions

    Floating window issue in various beta versions


    What issues should we report wrt beta versions? We are encountering a number of errors but, of course, errors are to be expected in beta versions. For example, we are seeing a number of errors that vary over the versions.

    Here are screenshots of an example. We provide user notifications using an animated window.

    This is how it should appear and does in 663 and earlier
    663.png


    How it appears in 778-803 (inclusive). In these versions the layout engine 'lost' the location of the source of the animation as in these versions the animation starts from the center of the <body> (our chosen root element).
    778.png


    How it appears in 825 and 836. As you can see, at the moment the window does not display a header.
    825.png

    We see more serious issues (to us) but are they worth reporting?

    Bill Seddon

  2. #2
    Sencha - Support Team slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    6,052
    Vote Rating
    215
    slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of

      0  

    Default


    Definitely report any issues you're seeing. When in doubt - report. We'll take a duplicate report over not having a bug reported any day.

    Can you share a test case for the issue / issues you're seeing and I'll test on my side as well and push up a bug as necessary?

  3. #3
    Sencha Premium Member
    Join Date
    Dec 2011
    Location
    London, UK
    Posts
    260
    Vote Rating
    8
    bseddon will become famous soon enough

      0  

    Default


    Here's an example. Try with any 4.2.1 version. Different versions exhibit different issue. The current nightly build (846) reverts to the behavior of 778.

    Code:
    Ext.onReady(function()
    {
        Ext.Loader.setConfig({
            enabled: true,
            scriptChainDelay: true
        });
    
        Ext.define('Ext.window.Notification', {
            extend: 'Ext.window.Window',
            alias: 'widget.uxNotification',
    
            title: 'Notification',
    
            cls: 'ux-notification-window',
            autoDestroy: true,
            autoHeight: true,
            plain: false,
            draggable: false,
            shadow: false,
            focus: Ext.emptyFn,
    
            // For alignment and to store array of rendered notifications. Defaults to document if not set.
            manager: null,
    
            useXAxis: false,
    
            // Options: br, bl, tr, tl
            corner: 'br',
    
            // Pixels between each notification
            spacing: 6,
    
            // Pixels from the managers borders to start the first notification
            paddingX: 30,
            paddingY: 10,
    
            slideInAnimation: 'easeIn',
            slideDownAnimation: 'bounceOut',
            autoDestroyDelay: 7000,
            slideInDelay: 1500,
            slideDownDelay: 1000,
            fadeDelay: 500,
            stickOnClick: true,
            stickWhileHover: true,
    
            // Private. Do not override!
            underDestruction: false,
            readyToDestroy: false,
            // Caching position coordinate to avoid windows overlapping when fading in simultaneously
            xPos: 0,
            yPos: 0,
    
            statics: {
                defaultManager: {
                    notifications: [],
                    el: null
                }
            },
    
            initComponent: function() {
                var me = this;
    
                me.callParent(arguments);
    
                switch (me.corner) {
                    case 'br':
                        me.paddingFactorX = -1;
                        me.paddingFactorY = -1;
                        me.siblingAlignment = "br-br";
                        if (me.useXAxis) {
                            me.managerAlignment = "bl-br";
                        } else {
                            me.managerAlignment = "tr-br";
                        }
                        break;
                    case 'bl':
                        me.paddingFactorX = 1;
                        me.paddingFactorY = -1;
                        me.siblingAlignment = "bl-bl";
                        if (me.useXAxis) {
                            me.managerAlignment = "br-bl";
                        } else {
                            me.managerAlignment = "tl-bl";
                        }
                        break;
                    case 'tr':
                        me.paddingFactorX = -1;
                        me.paddingFactorY = 1;
                        me.siblingAlignment = "tr-tr";
                        if (me.useXAxis) {
                            me.managerAlignment = "tl-tr";
                        } else {
                            me.managerAlignment = "br-tr";
                        }
                        break;
                    case 'tl':
                        me.paddingFactorX = 1;
                        me.paddingFactorY = 1;
                        me.siblingAlignment = "tl-tl";
                        if (me.useXAxis) {
                            me.managerAlignment = "tr-tl";
                        } else {
                            me.managerAlignment = "bl-tl";
                        }
                        break;
                }
    
                if (typeof me.manager == 'string') {
                    me.manager = Ext.getCmp(me.manager);
                }
    
                // If no manager is provided or found, then the static object is used and the el property pointed to the body document.
                if (!me.manager) {
                    me.manager = me.statics().defaultManager;
    
                    if (!me.manager.el) {
                        me.manager.el = Ext.getBody();
                    }
                }
                
                if (typeof me.manager.notifications == 'undefined') {
                    me.manager.notifications = [];
                }
    
            },
    
            onRender: function() {
                var me = this;
    
                    me.callParent(arguments);
    
                if (me.stickOnClick) {
                    if (me.body && me.body.dom) {
                        Ext.fly(me.body.dom).on('click', me.cancelAutoDestroy, me);
                    }
                }
    
                if (me.autoDestroy) {
                    me.task = new Ext.util.DelayedTask(me.doAutoDestroy, me);
                    me.task.delay(me.autoDestroyDelay);
                }
    
                me.el.hover(
                    function () {
                        me.mouseIsOver = true;
                    },
                    function () {
                        me.mouseIsOver = false;
                    },
                    me
                );
    
            },
    
            getXposAlignedToManager: function () {
                var me = this;
    
                var xPos = 0;
    
                if (me.corner == 'br' || me.corner == 'tr') {
                    xPos += me.manager.el.getRight();
                    xPos -= (me.el.getWidth() + me.paddingX);
                } else {
                    xPos += me.manager.el.getLeft();
                    xPos += me.paddingX;
                }
    
                return xPos;
            },
    
            getYposAlignedToManager: function () {
                var me = this;
    
                var yPos = 0;
    
                if (me.corner == 'br' || me.corner == 'bl') {
                    yPos += me.manager.el.getBottom();
                    yPos -= (me.el.getHeight() + me.paddingY);
                } else {
                    yPos += me.manager.el.getTop();
                    yPos += me.paddingY;
                }
    
                return yPos;
            },
    
            getXposAlignedToSibling: function (sibling) {
                var me = this;
    
                if (me.useXAxis) {
                    if (me.corner == 'tl' || me.corner == 'bl') {
                        // Using sibling's width when adding
                        return (sibling.xPos + sibling.el.getWidth() + sibling.spacing);
                    } else {
                        // Using own width when subtracting
                        return (sibling.xPos - me.el.getWidth() - me.spacing);
                    }
                } else {
                    return me.el.getLeft();
                }
    
            },
    
            getYposAlignedToSibling: function (sibling) {
                var me = this;
    
                if (me.useXAxis) {
                    return me.el.getTop();
                } else {
                    if (me.corner == 'tr' || me.corner == 'tl') {
                        // Using sibling's width when adding
                        return (sibling.yPos + sibling.el.getHeight() + sibling.spacing);                
                    } else {
                        // Using own width when subtracting
                        return (sibling.yPos - me.el.getHeight() - sibling.spacing);
                    }
                }
            },
    
            beforeShow: function () {
                var me = this;
    
                if (me.manager.notifications.length) {
                    me.el.alignTo(me.manager.notifications[me.manager.notifications.length - 1].el, me.siblingAlignment, [0, 0]);
                    me.xPos = me.getXposAlignedToSibling(me.manager.notifications[me.manager.notifications.length - 1]);
                    me.yPos = me.getYposAlignedToSibling(me.manager.notifications[me.manager.notifications.length - 1]);
                } else {
                    me.el.alignTo(me.manager.el, me.managerAlignment, [(me.paddingX * me.paddingFactorX), (me.paddingY * me.paddingFactorY)]);
                    me.xPos = me.getXposAlignedToManager();
                    me.yPos = me.getYposAlignedToManager();
                }
    
                Ext.Array.include(me.manager.notifications, me);
    
                me.el.animate({
                    to: {
                        x: me.xPos,
                        y: me.yPos
                    },
                    easing: me.slideInAnimation,
                    duration: me.slideInDelay,
                    dynamic: true
                });
    
            },
    
            slideDown: function () {
                var me = this;
    
                var index = Ext.Array.indexOf(me.manager.notifications, me)
    
                // Not animating the element if it already started to destroy itself
                if (!me.underDestruction && me.el) {
    
                    if (index) {
                        me.xPos = me.getXposAlignedToSibling(me.manager.notifications[index - 1]);
                        me.yPos = me.getYposAlignedToSibling(me.manager.notifications[index - 1]);
                    } else {
                        me.xPos = me.getXposAlignedToManager();
                        me.yPos = me.getYposAlignedToManager();
                    }
    
                    me.el.animate({
                        to: {
                            x: me.xPos,
                            y: me.yPos
                        },
                        easing: me.slideDownAnimation,
                        duration: me.slideDownDelay,
                        dynamic: true
                    });
                }
            },
    
            cancelAutoDestroy: function() {
                var me = this;
    
                me.addClass('notification-fixed');
                if (me.autoDestroy) {
                    me.task.cancel();
                    me.autoDestroy = false;
                }
            },
    
            doAutoDestroy: function () {
                var me = this;
    
                me.el.hover(
                    function () {
                    },
                    function () {
                        me.destroy();
                    },
                    me
                );
                
                if (!(me.stickWhileHover && me.mouseIsOver)) {
                    // Destroy immediately
                    me.destroy();
                }
            },
    
            listeners: {
                'beforehide': function (me, eOpts) {
                    if (!me.underDestruction) {
                        // Force window to animate and destroy, instead of hiding
                        me.destroy();
                        return false;
                    }
                }
            },
    
            destroy: function () {
                var me = this;
    
                // Avoids starting the last animation on an element already underway with its destruction
                if (!me.underDestruction) {
    
                    me.underDestruction = true;
    
                    me.cancelAutoDestroy();
                    me.stopAnimation();
    
                    me.el.animate({
                        to: {
                            opacity: 0
                        },
                        easing: 'easeIn',
                        duration: me.fadeDelay,
                        dynamic: true,
                        listeners: {
                            afteranimate: function () {
    
                                var index = Ext.Array.indexOf(me.manager.notifications, me);
                                if (index != -1) {
                                    Ext.Array.erase(me.manager.notifications, index, 1);
    
                                    // Slide "down" all notifications "above" the destroyed one
                                    for (;index < me.manager.notifications.length; index++) {
                                        me.manager.notifications[index].slideDown();
                                    }
                                }
                                me.readyToDestroy = true;
                                me.destroy();
                            }
                        }
                    });
                }
    
                // After animation is complete the component may be destroyed
                if (me.readyToDestroy) {
                    this.callParent(arguments);
                }
            }
    
        });
    
        Ext.define('MyApp.controller.MyController', {
            extend: 'Ext.app.Controller',
    
            refs: [
                {
                    ref: 'MyViewport',
                    selector: '#myviewport',
                    xtype: 'Ext.container.Viewport'
                }
            ],
    
            onNotifyButtonClick: function(button, e, eOpts) {
                var width = this.getMyViewport().getWidth() - 20;
                width = Math.min(400, width);
                Ext.create('Ext.window.Notification', {
                    corner: 'br',
                    width: width,
                    manager: 'validation',
                    cls: 'ux-notification-warning',
                    iconCls: 'ux-notification-icon-warning',
                    html: "<div style='margin: 4px;'>Test message</div>",
                    title: "My notification",
                    stickWhileHover: true,
                    slideDownDelay: 500,
                    slideInAnimation: 'bounceOut',
                    slideDownAnimation: 'easeIn',
                    autoDestroyDelay: 20000,
                    paddingX: 10
                }).show();
    
            },
    
            init: function(application) {
                this.control({
                    "#notify": {
                        click: this.onNotifyButtonClick
                    }
                });
            }
    
        });
    
        Ext.define('MyApp.view.MyViewport', {
            extend: 'Ext.container.Viewport',
    
            id: 'myviewport',
            layout: {
                type: 'border'
            },
    
            initComponent: function() {
                var me = this;
    
                Ext.applyIf(me, {
                    items: [
                        {
                            xtype: 'panel',
                            region: 'center',
                            layout: {
                                type: 'fit'
                            },
                            title: 'My Panel',
                            dockedItems: [
                                {
                                    xtype: 'toolbar',
                                    dock: 'bottom',
                                    items: [
                                        {
                                            xtype: 'button',
                                            id: 'notify',
                                            text: 'Notify'
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                });
    
                me.callParent(arguments);
            }
    
        });
    
        Ext.define('MyApp.view.Viewport', {
            extend: 'MyApp.view.MyViewport',
            renderTo: Ext.getBody()
        });
    
        Ext.application({
            views: [
                'MyViewport'
            ],
            autoCreateViewport: true,
            controllers: [
                'MyController'
            ],
            name: 'MyApp'
        });
    
    });

Thread Participants: 1

Tags for this Thread