วันศุกร์ที่ 6 มีนาคม พ.ศ. 2558

How to design content box without table and margin?

>> เรื่องนี้พี่ senior ที่ทำงานเป็นผู้เสนอวิธีการแก้ปัญหาการจัด style sheet แบบไม่มีแบบแผนให้มีแบบแผนเพื่อที่มันจะง่ายต่อการลดเพิ่มเติมแต่งในภายหลัง เรื่องนี้เป็นเรื่องสำคัญมากนะครับ ย้ำเลยสำหรับงาน front-end ควรทำความเข้าใจเป็นอย่างยิ่ง

>> จินตนาการว่าเรามีของอยู่สามชิ้น ได้แก่ ข้อความ กล่องข้อความ และปุ่มกด เราจะมีวิธีการจัดเลเอาท์มันอย่างไรให้
- ข้อความ อยู่ชิดซ้าย ห่างจากขอบด้านซ้าย 10px
- กล่องข้อความ อยู่ถัดจาก ข้อความ ห่างจากกัน 5px
- และปุ่มกด อยู่ด้านล่าง กล่องข้อความ ระยะเริ่มต้นเท่ากันโดยห่างจากัน 5px

>> แน่นอนเพื่อนๆสามารถเลือกวิธีการจัดการกับปัญหาข้างต้นด้วยตัวเลือกต่อไปนี้ เลือกได้มากกว่าหนึ่งอย่างครับ (ลองคิดและเลือกเลยนะ)
1) margin-left: 10px
2) margin-left: 5px
3) padding-left: 10px
4) padding-left: 5px
5) padding-top: 5px
6) ใช้ table tr และ td เป็น layout

>> เฉลย ไม่ว่าจะเลือกตัวเลือกใดก็ตามในข้อ 1) ถึงข้อ 6) โดยเฉพาะวิธีการจัดการของทั้งสามด้วย margin หรือ table ล้วนทำให้การแก้ไขเลเอาท์ลำบากในภายหลัง (เมื่อของมีมากกว่าสามชิ้น และ requirement จากลูกค้าไม่แน่นอน)

>> ครับก็อย่างที่ผมอยากเสนอ ตัวเอกของเรื่องในคราวนี้ก็คือ CSS เวอร์ชัน 3 ที่มีระบบ box-sizing มาให้ใช้ แล้วมันคืออะไร?

>> มันคือเรื่องที่ว่าด้วยการคำนวณขนาดของ content (ขนาดจริงๆของสิ่งของ) หรือจะให้มันคำนวณขนาดของ border ของ content นั้นแทน (box-sizing: border-box)





>> เอาล่ะ ตัวอย่างต่อจากนี้จะใช้แท็ก div แทนแท็ก table และเลิกใช้ margin ไปตลอดกาล (forever)
- รูปที่ 1 (ตัวเลขสีแดง) คือเป้าหมายที่เราอยากจะ design ให้ใกล้เคียงที่สุด โดยใช้หลักการ box-sizing
- รูปที่ 2 จากรูปแรกจะเห็นว่าเราสามารถแบ่งได้เป็นสิบช่อง
- รูปที่ 3 ใช้สิบช่องดังกล่าวกับเป้าหมาย
- รูปที่ 4 กำหนดแท็ก div ขึ้นมาทั้งสิ้นสิบเอ็ดตัว ตัวนอกสุดคือตัวบรรจุของอีกสิบตัวภายใน พร้อมกับเซตค่าสีพื้นหลังเป็น สีน้ำเงิน (เดี๋ยวจะเปลี่ยนให้เป็นสีใกล้เคียงกับเป้าหมาย) ขนาดความกว้าง 100%
- รูปที่ 5 เปลี่ยนสีพื้นหลังเฉยๆ (อันที่จริงมันซ้ำ แต่ขี้เกียจทำใหม่)
- รูปที่ 6 ใส่รายละเอียดบางตำแหน่งที่เป็นข้อความ
- รูปที่ 7 ใส่รายละเอียดของ content ที่ไม่ใช่ข้อความ เช่น กล่องข้อความและปุ่มกด
- รูปที่ 8 เอาตัวเอกมาช่วย นั่นก็คือ box-sizing: border-box ค่านี้ส่งผลให้การคำนวณความกว้างนั้นไปใช้ขนาดที่รวมกับ border แล้วเป็นหลัก ดังนั้น content จึงไม่มีทางล้นออกจาก container เด็ดขาดครับ

