Google Maps V3 + HTML5

จากบล็อคก่อนหน้านี้ที่แนะนำการใช้งาน Google Maps V3 ให้ลองไปใช้ดูกันแล้วนั้น อย่างหนึ่งที่ไม่ชอบก็คือตำแหน่งเริ่มต้นนั้นมันตายตัวไปหน่อย คือกำหนดแล้วฝังเข้าไปในโค้ด JavaScript เลย แล้วถ้าเราต้องการทำเว็บแอพพลิเคชั่น (เพื่อให้มันสั้นลงต่อไปจะเรียก ‘แอพ’ หรือ ‘app’) ที่คำนึงถึงตำแหน่งผู้ใช้เป็นสำคัญ เช่น ตำแหน่งร้านอาหารที่น่าสนใจใกล้เคียงนั้นๆ หรือ ร้านค้าลดราคาใกล้ๆ เป็นต้น ดังนั้นอย่างแรกที่จำเป็นก็คือตำแหน่งที่เราอยู่ปัจจุบัน เพื่อนำมาข้อมูลที่เกี่ยวข้องมาแสดงผล

ซึ่งในตัวอย่างที่จะทำนี้เป็นการพัฒนาต่อจากบล็อคก่อนหน้านี้ดังนั้นก็ให้ดาวน์โหลดไฟล์ maps-demo.html.zip มาไว้ที่เครื่องก่อนเพื่อเตรียมตัวแก้ไข ซึ่งด้านในมีโค้ดด้านล่างนี้ (ดูตัวอย่างการแสดงผล)

<!DOCTYPE html>
<html>
  <head>
    <title>Google Maps V3 Demostrate</title>
    <script src="http://maps.googleapis.com/maps/api/js?sensor=true"></script>

    <script>
      function initWithMapStart() {
        var latlng = new google.maps.LatLng(13.75, 100.517);
        var mapOptions = {
                            zoom: 12,
                            center: latlng,
                            mapTypeId: google.maps.MapTypeId.ROADMAP
                        };
        var maps = new google.maps.Map(
                         document.getElementById('map-canvas'),
                         mapOptions
                   );

        var marker = new google.maps.Marker({
                            position: latlng,
                            map: maps,
                            animation: google.maps.Animation.DROP,
                            title: "Welcome to Thailand"
                        });

        var info = new google.maps.InfoWindow({
                            content: '<h1>Hello</h1>'
                        });
        google.maps.event.addListener(marker, 'click', function(){
            info.open(maps, marker);
        });
      }
    </script>

    <style>
      header,
      footer {
        text-align: center;
      }
      #map-canvas {
        display: block;
        margin: 20px auto;
        height: 400px;
        width: 640px;
        background-color: #ccc;
      }
    </style>
  </head>
  <body onload="initWithMapStart()">
    <header>
      <h1>Google Maps Demo</h1>
    <header>
    <article>
      <div id="map-canvas"></div>
    </article>
    <footer>
      <small><a href="http://we.in.th/">we.in.th</a></small>
    </footer>
  </body>
</html>

fig.1: โค้ดเดิมสำหรับแสดงผลแผนที่

จากที่บอกในข้างต้นว่าจะพัฒนาต่อจากของเดิมที่มีอยู่แล้ว โดยสิ่งที่เพิ่มขึ้นมากก็คือคุณสมบัติที่เรียกว่า Geolocation ซึ่งอยู่ใน HTML5 ทำสามารถดึงข้อมูลตำแหน่ง เช่น พิกัด (Latitude, Longitude) หรือ ที่อยู่ปัจจุบัน ของผู้ใช้ขณะนั้นมาแสดง แต่ก่อนที่จะแสดงนั้นเบราเซอร์จะขออนุญาตจากผู้ใช้ก่อนเสมอ หากไม่ต้องการให้เว็บไซต์นำตำแหน่งไปใช้งานก็ปฏิเสธได้ ใช้งานได้กับ IE9+, Firefox 3.5+, Safari5+ และ Google Chrome 4+ โดยที่ ดังนั้นให้เพิ่มโค้ดด้านล่างถัดจากบรรทัดที่ 32 ลงไป ดังนี้

