<div>Well, Bertrand's Accordian example inspired me last night, so I came up with a client-side Atlas tabstrip. It basically supplants the Microsoft tabstrip, which I have come to despise over the last few years :) It works in both IE
and Mozilla. I don't really have anywhere to post this, so here it is:</div> <div> </div> <div>You can call this file something like TabSet.js</div>
Type.registerNamespace('Dice');
// Tabset view
Dice.Tabset = function(associatedElement) {
Dice.Tabset.initializeBase(this, [associatedElement]);
var _viewIndex = 0;
var _selectedTabStyle = '';
var _viewHeads = [];
var _viewPanes = [];
var _viewClickHandler;
this.get_viewIndex = function() {
return _viewIndex;
}
this.set_viewIndex = function(value) {
if (_viewIndex != value) {
_viewIndex = value;
_ShowCurrentPane.call(this);
this.raisePropertyChanged('viewIndex');
}
}
this.get_selectedTabStyle = function() {
return _selectedTabStyle;
}
this.set_selectedTabStyle = function(value) {
_selectedTabStyle = value;
}
this.dispose = function() {
if (_viewClickHandler) {
for (var i = _viewHeads.length - 1; i >= 0; i--) {
var head = _viewHeads[i];
if (head) {
head.detachEvent('onclick', _viewClickHandler);
}
}
delete _viewClickHandler;
delete _viewHeads;
delete _viewPanes;
}
Dice.Tabset.callBaseMethod(this, 'dispose');
}
Dice.Tabset.registerBaseMethod(this, 'dispose');
this.initialize = function() {
Dice.Tabset.callBaseMethod(this, 'initialize');
_viewClickHandler = Function.createDelegate(this, _onViewClick);
// Get tabstrip first.
var tabstrip;
var panes;
var children = this.element.childNodes;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.nodeName == 'UL') {
tabstrip = child.childNodes;
break;
}
}
for (var i = 0, p = 0; i < tabstrip.length; i++) {
var child = tabstrip[i];
if (child.nodeName == 'LI') {
_viewHeads.add(child);
child.viewIndex = p++;
child.attachEvent('onclick', _viewClickHandler);
}
}
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.nodeName == 'DIV') {
_viewPanes.add(child);
}
}
_ShowCurrentPane.call(this);
}
Dice.Tabset.registerBaseMethod(this, 'initialize');
function _onViewClick() {
var pane = window.event.srcElement;
while (pane && (typeof(pane.viewIndex) == 'undefined')) pane = pane.parentNode;
this.set_viewIndex(pane.viewIndex);
return false;
}
function _ShowCurrentPane() {
for (var i = _viewPanes.length - 1; i >= 0; i--) {
var selectedTab = _viewHeads[i];
var pane = _viewPanes[i];
if (i != _viewIndex) {
selectedTab.className = '';
pane.style.display = 'none';
} else {
selectedTab.className = _selectedTabStyle;
pane.style.display = 'block';
}
}
}
this.getDescriptor = function() {
var td = Dice.Tabset.callBaseMethod(this, 'getDescriptor');
td.addProperty('viewIndex', Number);
td.addProperty('selectedTabStyle', String);
return td;
}
Dice.Tabset.registerBaseMethod(this, 'getDescriptor');
}
Dice.Tabset.registerClass(Dice.Tabset', Sys.UI.Control);
Sys.TypeDescriptor.addType(dice, 'tabset', Dice.Tabset);
Make sure you add a reference to the file in your <atlas:scriptmanager> tag.
Then, on the page where you want to use the control, add this:
I'm not giving any kind of support for this control, so you're on your own. It's a foundation you can customize to your own needs, and a nice way to learn the client-side stuff in Atlas.
I know there isn't any support but I have a little problem that someone might solve quickly. When I run the code I get the message: "Assertion Failed: Unrecognized tag dice:tabset".
Maybe the tabset.js is inserted wrong. My scriptmanager has the code:
OK I got it all working and it looks good, however can someone tell me how I can set the tab index on the page? I can't seem to find a way to set that at runtime...
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.nodeName ==
'UL') {
tabstrip = child.childNodes;
break;
}
}
for (var i = 0, p = 0; i < tabstrip.length; i++) {
var child = tabstrip[i];
if (child.nodeName ==
'LI') {
this._viewHeads.add(child);
child.SelectedIndex = p++;
$addHandler(child,
"click",
this._viewClickHandler);
}
}
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.nodeName ==
'DIV') {
this._viewPanes.add(child);
}
}
this._ShowCurrentPane.call(this);
},
dispose :
function() {
// Remove all the event handlers
if (this._viewClickHandler) {
for (var i =
this._viewHeads.length - 1; i >= 0; i--) {
var header =
this._viewHeads[i];
if (header) {
The steps 1 (took out the closures and followed added prototype members) and 2 (remove the
TypeDescriptor and getDescriptor functions) are OK. The step 3 (xml-script) is wrong, because xml-script So, I had to rewrite it to JavaScript . Additionally the Array class extension was changed and "Array.add" method call had to be changed.
notifyScriptLoaded is added at the end of file to be loaded by ScriptManager. Not necessary if linked by standard <script ...> tag.
this,
'initialize');
this._viewClickHandler = Function.createDelegate(this,
this._onViewClick);
// Get tabstrip first.
var tabstrip;
var panes;
var children =
this.get_element().childNodes;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.nodeName ==
'UL') {
tabstrip = child.childNodes;
break;
}
}
for (var i = 0, p = 0; i < tabstrip.length; i++) {
var child = tabstrip[i];
if (child.nodeName ==
'LI') {
//this._viewHeads.add(child);
Array.add(
this._viewHeads,child);
child.viewIndex = p++;
child.attachEvent(
'onclick',
this._viewClickHandler);
}
}
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.nodeName ==
'DIV') {
Array.add(
this._viewPanes,child);
}
}
this._ShowCurrentPane.call(this);
} ,
_onViewClick:
function() {
var pane = window.event.srcElement;
while (pane && (typeof(pane.viewIndex) ==
'undefined')) {
pane = pane.parentNode;
}
this.set_viewIndex(pane.viewIndex);
return false;
} ,
_ShowCurrentPane:
function() {
for (var i =
this._viewPanes.length - 1; i >= 0; i--) {
var selectedTab =
this._viewHeads[i];
var pane =
this._viewPanes[i];
if (i != this._viewIndex) {
selectedTab.className =
'';
pane.style.display =
'none';
}
else {
selectedTab.className =
this._selectedTabStyle;
pane.style.display =
'block';
}
}
} ,
getDescriptor:
function() {
var td = Dice.Tabset.callBaseMethod(this,
'getDescriptor');
Hey everyone. Here's my small contribution to this great control! I noticed that this control didn't work correctly in Firefox - now it should (only tested in Firefox 2 though). Thanks to Shazam999 & valasekj for all of their previous work! I left the original
code, but commented out the line to notate the change that was required for it to work in Firefox.
// ASP.NET AJAX Tabset View
// Created by Shazam999
// Beta 2 compatibility by valasekj
// Last Modified: 12/13/06 - Firefox compatibility
Type.registerNamespace('Dice');
Dice.Tabset = function(associatedElement) {
Dice.Tabset.initializeBase(this, [associatedElement]);
this._viewIndex = 0;
this._selectedTabStyle = '';
this._viewHeads = [];
this._viewPanes = [];
this._viewClickHandler;
}
Dice.Tabset.prototype = {
get_viewIndex:function() {
return this._viewIndex;
},
set_viewIndex:function(value) {
if (this._viewIndex != value) {
this._viewIndex = value;
this._ShowCurrentPane.call(this);
this.raisePropertyChanged('viewIndex');
}
},
get_selectedTabStyle:function() {
return this._selectedTabStyle;
} ,
set_selectedTabStyle:function(value) {
this._selectedTabStyle = value;
} ,
dispose:function() {
if (this._viewClickHandler) {
for (var i = this._viewHeads.length - 1; i >= 0; i--) {
var head = this._viewHeads[i];
if (head) {
//head.detachEvent('onclick', this._viewClickHandler); //Changed to below for Firefox compatibility
$removeHandler(head,'click', this._viewClickHandler);
}
}
this._viewClickHandler = null;
this._viewHeads = null;
this._viewPanes = null;
}
Dice.Tabset.callBaseMethod(this, 'dispose');
},
initialize:function() {
Dice.Tabset.callBaseMethod(this, 'initialize');
this._viewClickHandler = Function.createDelegate(this, this._onViewClick);
// Get tabstrip first.
var tabstrip;
var panes;
var children = this.get_element().childNodes;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.nodeName == 'UL') {
tabstrip = child.childNodes;
break;
}
}
for (var i = 0, p = 0; i < tabstrip.length; i++) {
var child = tabstrip[i];
if (child.nodeName == 'LI') {
//this._viewHeads.add(child);
Array.add(this._viewHeads,child);
child.viewIndex = p++;
//child.attachEvent('onclick', this._viewClickHandler); //Changed to below for Firefox compatibility
$addHandler(child,'click', this._viewClickHandler);
}
}
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.nodeName == 'DIV') {
Array.add(this._viewPanes,child);
}
}
this._ShowCurrentPane.call(this);
} ,
_onViewClick:function(e) {
//var pane = window.event.srcElement; //Changed to below for Firefox compatibility
var pane = window.event ? window.event.srcElement : e ? e.target : null;
while (pane && (typeof(pane.viewIndex) == 'undefined')) {
pane = pane.parentNode;
}
this.set_viewIndex(pane.viewIndex);
return false;
} ,
_ShowCurrentPane:function() {
for (var i = this._viewPanes.length - 1; i >= 0; i--) {
var selectedTab = this._viewHeads[i];
var pane = this._viewPanes[i];
if (i != this._viewIndex) {
selectedTab.className = '';
pane.style.display = 'none';
}else{
selectedTab.className = this._selectedTabStyle;
pane.style.display = 'block';
}
}
} ,
getDescriptor:function() {
var td = Dice.Tabset.callBaseMethod(this, 'getDescriptor');
td.addProperty('viewIndex', Number);
td.addProperty('selectedTabStyle', String);
return td;
}
}
Dice.Tabset.inheritsFrom(Sys.UI.Control);
Dice.Tabset.registerClass('Dice.Tabset', Sys.UI.Control);
if (Sys && Sys.Application) { Sys.Application.notifyScriptLoaded(); }
None
0 Points
33 Posts
A gift to you all: An Atlas client-side tabstrip
Mar 29, 2006 05:36 PM|Shazam999|LINK
The unordered list will become the tabs, and the divs will become the panes.
You can style the tabs any way you want. Here's a sample style sheet you can use:
I'm not giving any kind of support for this control, so you're on your own. It's a foundation you can customize to your own needs, and a nice way to learn the client-side stuff in Atlas.
Have fun!
Member
3 Points
180 Posts
Re: A gift to you all: An Atlas client-side tabstrip
Jun 25, 2006 07:14 AM|sixtus|LINK
I know there isn't any support but I have a little problem that someone might solve quickly. When I run the code I get the message: "Assertion Failed: Unrecognized tag dice:tabset".
Maybe the tabset.js is inserted wrong. My scriptmanager has the code:
<atlas:ScriptManager ID="ScriptManager1" runat="server" EnableScriptComponents=true > <Scripts><atlas:ScriptReference Path ="tabset.js" /></Scripts> </atlas:ScriptManager>The aspx-file and tabset.js is placed at the same directory.
None
0 Points
7 Posts
Re: A gift to you all: An Atlas client-side tabstrip
Jul 05, 2006 07:57 AM|Kai-Uwe|LINK
Try this,
Dice.Tabset.registerClass('Dice.Tabset', Sys.UI.Control);
Sys.TypeDescriptor.addType('dice', 'tabset', Dice.Tabset);
None
0 Points
1 Post
Re: A gift to you all: An Atlas client-side tabstrip
Oct 02, 2006 11:25 AM|DPLyonnais|LINK
OK I got it all working and it looks good, however can someone tell me how I can set the tab index on the page? I can't seem to find a way to set that at runtime...
Member
1 Points
11 Posts
Re: A gift to you all: An Atlas client-side tabstrip
Nov 03, 2006 05:57 PM|uri|LINK
I tried your example in the latest AJAX V1.0 Beta and the code returns the following Javascript error:
Sys.TypeDescriptor is null or not an object
Member
1 Points
11 Posts
Re: A gift to you all: An Atlas client-side tabstrip
Nov 06, 2006 06:05 PM|uri|LINK
I did the following modifications to the code:
1) took out the closures and followed added prototype members.
2) remove the TypeDescriptor and getDescriptor functions.
3) In the xml-script added the reference... but it is still not working.
I am posting the modified broken code, hopefull the community can fix it again to the new Ajax 1.0
_________________________________
Type.registerNamespace('Dice');// Tabset view
Dice.Tabset =
function(element) { // Ctor creates private fields and calls base.Dice.Tabset.initializeBase(
this, [element]); this._viewIndex = 0; this._selectedTabStyle = ''; this._viewHeads = []; this._viewPanes = []; this._viewClickHandler = null;}
// Prototype: members
Dice.Tabset.prototype = {
initialize :
function() {Dice.Tabset.callBaseMethod(
this, 'initialize'); // Create the OnClick handler this._viewClickHandler = Function.createDelegate(this, this._onViewClick);tabstrip = child.childNodes;
break;}
}
child.SelectedIndex = p++;
$addHandler(child,
"click", this._viewClickHandler);}
}
}
}
this._ShowCurrentPane.call(this);},
dispose :
function() { // Remove all the event handlers if (this._viewClickHandler) { for (var i = this._viewHeads.length - 1; i >= 0; i--) { var header = this._viewHeads[i]; if (header) {$removeHandler(header,
"click", this._viewClickHandler);}
}
this._viewClickHandler = null; this._viewHeads = null; this._viewPanes = null;}
Dice.Tabset.callBaseMethod(
this, 'dispose');},
get_SelectedIndex:
function() { return this._viewIndex;},
set_SelectedIndex:
function(value) { if (this._viewIndex != value) { this._viewIndex = value; this._ShowCurrentPane.call(this); this.raisePropertyChanged('SelectedIndex');}
},
get_selectedTabStyle:
function() { return this._selectedTabStyle;},
set_selectedTabStyle:
function(value) { this._selectedTabStyle = value;},
_onViewClick :
function() { var pane = window.event.srcElement; while (pane && (typeof(pane.SelectedIndex) == 'undefined')) pane = pane.parentNode; this.set_SelectedIndex(pane.SelectedIndex); return false;},
_ShowCurrentPane :
function() { for (var i = _viewPanes.length - 1; i >= 0; i--) { var selectedTab = _viewHeads[i]; var pane = _viewPanes[i];selectedTab.className =
'';pane.style.display =
'none';}
else {selectedTab.className = _selectedTabStyle;
pane.style.display =
'block';}
}
}
}
Dice.Tabset.registerClass(
'Dice.Tabset', Sys.UI.Control);____________________
Here is the XML-script on the asp.net page:
<
script type="text/xml-script"><page xmlns:script=
"http://schemas.microsoft.com/xml-script/2005"xmlns:
"JavaScript: Sys.UI,Sys,Dice"><components>
<Dice:Tabset id=
"productTabset" selectedTabStyle="selected"/></components>
</page>
</
script>Ajax xml-script Tabstrip
None
0 Points
1 Post
Re: A gift to you all: An Atlas client-side tabstrip
Nov 16, 2006 07:45 AM|valasekj|LINK
I made it working under AJAX 1.0 Beta 2.
The steps 1 (took out the closures and followed added prototype members) and 2 (remove the TypeDescriptor and getDescriptor functions) are OK. The step 3 (xml-script) is wrong, because xml-script So, I had to rewrite it to JavaScript . Additionally the Array class extension was changed and "Array.add" method call had to be changed.
notifyScriptLoaded is added at the end of file to be loaded by ScriptManager. Not necessary if linked by standard <script ...> tag.
------------------------------------------------------------------------------------------------------------
// JScript File
Type.registerNamespace(
'Dice');Dice.Tabset =
function(associatedElement) {Dice.Tabset.initializeBase(
this, [associatedElement]); this._viewIndex = 0; this._selectedTabStyle = ''; this._viewHeads = []; this._viewPanes = []; this._viewClickHandler;}
Dice.Tabset.prototype = {
get_viewIndex:
function() { return this._viewIndex;},
set_viewIndex:
function(value) { if (this._viewIndex != value) { this._viewIndex = value; this._ShowCurrentPane.call(this); this.raisePropertyChanged('viewIndex');}
},
get_selectedTabStyle:
function() { return this._selectedTabStyle;} ,
set_selectedTabStyle:
function(value) { this._selectedTabStyle = value;} ,
dispose:
function() { if (this._viewClickHandler) { for (var i = this._viewHeads.length - 1; i >= 0; i--) { var head = this._viewHeads[i];head.detachEvent(
'onclick', this._viewClickHandler);}
}
this._viewClickHandler = null; this._viewHeads = null; this._viewPanes = null;}
Dice.Tabset.callBaseMethod(
this, 'dispose');},
initialize:
function() {Dice.Tabset.callBaseMethod(
this, 'initialize'); this._viewClickHandler = Function.createDelegate(this, this._onViewClick); // Get tabstrip first. var tabstrip; var panes; var children = this.get_element().childNodes; for (var i = 0; i < children.length; i++) { var child = children[i]; if (child.nodeName == 'UL') {tabstrip = child.childNodes;
break;}
}
for (var i = 0, p = 0; i < tabstrip.length; i++) { var child = tabstrip[i]; if (child.nodeName == 'LI') { //this._viewHeads.add(child);Array.add(
this._viewHeads,child);child.viewIndex = p++;
child.attachEvent(
'onclick', this._viewClickHandler);}
}
for (var i = 0; i < children.length; i++) { var child = children[i]; if (child.nodeName == 'DIV') {Array.add(
this._viewPanes,child);}
}
this._ShowCurrentPane.call(this);} ,
_onViewClick:
function() { var pane = window.event.srcElement; while (pane && (typeof(pane.viewIndex) == 'undefined')) {pane = pane.parentNode;
}
this.set_viewIndex(pane.viewIndex); return false;} ,
_ShowCurrentPane:
function() { for (var i = this._viewPanes.length - 1; i >= 0; i--) { var selectedTab = this._viewHeads[i]; var pane = this._viewPanes[i]; if (i != this._viewIndex) {selectedTab.className =
'';pane.style.display =
'none';}
else {selectedTab.className =
this._selectedTabStyle;pane.style.display =
'block';}
}
} ,
getDescriptor:
function() { var td = Dice.Tabset.callBaseMethod(this, 'getDescriptor');td.addProperty(
'viewIndex', Number);td.addProperty(
'selectedTabStyle', String); return td;}
}
Dice.Tabset.inheritsFrom(Sys.UI.Control);
Dice.Tabset.registerClass(
'Dice.Tabset', Sys.UI.Control);if
(Sys && Sys.Application) { Sys.Application.notifyScriptLoaded(); }-----------------------------------------------------------------------------------------
Replacement of xml-script in asp.net page:
<
script type="text/javascript">function
pageLoad() {$create(Dice.Tabset, {
"selectedTabStyle":"selected"}, null, null, document.getElementById('productTabset'));}
</
script>None
0 Points
5 Posts
Re: A gift to you all: An Atlas client-side tabstrip
Nov 24, 2006 05:44 PM|mbarnett|LINK
Great job valasekj! You saved me a bunch of conversion work. Thanks.
Nice client-side TabStrip from Shazam999
It is beyond me why this, or something similar, is not in the Control Toolkit...
Member
21 Points
11 Posts
Re: A gift to you all: An Atlas client-side tabstrip
Dec 13, 2006 10:49 AM|wdupree|LINK
Hey everyone. Here's my small contribution to this great control! I noticed that this control didn't work correctly in Firefox - now it should (only tested in Firefox 2 though). Thanks to Shazam999 & valasekj for all of their previous work! I left the original code, but commented out the line to notate the change that was required for it to work in Firefox.