>> มีคำถามว่า แล้วจะจัดระยะทางซ้าย ด้านบน ทางขวาหรือด้านล่างของแต่ละ content อย่างไรล่ะ คำตอบก็คือ ใช้ padding ล้วนๆครับ โดยให้แท็ก div เป็นตัวควบคุม padding ผลักเปลี่ยนตำแหน่ง content ของตัวเองไปตามประสงค์ของ design นั่นเอง ย้ำ! จงลืม margin อันน่าปวดหัวนั่นไปซะ
- รูปที่ 9 เสร็จเรียบร้อย (จบตัวอย่าง)

>> อ้อ อ่านเพิ่มเติม
- http://www.w3schools.com/cssref/css3_pr_box-sizing.asp

วันอังคารที่ 3 มีนาคม พ.ศ. 2558

GWT EventBus and Inheritance-Based Polymorphism part 2/2



>> และแล้วก็ทำตัวอย่างเสร็จเรียบร้อย แม้จะมีอีกหลายจุดที่สามารถปรับปรุงให้ดีกว่านี้ได้ ทว่าตอนนี้ก็คิดออกเท่านี้ล่ะครับ ฮ่า ตัวโค้ดไม่ขอเอ่ยถึงแล้วกัน ผมอัพให้แล้วที่นี่
- Card.zip

>> ถือว่าเป็นแนวทางแก่ผู้เริ่มต้นเพื่อประยุกต์หลักออกแบบ Inheritance-Based Polymorphism กับเทคโนโลยี GWT ที่ใช้โครงสร้าง MVP ตามตัวอย่างของเว็บนี้ครับ - http://www.gwtproject.org/articles/mvp-architecture.html

>> โปรแกรมเล็กๆหน้าเดียวนี้ทำอะไรได้บ้าง?
- เพื่อนๆสามารถกรอกชื่อของสมาชิกลงไปได้ แล้วก็เลือกประเภทบัตรให้กับเขา จากนั้นกดปุ่มเพิ่ม
- ชื่อของเขาบนบัตรจะไปปรากฏในตารางการใช้จ่ายด้านล่าง ทดสอบกรอกค่าใช้จ่ายของเขาลงไป ระบบก็จะคำนวณจำนวนเงินสดที่หักจากส่วนลดให้กับเจ้าของบัตรรายนั้นๆครับ

>> โหลด Card.zip ไปแล้วจะ run โปรแกรมนี้อย่างไร?
- ผมพัฒนามันบน Eclipse Java EE IDE for Web Developers. Version: Luna Service Release 1a (4.4.1) และ Google Plugin (GWT)
- ให้สร้างโปรเจ็กต์ด้วย GWT ของ google plugin ตั้งชื่อว่า Card โดยเริ่มต้น package ว่า com.sample
- ตัวเลือก Use Google App Engine ไม่ต้องเลือก กด Finish
- ลบ folder ชื่อ src ออกจากโปรเจ็กต์นี้
- คัดลอก folder ชื่อ src ใน Card.zip ไปวาง ณ ตำแหน่ง src เดิมของโปรเจ็กต์นี้
- คัดลอก folder ชื่อ war ใน Card.zip ไปวางทบ war ของโปรเจ็กต์นี้
- คลิกขวาที่โปรเจ็กต์เพื่อ run ได้เลยครับ

>> ไปเขียน Node.js ต่อล่ะครับ ฝันดีครับผม

GWT EventBus and Inheritance-Based Polymorphism part 1/2


>> ชื่อเรื่องยาวไปหน่อยครับ แต่มันก็เป็นตามนั้นแหละนะ ทีแรกว่าจะทบทวน GWT กะว่าเขียนสนุกๆ เอาวิธีการออกแบบคลาสของอาจารย์ Prasertcbs มาประยุกต์ก็น่าจะพอแล้ว แต่...จวบจนขณะนี้ก็ปาเข้าไป เออ...ตีสี่ (เฮ้ย เพลินไปหรือเปล่า เหอะๆ นอนดีปะเนี่ย) ก็ยังเขียนไม่เสร็จน่ะครับ แต่ถ้าไม่เล่าให้ฟังตอนนี้เกรงว่าเมื่อหลับไปคงลืมสิ้น (ฮ่า ว่าไปนั่น)

>> event bus คิดว่าเพื่อนๆคงทราบกันดีอยู่แล้ว เพราะได้ยกโค้ดตัวอย่าง ไฟเขียวไฟเหลืองไฟแดง มาเล่าให้ฟังเป็นที่เรียบร้อย

