Article
>  Home   HTML   CSS   JavaScript   PHP   Perl   Photoshop   TCP/IP 

การสร้างเมนูแบบ RealDev ตอนที่ 1: การสร้าง Class ของเมนู

โดย สรวุฒิ กอสุวรรณศิริ

ในที่สุดก็มาถึงบทความที่ทุกท่านรอคอย สำหรับเรื่องการสร้างเมนูแบบ RealDev นี้ผมจะแบ่งออก เป็น 3 ตอนนะครับ ตอนที่ 1 จะเป็นเรื่องของการออกแบบและสร้างคลาสของเมนูขึ้นมาก่อน และจะสอนวิธีการนำคลาสนี้มาใช้ในตอนที่ 2 ส่วนตอนที่ 3 จะเป็นการทำให้เมนูสามารถเลื่อนขึ้นเลื่อนลงได้นะครับ

ตามที่ผมเคยบอกกับผู้อ่านไปแล้วในบทความก่อนหน้านี้ว่า เมนูของผมผมเขียนมันเป็นคลาส และนำมาใช้โดยการประกาศเป็นอ็อบเจกต์ และตอนนี้ผมก็ได้ปูพื้อนฐานเรื่องการสร้างคลาส และการใช้ Layer มาพอสมควรแล้ว เมื่อท่านพร้อมแล้วเรามาออกแบบเมนูกันดีกว่าครับ

ออกแบบเมนู

เราลองมาคิดดูก่อนว่า คุณสมบัติของเมนูที่ต้องการควรจะมีอะไรบ้าง สิ่งที่เมนูทั่วๆไปจะต้องมีคืออะไร เมนูหนึ่งๆนั้น ไม่ว่าจะเป็นเมนูหลักหรือเมนูย่อย จะต้องประกอบด้วยตัวเลือกในเมนูหลายๆตัว ดังนั้น เมนูก็คือ Array ของตัวเลือกในเมนู ถูกไหมครับ ถ้าอย่างนั้น ผมจะสร้างคลาสของเมนูของผมแบบนี้

function MenuType() { this.MenuItems = new Array(); }

MenuItems ก็คือตัวเลือกในเมนูไงครับ ซึ่งผมจะทำให้เป็นคลาสเมนูไอเท็มซึ่งจะอธิบายในหัวข้อถัดไป ทีนี้ ในการนำเมนูมาวาด ก็จะต้องมี การกำหนดขนาด และการกำหนดสี ของเมนู ซึ่งสิ่งเหล่านี้อาจจะกำหนดไว้ตายตัวในฟังก์ชั่นก็ได้ แต่ถาทำเช่นนั้น เมนูของคุณจะมีสีได้เพียงสีเดียว แต่เมนูของผม จะต้องสามารถกำหนดสี และความกว้างได้ด้วย ยิ่งกว่านั้น ผมต้องการให้เมนูของผม สามารถกำหนดคุณลักษณะต่างๆผ่านทาง CSS ได้ด้วย เพื่อให้ เมนูที่ถูกทำเป็นเมนูย่อย สามารถ ซ่อน/แสดงเมนูได้ (จำได้ไหมครับ การซ่อน/แสดงต้องใช้ความสามารถของ JavaScript+CSS) ดังนั้น ผมจึงเพิ่มเติม Properties ลงไปแบบนี้

