Jan 28, 2011, 7:32 PM
[CLOSED] Best practice to integrate custom/generic plugins
Hi,
This post is kind of a continuation from this previous thread that Vladimir and Daniil in particular helped with:
http://forums.ext.net/showthread.php...event-on-a-tab
In the previous thread I was given help on how to get doubleclick to work on tabs to support renaming of them, which is neat.
The second thing I wanted to do is add a final tab that acts like an add button (bit like in IE and Firefox etc).
After digging around a bit, I came across this little plugin from Animal on the Ext Js forums (and a cut down version by a commenter).
http://www.sencha.com/forum/showthre...n-in-tab-strip
I used the cut down version and combined it with the renaming (so you can add new tabs, and rename them by double clicking) which is working really nicely.
However, I have 2 questions:
1) I get a JavaScript error (which does not break the page or stop other JS from executing)
2) I had to slightly tweak the plugin in the Ext Js forum to get it to work with the Ext.Net TabPanel plugin mechanism and want to ask about best practice
So, first the code, and then the details of the above two things:
From what I can tell, the JavaScript error only occurs when creating the new tab. In Firebug, I see "item is undefined" inside this code:
This may be an Ext Js issue which we can't do anything about, but just wondering if you can see a possible workaround or fix -- maybe the Add plugin is not doing something right, and I'm not so experienced with Ext Js plugins - which leads nicely to my second point :)
2) Best practice:
I was about to see if I can wrap the above functions (bodyInit, beforeComplete, setEditable, etc etc) into its own generic plugin that I could add to any Tab Panel.
This way, some people can choose what they want; add tabs but not rename, or allow renaming but not adding, or have both.
To reduce coupling between the two plugins, I guess I'd fire existing events or raise new ones and the other plugins can watch for them if needed. So, the new tab plugin can raise tabAdded or somethign like that which the rename one could watch for...
But, the renaming relies on an Editor being present. How do you normally handle dependencies like this? Do you supply an editor in the custom config?
If so, I am guessing that then means if we extend Object we may need to handle an empty config and initialize an Editor somehow?
Many thanks!
This post is kind of a continuation from this previous thread that Vladimir and Daniil in particular helped with:
http://forums.ext.net/showthread.php...event-on-a-tab
In the previous thread I was given help on how to get doubleclick to work on tabs to support renaming of them, which is neat.
The second thing I wanted to do is add a final tab that acts like an add button (bit like in IE and Firefox etc).
After digging around a bit, I came across this little plugin from Animal on the Ext Js forums (and a cut down version by a commenter).
http://www.sencha.com/forum/showthre...n-in-tab-strip
I used the cut down version and combined it with the renaming (so you can add new tabs, and rename them by double clicking) which is working really nicely.
However, I have 2 questions:
1) I get a JavaScript error (which does not break the page or stop other JS from executing)
2) I had to slightly tweak the plugin in the Ext Js forum to get it to work with the Ext.Net TabPanel plugin mechanism and want to ask about best practice
So, first the code, and then the details of the above two things:
<%@ Page Language="C#" %>
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Ext.Net Example</title>
<style type="text/css">
div.x-tab-strip-wrap .add-tab a span.x-tab-strip-inner {
background:url(/icons/add-png/ext.axd) no-repeat center center;
width:16px;
height:21px;
}
.new-tab { background-image:url(/icons/page_white_star-png/ext.axd); }
</style>
<ext:ResourcePlaceHolder ID="ResourcePlaceHolder1" runat="server" Mode="ScriptFiles" />
<script type="text/javascript">
// Courtesy: http://www.sencha.com/forum/showthread.php?83213-Add-new-tab-button-in-tab-strip&p=513914#post513914
Ext.ux.AddTabButton = Ext.extend(Object, {
constructor: function (config) {
config = config || {};
Ext.apply(this, config);
},
init: function(tp) {
if (tp instanceof Ext.TabPanel) {
tp.onRender = tp.onRender.createSequence(this.onTabPanelRender);
}
},
//private, ideally
onTabPanelRender: function() {
this.addTab = this.itemTpl.insertBefore(this.edge, {
id: this.id + 'addTabButton',
cls: 'add-tab',
text: this.addTabText || ' ',
iconCls: ''
}, true);
this.addTab.child('em.x-tab-left').setStyle('padding-right', '6px');
this.addTab.child('a.x-tab-right').setStyle('padding-left', this.tabPosition == 'top' ? '6px' : '0px');
new Ext.ToolTip({
target: this.addTab,
bodyCfg: {
html: 'New tab'
}
});
this.addTab.on({
click: this.onAddTabClick,
scope: this
});
}
});
Ext.reg('Ext.ux.AddTabButton', Ext.ux.AddTabButton);
</script>
<script type="text/javascript">
var bodyInit = function() {
this.items.each(function(item, index) {
setTabEditable(this, index);
},
this);
};
var setTabEditable = function(tabPanel, index) {
Ext.get(tabPanel.getTabEl(index)).on('dblclick', function(e, t) {
Editor1.field.setWidth(Ext.get(t).getWidth());
Editor1.startEdit(t);
});
};
var newTabAdded = function() {
this.add({
title : '(untitled)',
iconCls : 'new-tab',
html : 'new content',
id : Ext.id()
});
setTabEditable(this, this.items.items.length - 1);
};
var beforeComplete = function(editor, value, startValue) {
editor.setValue(editor.getValue());
return true;
};
var complete = function(editor, value, startValue) {
Ext.Msg.notify("Editor Changed", String.format("<b>{0}</b><br />changed to<br /><b>{1}</b>", startValue, value));
};
</script>
</head>
<body>
<form id="Form1" runat="server">
<ext:ResourceManager ID="ResourceManager1" runat="server" ScriptMode="Debug" SourceFormatting="true" />
<ext:TabPanel ID="TabPanel1" runat="server" TabPosition="Bottom" Height="100">
<Items>
<ext:Panel ID="Panel1" runat="server" Title="Tab1" Html="Content for tab 1" />
<ext:Panel ID="Panel2" runat="server" Title="Tab2" Html="Content for tab 2" />
<ext:Panel ID="Panel3" runat="server" Title="Tab3" Html="Content for tab 3" />
</Items>
<Listeners>
<AfterRender Fn="bodyInit" />
</Listeners>
<CustomConfig>
<ext:ConfigItem Name="onAddTabClick" Value="newTabAdded" />
</CustomConfig>
<Plugins>
<ext:GenericPlugin Id="AddTabButton" runat="server" InstanceName="Ext.ux.AddTabButton" />
</Plugins>
</ext:TabPanel>
<ext:Editor ID="Editor1" runat="server" Shadow="None" IgnoreNoChange="true">
<Alignment ElementAnchor="Left" TargetAnchor="Left" />
<Field>
<ext:TextField ID="TextField1" runat="server" AllowBlank="false" Width="110" SelectOnFocus="true" />
</Field>
<Listeners>
<BeforeComplete Fn="beforeComplete" />
<Complete Fn="complete" />
</Listeners>
</ext:Editor>
</form>
</body>
</html>
1) JavaScript errorFrom what I can tell, the JavaScript error only occurs when creating the new tab. In Firebug, I see "item is undefined" inside this code:
findTargets : function(e){ var item = null,
itemEl = e.getTarget('li:not(.x-tab-edge)', this.strip);
if(itemEl){
item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
if(item.disabled){
return {
close : null,
item : null,
el : null
};
}
}
return {
close : e.getTarget('.x-tab-strip-close', this.strip),
item : item,
el : itemEl
};
},
More specifically the problem seems to be at "if (item.disabled)"This may be an Ext Js issue which we can't do anything about, but just wondering if you can see a possible workaround or fix -- maybe the Add plugin is not doing something right, and I'm not so experienced with Ext Js plugins - which leads nicely to my second point :)
2) Best practice:
I was about to see if I can wrap the above functions (bodyInit, beforeComplete, setEditable, etc etc) into its own generic plugin that I could add to any Tab Panel.
This way, some people can choose what they want; add tabs but not rename, or allow renaming but not adding, or have both.
To reduce coupling between the two plugins, I guess I'd fire existing events or raise new ones and the other plugins can watch for them if needed. So, the new tab plugin can raise tabAdded or somethign like that which the rename one could watch for...
But, the renaming relies on an Editor being present. How do you normally handle dependencies like this? Do you supply an editor in the custom config?
If so, I am guessing that then means if we extend Object we may need to handle an empty config and initialize an Editor somehow?
constructor: function (config) {
config = config || {}; // I presume here we'd have to create a new config with an internally initialized editor with some useful default behaviour somehow... or just throw an exception maybe
Ext.apply(this, config);
},
From an Ext.Net perspective I guess passing in an Editor in the custom config is generally not an issue: whether it is created by markup or in codebehind the editor can be passed in. Is that how you would approach it?Many thanks!
Last edited by geoffrey.mcgill; Feb 01, 2011 at 4:53 PM.
Reason: [CLOSED]