1. #1
    Sencha User tobiu's Avatar
    Join Date
    May 2007
    Location
    Munich (Germany)
    Posts
    2,669
    Vote Rating
    110
    tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all

      0  

    Default [3.1.1]Ext.ux.panel.DDTabPanel

    [3.1.1]Ext.ux.panel.DDTabPanel


    hi together,

    there are quite a lot of changes, but i think it runs now fine with ext 3.1.1.
    i had to remove:
    Code:
    onRemove : function(c){
        // DragSource cleanup on removed tabs
        Ext.destroy(c.ds.proxy, c.ds);
    because this caused massive errors (afterwards ext.fly caused firebug-errors on each mouseMove...

    please let me know, if this ux works fine for you too and definitely tell me if the changes cause memory leaks.

    kind regards,
    tobiu

    Code:
    Ext.namespace('Ext.ux.panel');
    
    /**
     * @class Ext.ux.panel.DDTabPanel
     * @extends Ext.TabPanel
     * @author
     *     Original by
     *         <a href="http://extjs.com/forum/member.php?u=22731">thommy</a> and
     *         <a href="http://extjs.com/forum/member.php?u=37284">rizjoj</a><br />
     *     Published and polished by: Mattias Buelens (<a href="http://extjs.com/forum/member.php?u=41421">Matti</a>)<br />
     *     With help from: <a href="http://extjs.com/forum/member.php?u=1459">mystix</a>
     *     Polished and debugged by: Tobias Uhlig (info@internetsachen.com) 04-25-2009
     *     Ported to Ext-3.1.1 by: Tobias Uhlig (info@internetsachen.com) 02-14-2010
     * @license Licensed under the terms of the Open Source <a href="http://www.gnu.org/licenses/lgpl.html">LGPL 3.0 license</a>. Commercial use is permitted to the extent that the code/component(s) do NOT become part of another Open Source or Commercially licensed development library or toolkit without explicit permission.
     * @version 2.0.0 (Feb 14, 2010)
     */
    Ext.ux.panel.DDTabPanel = Ext.extend(Ext.TabPanel, {
        /**
         * @cfg {Number} arrowOffsetX The horizontal offset for the drop arrow indicator, in pixels (defaults to -9).
         */
        arrowOffsetX: -9,
        /**
         * @cfg {Number} arrowOffsetY The vertical offset for the drop arrow indicator, in pixels (defaults to -8).
         */
        arrowOffsetY: -8,
    
        // Assign the drag and drop group id
        /** @private */
        initComponent: function(){
            Ext.ux.panel.DDTabPanel.superclass.initComponent.call(this);
            if(!this.ddGroupId) this.ddGroupId = 'dd-tabpanel-group-' + Ext.ux.panel.DDTabPanel.superclass.getId.call(this);
        },
    
        // Declare the tab panel as a drop target
        /** @private */
        afterRender: function(){
            Ext.ux.panel.DDTabPanel.superclass.afterRender.call(this);
            // Create a drop arrow indicator
            this.arrow = Ext.DomHelper.append(
                Ext.getBody(),
                '<div class="dd-arrow-down"></div>',
                true
            );
            this.arrow.hide();
           // Create a drop target for this tab panel
           var tabsDDGroup = this.ddGroupId;
           this.dd = new Ext.ux.panel.DDTabPanel.DropTarget(this, {
               ddGroup: tabsDDGroup
           });
    		
           // needed for the onRemove-Listener
            this.move = false;
        },
    
    	// Init the drag source after (!) rendering the tab
    	/** @private */
    	initTab: function(tab, index){
    		Ext.ux.panel.DDTabPanel.superclass.initTab.call(this, tab, index);
    
    		var id = this.id + '__' + tab.id;
    		// Enable dragging on all tabs by default
    		Ext.applyIf(tab, { allowDrag: true });
    
            // Extend the tab
    		Ext.apply(tab, {
                // Make this tab a drag source
    			ds: new Ext.dd.DragSource(id, {
    				 ddGroup      : this.ddGroupId
    				,dropEl       : tab
    				,dropElHeader : Ext.get(id, true)
    				,scroll       : false
    
                    // Update the drag proxy ghost element
    				,onStartDrag : function(){
    					if(this.dropEl.iconCls){
    		                
    		                var el = this.getProxy().getGhost().select(".x-tab-strip-text");
    		                el.addClass('x-panel-inline-icon');
    		                
    		                var proxyText = el.elements[0].innerHTML;
    		                proxyText = Ext.util.Format.stripTags(proxyText);
    		                el.elements[0].innerHTML = proxyText;
    
    						el.applyStyles({
    							paddingLeft: "20px"
    						});
    					}
    				}
    				
    		// Activate this tab on mouse up
                    // (Fixes bug which prevents a tab from being activated by clicking it)
                    ,onMouseUp: function(event){
                        if(this.dropEl.ownerCt.move){
                            if(!this.dropEl.disabled && this.dropEl.ownerCt.activeTab == null){
                                this.dropEl.ownerCt.setActiveTab(this.dropEl);
                            }
                            this.dropEl.ownerCt.move = false;
                            return;
                        }
                        if(!this.dropEl.isVisible() && !this.dropEl.disabled){
                            this.dropEl.show();
                        }
                    }
    			})
    			// Method to enable dragging
    			,enableTabDrag: function(){
    				this.allowDrag = true;
    				return this.ds.unlock();
    			}
    			// Method to disable dragging
    			,disableTabDrag: function(){
    				this.allowDrag = false;
    				return this.ds.lock();
    			}
    		});
    
    		// Initial dragging state
    		if(tab.allowDrag){
    			tab.enableTabDrag();
    		}else{
    			tab.disableTabDrag();
    		}
    	}
    
    	/** @private */
    	,onRemove : function(c){
            var te = Ext.get(c.tabEl);
            // check if the tabEl exists, it won't if the tab isn't rendered
            if(te){
                // DragSource cleanup on removed tabs
                //Ext.destroy(c.ds.proxy, c.ds);
                te.select('a').removeAllListeners();
                Ext.destroy(te);
            }
            
            // ignore the remove-function of the TabPanel
            Ext.TabPanel.superclass.onRemove.call(this, c);
            
            this.stack.remove(c);
            delete c.tabEl;
            c.un('disable'     ,this.onItemDisabled     ,this);
            c.un('enable'      ,this.onItemEnabled      ,this);
            c.un('titlechange' ,this.onItemTitleChanged ,this);
            c.un('iconchange'  ,this.onItemIconChanged  ,this);
            c.un('beforeshow'  ,this.onBeforeShowItem   ,this);
    
            // if this.move, the active tab stays the active one
            if(c == this.activeTab){
                if(!this.move){
                    var next = this.stack.next();
                    if(next){
                        this.setActiveTab(next);
                    }else if(this.items.getCount() > 0){
                        this.setActiveTab(0);
                    }else{
                        this.activeTab = null;
                    }
                }
                else {
                    this.activeTab = null;
                }
            }
            if(!this.destroying){
                this.delegateUpdates();
            }
        }
    	
    
    	// DropTarget and arrow cleanup
    	/** @private */
    	,onDestroy: function(){
    		Ext.destroy(this.dd, this.arrow);
    		Ext.ux.panel.DDTabPanel.superclass.onDestroy.call(this);
    	}
    });
    
    // Ext.ux.panel.DDTabPanel.DropTarget
    // Implements the drop behavior of the tab panel
    /** @private */
    Ext.ux.panel.DDTabPanel.DropTarget = Ext.extend(Ext.dd.DropTarget, {
    	constructor: function(tabpanel, config){
    		this.tabpanel = tabpanel;
    		// The drop target is the tab strip wrap
    		Ext.ux.panel.DDTabPanel.DropTarget.superclass.constructor.call(this, tabpanel.stripWrap, config);
    	}
    
    	,notifyOver: function(dd, e, data){
    		var tabs = this.tabpanel.items;
    		var last = tabs.length;
    
    		if(!e.within(this.getEl()) || dd.dropEl == this.tabpanel){
    			return 'x-dd-drop-nodrop';
    		}
    
    		var larrow = this.tabpanel.arrow;
    
    		// Getting the absolute Y coordinate of the tabpanel
    		var tabPanelTop = this.el.getY();
    
    		var left, prevTab, tab;
    		var eventPosX = e.getPageX();
    
    		for(var i = 0; i < last; i++){
                prevTab = tab;
    			tab     = tabs.itemAt(i);
    			// Is this tab target of the drop operation?
    			var tabEl = tab.ds.dropElHeader;
    			// Getting the absolute X coordinate of the tab
    			var tabLeft = tabEl.getX();
    			// Get the middle of the tab
    			var tabMiddle = tabLeft + tabEl.dom.clientWidth / 2;
    
    			if(eventPosX <= tabMiddle){
    				left = tabLeft;
    				break;
    			}
    		}
    		
    		if(typeof left == 'undefined'){
    			var lastTab = tabs.itemAt(last - 1);
                if(lastTab == dd.dropEl)return 'x-dd-drop-nodrop';
    			var dom = lastTab.ds.dropElHeader.dom;
    			left = (new Ext.Element(dom).getX() + dom.clientWidth) + 3;
    		}
    		
    		else if(tab == dd.dropEl || prevTab == dd.dropEl){
                this.tabpanel.arrow.hide();
                return 'x-dd-drop-nodrop';
            }
    
    		larrow.setTop(tabPanelTop + this.tabpanel.arrowOffsetY).setLeft(left + this.tabpanel.arrowOffsetX).show();
    
    		return 'x-dd-drop-ok';
    	}
    
    	,notifyDrop: function(dd, e, data){
    		this.tabpanel.arrow.hide();
    		
    		// no parent into child
    		if(dd.dropEl == this.tabpanel){
    			return false;
    		}
    		var tabs      = this.tabpanel.items;
    		var eventPosX = e.getPageX();
    
    		for(var i = 0; i < tabs.length; i++){
                var tab = tabs.itemAt(i);
    			// Is this tab target of the drop operation?
    			var tabEl = tab.ds.dropElHeader;
    			// Getting the absolute X coordinate of the tab
    			var tabLeft = tabEl.getX();
    			// Get the middle of the tab
    			var tabMiddle = tabLeft + tabEl.dom.clientWidth / 2;
    			if(eventPosX <= tabMiddle) break;
    		}
    
            // do not insert at the same location
            if(tab == dd.dropEl || tabs.itemAt(i-1) == dd.dropEl){
                return false;
            }
            
    	dd.proxy.hide();
    
            // if tab stays in the same tabPanel
            if(dd.dropEl.ownerCt == this.tabpanel){
                if(i > tabs.indexOf(dd.dropEl))i--;
            }
    
            this.tabpanel.move = true;
    		var dropEl = dd.dropEl.ownerCt.remove(dd.dropEl, false);
            
    		this.tabpanel.insert(i, dropEl);
    		
    		return true;
    	}
    
    	,notifyOut: function(dd, e, data){
            this.tabpanel.arrow.hide();
    	}
    });
    
    Ext.reg('ddtabpanel', Ext.ux.panel.DDTabPanel);
    Best regards
    Tobias Uhlig
    __________

    S-CIRCLES Social Network Engine

  2. #2
    Ext JS Premium Member
    Join Date
    Oct 2007
    Posts
    81
    Vote Rating
    1
    miti is on a distinguished road

      0  

    Default


    Thanks for the update. Seems everything works fine except I have to override and comment out a line for the DragSource - otherwise I will get an error sometime when the drop is done - probably because dragsource is not properly destroyed?
    Code:
    ,afterRepair : function(){
    			        if(Ext.enableFx){
    			            //this.el.highlight(this.hlColor || "c3daf9");
    			        }
    			        this.dragging = false;
    			    }
    firebug trace:

    this.dom is undefined
    hasFxBlock()ext-all-debug.js (line 8611)
    queueFx(Object { name="o"}, Object { name="fn"})ext-all-debug.js (line 8618)
    highlight(Object { name="color"}, Object { name="o"})ext-all-debug.js (line 8135)
    afterRepair()DDTabPanel.js (line 109)
    afterRepair()ext-all-debug.js (line 30649)
    afterFx(Object { name="o"})ext-all-debug.js (line 8692)
    (?)()ext-all-debug.js (line 8446)
    apply()ext-base.js (line 7)
    apply()ext-base.js (line 7)
    fire()ext-all-debug.js (line 2415)
    apply()ext-base.js (line 7)
    fire()ext-all-debug.js (line 2415)
    apply(Object { name="r"}, Object { name="q"})ext-base.js (line 7)
    apply(Object { name="s"})ext-base.js (line 7)
    apply()ext-base.js (line 7)
    [Break on this error] var q = getQueue(this.dom.id);

  3. #3
    Sencha User tobiu's Avatar
    Join Date
    May 2007
    Location
    Munich (Germany)
    Posts
    2,669
    Vote Rating
    110
    tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all

      0  

    Default


    hi miti,

    tested quite a while and that error never occured to me.
    so, i need further information (or a small testcase) to track it down.

    the function afterRepair only gets called onInvalidDrop, working fine for me (tabs moving back with animation).

    if you need the override, i suggest a change to:
    Code:
    if(this.el)this.el.highlight(this.hlColor || "c3daf9");
    i changed the "no parent into child" condition of notifyDrop a bit for nested layouts, so that it is not possible to add a parent of any level into a child:

    Code:
    var parentEl = this.tabpanel.findParentBy(function(p){
        if(p.id == dd.dropEl.id)return true;
        return false;
    });
    
    // no parent of any level into child
    if(dd.dropEl == this.tabpanel || dd.dropEl == parentEl){
        return false;
    }
    kind regards,
    tobiu
    Best regards
    Tobias Uhlig
    __________

    S-CIRCLES Social Network Engine

  4. #4
    Ext JS Premium Member
    Join Date
    Oct 2007
    Posts
    81
    Vote Rating
    1
    miti is on a distinguished road

      0  

    Default


    Wow thanks for the quick reply. My case is a little complicated. The target panel is like a docking pane in eclipse that you can drag a tab to but will be hidden if no tab is docked. So I do some special code to handle it and maybe that cause problem. The weird thing is the problematic .afterRepair is called after a VALID drop.

    Code:
    if (this.el) this.el.highlight(this.hlColor || "c3daf9");
    won't help and this.el is some dragProxy. but

    Code:
    if (this.el.dom) this.el.highlight(this.hlColor || "c3daf9");
    fixed the problem. Obviously the dom is gone but the el is still there.

  5. #5
    Sencha User tobiu's Avatar
    Join Date
    May 2007
    Location
    Munich (Germany)
    Posts
    2,669
    Vote Rating
    110
    tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all

      0  

    Default


    it might be related to the point of the top-posting,
    i had to remove
    Code:
     Ext.destroy(c.ds.proxy, c.ds);
    which was resposible for cleaning up.
    i have more time next week and will try to find another solution (that line causes ext-fly to run amok...).


    kind regards,
    tobiu
    Best regards
    Tobias Uhlig
    __________

    S-CIRCLES Social Network Engine

  6. #6
    Sencha User
    Join Date
    Sep 2007
    Posts
    98
    Vote Rating
    1
    adam.jimenez is on a distinguished road

      0  

    Default


    Hi, thanks for this update.

    It has the same issue that the original DDtabpanel had. When you move a tab it removes it and re-inserts it. This is a problem for me as it triggers my beforeRemove handler.

    my rewritten notifydrop resolves this - altho it probably won't work between different tab groups:

    Code:
        ,notifyDrop: function(dd, e, data){
            this.tabpanel.arrow.hide();
            var tabs = this.tabpanel.items;
    
            var last = tabs.length;
            var eventPosX = e.getPageX();
    
            var newPos = last;
    //        dd.dropEl.position = last * 2 + 1; // default: 'behind the rest'
    
            var dragLeft=true;
    
            for(var i = 0; i < last-1; i++){            
                var tab = tabs.itemAt(i);
    
                if( dd.dropEl.id==tab.id ){
                    dragLeft=false;
                }
                
                // Is this tab target of the drop operation?
                var tabEl = tab.ds.dropElHeader;
                // Getting the absolute X coordinate of the tab
                var tabLeft = tabEl.getX();
                // Get the middle of the tab
                var tabMiddle = tabLeft + tabEl.dom.clientWidth / 2;
                
                var tabRight = tabLeft + tabEl.dom.clientWidth*1.5;
                
                if( dragLeft ){
                    if(eventPosX <= tabMiddle){
                        break;
                    }
                }else{
                    if(eventPosX <= tabRight){
                        break;
                    }
                }
            }
            
            //reset positions just in case new tabs were added
            tabs.each(function(tab, index){
    //            alert(tab.title);
                tab.position = (index + 1) * 2;
            });
    
            // Insert the tab element at the new position
    //        dd.proxy.hide();
            if( i+1==last ){
                dd.el.dom.parentNode.insertBefore(dd.el.dom, dd.el.dom.parentNode.childNodes[i].nextSibling);
                
                dd.dropEl.position=(last*2)+1;
            }else{
                if( dragLeft ){
                    dd.el.dom.parentNode.insertBefore(dd.el.dom, dd.el.dom.parentNode.childNodes[i]);
                
                    dd.dropEl.position=((i)*2)+1;
                }else{
                    dd.el.dom.parentNode.insertBefore(dd.el.dom, dd.el.dom.parentNode.childNodes[i+1]);
                
                    dd.dropEl.position=((i+1)*2)+1;
                }
            }
            
            // Sort tabs by their actual position
            tabs.sort('ASC', function(a, b){
                return a.position - b.position;
            });
            // Adjust tab position values
            tabs.each(function(tab, index){
                tab.position = (index + 1) * 2;
            });
            
            //var dropEl = dd.dropEl.ownerCt.remove(dd.dropEl, false);
            //this.tabpanel.insert(i, dropEl);
            //this.tabpanel.activate(dropEl);
    
            return true;
        }

  7. #7
    Sencha User
    Join Date
    Sep 2007
    Posts
    98
    Vote Rating
    1
    adam.jimenez is on a distinguished road

      0  

    Default


    Shouldn't the tabs activate onmousedown?

    I've added this to Ext.apply:

    Code:
                    ,onMouseDown: function(event) {
                        if (!this.dropEl.isVisible()) {
                            this.dropEl.show(); // simply call the tab's show() method to activate it
                        }
                    }
    or make it a config option..

  8. #8
    Sencha User tobiu's Avatar
    Join Date
    May 2007
    Location
    Munich (Germany)
    Posts
    2,669
    Vote Rating
    110
    tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all tobiu is a name known to all

      0  

    Default


    hi adam,

    with tabs activating onMousedown, it is not possible to drag and drop tabs without activating them. so this is a needed tradeoff from my point of view. could you please color your other changes?

    kind regards,
    tobiu
    Best regards
    Tobias Uhlig
    __________

    S-CIRCLES Social Network Engine

  9. #9
    Sencha User
    Join Date
    Sep 2007
    Posts
    98
    Vote Rating
    1
    adam.jimenez is on a distinguished road

      0  

    Default


    Quote Originally Posted by tobiu View Post
    hi adam,

    with tabs activating onMousedown, it is not possible to drag and drop tabs without activating them. so this is a needed tradeoff from my point of view. could you please color your other changes?

    kind regards,
    tobiu

    Apps like firefox/ chrome have tabs that activate onMouseDown. it's what users are used to. It could be made into a config option to keep everyone happy. e.g. activateTabsOnMouseDown= true/ false.

    WRT my changes - I didn't modify the new one. I copied the code that I rewrote from the original DDTabPanel.

  10. #10
    Ext User
    Join Date
    Feb 2009
    Posts
    56
    Vote Rating
    0
    uptodate is on a distinguished road

      0  

    Default


    In ExtJs 3.2.0 i can no change tabs

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi