-
19 Apr 2010 8:06 AM #11
Here my ExJs 3.2.0 Fix. (In ExtJs i can`t change the Tabs)
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; // Hotfix 3.2.0 Ext.fly(id).on('click', function(){tab.ownerCt.setActiveTab(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(); 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; } 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); // Event drop this.tabpanel.fireEvent('drop', this.tabpanel); return true; } ,notifyOut: function(dd, e, data){ this.tabpanel.arrow.hide(); } }); Ext.reg('ddtabpanel', Ext.ux.panel.DDTabPanel);
-
26 Apr 2010 6:53 AM #12
Seeing same tab activation problem with ExtJS 3.2
Seeing same tab activation problem with ExtJS 3.2
I too have encountered the problem with not being able to activate a tab by clicking on it. Seems to only be an issue when the tab in question has not been previously activated? The bit of code that seemed to be causing the problem was the visibility check which was returning true even though the tab was not the activate tab. Fixed by removing the visibility check from the onMouseUp handler but may be a better way :
Code:if(!this.dropEl.disabled){ this.dropEl.show(); }
-
26 Apr 2010 7:28 AM #13
Hi Rob_mac,
was inserted for forbidding to activate disabled tabs. I sometimes add tabs with the config disabled:true. In that case, the tab-headers get a gray font-color and i definitely don't want those tabs to be able to get activated (like i would not want disabled buttons to get clicked). You can enable tabs calling myTab.enable().Code:if(!this.dropEl.disabled){ this.dropEl.show(); }
Kind regards,
tobiu
-
26 Apr 2010 7:40 AM #14
Thanks
Thanks
Hi tobiu,
Thanks for your reply. Looking at my post I don't think I made myself clear. I don't have a problem with the disabled checking, it was the visibility check that I ended up removing. So the code used to be:
And I had to remove/comment out the isVisible() check in order to be able to activate a tab. Either that or use the hot fix posted earlier which calls setActiveTab() in the click handler.Code:if(!this.dropEl.isVisible() && !this.dropEl.disabled){ this.dropEl.show(); }
Kind Regards
-
26 Apr 2010 8:02 AM #15
Update
Update
Hi tobiu,
Just to let you know that adding the hidden: true config to my tabs seems to resolve the issue. The isVisible() check then correctly returns false for the unactivated tabs.

-
26 Apr 2010 8:05 AM #16
hi helen,
in this case i got you completely wrong =)
it has been a while since i ported this ux over...
the check for
i think it was designed to not be able to activate a tab, that is currently already activated.Code:if(!this.dropEl.isVisible())
it should be no problem to remove this part, if it makes trouble (or replace it with another condition to check, if it is the active-tab).
somehow strange, that the ux is still working fine in my fieldmanager-app. at least with firefox and chrome.
kind regards,
tobiu
-
26 Apr 2010 8:11 AM #17
Great. Thanks again for your help tobiu.
Kind Regards
Helen
-
20 Aug 2010 4:03 AM #18
New event - reorder
New event - reorder
The component is great! I allowed myself to be extended to cover additional event 'reordering'. Is called the 'drop' but has an additional parameter 'tab.'. This is a tab that has been postponed.
Here is source with 'reordering' event:
I usage this event, when i want make somthing with dropped tab,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); this.addEvents('reorder'); if (!this.ddGroupId) this.ddGroupId = 'dd-tabpanel-group-' + Ext.ux.panel.DDTabPanel.superclass.getId.call(this); }, // New Event fired after drop tab reorder:function(tab){ this.fireEvent('reorder', this, tab); }, // 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; // Hotfix 3.2.0 Ext.fly(id).on('click', function() { tab.ownerCt.setActiveTab(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); // Event drop this.tabpanel.fireEvent('drop', this.tabpanel); // Fire event reorder this.tabpanel.reorder(tabs.itemAt(i)); return true; } ,notifyOut: function(dd, e, data){ this.tabpanel.arrow.hide(); } }); Ext.reg('ddtabpanel', Ext.ux.panel.DDTabPanel);
example:
best regards, brombsCode:... 'reorder': function(tabPanel, tab) { tab.show(); } ...
-
6 May 2011 2:21 AM #19
This plugin is great. Has anyone got it working in Ext4?
-
6 Sep 2011 5:03 AM #20
Hi, thx for this good ux
i'm looking for the CSS but can't find it since http://extjs-ux.org is closed.
Does anyone can point me to it plz ?
Edit : i've found some http://lib.shiftcreate.com/dev/ddtabs.php
Edit 2 : i've also added the following to hide the bullet points; Unfortunatly it doesn't target this plugin specifically but all li tags inside a dd ghost.Code:.dd-arrow-down.dd-arrow-down-invisible { display: none; visibility: hidden; } .dd-arrow-down { background-image: url(../images/dd-arrow-down.gif); display: block; visibility: visible; z-index: 20000; position: absolute; width: 16px; height: 16px; top: 0; left: 0; }
Code:.x-dd-drag-ghost li { list-style: none outside none; }


Reply With Quote