if ( (typeof( window.navigator) != 'undefined') && !!navigator.geolocation ) {
    navigator.geolocation.getCurrentPosition(
        function(position) {
            panToCurrentLocation(position, maps, marker);
        },
        errorOccur
    );
}

fig.2: โค้ดสำหรับพิกัดที่ได้จากเบราเซอร์มาแสดงผล

Google Maps with Location Acquisition Notificationโดยที่

  • บรรทัดที่ 1 คือ การตรวจสอบว่าเบราเซอร์นี้รองรับ Geolocation หรือไม่
  • บรรทัดที่ 2-7 คือ การเรียกใช้งาน Geolocation ผ่านตัวแปร navigator ซึ่งก่อนจะดึงข้อมูลตำแหน่งของผู้ใช้เบราเซอร์จะขออนุญาตผู้ใช้ก่อนเสมอ เมื่อได้รับอนุญาตและได้ตำแหน่งผู้ใช้เรียบร้อยแล้วจะส่งไปยัง function(position) (บรรทัดที่ 3-5) โดยจะส่งไปให้ฟังก์ชั่น panToCurrentLocation ต่อไปพร้อมกับตัวแปร position, maps และ marker แต่ถ้าไม่สามารถอ่านพิกัดได้จะไปทำที่ฟังก์ชั่น errorOccur แทน

ถัดไปคือการสร้างฟังก์ชัน panToCurrentLocation และ errorOccur ขึ้นใหม่ ตามที่ได้ระบุไว้ใน fig.2 ดังนี้

function panToCurrentLocation(position, maps, marker) {
  var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
  maps.setCenter( latlng );
  maps.panTo( latlng );

  marker.setPosition( latlng );
  marker.setAnimation( google.maps.Animation.DROP );
}

function errorOccur( error ) {
  console.log( error );
}

fig.3: JavaScript สำหรับเปลี่ยนตำแหน่งในแผนที่

โดยที่

  • บรรทัดที่ 2: สร้างพิกัดจากแผนที่ใหม่
  • บรรทัดที่ 3: กำหนดจุดศูนย์กลางให้แผ่นที่ใหม่
  • บรรทัดที่ 4: เลื่อนตำแหน่งของแผนที่ไปยังตำแหน่งใหม่ที่ได้
  • บรรทัดที่ 6: เปลี่ยนตำแหน่งของ marker ให้แสดงที่ตำแหน่งปัจจุบัน
  • บรรทัดที่ 7: กำหนดแอนนิเมชั่นที่จะใช้แสดงผล marker

จากที่ทดลองใช้งานการค้นหาตำแหน่งนั้นอาจคลาดเคลื่อนได้ไม่ถูกต้องทุกครั้ง ดูตัวอย่างได้ที่ไฟล์ maps-demo-navigation หรือดาวน์โหลดไฟล์ maps-demo-navigation.html

ข้อมูลเพิ่มเติม:

Google Maps V3 Introduction

ก่อนหน้านี้เคยเขียนวิธีการนำเอา Google Maps มาใช้งานกับเว็บไซต์ด้วยกัน 2 ตอน (1, 2) ตอนที่เขียนไปนั้น Google Maps เวอร์ชั่น 2.x ปัจจุบันอยู่ในสถานะ deprecated หรืออยู่ระหว่างการเลิกใช้งานนั้นเอง โดยตอนนี้ Google Maps เองก็พยายามเข็ญให้นักพัฒนาขยับไปใช้ Google Maps เวอร์ชั่นปัจจุบันคือเวอร์ชั่น 3 หรือเรียกสั้นๆ ว่า V3 ซึ่งการเรียกใช้งานนั้นง่ายกว่าเวอร์ชั่นเก่ามาก อย่างแรกที่เห็นได้ชัดคือเราไม่จำเป็นต้องสมัครเพื่อขอ API Key สำหรับใช้ดาวน์โหลด Google Maps Library อีกต่อไปแล้ว และการกำหนดค่าทั้งหมดใช้การกำหนดค่าผ่าน Object ที่เข้าใจได้ง่ายกว่าเวอร์ชั่นเก่ามาก
Continue reading

