[ASP.net MVC / Html5] WebStorage - localStorage 進階實務應用

[ASP.net MVC / Html 5] WebStorage - localStorage 進階實務應用

承前篇:[Html 5] WebStorage - localStorage和sessionStorage 基本使用方法

前言

最近某案子客戶那邊的內部系統很神奇,使用者體驗很好(?),所以我正開發的系統被要求也得比照辦理=.=

假設在A頁面查詢完一個列表結果↓

※印象圖

image

 

接著使用者又瀏覽到此系統的其他頁↓

※印象圖

image

 

再誇張的是,使用者沒登出系統,可能工作偷懶什麼的,開了一個瀏覽器的tab上奇摩看一下新聞或玩個網頁遊戲後,再回到A頁↓

※印象圖

image

 

↑頁面上表單欄位、甚至查詢結果都還會殘留下來(⊙ˍ⊙)

 

說明

有經驗的人,一定馬上就有靈感:使用Session來做不就好了?

想想一下使用Session機制的流程:

1.可能要先在使用者Click 查詢按鈕時候,把表單各欄位和PageSize(每頁顯示幾筆)、CurrentPageIndex(目前第幾頁索引)儲存到Session裡

2.然後使用者可能透過瀏覽器Url網址輸入或點選超連結之類的Get Method動作進到畫面某頁時,程式再去判斷Session存不存在,如果該Session存在的話,

就把裡面的表單各欄位和PageSize(每頁顯示幾筆)、CurrentPageIndex(目前第幾頁索引)撈出來,然後放在ViewData,準備回傳給View

3.在View那邊,把表單各欄位和PageSize(每頁顯示幾筆)、CurrentPageIndex(目前第幾頁索引)等等的<input>、<select>、<textarea>各欄位的值填完後

4.再用Javascript或jQuery去click該查詢按鈕,顯示查詢結果

↑以上,使用Session實作不是說不好,因為要同時動到Controller和View,一個查詢畫面可能要花2、3小時,而我負責的系統總共有62個查詢畫面

 

 

偷懶習性的我,知道某高手一定有更快的解決辦法,能夠讓我在一天內就把62個查詢畫面全部改完XD

後來詢問結果就是要搭配以下幾個項目:

1.使用Html 5的localStorage,完全不用更動到現有Controller的程式碼,然後得在畫面上,click查詢按鈕時候,利用jQuery的serialize()函式把表單序列化,儲存到localStorage

2.在$(document).ready(function(){});裡,去判斷localStorage存不存在,有的話,把localStorage裡序列化的字串轉成JSON物件或JSON陣列

3.再把JSON物件或JSON陣列的值快速填入到畫面上表單欄位裡(應該沒人想一個一個把值assign到表單欄位吧)

4.再用Javascript或jQuery去click該查詢按鈕,顯示查詢結果

後來嘗試實作過後,開發速度真的快很多= =+ (Session做法就不理它,有新歡當然要忘了舊愛XDD)

 

實作

跟前篇[Html 5] WebStorage - localStorage 基本使用方法一樣,只要在View的Javascript裡寫寫程式碼就好了

考量到實務上情況可能會使用到PageSize(每頁顯示幾筆)、CurrentPageIndex(目前第幾頁索引)這兩個表單欄位

不知道大家的分頁pager是用什麼plugin還是自己打造?

我是習慣自己打造並用Ajax來查詢資料:[ASP.net MVC 4] 自己打造分頁Pager範例程式碼 (數字版,Ajax) ,因為可以做出「Loading…」的效果,使用者體驗較好,

而且我自己寫的pager會自動更新顯示目前在哪一頁(無須再靠Javascript assign pager的頁數)

 

直接看程式碼

不使用localStorage前


<html>
<head>
    <title>不使用localStorage的頁面</title>
   
