1. #1
    Sencha - Community Support Team mankz's Avatar
    Join Date
    Nov 2007
    Location
    Stockholm, Sweden
    Posts
    2,743
    Answers
    33
    Vote Rating
    104
    mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all

      0  

    Default Unanswered: [Ext Core] Ext.ux.FingerMenu

    Unanswered: [Ext Core] Ext.ux.FingerMenu


    New menu UX for Ext Core. Not sure what the usability department will say on this one... .

    • Tested in FF3, IE6-8, Chrome 2, Opera 10, Safari 4
    • CSS is optimized for 32x32 icons. See example or source code documentation for usage.
    • MIT License
    • Live Example


    Version history
    • 2009-07-02 v1.1 Code cleaning and refactoring. setSelectedIndex added






    Suggestions/bugs/feedback welcome!

    Example usage:

    Code:
    Ext.onReady(function(){
               var menu = new Ext.ux.FingerMenu({
                    cls : 'menuExample',
                    selectedIndex : 0,
                    items : [
                        {
                            text : 'Lightbox',
                            iconCls : 'icon-lightbox'
                        }, {
                            text : 'Carousel',
                            iconCls : 'icon-carousel'
                        }, {
                            text : 'JSONP Flickr',
                            iconCls : 'icon-flickr'
                        }, {
                            text : 'Tabs',
                            iconCls : 'icon-tab'
                        }
                    ]
               });
               
               menu.on('change', function(obj, index) {
                    switch(index) {
                        case 0:
                            // Do your thing here...
                        break;
                        
                        case 1:
                            // Do your thing here...
                        break;
               
                        case 2:
                           // Do your thing here...
                        break;
                        
                        case 3:
                           // Do your thing here...
                        break;
                    }
               });
    });

    Source:
    Code:
    /*
    The MIT License
    
    Copyright (c) 2009 Mats Bryntse
    
    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:
    
    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
    */
    
    /**
     * Ext.ux.FingerMenu
     *
     * @author    Mats Bryntse 
     * @version   1.1
     * 
     * This menu fires a 'change' event when an item is activated
     * 
     */
     
    Ext.ns('Ext.ux');
    
    Ext.ux.FingerMenu = Ext.extend(Ext.util.Observable, {
        /*
         * @cfg (array) array of menu config objects 
         *              The menu is built for 32x32 icons, if you need different size icons
         *              you'll have to modify the CSS.
         * 
         *              Example object : 
         *              {
         *                  text : 'Menu item 1',
         *                  iconCls : 'myIconClass',    
         *                  tooltip : 'This option is optional'
         *              }
         *
         */
        items : [],
        
         /*
         * @cfg (string) id of dom element to render the menu into
         */
        renderTo : null,
        
        /*
         * @cfg (int) selected menu index,  -1 for no selection
         */
        selectedIndex : -1,
        
        /*
         * @cfg (int) the width of a collapsed menu item
         */
        collapsedWidth : 40,
        
        /*
         * @cfg (int) the width of a menu item on hover
         */
        hoverWidth : 43,
        
         /*
         * @cfg (int) the full width of a selected menu item
         */
        itemWidth : 190,
        
         /*
         * @cfg (int) the height of a menu item
         */
        itemHeight  : 40,
        
         /*
         * @cfg (int) the amount of space between two menu items
         */
        verticalPadding  : 2,
        
        /*
         * @public (int) returns the currently selected item index
         */
        getSelectedIndex : function() {
            return this.selectedIndex;
        },
        
        /*
         * @public selects the passed index
         */
        setSelectedIndex : function(index) {
            this.onItemClick(null, 'menuitem-' + index);
        },
        
        /*
         * @private
         */
        onItemClick : function(notUsed, t) {
            var target = Ext.get(t);
            
            if (!target.hasClass('fingermenu-show')){
                var current = this.el.child('.fingermenu-show');
                target.radioClass('fingermenu-show');
                
                if (current) {
                    current.setX(this.collapsedWidth - this.itemWidth, {
                        duration : 0.3
                    });
                }
                
                target.setX(0, {
                    duration : 0.3,
                    callback : function() {
                        this.selectedIndex = parseInt(target.id.substring('menuitem-'.length), 10);
                        this.fireEvent.defer(10, this, ['change', this, this.selectedIndex]);
                    },
                    scope : this
                });
            }
       },
       
       /*
         * @private
         */
       onHover : function(e, t) {
           var target = Ext.get(t);
           target = target.is('div') ? target : target.up('div');
           if (target.getX() === (this.collapsedWidth - this.itemWidth)){
               target.setX(this.hoverWidth - this.itemWidth, {
                    duration : 0.1
               });
           }
       },
       
       /*
        * @private
        */
       onHoverLeave : function(e, t) {
           var target = Ext.get(t);
           target = target.is('div') ? target : target.up('div');
           
           if (!target.hasClass('fingermenu-show')){
               target.setX(this.collapsedWidth - this.itemWidth,{
                    duration : 0.2
               });
           }
       },
        
       /*
        * @private
        */
       constructor : function(config) {
            if (!config || !config.items) throw 'Invalid arguments, see documentation';
            
            Ext.apply(this, config);
            
            var menuCfg = {
                    tag: 'div',
                    cls: 'fingermenu-panel ' + (config.cls || ''),
                    children : []
                },
                items = config.items,
                item,
                selected,
                i;
            
            this.addEvents('change');
            
            for (i = 0; i < items.length; i++) {
                item = items[i];
                selected = (i === this.selectedIndex);
                
                menuCfg.children.push({
                    id : 'menuitem-' + i,
                    cls : selected ? 'fingermenu-show' : '',
                    style : {
                        width : this.itemWidth + 'px',
                        position : 'absolute',
                        left : (selected ? 0 : (this.collapsedWidth - this.itemWidth)) + 'px',
                        top : (i*(this.itemHeight + this.verticalPadding)) + 'px'
                    },
                    tag: 'div', 
                    title : item.tooltip || item.text,
                    children : [{
                            tag : 'span',
                            cls : item.iconCls ? ('fingermenu-icon ' + item.iconCls) : '',
                            html : item.text
                        }
                    ]
                });
            }
            
            this.el = Ext.DomHelper.append(this.renderTo || Ext.getBody(), menuCfg, true);
            
            this.el.on('click', this.onItemClick, this, { delegate: 'div' });
            
            var divs = this.el.select('div');
            divs.on('mouseenter', this.onHover, this);
            divs.on('mouseleave', this.onHoverLeave, this);
            
            Ext.ux.FingerMenu.superclass.constructor.call(this);
        }
    });
    Attached Files

  2. #2
    Ext JS Premium Member syscobra's Avatar
    Join Date
    Nov 2007
    Location
    Venezuela
    Posts
    140
    Vote Rating
    0
    syscobra is on a distinguished road

      0  

    Default


    Nice thanks for sharing...
    How about a show on hover?
    maybe not as far as when you click, i mean imagine just show the full menu on hover but the active one beeing with more width. Maybe you can change too the active item css as when you have a <a> html tag.
    Just suggestions.

    Edit: Forgot to say i tryed on IE8 and it works well so maybe it works good in IE6 too cause it doesn't have strange things on the code i thing.
    Last edited by syscobra; 13 Jun 2009 at 10:12 AM. Reason: Forgot to say
    Javier Rincón aka SysCobra

  3. #3
    Sencha - Community Support Team mankz's Avatar
    Join Date
    Nov 2007
    Location
    Stockholm, Sweden
    Posts
    2,743
    Answers
    33
    Vote Rating
    104
    mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all

      0  

    Default


    Good idea, original post & example page updated!

  4. #4

  5. #5
    Sencha User demongloom's Avatar
    Join Date
    Apr 2008
    Location
    Israel
    Posts
    30
    Vote Rating
    3
    demongloom is on a distinguished road

      0  

    Default


    Nice thing!
    Can it been backported to 2.x version?


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

      0  

    Default


    There is no 2.0 Core.

  7. #7
    Sencha - Community Support Team mankz's Avatar
    Join Date
    Nov 2007
    Location
    Stockholm, Sweden
    Posts
    2,743
    Answers
    33
    Vote Rating
    104
    mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all mankz is a name known to all

      0  

    Default


    Quote Originally Posted by galdaka View Post
    Not work in IE6, IE7 & IE8.

    Greeting,
    Thanks for the heads up, should be working in IE7/8 now (tried it in IE8 with and without compatibility mode), still haven't tested it in IE6. Would rather bite my tongue really bad than try getting it working in IE6...

    Original post and example page updated.

  8. #8
    Sencha User
    Join Date
    Mar 2009
    Posts
    356
    Answers
    1
    Vote Rating
    0
    koko2589 is on a distinguished road

      0  

    Default


    work very good on ext 2.2 to
    my ext js site
    http://www.itoto4.com/

  9. #9

  10. #10
    Ext User Joe's Avatar
    Join Date
    Apr 2007
    Posts
    243
    Vote Rating
    0
    Joe is on a distinguished road

      0  

    Default Thanks for posting that control

    Thanks for posting that control


    Great to see it working in IE now - cool.

    I tested it in IE6 and it worked perfect, so you'll need another good reason to bite your tounge.

    Nice to see a ExtJS Core based ux control geared towards content sites. Is this MIT open source - like ExtJS Core? If so, would you mind if I posted this in a SVN dedicated to ExtJS Core components for content sites? Are you interested in being part of such a project?

    Thanks again for your active posts in regards to ExtJS Core.
    Joseph Francis,
    CoreLan / Meeting Consultants