[FIXED] [#665] [4.3.0] Spotlight show and hide method callback isn't used

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1

    [FIXED] [#665] [4.3.0] Spotlight show and hide method callback isn't used

    Hi,

    The show and hide methods of Ext.ux.Spotlight are documented to have a callback (and scope).

    This worked nicely in 1.x

    Just realized in 2.x and 3.x (Ext JS 4.2.2 and Ext JS 5.1) while documented, and part of the function definition, the callback related code has gone...!

    Normally I think as a workaround I could just override the method and call the callback after the show and hide methods have run. But because of animation (which is true by default and good to have) it needs to be wired in correctly.

    Using show as an example:

    1.x code:

        show : function (el, callback, scope) {
            if (this.animated) {
                this.show.defer(50, this, [el, callback, scope]);
    
                return;
            }
            
            this.el = Ext.net.getEl(el);
            
            if (!this.right) {
                this.createElements();
            }
            
            if (!this.active) {
                this.all.setDisplayed("");
                this.applyBounds(true, false);
                this.active = true;
                Ext.EventManager.onWindowResize(this.syncSize, this);
                this.applyBounds(false, this.animate, false, callback, scope);
            } else {
                this.applyBounds(false, false, false, callback, scope); // all these booleans look hideous
            }
        },
    3.x code:

        show: function(el, callback, scope) {
            var me = this;
            
            //get the target element
            me.el = Ext.get(el);
    
            //create the elements if they don't already exist
            if (!me.right) {
                me.createElements();
            }
    
            if (!me.active) {
                //if the spotlight is not active, show it
                me.all.setDisplayed('');
                me.active = true;
                Ext.on('resize', me.syncSize, me);
                me.applyBounds(me.animate, false);
            } else {
                //if the spotlight is currently active, just move it
                me.applyBounds(false, false);
            }
        },
    Only solution I can think at the moment is to take the 1.x code and apply that. Also, applyBounds in Ext JS 5.1 doesn't have callback/scope arguments either, and it looks like that code is missing. So I wonder if this was accidentally taken out (seems odd)?

    Anyway, I tried to override Ext.ux.Spotlight to add it back in, and this is what I have so far, incorporated into a working example adapted from the Examples Explorer (further notes below)

    <%@ Page Language="C#" %>
     
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
     
    <!DOCTYPE html>
     
    <html>
    <head runat="server">
        <title>Spotlight - with fix</title>    
     
        <ext:ResourcePlaceHolder Mode="ScriptFiles" />
        
        <script>
            /*
             * Fixes to support callback/scope in show/hide methods
             * Unfortunately requires writing a lot more code than ideal.
             */
            Ext.ux.Spotlight.override({
                /**
                 * Show the spotlight
                 */
                show: function (el, callback, scope) {
                    var me = this;
     
                    //get the target element
                    me.el = Ext.get(el);
     
                    //create the elements if they don't already exist
                    if (!me.right) {
                        me.createElements();
                    }
     
                    if (!me.active) {
                        //if the spotlight is not active, show it
                        me.all.setDisplayed('');
                        me.active = true;
                        Ext.on('resize', me.syncSize, me);
                        me.applyBounds(me.animate, false, callback, scope); // FIX: added callback/scope
                    } else {
                        //if the spotlight is currently active, just move it
                        me.applyBounds(false, false, callback, scope); // FIX: added callback/scope
                    }
                },
     
                /**
                 * Hide the spotlight
                 */
                hide: function (callback, scope) {
                    var me = this;
     
                    Ext.un('resize', me.syncSize, me);
     
                    me.applyBounds(me.animate, true, callback, scope); // FIX: added callback/scope
                },
     
                /**
                 * Resizes the spotlight depending on the arguments
                 * @param {Boolean} animate True to animate the changing of the bounds
                 * @param {Boolean} reverse True to reverse the animation
                 */
                applyBounds: function (animate, reverse, callback, scope) {
                    var me = this,
                        box = me.el.getBox(),
                        //get the current view width and height
                        viewWidth = Ext.Element.getViewportWidth(),
                        viewHeight = Ext.Element.getViewportHeight(),
                        i = 0,
                        config = false,
                        from, to, clone;
     
                    //where the element should start (if animation)
                    from = {
                        right: {
                            x: box.right,
                            y: viewHeight,
                            width: (viewWidth - box.right),
                            height: 0
                        },
                        left: {
                            x: 0,
                            y: 0,
                            width: box.x,
                            height: 0
                        },
                        top: {
                            x: viewWidth,
                            y: 0,
                            width: 0,
                            height: box.y
                        },
                        bottom: {
                            x: 0,
                            y: (box.y + box.height),
                            width: 0,
                            height: (viewHeight - (box.y + box.height)) + 'px'
                        }
                    };
     
                    //where the element needs to finish
                    to = {
                        right: {
                            x: box.right,
                            y: box.y,
                            width: (viewWidth - box.right) + 'px',
                            height: (viewHeight - box.y) + 'px'
                        },
                        left: {
                            x: 0,
                            y: 0,
                            width: box.x + 'px',
                            height: (box.y + box.height) + 'px'
                        },
                        top: {
                            x: box.x,
                            y: 0,
                            width: (viewWidth - box.x) + 'px',
                            height: box.y + 'px'
                        },
                        bottom: {
                            x: 0,
                            y: (box.y + box.height),
                            width: (box.x + box.width) + 'px',
                            height: (viewHeight - (box.y + box.height)) + 'px'
                        }
                    };
     
                    //reverse the objects
                    if (reverse) {
                        clone = Ext.clone(from);
                        from = to;
                        to = clone;
                    }
     
                    if (animate) {
                        Ext.Array.forEach(['right', 'left', 'top', 'bottom'], function (side) {
                            me[side].setBox(from[side]);
     
                            me[side].animate({
                                duration: me.duration,
                                easing: me.easing,
                                to: to[side],
     
                                /* FIX for missing callback support */
                                listeners: {
                                    afteranimate: {
                                        fn: callback || Ext.emptyFn,
                                        scope: scope
                                    }
                                }
                            });
                        },
                        this);
                    } else {
                        Ext.Array.forEach(['right', 'left', 'top', 'bottom'], function (side) {
                            me[side].setBox(Ext.apply(from[side], to[side]));
                            me[side].repaint();
     
                            /* FIX for missing callback support */
                            if (callback) {
                                callback.apply(scope); // not sure what arguments to pass here
                            }
                        },
                        this);
                    }
                }
            });
        </script>
     
        <script>
            var updateSpot = function (cmp) {
                App.Spot.show(cmp.el);
                updateButtons(cmp);
            };
     
            var hideSpot = function () {
                if (App.Spot.active) {
                    App.Spot.hide();
                }
     
                updateButtons();
            };
     
            var getButton = function (panel) {
                return panel.dockedItems.last().items.first();
            };
     
            var updateButtons = function (cmp) {
                cmp = cmp || {};
                getButton(App.Panel1).setDisabled(cmp.id != App.Panel1.id);
                getButton(App.Panel2).setDisabled(cmp.id != App.Panel2.id);
                getButton(App.Panel3).setDisabled(cmp.id != App.Panel3.id);
            };
        </script>
    </head>
    <body>
        <form runat="server">
            <ext:ResourceManager ID="ResourceManager1" runat="server">
                <Listeners>
                    <DocumentReady Handler="updateButtons();" />
                </Listeners>
            </ext:ResourceManager>
            
            <h1>Spotlight</h1>
     
            <p>This control allows you to restrict input to a particular element by masking all other page content.</p>
            
            <ext:Spotlight ID="Spot" runat="server" Easing="EaseOut" Duration="300" />
            
            <ext:Button runat="server" Text="Start">
                <Listeners>
                    <Click Handler="updateSpot(App.Panel1);" />
                </Listeners>
            </ext:Button>
            
            <ext:Panel runat="server" Border="false" Layout="TableLayout" ShrinkWrap="Width">
                <LayoutConfig>
                    <ext:TableLayoutConfig Columns="3" />
                </LayoutConfig>
                <Items>
                    <ext:Panel ID="Panel1" runat="server" 
                        Frame="true"
                        Title="Demo Panel"
                        Width="200"
                        Height="150"
                        Html="Some panel content goes here!" 
                        PaddingSummary="10px 15px">
                        <Buttons>
                            <ext:Button ID="Button1" runat="server" Text="Next Panel">
                                <Listeners>
                                    <Click Handler="updateSpot(App.Panel2);" />
                                </Listeners>
                            </ext:Button>
                        </Buttons>
                    </ext:Panel>
                    <ext:Panel ID="Panel2" runat="server" 
                        Frame="true"
                        Title="Demo Panel"
                        Width="200"
                        Height="150"
                        Html="Some panel content goes here!" 
                        PaddingSummary="10px 15px">
                        <Buttons>
                            <ext:Button ID="Button2" runat="server" Text="Next Panel">
                                <Listeners>
                                    <Click Handler="updateSpot(App.Panel3);" />
                                </Listeners>
                            </ext:Button>
                        </Buttons>
                    </ext:Panel>
                    <ext:Panel ID="Panel3" runat="server" 
                        Frame="true"
                        Title="Demo Panel"
                        Width="200"
                        Height="150"
                        Html="Some panel content goes here!" 
                        PaddingSummary="10px 15px">
                        <Buttons>
                            <ext:Button ID="Button3" runat="server" Text="Done">
                                <Listeners>
                                    <Click Handler="hideSpot();" />
                                </Listeners>
                            </ext:Button>
                        </Buttons>
                    </ext:Panel>
                </Items>
            </ext:Panel>        
        </form>
    </body>
    </html>
    I have tested the animated version and it seems to work.

    Looks for comments that include the word FIX to see where I put my actual changes.

    Initially I noticed the animation isn't the same as 1.x. For example, compare the Spotlight animation on the Examples Explorer for 1.x and 3.x. In 1.x the four sides animate in one after the other. This does not happen in the latest version. Turns out the duration in 5.x (maybe since 4.x) of Ext JS has changed to milliseconds. So instead of 0.3 in the duration I changed it to 300 (maybe it is worth updating the Examples Explorer accordingly)?

    Note, in the updateSpot method, I ended up passing cmp.el into the show method, instead of just cmp. This might be a subtle change between Ext JS 5.0 and 5.1; not sure...

    Remaining questions/issues:
    1) Is this the best fix? Is there a better way to do this without copying so much original code to inject the fixes?
    2) Can this, or a similar (better!) fix be incorporated into Ext.NET 3.x?
    3) If incorporated into Ext.NET and/or improved, at that time, you or I can report it to Sencha perhaps?
    Last edited by fabricio.murta; Jun 08, 2017 at 12:42 PM.

Similar Threads

  1. Show/Hide fieldset
    By JosefTrbusek in forum 2.x Help
    Replies: 2
    Last Post: Aug 03, 2012, 7:04 AM
  2. Replies: 3
    Last Post: Mar 19, 2012, 12:35 PM
  3. Replies: 0
    Last Post: Mar 03, 2011, 1:08 PM
  4. MessageBox does't show till after method
    By jarremw in forum 1.x Help
    Replies: 3
    Last Post: Jun 23, 2009, 4:08 AM

Posting Permissions