PHPUnit Setup

PHPUnit เป็น Unit Test Framework สำหรับ PHP ใครใช้ JUnit มาแล้วก็อารมณ์เดียวกัน แค่เปลี่ยนจาก Java มาเป็น PHP

ก่อนอื่น ผมติดตั้งใน Mac OS X วิธีคงไม่ต่างกันมากนักกับ Linux แต่สำหรับ Windows อันนี้ไม่แน่ใจครับ เพราะเลิกใช้นานแล้ว

วิธีการติดตั้ง

  1. ให้แน่ใจว่าใช้คำสั่ง php ที่ terminal ได้
  2. PHPUnit ต้องการ pear ด้วย สำหรับใครที่ใช้ Windows ก็ต้องโหลดมาเพิ่ม ได้ที่ pear.php.net ส่วน Linux และ OS X ไม่ต้องเพราะมีแล้ว
  3. โหลด PHPUnit จาก pear.phpunit.de/get เลือกเอาตามชอบครับ ผมเลือกเป็น PHPUnit-3.4.9
  4. ไฟล์ที่ได้จะเป็นไฟล์ PHPUnit-x.x.x.tgz ใช้คำสั่งด้านล่างเพื่อแตกไฟล์ออก
    tar xzf PHPUnit-x.x.x.tgz
    จะได้โฟล์เดอร์ PHPUnit-x.x.x
  5. ในโฟล์เดอร์ PHPUnit-x.x.x จะมีไฟล์ phpunit.php คือไฟล์ที่เราต้องการ เปลี่ยน phpunit.php -> phpunit ก็ได้ไม่มีปัญหา
  6. ในไฟล์ phpunit.php บรรทัดที่ 43 เพื่อใช้ได้แน่นอนให้เปลี่ยน dirname(__FILE__) เป็น '/path/to/PHPUnit-x.x.x'
  7. และเพื่อให้ใช้คำสั่งจากที่ไหนก็ได้ ก็แก้ไขค่าใน .profile นิดหน่อย
    # vi ~/.profile
    ...
    export PHPUNIT_HOME=/path/to/PHPUnit-x.x.x
    export PATH=$PHPUNIT_HOME:$PATH
    :wq
    # source ~/.profile
  8. ลองเขียนโปรแกรมเล็กๆ ทดสอบดู
    <?php
    # StackTest.php
    require_once 'PHPUnit/Framework.php';
    class StackTest extends PHPUnit_Framework_TestCase
    {
        public function testPushAndPop()
        {
            $stack = array();
            $this->assertEquals(0, count($stack));
        }
    }
    
  9. จะได้ผลลัพธ์ดังนี้ ถือว่าสำเร็จใช้ได้

    PHPUnit

    PHPUnit

ข้อมูลเพิ่มเติม: PHPUnit Book [PDF]

สร้าง XML Binding Class ด้วย JAXB

สไลด์ยังอุ่นๆ อยู่เลยเพราะพึ่งออกจากเตาใหม่ๆ สไลด์นี้ว่าด้วยการสร้าง XML Binding Class ด้วย JAXB ใน Java เป็นตัวอย่างและสรุปสั้นๆ ให้พี่ที่ทำงานฟัง ถ้าต้องการรายละเอียดถามได้ครับ

ลายน้ำใน Pages

1. เปิดเอกสารที่ต้องการใส่ลายน้ำ

เอกสารเปล่า

เอกสารเปล่า