</head>
<body>
    <!--如果使用ASP.net MVC寫View的話,記得把<form>改成 
    @using (Html.BeginForm("", "", FormMethod.Post, new { name = "myForm"})  )
    { 
      裡面就是一堆表單欄位...等等    
    
    ※這邊給actionName和controllerName空字串是因為待會要用jQuery Ajax查詢資料,到時候再指定呼叫的url就好
    }-->
    <form name="myForm" method="post" action="" style="width:800px;border: 1px solid #000000;float:left;">
        輸入您對此頁的感想:<textarea name="demoTextArea"></textarea>
        <br />
        <br />
        輸入隨便幾個字串:<input type="text" name="demoText" />
        <br />
        <br />
        選擇您的性別:<input type="radio" name="demoRadio" value="男" checked="checked" />男&nbsp;&nbsp;<input type="radio" name="demoRadio" value="女" />女
    <br />
        <br />

        選擇您想進哪家公司:<br />
        <input type="checkbox" name="chk鴻海" value="鴻海" />鴻海&nbsp;&nbsp;<input type="checkbox" name="chkGoogle" value="Google" />Google<br />
        <input type="checkbox" name="chkMicrosoft" value="Microsoft" />Microsoft&nbsp;&nbsp;<input type="checkbox" name="chkApple" value="Apple" />Apple
    <br />
        <br />


        選擇您的夢想:<br />
        <select name="demoSelect">
            <option value="-1">請選擇</option>
            <option value="買下信義區的豪宅">買下信義區的豪宅</option>
            <option value="買部跑車">買部跑車</option>
            <option value="脫離單身">脫離單身</option>
            <option value="環遊世界">環遊世界</option>
            <option value="成為微軟MVP,並一直持續連任">成為微軟MVP,並一直持續連任</option>
        </select>
        <br />
        <br />


        每頁顯示幾筆:<select name="selectPageSize">
            <option value="5">5</option>
            <option value="10">10</option>
            <option value="15">15</option>
        </select>
        <br />
        <input type="hidden" name="CurrentPageIndex" />
        <br />
      

        <input type="button" value="查詢" onclick="searchData(1);" />
    </form>
    <span style="margin-left:30px;"><a href="javascript:Logout();">登出</a></span>
    <br />
    <br />
    <span style="margin-left:30px;"><a href="javascript:window.location.href=window.location.href"> 重新連結本頁</a></span>
    <br />
    <br />
    <span style="margin-left:30px;"><a href="javascript:alert('不登出,直接連結到你的最愛網站,請記得輸入Url網址回本頁看看查詢結果還在不在');window.location.href='http://msdn.microsoft.com/ja-jp/windowsazure/claudia/';">連結到你的最愛網站</a></span>
    <br style="clear:both;" />
    <h4>顯示查詢結果:</h4>
    <div id="divResult" style="width:800px;" >
    </div>
    <br />
    <br />
    <br />
   <!-- ※我自己打造的pager,頁數是在表單外:[ASP.net MVC 4] 自己打造分頁Pager範例程式碼 (數字版,Ajax)  http://www.dotblogs.com.tw/shadow/archive/2013/05/09/103351.aspx  
        且會自動更新View上面頁數的顯示,我想不出頁數該怎麼模擬,就略過吧Orz-->





    <!--引用jQuery核心函式庫-->
    <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
    <!--可以做出「Loading...」效果的套件,非本文重點-->
    <script src="http://malsup.github.io/jquery.blockUI.js"></script>
     <script type="text/javascript">
         //產生假資料是為了Demo用,因為這是.html檔,實務上應該要去Query DB裡的資料才對
         var Persons = new Array();//弄一個靜態的假資料
         //宣告一個js物件
         function Person() {
             this.Name = "";
         }
         //當畫面上的DOM都載入時
         $(document).ready(init);
         function init() {
             registerRadio_CheckBox_Select();
             //產生9筆假資料
             GeneratePersons();
              
           
         }//end init
         //隨便塞資料給js物件
         function GeneratePersons() {
             

                 var obj = new Person();
                     obj.Name = "肯幫忙全部填寫的好人,祝大大一生平安";
                     Persons.push(obj);//放入集合中
                     obj = new Person();
                     obj.Name = "可能是IT界微軟MVP的人";
                     Persons.push(obj);//放入集合中
                     obj = new Person();
                     obj.Name = "懶惰不想填寫的人";
                     Persons.push(obj);//放入集合中
                     obj = new Person();
                     obj.Name = "孤單寂寞的大叔";
                     Persons.push(obj);//放入集合中
                     obj = new Person();
                     obj.Name = "孤單寂寞的輕熟女";
                     Persons.push(obj);//放入集合中
                     obj = new Person();
                     obj.Name = "可能是車狂的大叔";
                     Persons.push(obj);//放入集合中
                     obj = new Person();
                     obj.Name = "可能需要安全感的輕熟女";
                     Persons.push(obj);//放入集合中
                     obj = new Person();
                     obj.Name = "愛好旅行的人";
                     Persons.push(obj);//放入集合中
                     obj = new Person();
                     obj.Name = "您可能立馬要準備存款了";
                     Persons.push(obj);//放入集合中
             
         }
         //End 塞假資料
  </script>
    <script type="text/javascript">
        //可以做出「Loading...」效果的兩個jQuery Plugin函式,非本文重點
        function blockUI() {
            $("form").block({
                message: '<h1>讀取中...</h1>',
                css: { border: '3px solid #a00' }
            });

        }
        function unBlockUI() {
            $("form").unblock();
        }
        //End blockUI
    </script>

    <script type="text/javascript">
        //查詢資料
        function searchData(pageNumber)
        {
            //「Loading...」畫面,使用jQuery blockUI套件
            //畫面會鎖住,避免使用者按完查詢鈕後又馬上再按一次查詢鈕,同時也讓使用者知道系統查詢資料中,非本文重點
            blockUI();
             


            //目前頁索引
            $("input[name='CurrentPageIndex']").val((pageNumber - 1));
            //查詢參數表單
            var myForm = $("form[name='myForm']").serialize();//把表單序列化成QueryString
            
          
            //透過ajax呼叫資料
            //假裝資料讀取了2秒
            setTimeout(function () {
                $.ajax({
                    url: window.location.href,//實務上若使用ASP.net MVC的話,要改寫為"@Url.Action(actionName,controllerName)"
                    type: "get",//為了demo才用get,實務上查資料最好用post
                    async: true,//非同步執行
                    data: myForm,//傳遞的表單參數
                    cache: false,
                    success: function (result) {
                        //原本實務上應該要這樣寫↓
                        //$("#divResult").empty().html(result);
                        //result變數為從Controller回傳的Partial View,該Partial View的Action(上面的url參數)裡面的程式碼就是從DB撈出IQueryable<T>的結果資料集,
                        //然後在Razor那邊用C#跑迴圈組出Html Table

                        //為了Demo而寫的js搜尋資料版,非本文重點
                        showResult(myForm);
                       
                        //解除blockUI(),非本文重點
                        unBlockUI();
                    },
                    error: function (xhr) {
                        //解除blockUI(),非本文重點
                        unBlockUI();
                        
                    }

                });//End ajax

            }, 2000);
            

        }

        //顯示查詢結果 為了Demo才亂寫一堆js,非本文重點
        function showResult(UserInputQueryString)
        {
            //把使用者填寫的QueryString轉成JsonObject
            var userJsonObj = QueryStringToJSONObject(decodeURIComponent(UserInputQueryString));
           
            //查詢結果
            var queryResult = new Array();
            //搜尋跟使用者同類型的人
            $(Persons).each(function (index, jsObj) {
                 
                if (jsObj.Name == "肯幫忙全部填寫的好人,祝大大一生平安")
                {
                    if (userJsonObj.demoTextArea != "" && userJsonObj.demoText != ""
                        && (userJsonObj.chk鴻海 || userJsonObj.chkGoogle || userJsonObj.chkMicrosoft || userJsonObj.chkApple) && userJsonObj.demoSelect != "-1")
                    {
                        queryResult.push(jsObj);
                    }
                      
                }
                if (jsObj.Name == "懶惰不想填寫的人") {
                    if (userJsonObj.demoTextArea == "" && userJsonObj.demoText == ""
                       && (userJsonObj.chk鴻海 == undefined && userJsonObj.chkGoogle == undefined && userJsonObj.chkMicrosoft == undefined && userJsonObj.chkApple == undefined) && userJsonObj.demoSelect == "-1")
                    {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "可能是IT界微軟MVP的人") {
                    if (userJsonObj.demoSelect == "成為微軟MVP,並一直持續連任" && userJsonObj.chkMicrosoft)
                    {
                        queryResult.push(jsObj);
                    }
                }
            
                if (jsObj.Name == "孤單寂寞的大叔")
                {
                    if (userJsonObj.demoSelect == "脫離單身" && userJsonObj.demoRadio=="男") {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "孤單寂寞的輕熟女") {
                    if (userJsonObj.demoSelect == "脫離單身" && userJsonObj.demoRadio == "女") {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "可能是車狂的大叔") {
                    if (userJsonObj.demoSelect == "買部跑車" && userJsonObj.demoRadio == "男") {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "可能需要安全感的輕熟女") {
                    if (userJsonObj.demoSelect == "買下信義區的豪宅" && userJsonObj.demoRadio == "女") {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "愛好旅行的人") {
                    if (userJsonObj.demoSelect == "環遊世界") {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "您可能立馬要準備存款了")
                {
                    if (userJsonObj.demoSelect == "買下信義區的豪宅") {
                        queryResult.push(jsObj);
                    }
                }
                
                    if ($(queryResult).size() > 0)//有結果
                    {
                        var str = "<div>您是這樣的人↓</div>" +
                                   "<ul>";
                        $(queryResult).each(function (index, jsObj) {

                            str += "<li>";
                            str += jsObj.Name;
                            str += "</li>";
                        });
                        str += "</ul>";
                        $("#divResult").empty().html(str);//顯示結果
                    } else {
                        $("#divResult").empty().html("查無資料,請多嘗試,也許右鍵檢視原始碼可以幫助您");//顯示結果    
                    }
                 
                });
             
        } 
              
          
       
    
    </script>
    <script type="text/javascript">
        //底下的javascript很重要,請自行抽出.js檔再引用

        //將queryString轉成JsonObject
        //※使用此函數要注意,<input type='checkbox' />不能取相同的name,否則checkbox部份一律只會回傳一個值
        function QueryStringToJSONObject(queryString) {
            var pairs = queryString.split('&');

            var result = {};
            pairs.forEach(function (pair) {
                pair = pair.split('=');
                result[pair[0]] = decodeURIComponent(pair[1] || '');
            });

            return JSON.parse(JSON.stringify(result));

        }


        //處理radio、checkbox、select元素,讓它們的狀況跟以前一樣
        function registerRadio_CheckBox_Select() {
            //註冊radio click時,是否加上checked屬性的事件
            $("input[type='radio']").click(function () {
                $("input[type='radio']").removeAttr("checked");
                $(this).attr("checked", true).prop("checked", true);
            });
            //註冊checkbox click時是否加上checked屬性的事件
            $("input[type='checkbox']").click(function () {
                //判斷CheckBox勾選狀態
                if ($(this).prop("checked") == true) {
                    $(this).attr("checked", true);
                } else {
                    $(this).attr("checked", false);
                }

            });
            //註冊下拉選單更動時的事件
            $("select").change(function () {
               
                var value = $(this).val();//選中的值
                $(this).find("option").not("[value='" + value + "']").removeAttr("selected");
                $(this).find("option[value='" + value + "']").attr("selected", true);
                
            });

        }

    </script>


    <script type="text/javascript">
        function Logout()
        {//登出
            alert("完成登出,畫面將導至您的最愛網站,記得回來此頁看看查詢結果還在不在");
            window.location.href = "http://www.microsoft.com/taiwan/silverlight/FanClub2014/";
        }
    </script>
</body>
</html>

線上Demo(請用IE瀏覽):

http://shadowjapan.blob.core.windows.net/dotblogsshare/NoUseLocalStorage.html

體驗方法↓

image

 

 

 

使用localStorage之後

※這次我故意把每頁顯示幾筆PageSize的下拉選單丟到表單外,可以參考看看處理方式


<html>
<head>
    <title>使用localStorage的頁面</title>
</head>
<body>
    <!--如果使用ASP.net MVC寫View的話,記得把<form>改成 
    @using (Html.BeginForm("", "", FormMethod.Post, new { name = "myForm"})  )
    { 
      裡面就是一堆表單欄位...等等    
    
    ※這邊給actionName和controllerName空字串是因為待會要用jQuery Ajax查詢資料,到時候再指定呼叫的url就好
    }-->
    <form name="myForm" method="post" action="" style="width:800px;border: 1px solid #000000;float:left;">
        輸入您對此頁的感想:<textarea name="demoTextArea"></textarea>
        <br />
        <br />
        輸入隨便幾個字串:<input type="text" name="demoText" />
        <br />
        <br />
        選擇您的性別:<input type="radio" name="demoRadio" value="男" checked="checked" />男&nbsp;&nbsp;<input type="radio" name="demoRadio" value="女" />女
    <br />
        <br />

        選擇您想進哪家公司:<br />
        <input type="checkbox" name="chk鴻海" value="鴻海" />鴻海&nbsp;&nbsp;<input type="checkbox" name="chkGoogle" value="Google" />Google<br />
        <input type="checkbox" name="chkMicrosoft" value="Microsoft" />Microsoft&nbsp;&nbsp;<input type="checkbox" name="chkApple" value="Apple" />Apple
    <br />
        <br />


        選擇您的夢想:<br />
        <select name="demoSelect">
            <option value="-1">請選擇</option>
            <option value="買下信義區的豪宅">買下信義區的豪宅</option>
            <option value="買部跑車">買部跑車</option>
            <option value="脫離單身">脫離單身</option>
            <option value="環遊世界">環遊世界</option>
            <option value="成為微軟MVP,並一直持續連任">成為微軟MVP,並一直持續連任</option>
        </select>
        <br />
        <br />
        <br />
        <input type="hidden" name="CurrentPageIndex" />
        <input type="hidden" name="PageSize" />
        <br />
        <!--※↑上面幾個欄位主要展示,如何利用localStorage儲存表單欄位,待重新進入此頁時,再把欄位的值顯示出來-->

        <input type="button" value="查詢" onclick="searchData(1);" />
    </form>
    <span style="margin-left:30px;"><a href="javascript:Logout();">登出</a></span>
    <br />
    <br />
    <span style="margin-left:30px;"><a href="javascript:window.location.href=window.location.href">重新連結本頁</a></span>
    <br />
    <br />
    <span style="margin-left:30px;"><a href="javascript:alert('不登出不清除localStorage,直接連結到你的最愛網站,請記得輸入Url網址或瀏覽器的上一頁,回本頁再看看查詢結果還在不在');window.location.href='http://msdn.microsoft.com/ja-jp/windowsazure/claudia/';">連結到你的最愛網站</a></span>
    <br style="clear:both;" />
    每頁顯示幾筆:<select name="selectPageSize" id="selectPageSize">
            <option value="5">5</option>
            <option value="10">10</option>
            <option value="15">15</option>
        </select>
    <br />
    <br />
    <h4>顯示查詢結果:</h4>
    <div id="divResult" style="width:800px;" >
    </div>
    <br />
    <br />
    <br />
   <!-- ※我自己打造的pager,頁數是在表單外:[ASP.net MVC 4] 自己打造分頁Pager範例程式碼 (數字版,Ajax)  http://www.dotblogs.com.tw/shadow/archive/2013/05/09/103351.aspx  
        且會自動更新View上面頁數的顯示,我想不出頁數該怎麼模擬,就略過吧Orz-->





    <!--引用jQuery核心函式庫-->
    <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
    <!--可以做出「Loading...」效果的套件,非本文重點-->
    <script src="http://malsup.github.io/jquery.blockUI.js"></script>
     <script type="text/javascript">
         //產生假資料是為了Demo用,因為這是.html檔,實務上應該要去Query DB裡的資料才對
         var Persons = new Array();//弄一個靜態的假資料
         //宣告一個js物件
         function Person() {
             this.Name = "";
         }
         //宣告一個localStorage名稱的js全域變數,專門for此頁
         var localStorageName = "實務上給這個畫面一個命名吧";
         //當畫面上的DOM都載入時
         $(document).ready(init);
         function init() {
             registerRadio_CheckBox_Select();

             //還原表單資料,並顯示結果
             RestoreForm(localStorageName);


             //產生9筆假資料
             GeneratePersons();
              
           
         }//end init
         //隨便塞資料給js物件
         //隨便塞資料給js物件
         function GeneratePersons() {
              
             var obj = new Person();
             obj.Name = "肯幫忙全部填寫的好人,祝大大一生平安";
             Persons.push(obj);//放入集合中
             obj = new Person();
             obj.Name = "可能是IT界微軟MVP的人";
             Persons.push(obj);//放入集合中
             obj = new Person();
             obj.Name = "懶惰不想填寫的人";
             Persons.push(obj);//放入集合中
             obj = new Person();
             obj.Name = "孤單寂寞的大叔";
             Persons.push(obj);//放入集合中
             obj = new Person();
             obj.Name = "孤單寂寞的輕熟女";
             Persons.push(obj);//放入集合中
             obj = new Person();
             obj.Name = "可能是車狂的大叔";
             Persons.push(obj);//放入集合中
             obj = new Person();
             obj.Name = "可能需要安全感的輕熟女";
             Persons.push(obj);//放入集合中
             obj = new Person();
             obj.Name = "愛好旅行的人";
             Persons.push(obj);//放入集合中
             obj = new Person();
             obj.Name = "您可能立馬要準備存款了";
             Persons.push(obj);//放入集合中

         }
         //End 塞假資料
  </script>
    <script type="text/javascript">
        //可以做出「Loading...」效果的兩個jQuery Plugin函式,非本文重點
        function blockUI() {
            $("form").block({
                message: '<h1>讀取中...</h1>',
                css: { border: '3px solid #a00' }
            });

        }
        function unBlockUI() {
            $("form").unblock();
        }
        //End blockUI
    </script>

    <script type="text/javascript">
        //查詢資料
        function searchData(pageNumber)
        {
            //「Loading...」畫面,使用jQuery blockUI套件
            //畫面會鎖住,避免使用者按完查詢鈕後又馬上再按一次查詢鈕,同時也讓使用者知道系統查詢資料中,非本文重點
            blockUI();
             
            //每頁顯示幾筆PageSize
            //※因為selectPageSize下拉選單在表單外,要把它的值抓過來表單裡
            var pageSize = $("select[name='selectPageSize']").val();
          
            $("input[name='PageSize']").val(pageSize);
             
            //目前頁索引
            $("input[name='CurrentPageIndex']").val((pageNumber - 1));
            //查詢參數表單
            var myForm = $("form[name='myForm']").serialize();//把表單序列化成QueryString
            localStorage[localStorageName] = myForm;//把QueryString存入localStorage
          
            //透過ajax呼叫資料
            //假裝資料讀取了2秒
            setTimeout(function () {
                $.ajax({
                    url: window.location.href,//實務上若使用ASP.net MVC的話,要改寫為"@Url.Action(actionName,controllerName)"
                    type: "get",//為了demo才用get,實務上查資料最好用post
                    async: true,//非同步執行
                    data: myForm,//傳遞的表單參數
                    cache: false,
                    success: function (result) {
                        //原本實務上應該要這樣寫↓
                        //$("#divResult").empty().html(result);
                        //result變數為從Controller回傳的Partial View,該Partial View的Action(上面的url參數)裡面的程式碼就是從DB撈出IQueryable<T>的結果資料集,
                        //然後在Razor那邊用C#跑迴圈組出Html Table

                        //為了Demo而寫的js搜尋資料版,非本文重點
                        showResult(myForm);
                       
                        //解除blockUI(),非本文重點
                        unBlockUI();
                    },
                    error: function (xhr) {
                        //解除blockUI(),非本文重點
                        unBlockUI();
                        
                    }

                });//End ajax

            }, 2000);
            

        }

        //顯示查詢結果 為了Demo才亂寫一堆js,非本文重點
        function showResult(UserInputQueryString)
        {
            //把使用者填寫的QueryString轉成JsonObject
            var userJsonObj = QueryStringToJSONObject( decodeURIComponent(UserInputQueryString));
           
            //查詢結果
            var queryResult = new Array();
            //搜尋跟使用者同類型的人
            $(Persons).each(function (index, jsObj) {
                 
                if (jsObj.Name == "肯幫忙全部填寫的好人,祝大大一生平安")
                {
                    if (userJsonObj.demoTextArea != "" && userJsonObj.demoText != ""
                        && (userJsonObj.chk鴻海 || userJsonObj.chkGoogle || userJsonObj.chkMicrosoft || userJsonObj.chkApple) && userJsonObj.demoSelect != "-1")
                    {
                        queryResult.push(jsObj);
                    }
                      
                }
                if (jsObj.Name == "懶惰不想填寫的人") {
                    if (userJsonObj.demoTextArea == "" && userJsonObj.demoText == ""
                       && (userJsonObj.chk鴻海 == undefined && userJsonObj.chkGoogle == undefined && userJsonObj.chkMicrosoft == undefined && userJsonObj.chkApple == undefined) && userJsonObj.demoSelect == "-1")
                    {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "可能是IT界微軟MVP的人") {
                    if (userJsonObj.demoSelect == "成為微軟MVP,並一直持續連任" && userJsonObj.chkMicrosoft)
                    {
                        queryResult.push(jsObj);
                    }
                }
            
                if (jsObj.Name == "孤單寂寞的大叔")
                {
                    if (userJsonObj.demoSelect == "脫離單身" && userJsonObj.demoRadio=="男") {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "孤單寂寞的輕熟女") {
                    if (userJsonObj.demoSelect == "脫離單身" && userJsonObj.demoRadio == "女") {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "可能是車狂的大叔") {
                    if (userJsonObj.demoSelect == "買部跑車" && userJsonObj.demoRadio == "男") {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "可能需要安全感的輕熟女") {
                    if (userJsonObj.demoSelect == "買下信義區的豪宅" && userJsonObj.demoRadio == "女") {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "愛好旅行的人") {
                    if (userJsonObj.demoSelect == "環遊世界") {
                        queryResult.push(jsObj);
                    }
                }
                if (jsObj.Name == "您可能立馬要準備存款了")
                {
                    if (userJsonObj.demoSelect == "買下信義區的豪宅") {
                        queryResult.push(jsObj);
                    }
                }
                
                    if ($(queryResult).size() > 0)//有結果
                    {
                        var str = "<div>您是這樣的人↓</div>" +
                                   "<ul>";
                        $(queryResult).each(function (index, jsObj) {

                            str += "<li>";
                            str += jsObj.Name;
                            str += "</li>";
                        });
                        str += "</ul>";
                        $("#divResult").empty().html(str);//顯示結果
                    } else {
                        $("#divResult").empty().html("查無資料,請多嘗試,也許右鍵檢視原始碼可以幫助您");//顯示結果    
                    }
                 
                });
             
        } 
              
          
       
       
    </script>
    <script type="text/javascript">
        //底下的javascript很重要,請自行抽出.js檔再引用

        //將queryString轉成JsonObject
        //※使用此函數要注意,<input type='checkbox' />不能取相同的name,否則checkbox部份一律只會回傳一個值
        function QueryStringToJSONObject(queryString) {
            var pairs = queryString.split('&');

            var result = {};
            pairs.forEach(function (pair) {
                pair = pair.split('=');
                result[pair[0]] = decodeURIComponent(pair[1] || '');
            });

            return JSON.parse(JSON.stringify(result));

        }
        //還原表單欄位值,並顯示查詢結果
        function RestoreForm(name) {

            //此localStorage[name] 有存在
            if (localStorage[name]) {
                var queryString = localStorage[name];
                var jsonObj = QueryStringToJSONObject(decodeURIComponent(queryString));
                  
                RestoreFormValues(jsonObj);//把值還原回表單

                //因為「每頁顯示幾筆PageSize」下拉選單不在表單裡,所以要另外處理
                var $form = $("form");//第一個表單
                //從表單內的hidden欄位取值
                var PageSize = Number($form.find("input[type='hidden'][name='PageSize']").val());
                $("select[name='selectPageSize']").val(PageSize);//更改下拉選項
                  

                var js查詢按鈕Obj = $("input[value='查詢']")[0];//轉型成js物件
                if (js查詢按鈕Obj) { //有查詢按鈕
                    $(js查詢按鈕Obj).click();//點擊它,顯示資料
                } else {
                    //因為有些查詢畫面,無須下條件(表單欄位)查詢,單純查看畫面然後點選哪一頁(pager),且無查詢按鈕
                    //為了還原原本使用者瀏覽的資料,要依據「每頁顯示幾筆」和「目前在哪一頁」來顯示上次瀏覽的資料
                    //※如果偷懶的話,其實可以不用寫if判斷查詢按鈕在不在畫面上,直接使用底下三行來Run就好了XD
                    var CurrentPageIndex = Number($form.find("input[type='hidden'][name='CurrentPageIndex']").val());
                    var pageNumber = CurrentPageIndex + 1;//目前頁數
                    searchData(pageNumber);//查詢資料
                }
            }

        }


        //把JsonObj裡的每個屬性值填入到各表單欄位
        function RestoreFormValues(jsonObj) {


            // reset form values from jsonObject
            $.each(jsonObj, function (name, val) {
                var $el = $('[name="' + name + '"]'),
                    type = $el.attr('type');

                switch (type) {
                    case 'checkbox':
                        $el.prop("checked",true).attr('checked', true);
                        break;
                    case 'radio':
                        $el.filter('[value="' + val + '"]').prop("checked", true).attr('checked', true);
                        break;
                    default://預設是input元素,也有可能是textarea
                        $el.val(val);
                }
            });


        }



        //處理radio、checkbox、select元素,讓它們的狀況跟以前一樣
        function registerRadio_CheckBox_Select() {
            //註冊radio click時,是否加上checked屬性的事件
            $("input[type='radio']").click(function () {
                $("input[type='radio']").removeAttr("checked");
                $(this).attr("checked", true).prop("checked", true);
            });
            //註冊checkbox click時是否加上checked屬性的事件
            $("input[type='checkbox']").click(function () {
                //判斷CheckBox勾選狀態
                if ($(this).prop("checked") == true) {
                    $(this).attr("checked", true);
                } else {
                    $(this).attr("checked", false);
                }

            });
            //註冊下拉選單更動時的事件
            $("select").change(function () {
               
                var value = $(this).val();//選中的值
                $(this).find("option").not("[value='" + value + "']").removeAttr("selected");
                $(this).find("option[value='" + value + "']").attr("selected", true);
                
            });

        }

    </script>


    <script type="text/javascript">
        function Logout()
        {//登出
            //記得localStorage要清掉,不清也是可以,看需求
            //或者如果是後台網站的話,在登入畫面click登入按鈕那個時候,清除localStorage也是可以
            localStorage.clear();//清除此網站的localStorage
            alert("完成登出並清除localStorage,畫面將導至您的最愛網站,請記得回來此頁看看查詢結果還在不在");
            window.location.href = "http://www.microsoft.com/taiwan/silverlight/FanClub2014/";
        }
    </script>
</body>
</html>

 

附上關鍵的程式碼片段↓,要使用localStorage還原原本的表單欄位值並顯示原先的查詢結果

請先準備以下三個JS函式


        //將queryString轉成JsonObject
        //※使用此函數要注意,<input type='checkbox' />不能取相同的name,否則checkbox部份一律只會回傳一個值
        function QueryStringToJSONObject(queryString) {
            var pairs = queryString.split('&');

            var result = {};
            pairs.forEach(function (pair) {
                pair = pair.split('=');
                result[pair[0]] = decodeURIComponent(pair[1] || '');
            });

            return JSON.parse(JSON.stringify(result));

        }
        //還原表單欄位值,並顯示查詢結果
        function RestoreForm(name) {

            //此localStorage[name] 有存在
            if (localStorage[name]) {
                var queryString = localStorage[name];
                var jsonObj = QueryStringToJSONObject(decodeURIComponent(queryString));
                  
                RestoreFormValues(jsonObj);//把值還原回表單

                //因為「每頁顯示幾筆PageSize」下拉選單不在表單裡,所以要另外處理
                var $form = $("form");//第一個表單
                //從表單內的hidden欄位取值
                var PageSize = Number($form.find("input[type='hidden'][name='PageSize']").val());
                $("select[name='selectPageSize']").val(PageSize);//更改下拉選項
                  

                var js查詢按鈕Obj = $("input[value='查詢']")[0];//轉型成js物件
                if (js查詢按鈕Obj) { //有查詢按鈕
                    $(js查詢按鈕Obj).click();//點擊它,顯示資料
                } else {
                    //因為有些查詢畫面,無須下條件(表單欄位)查詢,單純查看畫面然後點選哪一頁(pager),且無查詢按鈕
                    //為了還原原本使用者瀏覽的資料,要依據「每頁顯示幾筆」和「目前在哪一頁」來顯示上次瀏覽的資料
                    //※如果偷懶的話,其實可以不用寫if判斷查詢按鈕在不在畫面上,直接使用底下三行來Run就好了XD
                    var CurrentPageIndex = Number($form.find("input[type='hidden'][name='CurrentPageIndex']").val());
                    var pageNumber = CurrentPageIndex + 1;//目前頁數
                    searchData(pageNumber);//查詢資料
                }
            }

        }


        //把JsonObj裡的每個屬性值填入到各表單欄位
        function RestoreFormValues(jsonObj) {


            // reset form values from jsonObject
            $.each(jsonObj, function (name, val) {
                var $el = $('[name="' + name + '"]'),
                    type = $el.attr('type');

                switch (type) {
                    case 'checkbox':
                        $el.prop("checked",true).attr('checked', true);
                        break;
                    case 'radio':
                        $el.filter('[value="' + val + '"]').prop("checked", true).attr('checked', true);
                        break;
                    default://預設是input元素,也有可能是textarea
                        $el.val(val);
                }
            });


        }

再來要做的事情就很輕鬆,View加三行程式碼就好,開發速度超快XD

image

↑在$(document).ready();裡,去還原表單欄位的值&顯示之前的查詢結果

 

image

 

這樣就差不多了,↓剩下就是自行決定什麼時候要幫使用者清除localStorage

image

線上Demo(請用IE瀏覽):

http://shadowjapan.blob.core.windows.net/dotblogsshare/UseLocalStorage.html

體驗方法↓

image

 

※2014-07-13追記:發現Demo網頁有一個小Bug

因為鴻海Checkbox的name我取名為chk鴻海,可能是Windows Azure或程式碼哪邊不支援中文命名,所以勾選鴻海的話,鴻海Checkbox無法勾選回去,糗了XD

※2014-07-14追記:

在鍥而不捨追查下,發現chk鴻海勾不回去的原因在這行↓


var myForm = $("form[name='myForm']").serialize();

jQuery的serialize()函式很貼心地,會自動把表單欄位的name和value全都做encodeURIComponent

所以在還原表單欄位值時↓

image

解決寫法有兩種

第一種↓

image

或第二種↓

image

個人偏向第二種,因為我自己開發上,已把RestoreForm的JS函式抽到.js檔,所以改一次就全部都套用了

以上Bug已修正,並更新部落格文章和線上Demo,請安心服用。

 

 

 

 

結語

以後有keep住值的需求,不只是傳統的Session、Cookie,新玩意的localStorage有時候會出乎意料地加快開發速度。

 

 

 

 

 

參考文章:

Turning the Querystring into a JSON object using JavaScript

Use jquery to re-populate form with JSON data - StackOverflow