Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Div's Class not persisting when 'back' button is used

I have an ASP.NET page that contains two div's. Both have search fields and a search button contained within each of them. When I first come to this page, Div A has the class 'SearchDiv' while Div B has 'SearchDivDisabled'. These classes change the appearance so the user knows which search type they currently have enabled.

When Div B is clicked, JavaScript changes it's class to 'SearchDiv', and changes Div A to 'SearchDivDisabled'. This all works like a charm. The problem I have is when a user changes to Div B, clicks Div B's search button (which obviously redirects to a results page), and then uses the browser's back button. When they return to the search page, Div A is enabled again, and Div B is Disabled, even though they last used Div B. In the search button event handler I set the class attribute of the Divs before I redirect, hoping this will update the page on the server so when the user returns, their last-enabled Div will still be enabled (regardless of which one was enabled when the page was first visited).

I believe this involves the ViewState, but I'm unsure why the class attribute is not saved so when the user returns to the page it is restored. Is there something I'm missing here, or some easy way to guarantee the behavior I want? Thanks!

Edit: Here is the button event handler code:

protected void RedirectToResults(int searchEnum, string resultPage)
{
    ShowContainer(searchEnum);
    Response.Redirect(resultPage + this.webParams.getAllVariablesString(null));
}

  protected void ShowContainer(int searchContainerToShow)
  {
     if (searchContainerToShow < 0 || searchContainerToShow > SearchContainers.Count || SearchContainers.Count == 0)
        return;

     //disable all search panels
     foreach (SearchContainer container in SearchContainers.Values)
     {
        container.searchDiv.Attributes.Add("class", "SearchDivDisabled");
     }

     //enable selected panel
     SearchContainers[searchContainerToShow].searchDiv.Attributes.Add("class", "SearchDiv");
  }

RedirectToResults() is called from the actual button event handler with the enum representing the selected search panel and the results page url. SearchContainers is a dictionary mapping an integer to the search Div. The important code is the last line, where I'm updating the selected search container with the 'active' search class, rather than the disabled one (which I assign to the other div(s) )

Additional Update: I have been battling with this issue for the last couple days. I was sort of able to get the following code to work (in page_load):

        Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
        Response.AppendHeader("Expires", "0"); // Proxies.

But this really isn't a solution, as everything else that gets cached correctly is lost, which leaves me worse off than when I started. Everything else seems to persist fine, it is just the class of the div that is causing me struggles.

Edit: Just wanted to update this for anyone else that comes across this. While I believe there is a solution here with setting the cacheability of the page to force the browser to postback, I could not get it working 100% with all browsers (primarily Firefox was giving me fits, which is a documented bug). I do believe the cookie solution would work, but I felt that may be a bit more complex than necessary for just trying to store the state of a couple div's.

What I ended up doing was tying the div's class to the state of it's correlating radio button (there are radio buttons next to the div which allow the users a more visual way of enabling search panels). I noticed these radio buttons retained the correct checked value when the back button was used, so I could guarantee they would indicate the correct div to be enabled. So in JavaScript's onload I check which radio button is enabled, and then adjust the classes of the search div's accordingly. This is a pretty big hack, but has worked 100% across all browsers, and only took about 10 lines of JavaScript.

like image 270
Kevin Avatar asked Aug 18 '10 13:08

Kevin


4 Answers

Because you are not posting back to change the div's style, when the user hits the back button it is taking it back to how the page was originally posted. The easy way to fix this is to have the button cause a postback that toggles the style.

like image 136
fizch Avatar answered Nov 11 '22 05:11

fizch


Store the setting in a cookie on the client side, then check the cookie via JavaScript on load of the page and change the CSS class. Other ways of fixing this might not work because the page isn't always requested from the server when a user hits the Back button.

using the jQuery cookie plugin

// this function will update the style of the divs based on the cookie's settings
function updateClass(){
    var val = $.cookie('myCookieName');

    // set your div's class
    if (!val || val=='divA')
    {
        $('#divA').removeClass('SearchDivDisabled');
        $('#divA').addClass('SearchDiv');
        $('#divB').removeClass('SearchDiv');
        $('#divB').addClass('SearchDivDisabled');
    }else{
        $('#divB').removeClass('SearchDivDisabled');
        $('#divB').addClass('SearchDiv');
        $('#divA').removeClass('SearchDiv');
        $('#divA').addClass('SearchDivDisabled');
    }
}

// call this passing in 'divA' or 'divB' depending on which is selected
function updatePage(selectedDiv){
    $.cookie('myCookieName', selectedDiv, { path: '/', expires: 10 });
    updateClass();
}

// change the class of the divs when the page is finished rendering
$(document).ready(function(){updateClass();}):
like image 36
Pete Amundson Avatar answered Nov 11 '22 05:11

Pete Amundson


I don't think ViewState is the issue here; it may be something that needs managed in client-side javascript code, as switching states on the client doesn't get reflected automatically on the server...

What you want to look at potentially is the management of browser history through the history points feature: http://msdn.microsoft.com/en-us/library/cc488548.aspx

HTH.

like image 2
Brian Mains Avatar answered Nov 11 '22 06:11

Brian Mains


As mentioned in my previous answer you can acheive all that you need using session variables. Since you had mentioned about persisting DIV selection i had asked you to have that in a session variable. If you want other form data to be persisted as well dump them all in session variables(make sure that you clean them up as and when you are done with them)

This would be the easiest way for you to meet your requirement.

Also you are using

Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
    Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
    Response.AppendHeader("Expires", "0"); // Proxies.

you can simple use

Response.Cache.SetCacheability(HttpCacheability.Private);

in your Page_load and acheive the same functionality

Let me know if you have any sppecific concerns implementing this.

like image 1
Vinay B R Avatar answered Nov 11 '22 05:11

Vinay B R