2. ใส่ข้อความหรือรูปภาพที่จะน้ำมาทำลายน้ำ

ต้นแบบลายน้ำ

ต้นแบบลายน้ำ

3. คลิ้กที่ต้นแบบในข้อ 2 เลือกเมนู “Format” > “Advanced” > “Move Object to Section Master”

กำหนดลายน้ำ

กำหนดลายน้ำ

4. จะได้ลายน้ำดังรูป

ลายน้ำที่ได้

ลายน้ำที่ได้


5. ถ้าหากต้องการแก้ไขให้ดับเบิ้ลคลิ้กที่ลายน้ำ Pages จะถามว่าจะให้เปลี่ยนลายน้ำนี้ไปสู่โหมดที่คลิ้กเลือกได้หรือไม่ อันนี้แล้วแต่ชอบ จากนั้นจึงแก้ไขได้ตามใจ ผลการเปลี่ยนแปลงก็จะเป็นไปในทุกๆ หน้าใน Section (ในกรณีที่มีหลาย Section ในเอกสารสามารถเลือกได้ว่าส่วนไหนไม่ต้องการใส่ลายน้ำ)

Pages, iWork ’09, Apple

แสดงหัวตารางซ้ำ

บันทึกความจำกันอีกตอนหนึ่งเพราะช่วงนี้ต้องใช้ OpenOffice.org (OO.o) อย่างหนักเมื่อก่อนไม่ค่อยได้ใช้มากเท่าไหร่นักอย่างมากก็พิมพ์งานนิดหน่อย แต่ช่วงนี้เริ่มต้องใช้รูปแบบที่ซับซ้อนขึ้น ตอนนี้กว่าจะหาเจอก็นานอยู่เหมือนกัน หรืออีกเหตุผลหนึ่งก็เพราะไม่คุ้นกับ OO.o เท่าไหร่นัก

ข้อมูลปริมาณมาก

รูปที่ 1: ข้อมูลปริมาณมาก


เมื่อข้อมูลมีความยาวเกินกว่า 1 หน้า

รูปที่ 2: เมื่อข้อมูลมีความยาวเกินกว่า 1 หน้า

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

Table

รูปที่ 3: Table


Table > Table Properties...

รูปที่ 4: Table > Table Properties...

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

Table Format | Table Flow > Repeat Heading

รูปที่ 5: Table Format | Table Flow > Repeat Heading

จะได้หน้าต่าง Table Format ดังรูปที่ 5 จากนั้นเลือกที่แถบ Table Flow และคลิ้กเลือกที่ Repeat Heading และเปลี่ยนจำนวนแถวของหัวตารางที่ต้องการให้แสดงซ้ำตามต้องการจากนั้นจะได้ตารางดังรูปที่ 6 ซึ่งหากแก้ไขหัวตารางในรูปที่ 6 นี้ก็จะส่งผลไปยังหัวตารางที่เห็นในรูปที่ 1 ด้วย

Repeat Table Heading

รูปที่ 6: Repeat Table Heading

ฟังก์ชั่นนี้เป็นฟังก์ชั่นพื้นฐานที่พบได้ในโปรแกรม Word Processing ทั่วไป ทั้ง MS Word, และ Pages ครับ

โปรแกรมที่ใช้: OpenOffice.org 3.1.1 Writer

Subversion in Actions II

คราวที่แล้วเขียนเกี่ยวกับการใช้ Subversion (svn) เบื่องต้น ได้แก่ การสร้าง Repository, เพิ่มไฟล์เข้าสู่ index ใน working copies (add), และส่งเข้าสู่ Repository (commit) ส่วนตอนนี้ก็จะขอพูดส่วนเกี่ยวกับคำสั่งต่างๆ ที่เอาไว้ติดตามความเคลื่อนไหว และการเปลี่ยนแปลงของ Repository ครับ

ข้อมูลประจำรุ่น (log)

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

REVISION_NO | USER_NAME | DATE_TIME | LINE_CHANGED

