可凍結式GridView強化版: 隱藏、跳列、尋找
| | 20 | | ![]() |
自從前幾天幫同事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="尋找" />
移至第<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的部分倒歡迎大家討論。
Comments
# by Joey
你是我的神!
# by Ammon
關鍵字部分有個 :contains 可以用 http://docs.jquery.com/Selectors/contains#text
# by Jeffrey
to Ammon, 謝謝補充,在以上的程式範例可用contains()取代indexOf(),寫成filter("td:gt(" + focusIdx + "):contains(" + keywd+ ")"),程式碼又會更簡潔。不過,keywd可能會出現")"之類的字元,會有要Escape的問題。這部分我還沒想出好方法。 寫Code時本來野心更大,想說還可以加入模糊比對(Regular Expression)之類的邏輯,所以特別用each一一抓出來,以便可以自己組出各式精彩的if條件進行判別,結果... 嘿嘿,在虎頭蛇尾中劃上句點。
# by Ark
可不可以幹掉FarPoint Spread 7這鬼東西 (專跑 VBscript in IE 其他都死) edit的狀態 鎖定cell的型別(int ,date, text or double ) 不給user 亂key onblur 抓出第幾row第幾欄 並且有cell_leave ,cell_onclick 等event 可加自己的function 運算:比如我要得到這row 裡 1,3,5,7的加總值 放到第10 col
# by Jeffrey
to Ark, 聽起來這些需求用jQuery都可以簡單做到,Case-By-Case客製還OK,要達到包成元件可以適用不同情境彈性組合運用,恐怕就是一番不小的工程,阿彌陀佛... XD
# by Howie
Spread還挺好用的呀..(煙)
# by citypig
flexigrid 可以動態調整表格大小、欄寬、顯示欄位... 也是用 jQuery 站長要不要順便整合看看? http://www.flexigrid.info/
# by Jeffrey
to citypig, Flexgrid看起來挺強的,還是Pure jQuery Code, 改造潛力無限,有時間來瞧一下,感謝推薦。
# by alan
黑大您好,剛試了一下,只能說您太強了 小弟剛測了一個問題 就是當點了欄位頭的CheckBox,就會全選沒錯 可是當我把第一筆的勾勾取消,按下隱藏勾選 照理只會秀第一筆的資料條,可是顯示的卻是只有"料號" 後面庫存的數字都不見了!這是何解呢?
# by Jeffrey
to alan, 嘿... 被你抓到蟲蟲了。 $(".sFData tr:not(:visible)") : $(".clsHideCbx:checked").closest("tr") 這一列有問題,要改成 $(".sFData tr:not(:visible)") : $(".sFData .clsHideCbx:checked").closest("tr") 才對。測了一下,該Bug應該已排除。
# by 萧萧
如果遇到分页怎么搞呢,这些功能是比较好,最好是能加上分页的就完美了
# by Maxi
暗黑大,這一下沒有打包下載回來玩嗎?
# by ddt
版主您好 請教我該怎麼樣讓分頁show出來呢 感恩歐
# by ddt
版主您好 請教您 我該怎麼樣讓 分頁 show 出來呢 感恩感恩
# by Jeffrey
to ddt, 萧萧, 這種凍結模式我想多半應用的情境是一口氣載入表格全部內容,再用捲動的檢視內容,我倒沒有把它改造成分頁檢視的動機。不要一次載入全部,捲到哪再預先載入之後要顯示的內容倒是挺實用的改良(有點像噗浪河道的拖拉操作概念),評估了一下,頗具難度,只能看未來是否能累積足夠的熱血再攻頂看看。(或是有高手達人願意露兩手讓大家見識一下,歡迎之至)
# by ddt
版主您好 謝謝您的回應 我的問題是說 gridview 下方自動生成的分頁項 套入js 之後就不見了, 可否給個方向呢 謝謝嚕
# by 大元
我用感動的態度欣賞你
# by gym
楼主 IE8下不好用 这个问题有解决吗? 58963034@163.com
# by thtomas
版主: 我想請問一下,如果要凍結表頭兩列的話,要如何修改呢? 因為有自訂多表頭的需求,謝謝~
# by thtomas
版主: 如果一個頁面有兩個GRIDVIEW的話,似乎只有一個gridview可以正常顯示耶...另一個就便回原形,無法有凍結的效果...可否有辦法解決?