>> อะไรคือ Inheritance-based polymorphism? มันก็คือ การเขียนคลาสเพื่อผู้อื่นจะสืบทอดไปใช้ โดยที่ใช้ตัวมันเป็นคลาส instance และตัวมันต้องชี้ไปยังออบเจ็กต์ที่เป็น concrete คลาสถ่ายทอดชนิดนั้นๆ

>> ยกตัวอย่างเช่น A เป็นคลาสแม่ ส่วน B และ C ต่างสืบทอดมาจาก A หรือเรียก B และ C ว่าลูกของ A เวลาจะใช้งานก็ว่า
A b = new B(); หรือ
A c = new C(); อย่างนี้เป็นต้น

>> อาจารย์ท่านก็ยกตัวอย่างมาดีมากเลยนะครับ เป็นเรื่องของการ์ด (card) ซึ่งอาจแบ่งเป็นหลายประเภทขึ้นอยู่กับความสามารถของมัน ในที่นี้คือการ์ดซื้อของครับ แบ่งออกเป็น
- Silver card (สีเงิน)
- Gold card (สีเหลือง)
- Platinum card (สีดำ)

>> แต่ละใบให้ส่วนลด (discount) แตกต่างกันไป
- Silver card ส่วนลด 0.02%
- Gold card ส่วนลด 0.05%
- Platinum card ส่วนลด 0.10%

>> คำถามคือ เราจะประยุทต์เขียนโปรแกรมด้วยภาษาจาวาในลักษณะงานเช่นนี้ได้อย่างไร อาจารย์ท่านก็ได้เล่าทุกอย่างไว้ ณ ที่นี่ครับ
- Inheritance-Based Polymorphism

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

>> ทว่าตอนนี้ดึกไปแล้ว ขอนอนก่อนนะครับ

Pie Chart by GWT Google Chart APIs


>> มาวาด Pie Chart ด้วย GWT Google Chart APIs กันเถอะ ยังจำกันได้ไหมครับที่ผมเคยเล่าให้ฟังว่าเราสามารถใช้ Google Chart APIs มาวาด chart ให้เราบนเอกสาร HTML ได้อย่างไร คราวนี้จะวาดโดยใช้ GWT กันบ้าง

>> ทราบกันดีอยู่แล้วว่า GWT ไม่เน้นจาวาสคริปต์ เขียนแต่จาวาล้วนๆ และมันต้องการ .jar ซึ่งเป็น library เพื่อทำงานต่างๆ ดังนั้นเราต้องการ gwt-visualization-XXX.jar เพื่อวาด chart ให้เราครับ (เมื่อ XXX คือหมายเลขเวอร์ชัน)

>> ตรงไปดาวน์โหลด .jar ดังกล่าวที่ https://code.google.com/p/gwt-google-apis/wiki/Downloads?tm=2
เลือกลิงค์โหลดภายใต้หัวข้อ Google Chart Tools (aka Visualization) Library

>> สร้างโปรเจ็กต์ชื่อ PieChartExample

>> ณ war/WEB-INF/lib คัดลอก .jar ของเราที่โหลดมาไปวางไว้ แล้วคลิกขวาที่ .jar ตัวเดิม เลือก Build Path > Add to Build Path เพื่อนำ .jar เข้าสู่ระบบ

>> เปิดไฟล์ config ที่ชื่อ PieChartExample.gwt.xml แล้วเพิ่มโค้ดนี้ลงไป

เป็นการบอกต่อ GWT ว่าจะหาคลาสไลบรารี่ที่เกี่ยวข้องกับ chart นี้ได้ที่ไหน

>> เอาล่ะครับ ต่อจากนี้ก็เป็นการโค้ดภาษาจาวาล้วนๆ โดยหัวใจของ chart ในเบื้องต้นต้องการสองอย่าง
1) data ให้เราใช้คลาส DataTable เป็นตัวจัดการข้อมูล โดยมีข้อกำหนดดังนี้
- กำหนด column ก่อน บอกประเภทและชื่อที่ใช้ใน column นั้น
- กำหนดจำนวน row หรือปริมาณข้อมูลที่ต้องการ
2) options ให้เราใช้คลาสประเภท options ของตัว chart นั้นๆครับ ในที่นี้ผมจะวาด Pie Chart ก็จะใช้คลาส PieOptions
- กำหนดลวดลาย กว้าง ยาว สี เส้น ฯลฯ ของ chart

>> สุดท้ายเรียก VisualizationUtils เพื่อทำการโหลด chart ผ่านคลาส Runnable เพื่อคอยให้มันเตรียม chart เสร็จ มันก็จะจับ chart มาแสดงให้เรา แต่นแต้น! ดังรูปที่เพื่อนๆเห็นนี่แหละ เคี๊ยกๆ