function MenuType(mid,wid) { this.id=mid; // เป็น id ของ Style ที่กำหนดไว้ใน CSS this.MenuItems = new Array(); this.bgColor = "#006699"; // สีพื้นหลังของเมนู this.width=wid; // ความกว้งของเมนู this.build=MenuBuild; // ฟังก์ชั่นสร้างเมนู this.add = addMenuItem; // ฟังก์ชั่น เพิ่มตัวเลืองลงในเมนู }

สำหรับ ฟังก์ชั่นสร้างเมนู และ ฟังก์ชั่น เพิ่มตัวเลืองลงในเมนู เป็นเมทธอดของเมนูครับ ฟังก์ชั่นสร้างเมนูจะเป็นส่วนที่วาดเมนูของเราลงบนเอกสาร HTML ตามคุณสมบัติที่เรากำหนดเอาไว้ ส่วนฟังก์ชั่นเพิ่มตัวเลืองลงในเมนู เป็นฟังก์ชั่น ที่จะใส่ตัวเลือกในเมนูเข้าไปครับ สำหรับรายละเอียดการทำงาน ผมขออธิบายในตอนท้าย เพราะเราจะต้องเข้าใจหลักการทำงานโดยรวมก่อน จึงจะเขียนโปรแกรมได้

ออกแบบเมนูไอเท็ม

เมนูไอเท็ม(MenuItem) คืออะไร มันก็คือตัวเลือกในเมนู หากจะทำเมนูแบบธรรมดาทั่วไป เราคงไม่ต้อง วุ่นวายสร้างคลาสของเมนูไอเท็มก็ได้ แต่เมนูที่ผมกำลังจะสอนคุณสร้างนี้ เป็นเมนูที่พิเศษ คือมีเมนูย่อยได้ ไม่จำกัดลำดับขั้น ดังนั้น ส่วนการประกาศคลาสของเมนูไอเท็มจึงเป็นดังนี้ function MenuItem(lb,ti,li,cl,su) { this.label=lb; this.title=ti; this.linkto=li; this.classname=cl; this.bgColor1 = "#006699"; // normal color this.bgColor2 = "#003366"; // hilight color this.build=MenuItemBuild; this.submenu=su; }

มาดูกันดีกว่า Properties และเมทธอดต่างๆ ใช้ทำอะไร

label เป็นข้อความของตัวเลือกนี้ ที่จะให้แสดงในเมนู
title เป็นข้อความที่จะให้แสดง เมื่อนำ mouse มาชี้ในเมนูนี้
linkto เป็น URL ที่จะให้ลิงก์ไปเมื่อผู้ใช้เลือกเมนูนี้
classname เป็นชื่อคลาสใน CSS ใช้สำหรับกำหนดสี,ฟอนต์,ขนาดของตัวอักษรในตัวเลือกนี้
bgColor1 ใช้กำหนดสีตัวอักษรในสภาวะปกติ
bgColor2 ใช้กำหนดสีตัวอักษรเมื่อนำ mouse มาชี้ที่ตัวเลือกนี้
build เป็นเมธอดที่ใช้วาดตัวเลือกนี้ลงในเอกสาร HTML เมธอดนี้จะถูกเรียกจากเมทธอด build() ของเมนูโดยอัตโนมัติเมื่อมีการวาดเมนู
submenu เป็นเมนูย่อยที่จะให้แสดงเมื่อนำ Mouse มาชี้ที่ตัวเลือกนี้

อย่าเพิ่งงงนะครับ คุณอาจจะเห็นพรอเพอร์ตีและเมธอดมากมาย แต่ก็เป็นเพราะเมนูของผมมีความยืดหยุ่น มากนั่นเอง เวลาที่คุณสร้างเมนูของตัวเอง อาจจะเพิ่มหรือลดพรอเพอร์ตีบางตัวลงก็ได้ แล้วแต่ว่าคุณต้องการให้เมนู ของคุณทำอะไรได้บ้างเท่านั้นเอง

คำถาม ?? การเขียนคลาสที่ผ่านมา เสร็จสมบูรณ์พร้อมใช้แล้วใช่หรือไม่ ??

คำตอบ ยังครับ ที่ผ่านมาเป็นการนิยามเท่านั้น ว่าจะให้เมนูและเมนูไอเท็มมีคุณสมบัติและทำอะไรได้บ้าง มันเป็นแค่ "จินตนาการ" ของผมเท่านั้น ยังไม่สามารถนำไปใช้ได้จริง จนกว่าจะเขียนส่วนกำหนดการทำงานของเมทธอดที่ได้นิยามไว้ครบทั้งหมด

คำถาม ?? นิยามเมนูแบบนี้ จะสร้างเมนูย่อยได้อย่างไร ??

คำตอบ เราลองคิดกันก่อนว่า เมนูย่อยคืออะไร? มันก็คือ "เมนู" ที่ปรากฎขึ้นมา เมื่อมีการเลือกตัวเลือกนั่นเอง ดังนั้น ในคลาสเมนูไอเท็ม ผมจึงกำหนดพรอเพอร์ตี "submenu" เพื่อเป็นตัวแปรพ้อยเตอร์ ชี้ไปที่เมนูย่อยของมัน ดังนั้น ทุกๆตัวเลือกในเมนู(และเมนูย่อย)จึงสามารถมีเมนูย่อยได้ เมนูของผมจึงมีเมนูย่อยได้ไม่จำกัด ระดับขั้น

กำหนดการทำงานของ Method ในเมนู

เอาละครับ เรากำหนดคุณสมบัติของเมนูแล้ว ทีนี้ก็มาถึงส่วนสำคัญ คือการเขียนเมธอด ที่ได้ ออกแบบไว้ในตอนต้น เอ... จะเอาเมทธอดอะไรก่อนดีนะ ผมขอเป็นเมธอด addMenuItem ของคลาสเมนูก็แล้วกัน ง่ายดี

อย่างที่บอกไปแล้วนะครับ เมนูไอเท็มของผมเป็นคลาส เวลานำมาใช้จึงเป็นอ็อบเจกต์ และเมนูของผมก็เป็นอาเรย์ของอ็อบเจกต์เมนูไอเท็ม ดังนั้นการทำงานของเมทธอดนี้ก็แคนำ อ็อบเจกต์ ของเมนูไอเท็มใส่ลงไปในลำดับสุดท้ายของอาเรย์ รายละเอียดของเมทธอดนี้จึงมีแค่นี้เท่านั้นครับ

function addMenuItem(MenuItemObject) // add Menu Item { this.MenuItems[this.MenuItems.length]=MenuItemObject; }

ส่วนเมทธอด MenuBuild() มีการทำงานคือ มันจะวาดเมนูลงบนเอกสาร HTML โดยใช้ตาราง เมื่อเปิดส่วนบนของตารางแล้ว มันจะไปเรียกเมทธอด build() ของเมนูไอเท็มแต่ละตัว ที่อยู่ใน List ของมันขึ้นมาทำงาน เพื่อวาดตัวเลือกในเมนูจนครบ แล้วเขียนส่วนท้ายของตารางเพื่อปิดตาราง

function MenuBuild() { var n=0; document.write('<div id="'+this.id+'">'); document.write('<table border=0 cellpadding=0 cellspacing=0 bgcolor="#000000" width='+this.width+'><tr><td>'); document.write('<table border=0 cellpadding=0 cellspacing=1 bgcolor="#000000" width=100%>'); for (n=0;n<this.MenuItems.length;n++) { this.MenuItems[n].build(); } document.write('</table></td></tr></table></div>'); }

ส่วนการสร้างเมนูไอเท็มนั้น ถ้าท่านลองสังเกตดีๆ จะพบว่าผมทำให้ตัวคลาสเป็น Constructor อยู่แล้ว คือเป็นฟังก์ชั่นสำหรับการสร้างอ็อบเจกต์และกำหนดค่าเริ่มต้นให้ด้วยในตัว ลองดูที่ส่วนหัวของ ส่วนประกาศสิครับ

function MenuItem(lb,ti,li,cl,su)

แล้วก็มาถึงเมทธอดสุดท้าย ที่ใช้ในการวาด เมนูไอเท็ม การทำงานก็คือ จะตรวจสอบก่อนว่า มีการกำหนดค่าใน linkto หรือไม่ ถ้าไม่ จะถือว่าเมนูนั้น links ไม่ได้ และไม่ทำลิงก์ให้ แต่จะถือว่าเป็นข้อความธรรมดา (ตัวอย่าเช่น คำว่า Fun Stuff ในเมนูไงครับ) ขั้นต่อมาก็จะวาดเมนูโดยการเขียน โค้ด HTML ซึ่งเป็นส่วนหนึ่งของตาราง โดยใช้คุณสมบัติต่างๆตามที่กำหนดไว้ใน Properties นั่นเอง โปรดสังเกตนะครับ เมนูของผม จะแบ่งวิธีการแสดงผลตามชนิดและเวอร์ชั่นของ Browser ไม่เหมือนกัน ตรงนี้คือส่วนที่ยังไม่สมบูรณ์นะครับ ถ้าใครนำไปพัฒนาต่อให้สมบูรณ์แล้ว ก็ส่งกลับมาให้ผมดูบ้างนะครับ

function MenuItemBuild() // Build Menu via Generate html code. { if (this.linkto=='nolink') { document.write('<tr><td class="'+this.classname+'">'+this.label); } else { if ((this.submenu != null)&& (navigator.appName == "Microsoft Internet Explorer")) { document.write('<tr><td bgcolor="'+this.bgColor1+'" onmouseover="menuOver(this,\''+this.bgColor2+'\'); '+this.submenu.id+'.style.visibility = \'visible\';" onmouseout="menuOut(this,\''+this.bgColor1+'\'); '+this.submenu.id+'.style.visibility = \'hidden\';" onclick="menuClick(this)"><div class="'+this.classname+'"><a href="'+this.linkto+'" class="'+this.classname+'" title="'+this.title+'">'+this.label+'</a></div>'); this.submenu.build(); } else { if (navigator.appName == "Microsoft Internet Explorer") { document.write('<tr><td bgcolor="'+this.bgColor1+'" onmouseover="menuOver(this,\''+this.bgColor2+'\')" onmouseout="menuOut(this,\''+this.bgColor1+'\')" onclick="menuClick(this)"><div class="'+this.classname+'"> <a href="'+this.linkto+'" class="'+this.classname+'" title="'+this.title+'">'+this.label+'</a></div>'); } else {document.write('<tr><td bgcolor="'+this.bgColor1+'"><div class="'+this.classname+'"><a href="'+this.linkto+'" class="'+this.classname+'" title="'+this.title+'">'+this.label+'</a></div>');} } // else } document.write('</td></tr>'); }

เพิ่มเติมอีกนิด กับฟังก์ชั่น menuOver() menuOut() และ menuClick() ที่ใช้ใน MenuItemBuild()

ฟังก์ชั่นทั้งสามเป็นฟังก์ชั่นที่ใช้เพิ่ม effect ให้กับเมนูนะครับ คือใช้เปลี่ยนสีเมนูไปตามการเอา mouse ชี้ การเอา mouse ออก และการกดคลิก แต่จะทำงานได้บน IE เท่านั้นครับ ฟังก์ชั่นทั้ง 3 มีรายละเอียดดังนี้ครับ

function menuOver(src,Colour) { if (!src.contains(event.fromElement)) { src.style.cursor = 'hand'; src.bgColor = Colour; } } function menuOut(src,Colour) { if (!src.contains(event.toElement)) { src.style.cursor = 'default'; src.bgColor = Colour; } } function menuClick(src) { if(event.srcElement.tagName=='TD') { src.children.tags('A')[0].click(); } }

ไฟล์สำเร็จรูปของ คลาสเมนู และเมนูไอเท็ม menu.js [Download]

ตอนที่ 1 เรื่องการสร้างเมนู ขอจบเพียงเท่านี้ครับ วันพรุ่งนี้จะเป็นตอนที่ 2 การนำ Class นี้ไปใช้ อย่าลืมติดตามนะครับ

Back to top





© copyright 2001 Sorrawut Korsuwansiri