суббота, сентября 23, 2006

Sharepoint и history.back

Давно висела задача не дать пользователям возможности уйти с открывшейся страницы не предусмотренным способом с сохранением введённых данных или с удалением незаполненных записей, а при помощи кнопки Back в браузере. Такой "уход" приводит к появлению пустых записей в списках и другим нежелательным эффектам типа воплей о пропавших данных.

При внимательном рассмотрении выяснилось, что "легальная" смена УРЛа происходит при помощи трёх элементов - Button, LinkButton и HyperLink. Для каждого из них требуется специфическое решение для занесения в history адреса перехода (что и даёт эффект "очистки" истории и "блокировки" кнопки Back).

HyperLink

Для этого элемента просто переопределяем реакцию на нажатие:

//Настройка элемента
HyperLink link = new HyperLink();
l
ink.Text = ...;
link.NavigateUrl = ...;
//обработчик нажатия на клиенте
link.NavigateUrl = "javascript:window.location.replace('"+link.NavigateUrl+"')";

LinkButton

Для этого элемента кроме переопределения реакции на нажатие требуется добавить на страницу скрипт и передать в элементе hidden адрес перехода (такая передача требуется на случай, если таких элементов на странице больше одного):

//Настройка элемента
LinkButton linkButton =
new LinkButton();
linkButton.Text = ...;
linkButton.Click += new EventHandler(linkButton_Click);
//обработчик нажатия на клиенте
linkButton.Attributes.Add("onclick", "javascript:SetBack('"+this.ClientID+"')");
//функция настройки адреса перехода
string _backScript = @"<SCRIPT language=""javascript"" type=""text/javascript"" >
var __BackUrl__="""";
function SetBack(id){
var hf=document.getElementById(""_backurl_""+id);
if(hf){ __BackUrl__=hf.value; }
} </SCRIPT>"
;
if(!this.Page.IsClientScriptBlockRegistered("_SetBack"))
   
this.Page.RegisterClientScriptBlock("_SetBack", _backScript);

//функция подмены адреса history.back
string _OnUnloadScript = @"<SCRIPT language=""javascript"" type=""text/javascript"" FOR=window EVENT=onunload>
if(__BackUrl__ != """"){window.location.replace(__BackUrl__);}
</SCRIPT>"
;
if(!this.Page.IsStartupScriptRegistered("_OnUnload"))
   
this.Page.RegisterStartupScript("_OnUnload", _OnUnloadScript);

//адрес перехода
this.Page.RegisterHiddenField("_backurl_" + this.ClientID, <url>);

Button

Для элемента Button настройки аналогичны элементу LinkButton.

 

После таких модификаций переходы по нажатию на такие элементы приводят в "блокировке" кнопки Back браузера.

Естественно, нашлась ложка дёгтя - при наличии на странице других элементов, не обладающих таким же поведением, "блокировка" кнопки Back может быть нарушена. Таким элементом, например, является пункт меню "Изменить общую веб-часть..." :-(

4 комментария:

DkmS комментирует...

Почему это? На кнопках у меня повешены "содержательные" обработчики, все нужные действия выполняются, а не только переходы.

Анонимный комментирует...

Только вот неплохо бы уже и на xhtml перейти. То бишь не <SCRIPT>, а <script> использовать в данном случае :)

DkmS комментирует...

Дык флаг в руки!

DkmS комментирует...

Всё равно никто не различает. Так что, пижонство это...