MESSAGE_LOG

ตัวอย่างเช่น

  $ svn log file:///Users/sitdh/Repository/helloSVNServer
  ------------------------------------------------------------------------
  r2 | sitdh | 2009-09-10 00:40:52 +0700 (Thu, 10 Sep 2009) | 1 line

  Create Project
  ------------------------------------------------------------------------
  r1 | sitdh | 2009-09-09 21:56:38 +0700 (Wed, 09 Sep 2009) | 1 line

  test
  ------------------------------------------------------------------------

คำอธิบาย:

  • บรรทัดที่ 03 และ 07 คือ ข้อมูลประจำรุ่น
  • บรรทัดที่ 05 และ 09 คือ คำอธิบายการเปลี่ยนแปลงที่ผู้ commit เขียนอธิบายไว้

หมายเหตุ: ข้อมูลดังกล่าวเป็นข้อมูลที่ได้จาก Repository เนื่องจากเราระบุพาธไว้ด้านหลัง หากให้คำสั่ง svn log จะเอา log ที่อยู่ใน Working Copies มาแสดงแทน ซึ่งข้อมูลที่ได้อาจไม่ตรงกับ Repository วิธีแก้คือใช้คำสั่ง update เพื่อปรับปรุงข้อมูลให้ตรงกัน (Synchonize – sync) ระหว่าง Working Copies และ Repository

  $ svn update file:///User/sitdh/Repository/helloSVNServer
  At revision 3.

คำอธิบาย:

  • บรรทัดที่ 01 ใช้คำสั่งเพื่อ sync ข้อมูล หามีข้อมูลที่ไม่ตรงกับ Repository จะแสดงรายการเปลี่ยนแปลงด้านล้าง
  • บรรทัดที่ 02 เป็นบรรทัดที่บอก Revision ล่าสุดที่อยู่ใน Repository (HEAD Revision)

หาความแตกต่างระหว่างเวอร์ชั่น (diff)

ก่อนอื่นต้องทบทวนก่อนว่าในตัวอย่างของ blog ที่แล้วได้สร้างข้อมูลตัวอย่างและส่งเข้า Repository เรียบร้อยแล้ว (Revision 3 หรือ r3) จากนั้นได้แก้ไขข้อมูลในไฟล์ ‘index.php’ เล็กน้อย และ commit เข้าไปยัง Repository เรียบร้อยแล้ว (Revision 4 หรือ r4) ดังนั้นถ้าอยากรู้ว่าระหว่าง r3 และ r4 มีความแตกต่างตรงไหนบ้าง คำสั่งที่ช่วยได้ก็คือ diff ดังนี้

$ svn diff -r 3:4
Index: index.php
===================================================================
--- index.php	(revision 3)
+++ index.php	(revision 4)
@@ -1,3 +1,4 @@
-hello, world

\n"; + echo "

hope you like it

"; ?>

คำอธิบาย:

  • บรรทัดที่ 02 Index จะบอกว่าตอนนี้เปรียบเทียบไฟล์ไหนอยู่
  • บรรทัดที่ 04 – 05 กำหนดเครื่องหมายสำหรับ r3 แทนด้วย ‘-’ และ r4 แทนด้วย ‘+’ โดย ใช้บอกว่าบรรทัดไหนหายไปจาก r4 (-) และเพิ่มเข้ามาใน r4 (+) ถ้าบรรทัดไหนไม่เปลี่ยนแปลงก็จะไม่มีเครื่องหมายนำหน้า
  • บรรทัดที่ 07 – 08 คือ บรรทัดที่มีอยู่ใน r3 แต่หายไปจาก r4 (เครื่องหมาย - นำหน้า)
  • บรรทัดที่ 09 – 11 คือ บรรทัดที่เพิ่มเข้ามาใน r4
  • บรรทัดที่ 12 เป็นบรรทัดที่ไม่เปลี่ยนแปลง