1. #11
    Ext User
    Join Date
    Mar 2010
    Posts
    15
    Vote Rating
    0
    acidtonic is on a distinguished road

      0  

    Default


    From what I'm finding, this.ownerCt.isVisible() returns true even when it really isnt.

    I'm confused because the ghostbar is a plugin to a panel which is inside a tab panel.

    When either the panel shades OR the current tab is changed on the tabpanel, the ghostbar still renders but realigns to (0,0) placing it in the upper left.

    I'm not sure why it realigns up there though. It's almost like this.ownerCt is returning the parent of the parent which would be the tab panel, which is visible and thus the toolbar gets drawn.

  2. #12
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,496
    Vote Rating
    44
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    The ownerCt Panel may be visible, but ITS ownerCt may be hidden. There will have to be a "recursive" parameter to Component.isVisible which goes all the way up the chain.

    I'll leave that as an exercise for you.

  3. #13
    Ext User
    Join Date
    Mar 2010
    Posts
    15
    Vote Rating
    0
    acidtonic is on a distinguished road

      0  

    Default


    In my case I *always* use the plugin inside a shadeable panel.

    My hack was to simply check twice and never any higher. Also added a hide for when it fails the test yet it's visible.

    The other thought was to also check the parent component for the "beforeCollapse" event, and if it exists, listen to it and hide() on invocation.

    My updated code is here for anyone else solving these problems.

    Code:
        checkMousePosition: function(e) {
            this.syncPosition();
            var o = 1, d = this.region.getDistanceBetween(e.getPoint());
            if (d > this.threshold + this.fullVisibilityZone) {
                this.hide();
            } else if ((d -= this.fullVisibilityZone) > 0) {
    
    //          Mouse is within range of this Toolbar, so show it if its not already visible
                if (!this.isVisible()) {
                    if (this.ownerCt.isVisible() && this.ownerCt.ownerCt.isVisible()) {
                        this.show();
                    }
                } else {
                    if (!this.ownerCt.isVisible() || !this.ownerCt.ownerCt.isVisible()) {
                        this.hide();
                    }
                }
                o = 1 - (d / this.threshold);
            }
            this.el.setStyle({
                opacity: o,
                //'z-index': this.ownerCt.el.zindex+3
                'z-index': 20
            });
        },

  4. #14
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,496
    Vote Rating
    44
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    How about an override of Component.isVisible?

  5. #15
    Ext User
    Join Date
    Mar 2010
    Posts
    15
    Vote Rating
    0
    acidtonic is on a distinguished road

      0  

    Default


    Quote Originally Posted by Animal View Post
    How about an override of Component.isVisible?
    That's what I instantly thought, but remembered how much help I got simply trying to extend my first component(zero), and decided I wouldn't undertake that one.

  6. #16
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,496
    Vote Rating
    44
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    You're going to have to do it sooner or later. It's not as if there isn't deep and complete documentation, and hundreds of examples.

  7. #17
    Ext User
    Join Date
    Mar 2010
    Posts
    15
    Vote Rating
    0
    acidtonic is on a distinguished road

      0  

    Default


    I solved this by adding a new function to the GhostBar superclass called "parentsVisible" which simply accepts a start object and traverses it back up until there is no parent. It checks each step for a non visible parent and short circuits as soon as one isn't.

    There is one caveat I should mention and that's when the passed object doesnt have a parent. That will return true and that's simply by design since the function doesnt care if the passed object is visible or not, only it's parents. And if it has none, then technically all the parent's are visible.

    Code:
        parentsVisible: function(start) {
            var current = start;
            //alert(start);
            while(current) {
                if (current.ownerCt) {
                    if (current.ownerCt.isVisible()) {
                        current = current.ownerCt;
                    } else {
                        return false;
                    }
                } else {
                    return true;
                }
            }
            return false;
        },
        checkMousePosition: function(e) {
            this.syncPosition();
            var o = 1, d = this.region.getDistanceBetween(e.getPoint());
            if (d > this.threshold + this.fullVisibilityZone) {
                this.hide();
            } else if ((d -= this.fullVisibilityZone) > 0) {
    //          Mouse is within range of this Toolbar, so show it if its not already visible
                if (!this.isVisible()) {
                    if (this.parentsVisible(this)) {
                        this.show();
                    }
                } else {
                    if (!this.parentsVisible(this)) {
                        this.hide();
                    }
                }
                o = 1 - (d / this.threshold);
            }
            this.el.setStyle({
                opacity: o,
                //'z-index': this.ownerCt.el.zindex+3
                'z-index': 20
            });
        },

  8. #18
    Ext User
    Join Date
    Mar 2010
    Posts
    15
    Vote Rating
    0
    acidtonic is on a distinguished road

      0  

    Default


    I also found that my new function didn't properly handle collapsed panels, so i added a quick check for that. Updated code below.

    Code:
    parentsVisible: function(start) {
            var current = start;
            //alert(start);
            while(current) {
                if (current.ownerCt) {
                    if (current.ownerCt.isVisible()) {
                        if (current.ownerCt.collapsed) { return false; }
                        current = current.ownerCt;
                    } else {
                        return false;
                    }
                } else {
                    return true;
                }
            }
            return false;
        },
        checkMousePosition: function(e) {
            this.syncPosition();
            var o = 1, d = this.region.getDistanceBetween(e.getPoint());
            if (d > this.threshold + this.fullVisibilityZone) {
                this.hide();
            } else if ((d -= this.fullVisibilityZone) > 0) {
    //          Mouse is within range of this Toolbar, so show it if its not already visible
                if (!this.isVisible()) {
                    if (this.parentsVisible(this)) {
                        this.show();
                    }
                } else {
                    if (!this.parentsVisible(this)) {
                        this.hide();
                    }
                }
                o = 1 - (d / this.threshold);
            }
            this.el.setStyle({
                opacity: o,
                //'z-index': this.ownerCt.el.zindex+3
                'z-index': 20
            });
        },

  9. #19
    Ext User
    Join Date
    Mar 2010
    Posts
    15
    Vote Rating
    0
    acidtonic is on a distinguished road

      0  

    Default


    Posted full version here since someone on IRC asked and said it wasn't obvious which code snippit to use.

    This one has my additional function for handling visibility.

    Code:
    Ext.override(Ext.lib.Region, {
        /**
         * Returns the shortest distance between this Region and another Region.
         * Either or both Regions may be Points.
         * @param {Region} r The other Region
         * @return {Number} The shortest distance in pixels between the two Regions.
         */
        getDistanceBetween: function(r) {
    
    //      We may need to mutate r, so make a copy.
            r = Ext.apply({}, r);
            
    //      Translate r to the left of this
            if (r.left > this.right) {
                var rWidth = r.right - r.left;
                r.left = this.left - (r.left - this.right) - rWidth;
                r.right = r.left + rWidth;
            }
    
    //      Translate r above this
            if (r.top > this.bottom) {
                var rHeight = r.bottom - r.top;
                r.top = this.top - (r.top - this.bottom) - rHeight;
                r.bottom = r.top + rHeight;
            }
    
    //      If r is directly above
            if (r.right > this.left) {
                return this.top - r.bottom;
            }
    
    //      If r is directly to the left
            if (r.bottom > this.top) {
                return this.left - r.right;
            }
    
    //      r is on a diagonal path
            return Math.round(Math.sqrt(Math.pow(this.top - r.bottom, 2) + Math.pow(this.left - r.right, 2)));
        }
    });
    
    /**
     * @class Ext.ux.GhostBar
     * @extends Ext.Toolbar
     * A Toolbar class which attaches as a plugin to any BoxComponent, and fades in at the configured
     * position whenever the mouse is brought within a configurable threshold. eg: <code><pre>
    new Ext.Panel({
        renderTo: document.body,
        title: 'Test',
        width: 600,
        height: 400,
        plugins: [ new Ext.ux.GhostBar([{ text: 'Click Me' }]) ]
    });
    </pre></code>
     */
    Ext.ux.GhostBar = Ext.extend(Ext.Toolbar, {
    
        listenerAdded: false,
    
        cache: [],
        
        /**
         * @cfg {Number} threshold The number of pixels around the toolbar position in which
         * opacity is 100%.
         */
        fullVisibilityZone: 50,
    
        /**
         * @cfg {Number} threshold The number of pixels around the full visibility zone in which
         * fading is performed.
         */
        threshold: 100,
    
        /**
         * @cfg {String} position The alignment of this Toolbar, <code><b>top</b></code>, or <code><b>bottom</b></code>.
         * Defaults to <code><b>bottom</b></code>.
         */
        /**
         * @cfg {Array} offsets A two element Array containing the [x, y] offset from the default position
         * in which to display the Toolbar.
         */
    
        initComponent: function() {
    
    //      Only use one mousemove listener. Check the cache of GhostBars for proximity on each firing
            if (!this.listenerAdded) {
                Ext.getDoc().on('mousemove', Ext.ux.GhostBar.prototype.onDocMouseMove, Ext.ux.GhostBar.prototype);
                this.listenerAdded = true;
            }
            this.renderTo = document.body;
            this.hideMode = 'visibility';
            Ext.ux.GhostBar.superclass.initComponent.apply(this, arguments);
        },
    
        onRender: function() {
            Ext.ux.GhostBar.superclass.onRender.apply(this, arguments);
            this.el.setStyle({
                position: 'absolute'
            });
            this.hide();
            this.cache.push(this);
        },
    
        init: function(c) {
            this.ownerCt = c;
            c.on({
                render: this.onClientRender,
                scope: this,
                single: true
            });
            c.onPosition = c.onPosition.createSequence(this.onClientPosition, this);
            c.onResize = c.onResize.createSequence(this.onClientResize, this);
        },
    
        onClientRender: function() {
            this.clientEl = this.ownerCt.getLayoutTarget ? this.ownerCt.getLayoutTarget() : this.ownerCt.el;
        },
    
        onClientResize: function() {
            this.setWidth(this.clientEl.getWidth(true));
            this.syncPosition();
        },
    
        onClientPosition: function() {
            this.syncPosition();
        },
    
        syncPosition: function() {
            var offsets = [this.clientEl.getBorderWidth('l'), 0];
            if (this.offsets) {
                offsets[0] += this.offsets[0];
                offsets[1] += this.offsets[1];
            }
            this.el.alignTo(this.clientEl, (this.position == 'top') ? 'tl-tl' : 'bl-bl', offsets);
            this.region = this.el.getRegion();
        },
    
        onDocMouseMove: function(e) {
            for (var i = 0; i < this.cache.length; i++) {
                if (this.cache[i].ownerCt.isVisible()) {
                    this.checkMousePosition.call(this.cache[i], e);
                }
            }
        },
    
        checkMousePosition: function(e) {
            this.syncPosition();
            var o = 1, d = this.region.getDistanceBetween(e.getPoint());
            if (d > this.threshold + this.fullVisibilityZone) {
                this.hide();
            } else if ((d -= this.fullVisibilityZone) > 0) {
    
    //          Mouse is within range of this Toolbar, so show it if its not already visible
                if (!this.isVisible()) {
                    this.show();
                }
                o = 1 - (d / this.threshold);
            }
            this.el.setStyle({
                opacity: o,
                'z-index': this.ownerCt.el.zindex+3
            });
        },
    
        onDestroy: function() {
    //      Uncache this Toolbar when we are destroyed
            this.cache.splice(this.cache.indexOf(this), 1);
            Ext.ux.GhostBar.superclass.onDestroy.apply(this, arguments);
        },
        parentsVisible: function(start) {
            var current = start;
            //alert(start);
            while(current) {
                if (current.ownerCt) {
                    if (current.ownerCt.isVisible()) {
                        if (current.ownerCt.collapsed) { return false; }
                        current = current.ownerCt;
                    } else {
                        return false;
                    }
                } else {
                    return true;
                }
            }
            return false;
        },
        checkMousePosition: function(e) {
            this.syncPosition();
            var o = 1, d = this.region.getDistanceBetween(e.getPoint());
            if (d > this.threshold + this.fullVisibilityZone) {
                this.hide();
            } else if ((d -= this.fullVisibilityZone) > 0) {
    //          Mouse is within range of this Toolbar, so show it if its not already visible
                if (!this.isVisible()) {
                    if (this.parentsVisible(this)) {
                        this.show();
                    }
                } else {
                    if (!this.parentsVisible(this)) {
                        this.hide();
                    }
                }
                o = 1 - (d / this.threshold);
            }
            this.el.setStyle({
                opacity: o,
                //'z-index': this.ownerCt.el.zindex+3
                'z-index': 20
            });
        },
    });

  10. #20
    Sencha User dias's Avatar
    Join Date
    Feb 2008
    Location
    Portugal
    Posts
    96
    Vote Rating
    0
    dias is on a distinguished road

      0  

    Default


    Hello, i'm using this plugin... it very good. But i have a problem... if the panel where i use this plugin have a scrollbar, the GhostBar is over the scrollbar... it's possible to solve this.

    Thanks in advance,
    Portugal
    Castelo Branco