>> อ่านเพิ่มเติม
- http://www.codedrops.in/gwt-tutorial/gwt-chart/
- https://developers.google.com/chart/interactive/docs/gallery หรือ
https://google-developers.appspot.com/chart/interactive/docs/gallery/piechart

>> ดาวน์โหลด source code ของ chart นี้ที่ผมเขียนเลียนแบบได้ที่
PieChartExample.java

>> chart นี้แสดงปริมาณการทำงานเทียบกับปริมาณการนอนเป็นชั่วโมงในหนึ่งวัน (24 ชั่วโมง) คืนนี้ฝันดีครับ

TrafficLight ด้วย EventBus (สัญญาณไฟจราจร)


>> เนื่องจากวันนี้ฝึกการใช้และทำความเข้าใจกับสิ่งที่เรียกว่า event bus เพื่อนคนไหนที่เขียน android คงจะได้ยินได้อ่านผ่านหูผ่านตามาบ้าง สำหรับผมแล้วเพิ่งจะรู้จักกับ event bus ผ่านทาง GWT นี่แหละครับ

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

>> สัญญาณไฟจราจรมีสามสี แดง เหลืองและเขียว ในกรณีนี้คืออยากให้
- สีแดงสว่างก่อน นาน 3 วินาที
- แล้วสีเขียวจึงสว่าง นาน 5 วินาที
- ก่อนที่สีเหลืองจะสว่างเพื่อเตือนอีก 2 วินาทีแล้ววนไปที่สีแดง เป็นเช่นนี้ทุกรอบ เราจะเขียนโค้ดด้วย GWT โดยใช้ EventBus ได้อย่างไร?

>> EventBus คือ queue (คิว) ที่ใช้เก็บ event ประมาณว่าเป็นกล่องปลายเปิดสองด้านที่เราสามารถใส่ event เข้าไปได้ จากด้านหนึ่งทะลุสู่อีกด้านหนึ่ง เข้าก่อนก็ทำก่อนเป็นลำดับตามคิวไป (เข้าแถวซื้อกับข้าวไง) ดังนั้นสำหรับเรื่องนี้แน่นอนว่าเราจะต้องมี event อยู่สามตัว (ขอเรียกเป็นตัวแล้วกันนะครับ) ได้แก่
- event ของไฟแดง ชื่อว่า RedLightEvent
- event ของไฟเหลือง ชื่อว่า YellowLightEvent
- event ของไฟเขียว ชื่อว่า GreenLightEvent
สามตัวนี้จะถูกสร้างขึ้นเรื่อยๆแล้วทยอยส่งเข้าคิวไป

>> มี event แล้วก็ต้องมีตัวจัดการซึ่งเรียกว่า handler หรือตัวคอยตรวจจับว่าเมื่อพบ event เหล่านี้จะให้ทำงานอะไร ฮั่นแน่ เรามีสาม event เราก็จะสร้างสาม handler (เอาอย่างนี้ไปก่อนนะ)
- handler ของไฟแดง ได้ว่า RedLightEventHandler
- handler ของไฟเหลือง ได้ว่า YellowLightEventHandler
- handler ของไฟเขียว ได้ว่า GreenLightEventHandler

>> ลำดับของสัญญาณไฟจะเกิดจากการที่ event ไปกระตุ้นให้ handler ทำงาน ตามความต้องการข้างต้นนั้น เราจะกระตุ้น RedLightEvent ก่อน เพื่อให้ RedLightEventHandler ทำงาน เมื่อเจ้า handler ตัวนี้ทำงาน เราจะหน่วงเวลาด้วย Timer เป็นเวลา 3 วินาทีก่อนที่เราจะสั่งให้มันกระตุ้น GreenLightEvent ต่อไป และต่อไปด้วยโค้ดลักษณะเดียวกันนี้ตามลำดับที่ได้วางไว้

>> พอมองเห็นภาพลางๆแล้วใช่ไหมว่าสัญญาณไฟของเราจะวนเป็นรอบได้อย่างไร สำหรับโพสต์นี้ผมไม่ขอยกโค้ดให้วุ่นวาย แต่แนบเป็นไฟล์ source code แทน ตามลิงค์นี้ครับสำหรับเพื่อนที่สนใจ
- TrafficLightEventBus.java

>> ผิดพลาดประการใดขออภัยด้วย อย่างไรชี้แนะผมได้เสมอนะครับเพื่อนๆ ฝันดีครับผม