ailerifren
ailerifren

Reputation: 97

preserve javascript state in .NET MVC

I have some problem with the stateless nature of .NET MVC framework.

I have some HTML like

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
</ul>
<button id="btnShowMore">Show More</button>
<a href="www.google.com">Google</a>

and my javascript goes like

var maxDisplay = 5;
var unit = 5;
$("li").slice(maxDisplay).hide();
if ($("li").length <= maxDisplay) $('#btnShowMore').hide();
$('#btnShowMore').click(function () {
    maxDisplay += unit;
    $("li").slice(0, maxDisplay - 1).show();
    if ($("li").length <= maxDisplay) $('#btnShowMore').hide();
});

Now if I expand my list, navigate to google, and click back button in my browser, the list would forget what I did and shows only the first 5 list item, which is not what I want.

I thought of some options:

  1. cookie. not quite what I want because there are lots of pages like this, and I would need cookie for each of them

  2. manipulate url a bit, like taking advantage of window.location.hash. also not good, because that would be another page

Is there some conventional way to do this?

Thanks in advance


UPDATE:

seems like no more solutions coming out. I'd definitely prefer localStorage over cookie as there's no need to transfer this variable between client and server, but there needs a check whether the page is first load (clear cached variable and show 5 items) or load from navigate back(read cache and show cached number of items).

maybe I should go with hash...

Upvotes: 1

Views: 480

Answers (1)

bevacqua
bevacqua

Reputation: 48566

You could always use localStorage to persist your application state. And have your script adapted so that it reads and writes to it directly instead.

Here are a couple of functions I commonly use to read and write from the localStorage

function setStorageItem(key, value) {
    var localStorage = window.localStorage;
    if (localStorage) {
        try {
            localStorage.setItem(key, window.JSON.stringify(value));
        } catch (e) {
        }
    }
    return !!localStorage;
}

function getStorageItem(key, defaultValue) {
    var localStorage = window.localStorage;
    if (localStorage) {
        var value = localStorage.getItem(key);
        if (value) {
            return $.parseJSON(value);
        }
    }
    return defaultValue || undefined;
}

Your code would be:

var maxDisplay = getStorageItem('maxDisplay', 5),
    unit = 5,
    more = $('#btnShowMore');

$("li").slice(maxDisplay).hide();

if ($("li").length <= maxDisplay){
    more.hide();
}

more.click(function () {
    maxDisplay += unit;

    setStorageItem('maxDisplay', maxDisplay); // remember it.

    $("li").slice(0, maxDisplay - 1).show();

    if ($("li").length <= maxDisplay){
        more.hide();
    }
});

If localStorage isn't working, your code will work the same, and if it is, it'll remember the maxDisplay property.

Update

In case you insist on using cookies:

function setCookie(key, value, expires) {
    var defaults = {
        path: '/',
        expires: 1000 * 60 * 60 * 6 * 24 * 30 // 6 months
    };
    var date = new Date();
    var offset = expires || defaults.expires;
    date.setTime(date.getTime() + offset);
    var json = window.JSON.stringify(value);
    var cookie = '{0}={1}; expires={2}; path={3}'.format(key, json, date.toGMTString(), defaults.path);
    document.cookie = cookie;
}

function getCookie(key, defaultValue) {
    var identifier = '{0}='.format(key);
    var cookies = document.cookie.split(';');
    for (var i = 0; i < cookies.length; i++) {
        var cookie = cookies[i];
        while (cookie.charAt(0) == ' ') {
            cookie = cookie.substring(1, cookie.length);
        }
        if (cookie.indexOf(identifier) == 0) {
            var value = cookie.substring(identifier.length, cookie.length);
            return $.parseJSON(value);
        }
    }
    return defaultValue;
}

Upvotes: 3

Related Questions