วันพฤหัสบดีที่ ๑๒ พฤศจิกายน พ.ศ. ๒๕๕๒

Javascript - สร้าง TextBox เพื่อ filter รายการใน DropDownList

ผมได้รับ requirement ใหม่จาก user เจ้ากรรมอีกแล้ว นั่นคือมี DropDownList ตัวหนึ่งใน ASP.NET ที่มีรายการมากกว่า 100 รายการ (อันนี้กรองมาแล้วนะครับ) ซึ่ง option มันเยอะมาก ดังนั้น user ต้องการให้โปรแกรมสามารถ filter รายการใน DropDownList นี้ได้ครับ ทีนี้จะเขียนโปรแกรมที่ฝั่ง server ก็สามารถทำได้ แต่มันจะทำให้มีการ postback ไปหา ซึ่งไม่ค่อยดีเท่าไหร่ ดังนั้นผมเลยใช้ javascript สำหรับ filter แทนครับ

วิธีก็คือผมสร้าง Textbox ขึ้นมาหนึ่งตัว สำหรับให้ user พิมพ์ข้อความที่ต้องการกรอง และสร้าง drop-down list อีกหนึ่งตัวโดยให้ visibility=hidden คือซ่อนไม่ให้ user เห็น สำหรับเก็บ option ทั้งหมดที่ไม่ได้ทำการกรองครับ ลองมาดูโค้ดกัน

เริ่มจาก WebControl ก่อน มี DropDownList 2 ตัว และ TextBox ครับ


<asp:DropDownList ID="ddlWorkCode" runat="server" CssClass="txtRequired" Width="540px" AutoPostBack="True" style="height:24px"></asp:DropDownList"> 
<asp:TextBox ID="txtSearchWorkCode" runat="server" Width="421px" style="color: #000099; background-color: #afeeee;""></asp:TextBox">
<asp:DropDownList ID="ddlCache" runat="server" Width="0px" style="visibility:hidden" "></asp:DropDownList"> 


ในหน้า Code Behind ก็ทำการ Add Attribute ให้ txtSearchWorkCode

txtSearchWorkCode.Attributes.Add("onkeyup", "txtSearchWorkCode_OnKeyUp(this);")
txtSearchWorkCode.Attributes.Add("onblur", "txtSearchWorkCode_OnBlur();")



คราวนี้มาถึง javascript บ้าง คราวนี้เขียนสดๆไม่ได้ใช้ jQuery ครับ

function txtSearchWorkCode_OnKeyUp(obj) {
if (event.keyCode != 13 || event.keyCode != 9) {
var str = obj.value.toUpperCase();
var ddlWorkCode = $get("ddlWorkCode");
var ddlCache = $get("ddlCache");
var listWorkCode = ddlCache.getElementsByTagName("OPTION");

// ถ้าไม่มี OPTION ใน cache ให้ออกจาก function
if(listWorkCode.length==0) return false;

//clear option ใน DropDownList
ddlWorkCode.length = 0;
for (i = 0; i < listWorkCode.length; i++) {
if (listWorkCode[i].text.toUpperCase().indexOf(str) > -1) {
var o = listWorkCode[i].cloneNode(true);
ddlWorkCode.appendChild(o);
}
}
ddlWorkCode.selectedIndex = 0;
}
}

function txtSearchWorkCode_OnBlur() {
if ($get("txtSearchWorkCode").value == "") {
// ถ้าไม่มีคำสั่งกรอง ให้ไปดึง OPTION ทั้งหมดจาก DropDownList2 มาใส่คืน
var ddlWorkCode = $get("ddlWorkCode");
var ddlCache = $get("ddlCache");

ddlWorkCode.lenght = 0;
for (i = 0; i < ddlWorkCode2.options.length; i++) {
var o = ddlWorkCode2.options[i].cloneNode(true);
ddlWorkCode.appendChild(o);
}
ddlWorkCode.selectedIndex = 0;
}
}


ในส่วนคำสั่ง javascript มีสองจุดที่น่าสนใจครับ นั่นคือ
1. ผมใช้ ddlWorkCode.length=0; ในการเคลียร์ option ของ drop-down list ทิ้งครับ ถือว่าง่ายและสะดวกมาก ทีแรกผมใช้ for วนลูปเพื่อ remove element ออก ซึ่งแน่นอนว่าช้ากว่าครับ

2. ผมใช้ cloneNode method ในการ copy OPTION จาก drop-down list ตัวที่สอง (ที่เก็บข้อมูลทั้งหมดไว้) แล้วก็เอา OPTION ที่ clone ได้ไปใส่ใน drop-down list ตัวแรกด้วยคำสั่ง appendChild ทีแรกผมใช้วิธีสร้าง new Option ครับ แต่เจอคำสั่ง cloneNode ที่ www.java2s.com ใช้ได้สะดวกดีครับ และที่สำคัญพอลอง search ใน google พบว่าคำสั่ง cloneNode ทำได้เร็วกว่า New element ซะอีก

ตอนนี้ลองทดสอบโปรแกรมดู ก็ใช้งานได้ดียังไม่เจอ bug แต่เพิ่งทดสอบได้นิดเดียวคงต้องลองเล่นดูอีกสักพักครับ

ปล. สำหรับ $get() เป็น shortcut ของ ASP.NET AJAX ครับ มีค่าเท่ากับ document.getElementById()

ไม่มีความคิดเห็น: