Friday, February 20, 2009 - 文章

可凍結式GridView強化版: 隱藏、跳列、尋找

自從前幾天幫同事Survey了可凍結列、欄的GridView的解決方案後,反應出奇熱烈... 大家熱烈地提出許多希望能"更方便使用"的"好點子"。啊! 腦海中浮現經典的場景: User看完Prototype後,興奮地提出更多的規格需求,一片歡樂中,唯有一人悶悶不樂、背脊發涼、冷汗直流 --- 負責Coding的那個可憐蟲...

看人口渴,貼心奉上一杯茶,誰知,張三問能不能少糖去冰多加檸檬,李四則嚷著想改成加蛋不加槓丸。

不過,愈是複雜的Scenario,就愈能突顯jQuery的威力,害不服輸的我又熱血起來,所以...

有興趣的人可以看一下線上展示,打勾並按【隱藏選取列】可以把部分資料列藏起來、也可以輸入列號後移至指定的表格列,最後還實作了尋找會自動捲動到所在位置並反白顯示關鍵字的功能(一直按尋找會自動找下一筆吻合者)。

多虧jQuery,程式寫起來比想像中簡短,而且用到的API還挺多的: after, attr, remoteAttr, addClass, css, evt.target, toggle, find, end, $.browser.ie, offset, position, val, scrollTop, scrollLeft, text, html, is, filter, each, click...

    <script type="text/javascript">
        $(function() {
            //在表格裡塞入選取欄位
            $("#GridView1 th:nth-child(1)")
            .after("<th><input type='checkbox' id='cbxSelAll' /></th>");
            $("#GridView1 td:nth-child(1)")
            .after("<td><input type='checkbox' class='clsHideCbx' /></td>");
            //配合SuperTable的多Table同步處理,加上列號
            $("#GridView1 tr").each(function(i) {
                $(this).attr("rowidx", i)
                .find("td").each(function(j) {
                    $(this).attr("pos", i + "_" + j);
                });
            });
            //設定SuperTable
            $("#GridView1").toSuperTable({ width: "640px", height: "480px", fixedCols: 3 })
            .find("tr:even").addClass("altRow");
            //加上全選/全不選功能(.sFHeader為配合SuperTable才加)
            $(".sFHeader #cbxSelAll")
            .click(function() {
                if (this.checked)
                    $(".clsHideCbx").attr("checked", "checked");
                else
                    $(".clsHideCbx").removeAttr("checked");
            });
            //加上隱藏/顯示功能
            $("#btnHide,#btnShowAll").click(toggleRow);
            //隱藏/顯示共用一個事件,由evt.target判別按的是哪一顆
            function toggleRow(evt) {
                var show = (evt.target.id == "btnShowAll");
                var rowSet = (show) ?
                    $(".sFData tr:not(:visible)") : $(".sFData .clsHideCbx:checked").closest("tr");
                rowSet.toggle(show)
                //一般情況到hide()即可,以下這段是為了SuperTable而加的
                //把捲動區裡那一份<table>對應的資料列也同步藏起來
                .each(function() {
                    $(".sData tbody tr[rowidx=" + $(this).attr("rowidx") + "]").toggle(show);
                });
                $(".sData tbody").find(".altRow").removeClass("altRow")
                .end().find("tr:visible:even").addClass("altRow");
                //修正IE隱藏結尾會不齊的問題
                if ($.browser.msie) {
                    var fixedColZone = $(".sFDataInner");
                    var cellZone = $(".sData table");
                    var p1 = fixedColZone.offset().top;
                    var p2 = cellZone.offset().top;
                    if (p1 != p2) {
                        fixedColZone.css("top", (p2 - fixedColZone.parent().offset().top) + "px");
                    }
                }
            }
 
            function getPosVal(s) {
                return parseInt(s.replace("px", ""));
            }
 
            $("#btnScroll").click(function() {
                scrollToRow($("#rowIdx").val());
            });
 
            //捲動到指定列數
            function scrollToRow(rowIdx) {
                //IE下有一列的位移,鋸箭法校正
                if ($.browser.msie && !isNaN(rowIdx))
                    rowIdx = parseInt(rowIdx) - 1;
                var x = $(".sData tr[rowidx=" + rowIdx + "]");
                if (x.length > 0) {
                    //alert($(".sData").scrollTop() + "," + x.position().top);
                    $(".sData").scrollTop(
                        $(".sData").scrollTop() +
                        x.position().top);
                }
            }
            //捲動到指定的欄數
            function scrollToCol(colIdx) {
                var x = $(".sData td:eq(" + colIdx + ")");
                $(".sData").scrollLeft($(".sData").scrollLeft() + x.position().left);
            }
 
            //保留所有Cell的集合
            var allCells = $(".sData #GridView1 td");
 
            $("#btnFind").click(function() {
                var keywd = $("#keywd").val();
                //先找到上次的焦點
                var focusIdx = 0;
                var hasPrevFocus = false;
                allCells.filter("td[findfocus]").each(function() {
                    focusIdx = allCells.index(this);
                    //將focus移除
                    $(this).removeAttr("findfocus")
                    //去除Highlight
                    .html($(this).text());
                    hasPrevFocus = true;
                });
                //由焦點開始往後找
                allCells.filter("td:gt(" + focusIdx + ")")
                .each(function() {
                    var td = $(this);
                    if (td.text().indexOf(keywd) > -1) {
                        var p = td.attr("pos").split("_");
                        scrollToRow(p[0]);
                        var cell = allCells.filter("td[pos=" + td.attr("pos") + "]");
                        cell.attr("findfocus", "true")
                        .html(cell.text().replace(keywd, 
                            "<span style='background-color:yellow;'>" + keywd + "</span>"));
                        scrollToCol(p[1]);
                        return false;
                    }
                });
                if (!allCells.is("td[findfocus]")) {
                    if (hasPrevFocus) {
                        if (confirm("已搜尋至結尾,要從頭開始再找一次嗎?"))
                            $("#btnFind").click();
                    } else
                        alert("找不到指定的關鍵字!");
                }
            });
 
        });
    </script>
    <style type="text/css">
    .clsLinkButton  
    { font-size: 9pt; cursor: pointer; text-decoration: underline; color: Blue; }
    #rowIdx { width: 20px; text-align: right; }
    #spnCmdBar { font-size: 9pt; margin-left: 15px; }
    </style>
</head>
<body>
<span id="spnCmdBar">
關鍵字: <input type="text" id="keywd" style="width: 80px;" /> 
<input type="button" id="btnFind" value="尋找" />&nbsp;
移至第<input type="text" id="rowIdx" value="1" />
<input type="button" value="捲動吧! 表格" id="btnScroll" /></span>
<span id="btnHide" class="clsLinkButton" style="margin-left: 150px;">隱藏選取列</span>
<span id="btnShowAll" class="clsLinkButton">顯示全部</span>

這只是個jQuery Coding Demo,不是產品或解決方案的發表會,大家要冷靜,關於功能面的提議不要太熱烈吶~~~ Coding的部分倒歡迎大家討論。

搜尋

Go

<February 2009>
SunMonTueWedThuFriSat
25262728293031
1234567
891011121314
15161718192021
22232425262728
1234567
 
RSS
【工商服務】
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


BlogLook Score and Rank

Syndication