document.location = "..." ;There will be a page reload, which doesn’t get us at all. A short googling indicates that the only part of the url that is not transmitted to the server and does not reload the page is the anchor, that is, what comes after the '#' in the address, for example, http://site.com/user/vasya/profile / #contacts . And it can be changed without causing a reboot, like this:
document.location.hash = "myTabName" ;Thus, the current tab will be displayed on the anchor, for example, like this:
< ajax: TabContainer ID = "tbcProfile" runat = "server"We first write the prototype of the solution (without making it into classes, etc.), just to make sure that the approach works. First, we must ensure that the url is rewritten in response to a tab switch. The TabContainer client has an OnClientActiveTabChanged client event for this. Specifying the name of the handler function in it, we get what we wanted. Here is the function:
ActiveTabIndex = "0" >
< ajax: TabPanel ID = "tabContacts" runat = "server" >
< ContentTemplate >
...
ContentTemplate >
ajax: TabPanel >
< ajax: TabPanel ID = "tabPassword" runat = "server" >
< ContentTemplate >
...
ContentTemplate >
ajax: TabPanel >
< ajax: TabPanel ID = "tabSubscribe" runat = "server" >
< ContentTemplate >
...
ContentTemplate >
ajax: TabPanel >
ajax: TabContainer >
var tabNames = [ 'contacts' , 'password' , 'subscribe' ];
function onTabChanged (sender, args) {
document .location.hash = tabNames [sender.get_activeTabIndex ()];
}Here, sender is a TabContainer client object that has a get_activeTabIndex method that returns the number of the currently selected tab. And tabNames is an array of tab names displayed in the URL.
var lastSetTab = null ;And it remains only to call setTabFromUrl in the page load handler. I must say that the approach worked. (UPD: adjusted for IE )
function setTabFromUrl ()
{
// get the tab name from the URL
var tabFromUrl = window.location.hash.replace ( '#' , '' );
// find the TabContainer client object
var tbcMenu = $ find ( '<% = tbcProfile.ClientID%>' );
// if the object has already been initialized and the tab in the URL has changed since the last check
if (tbcMenu! = null && tabFromUrl! = lastSetTab)
{ // then remember the last switch
lastSetTab = tabFromUrl;
// look for which index of the required tab
for ( var i = 0; i <tabNames.length; i ++)
{
if (tabFromUrl == tabNames [i])
{ // if found, then
// temporarily disable reverse synchronization with URL
tbcMenu.supressTabChanged = true ;
// try to make the selected tab active
try {tbcMenu.set_activeTabIndex (i); }
// if the object is not fully initialized, an exception may be
catch (e) {lastSetTab = null ; } // then simply cancel the memorization of the switch - as if nothing had happened
// enable reverse synchronization with URL
tbcMenu.supressTabChanged = false ;
break ;
}
}
}
// run the same method in a short time interval - thus tracking the “Back” and “Forward” buttons.
setTimeout (setTabFromUrl, 200);
}
< ajax: TabContainer ID = "tbcProfile" runat = "server"Ad is added:
ActiveTabIndex = "0" >
< ajax: TabPanel ID = "tabContacts" runat = "server" >
< ContentTemplate >
...
ContentTemplate >
ajax: TabPanel >
< ajax: TabPanel ID = "tabPassword" runat = "server" >
< ContentTemplate >
...
ContentTemplate >
ajax: TabPanel >
< ajax: TabPanel ID = "tabSubscribe" runat = "server" >
< ContentTemplate >
...
ContentTemplate >
ajax: TabPanel >
ajax: TabContainer >
< ext: UrlFriendlyTabExtender runat = "server" TargetControlID = "tbcProfile" TabNames = "contacts, password, subscribe" />And after that, all of the above should work.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using AjaxControlToolkit;
using System.Text;
using System.ComponentModel;
namespace Utils.Web.Extenders
{
/// <summary>
/// Ensures that using TabControl matches the currently selected tab with the contents of the browser’s address bar.
/// I.e,
/// - so that when switching between tabs the address is changed accordingly,
/// - it was possible at any time to copy the link, and after opening it after, get on the same tab,
/// where the link was copied from
/// - to ensure correct operation of the browser's Back and Forward buttons for navigating tabs.
/// </ summary>
[ // indicate that our extender is for TabContainer
TargetControlType ( typeof (TabContainer))
]
public class UrlFriendlyTabExtender: ExtenderControl
{
protected override void OnPreRender ( EventArgs e)
{
base .OnPreRender (e);
// sign the TabContainer on its client event of changing the current tab
// assign the "static" method of the client class UrlFriendlyTabClientBehavior.onTabChanged to the handler
((TabContainer) Parent.FindControl (TargetControlID)). OnClientActiveTabChanged =
"Utils.Web.Extenders.UrlFriendlyTabClientBehavior.onTabChanged" ;
// we describe how to initialize an array of tabs names - the gene script of this array
// and replace the UrlFriendlyTabClientBehavior.initTabNames method with this code.
Page .ClientScript.RegisterStartupScript ( Page .GetType (), ClientID, string .Format ( @ "
Utils.Web.Extenders.UrlFriendlyTabClientBehavior.prototype.initTabNames = function ()
{{
this._tabNames = [{0}];
}}
" , ScriptTabNamesAsJavaScriptArray ()), true );
}
/// <summary>
/// A list of words separated by spaces, commas or semicolons
/// which represent the reference names (anchors) for the tabs of our panel.
/// Names go in the order of the tabs.
/// <example> TabNames = "main, photos, news" </ example>
/// </ summary>
[Bindable ( true ), Category ( "Behavior" )]
public string TabNames
{
get
{
if ((ViewState [ "TabNames" ] as string )! = null )
return ( string ) ViewState [ "TabNames" ];
else
return string .Empty;
}
set
{
ViewState [ "TabNames" ] = value ;
}
}
// standard overload for Extender
protected override IEnumerable <ScriptDescriptor>
GetScriptDescriptors (System.Web.UI.Control targetControl)
{
yield return new ScriptBehaviorDescriptor ( "Utils.Web.Extenders.UrlFriendlyTabClientBehavior" , targetControl.ClientID);
}
protected override IEnumerable <ScriptReference>
GetScriptReferences ()
{
yield return new ScriptReference ( "Utils.Web.Extenders.UrlFriendlyTabClientBehavior.js" , this .GetType (). Assembly .FullName);
}
/// <summary>
/// From the string with delimiters generates a script JS-array (without parentheses).
/// </ summary>
/// <returns> </ returns>
private string ScriptTabNamesAsJavaScriptArray ()
{
var tabsMapDeclaration = new StringBuilder ();
IEnumerable < string > tabNames = GetTabNames (TabNames);
int tabNamesCount = tabNames.Count ();
int tabNamesIndex = 0;
foreach ( string tabName in tabNames)
{
if (tabNamesIndex <(tabNamesCount - 1))
tabsMapDeclaration.AppendFormat ( "'{0}'," , tabName);
else
tabsMapDeclaration.AppendFormat ( "'{0}'" , tabName);
tabNamesIndex ++;
}
return tabsMapDeclaration.ToString ();
}
private IEnumerable < string > GetTabNames ( string tabNamesAggregated)
{
return tabNamesAggregated.Split ( new [] { '' , ',' , ';' }, StringSplitOptions.RemoveEmptyEntries);
}
}
}
Type.registerNamespace ( "Utils.Web.Extenders" );
// short method to create an associated delegate
// if it causes questions, go here: http://habrahabr.ru/blogs/javascript/31647/
function $ delegate ($ this , method)
{
return function ()
{
return method.apply ($ this , arguments);
};
};
// constructor of the UrlFriendlyTabClientBehavior class
// param: element - the DOM element that our TabContainer is wearing
Utils.Web.Extenders.UrlFriendlyTabClientBehavior = function (element)
{
// base class constructor
Utils.Web.Extenders.UrlFriendlyTabClientBehavior.initializeBase ( this , [element]);
// description and initialization of the fields of our class
this ._lastSetTab = null ;
this ._tabNames = [];
};
// static method - handler of the client event of the change of the selected tab
Utils.Web.Extenders.UrlFriendlyTabClientBehavior.onTabChanged = function (sender, args)
{
// passed to the TabContainer client object
var tbcMenu = sender;
// from it we get a DOM object (get_element ()), and from it - an object of our class UrlFriendlyTabClientBehavior
var extender = tbcMenu.get_element (). UrlFriendlyTabClientBehavior;
// if it is not our code that caused tab switching
if (! tbcMenu.supressTabChanged)
{ // then rewrite the anchor in the address bar, getting the name of the anchor using the UrlFriendlyTabClientBehavior.getTabName method (see below)
document .location.hash = extender.getTabName (tbcMenu.get_activeTabIndex ());
}
};
// methods of the UrlFriendlyTabClientBehavior class
Utils.Web.Extenders.UrlFriendlyTabClientBehavior.prototype =
{
initialize: function ()
{
Utils.Web.Extenders.UrlFriendlyTabClientBehavior.callBaseMethod ( this , 'initialize' );
// load the tab names array into the _tabNames field
this .initTabNames ();
// try to set the one specified in the URL
this .setTabFromUrl ();
},
// set the current tab as specified in the URL
setTabFromUrl: function ()
{
// get its name from the URL
var tabFromUrl = window.location.hash.replace ( '#' , '' );
// find the TabContainer client object
var tbcMenu = $ find ( this .get_element (). id);
// if the object has already been initialized and the tab in the URL has changed since the last check
if (tbcMenu! = null && tabFromUrl! = this ._lastSetTab)
{ // then remember the last switch
this ._lastSetTab = tabFromUrl;
// look for which index of the required tab
for ( var i = 0; i < this ._tabNames.length; i ++)
{
if (tabFromUrl == this ._tabNames [i])
{ // if found, then
// temporarily disable reverse synchronization with URL
tbcMenu.supressTabChanged = true ;
// try to make the selected tab active
try {tbcMenu.set_activeTabIndex (i); }
// if the object is not fully initialized, an exception may be
catch (e) { this ._lastSetTab = null ; } // then simply cancel the memorization of the switch - as if nothing had happened
// enable reverse synchronization with URL
tbcMenu.supressTabChanged = false ;
break ;
}
}
}
// run the same method in a short time interval - thus tracking the “Back” and “Forward” buttons.
window.setTimeout ($ delegate ( this , this .setTabFromUrl), 200);
},
// get the name of the index tab
getTabName: function (index)
{
return this ._tabNames [index];
},
dispose: function ()
{
Utils.Web.Extenders.UrlFriendlyTabClientBehavior.callBaseMethod ( this , 'dispose' );
}
};
Utils.Web.Extenders.UrlFriendlyTabClientBehavior.registerClass ( 'Utils.Web.Extenders.UrlFriendlyTabClientBehavior' , Sys.UI.Behavior);
if ( typeof (Sys)! == 'undefined' ) Sys.Application.notifyScriptLoaded ();
Source: https://habr.com/ru/post/38495/
All Articles