วันศุกร์ที่ ๓ กรกฎาคม พ.ศ. ๒๕๕๒

jQuery กับการทำ Multi Column Autocomplete

พอดีได้รับ requirement ให้ทำ auto complete function ครับ สมมติว่า user คีย์ชื่อพนักงาน ให้โปรแกรมไปดึงรายชื่อพนักงานทั้งหมดที่ใกล้เคียงมาแสดง พอ user เลือกพนักงานที่ต้องการจากใน list ก็ให้ไปแสดงข้อมูลอื่นๆของพนักงานใน field อื่นๆด้วย เช่นรหัสพนักงาน ชื่อ นามสกุล แผนก วันเริ่มงาน เป็นต้นครับ
ทีนี้ลอง search ดูพวก autocomplete จาก google พบว่าส่วนใหญ่มันเป็นแบบ single field คือใช้กับ textbox ตัวเดียวครับ เลยต้องเขียน javascript เพื่อไปดึงข้อมูลจาก Web Service มาให้ user เลือก แล้วพอเลือกแล้วก็เขียน javascript ให้ไปตัดข้อมูลลงใน element ต่างๆ
รู้สึกว่าการเขียน javascript เองนี่มันยาวพอสมควรครับ พอมีเวลาว่างก็เลยมาลองใช้ jQuery ดูว่ามันจะง่ายและดีสมคำร่ำลือหรือเปล่า ผมเลยสร้าง web page สำหรับทดสอบดู เอาเป็นว่ามีแค่ 2 field คือ ID กับ ชื่อนามสกุลก็พอครับ
ก่อนอื่นมาดูโค้ดหน้าเวบกันก่อน

<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/Employee.asmx" />
</Services>
</asp:ScriptManager>
<div>
<asp:TextBox ID="txtEmpId" runat="server" style="width:100px" MaxLength="6"></asp:TextBox>
<asp:TextBox ID="txtEmpName" runat="server" style="width:250px"></asp:TextBox>
</div>
</form>
</body>

จะเห็นว่ามี textbox แค่สองอัน และมีการใช้ ScriptManager เพื่อไปเรียก WebService ครับ
โค้ดส่วน WebService ขอไม่เขียนนะครับ เพราะไม่ยาก โดยตัว WebService จะคืน Employee Object มาให้ในรูปของ JSON (ตาม default ครับ)
ทีนี้มาดูโค้ดส่วน javascript กันบ้าง

<script type="text/javascript" src="../Scripts/jquery-1.3.2-vsdoc.js"></script>
<script type = "text/javascript">
$(function() {
$("#txtEmpName").keyup(function(event) {txtEmpName_OnKeyUp(event)});
});

function txtEmpName_OnKeyUp(e) {
if (e.keyCode != 13 || e.keyCode != 9) {
$("#txtEmpId").val("");
var empName = $("#txtEmpName").val();
if (empName.length > 2) {
jnithi.Employee.GetStaffsByKeyword(empName, GetStaffSuccess);
} else {
$("#divStaff").hide();

}
}
}

function GetStaffSuccess(result, methodName, context) {
if ($("#divStaff").length == 0) {
var txtEmpName = $("#txtEmpName");
var pos = txtEmpName.position();
var divStyle = {'position':'absolute','top': pos.top + txtEmpName.outerHeight() + 'px','left': pos.left + 'px','width': txtEmpName.outerWidth() +'px','border':'1px solid #666666' };
$(document.createElement("div")).attr("id", "divStaff").css(divStyle).appendTo("body");
}
var divStaff=$("#divStaff");
divStaff.empty();

if (typeof (result) != "undefinded" && result.length > 0) {
$(document.createElement("dl")).width(divStaff.width()).appendTo("#divStaff");
var i;
for (i = 0; i < result.length; i++) {
var employee = result[i];
var html = "<dt><a class='search' href='#' onclick='dtStaff_OnClick(this);' >" + employee.NewEmployeeId + ":" + employee.NameEng + "</a></dt>";
$("dl").append(html);
}
if (i > 0) {
divStaff.show();
}
} else {
divStaff.hide();
}
}
function dtStaff_OnClick(obj) {
result = obj.innerHTML.split(":");
$("#txtEmpId").val(result[0]);
$("#txtEmpName").val(result[1]);
$("#divStaff").hide();
}
</script>


เริ่มต้นก็ไปกำหนด Event Handler ให้กับ keyup event ของ txtEmpName ครับ
$(function() {
$("#txtEmpName").keyup(function(event) {txtEmpName_OnKeyUp(event)});
});

โดยปกติตัวอย่างของ jQuery จะเขียน function ไปเลย แต่ปรากฎว่า Visual Studio มัน debug ลำบาก ผมเลยแยกมาเขียน function ต่างหากครับ โดยมี window.event เป็น parameter หรือเราใช้ MSAjax อยู่แล้วอาจจะพิจารณาใช้ $addHandler() ของ MSAjax แทนก็ได้ครับ เมื่อเกิด keyup event มันก็จะไปเรียก txtEmpName_OnKeyUp ให้ทำงาน โดยจะไปเรียก WebService และกำหนด succeed callback function ไปที่ GetStaffSuccess ครับ (จริงๆควรจะกำหนด onFailed callback function ด้วยนะครับ)

ใน GetStaffSuccess function ผมให้มันทำการสร้าง div ที่บรรจุ dl element ไว้ครับ เพื่อเป็น list ให้ user เลือก สังเกตุว่าใน function นี้ผมทดลองทำการ creat element ไว้ 2 แบบ แบบแรกคือใช้ $(document.createElement(element)).appendTo(element) กับอีกแบบคือ $(element).append(html) แล้วก็ต้องกำหนด onclick event ด้วย เพื่อที่ว่าเมื่อ user เลือกรายชือพนักงานแล้ว จะได้ไปทำ dtStaff_OnClick ซึ่งจะทำการตัดข้อมูลไปใส่ใน textbox ทั้ง 2 ตัวครับ

ลองเอาโค้ดที่เขียน javascript เอง กับที่เขียนด้วย jQuery เห็นได้ว่าโค้ดสั้นลงประมาณ 30% เพราะใช้ประโยชน์ของ Chainability นั่นเองครับ

1 ความคิดเห็น:

Unknown กล่าวว่า...

jqury สามารถ createelement ได้โดยแบบนี้คับ
$("น้อยกว่า img/ มากกว่า").attr("src", "http://www.google.co.th/intl/en_com/images/logo_plain.png").appendTo("#google");