Thursday, November 20, 2014

jQuery Mobile กับปัญหาการคลิกเอง (Firing twice / Firing multiple times)

เขียน jQuery Mobile กับ Cordova อยู่ เจอปัญหาปุ่มถูกคลิกเอง คลิกหลายๆครั้งด้วย ทำให้กระโดดไปหน้าอื่นทั้งๆที่ยังไม่ได้คลิก

ไปค้นดูครับ คนเจอปัญหาเยอะแยะ เช่น
http://stackoverflow.com/questions/14411532/all-jquery-mobile-events-firing-twice
http://stackoverflow.com/questions/10794181/jquery-mobile-tap-event-triggered-for-twice

และมีหลายวิธีแก้เหลือเกิน เช่น
1. เปลี่ยน event สำหรับการแตะ จาก tap เป็น click คือให้ใช้
$("#btt").off().on("click",function(){
 //do something
})

2. ใช้ off ปิด event ก่อนหน้า แล้วตามด้วย on เช่น
$("#btt").off().on("tap",function(){
      //off then on
});

หรือ
$("#btt").off("tap").on("tap",function(){
      //off then on
});

3. ย้าย script ไปไว้ระหว่างแท็ก head ไม่ใช่ส่วน body

4. เพิ่ม event.preventDefault(); เช่น
$("#btt").on("tap",function(event){
    event.preventDefault();
    //other codes
});

5. วางลำดับการอ้างถึง JavaScript และแทรก script ต่อไปนี้ลงไป
<link rel="stylesheet" href="css/jquery.mobile-1.4.4.min.css" />
<script src="js/jquery-2.1.1.min.js"></script>
<script>
 $(document).on("mobileinit", function() {
  $.mobile.ajaxEnabled = false;
  $.mobile.pushStateEnabled = false;
  $.mobile.linkBindingEnabled = false;
  $.mobile.hashListeningEnabled = false;
  $.mobile.defaultTransition = 'none';
 });   
</script>
<script src="js/jquery.mobile-1.4.4.min.js"></script>  
<script src="js/index.js"></script>
<script src="cordova.js"></script>
<script src="cordova_plugins.js"></script>

และอีกมากมาย

ส่วนตัวผมเองเจอปัญหากับ tap แล้วแค่พอเปลี่ยนเป็น click ก็หาย

สาเหตุอีกอย่างนึง ที่สังเกตดูคือ ถ้าเราสร้างแอพโดยมีหลายๆ หน้า และแต่ละหน้าเชื่อมโยงกันไปมา คือสามารถกระโดดไป-กลับ ไปหน้าอื่นๆได้
การกำหนด event สำหรับปุ่มต่างๆ ควรจะเอาไว้ใน

$(document).on("pagecreate","#pageID",function(){
    //begin code here
});

ส่วนตัวแปรที่ต้องการอัพเดททุกครั้ง เช่น เพื่อการแสดงผล ให้เอาไว้ใน

$(document).on("pagebeforeshow","#pageID",function(){
    //begin code here
});

ไม่ควรเอา event สำหรับปุ่มไว้ใน page event: pagebeforeshow เพราะทุกครั้งที่กลับมาที่หน้านี้ ผมเข้าใจว่าปุ่มมันเหมือนจะถูกกำหนด event สองครั้งซ้อน เมื่อเรากดปุ่มก็เลยเหมือนกดสองครั้ง

ถ้าใครเจอปัญหานี้ ลองวิธีแก้ต่างๆข้างต้นดูครับ

jQuery Mobile กับ Apache Cordova จะวางลำดับกันอย่างไร

เคยสงสัยเหมือนผมไหมครับว่าถ้าเราใช้ jQuery Mobile กับ Apache Cordova จะวางลำดับการเริ่มโปรแกรมอย่างไร เพราะ

jQuery Mobile ให้เริ่มด้วย
$(document).on("pagecreate","#pageID",function(){
    //begin code here
});

แต่ Cordova บอกให้เริ่มด้วย
document.addEventListener("deviceready", onDeviceReady, false);

function onDeviceReady(){
    //begin code here
}

เชื่อใครดีล่ะ

ในเน็ตก็มีคนสอบถามกันเยอะครับ เหมือนว่าคำตอบที่เป็นที่ยอมรับอยู่ในนี้ http://stackoverflow.com/questions/10945643/correct-way-of-using-jquery-mobile-phonegap-together

ถ้าเอาแบบลูกทุ่ง ส่วนตัวผมคิดว่ามีหลักของตัวเองคือ
1. หน้าไหนไม่มีการใช้คุณสมบัติของ Cordova เช่น ไม่ได้ใช้ Cordova events, plugin ก็ไม่ต้อง include ไฟล์ cordova.js, cordova_plugin.js ใช้แบบ jQuery Mobile เลย คือใช้การเริ่มแบบ jQuery

2. หน้าที่ใช้คุณสมบัติของ Cordova ให้  include ไฟล์ cordova.js, cordova_plugin.js และเริ่มแบบนี้
$(document).on("pagecreate","#pageID",function(){
    document.addEventListener("deviceready", onDeviceReady, false);
});

function onDeviceReady(){
    //begin code here
}

เป็นการลองแบบคาดการณ์ดูนะครับ ไม่รู้ว่าจะมีปัญหาอะไรที่ยังไม่ทราบไหม

Thursday, November 13, 2014

การเพิ่ม plug-in ให้กับ Cordova project

Apache Cordova ตั้งแต่รุ่น 3.0 มา ได้แยกส่วนของ plug-in ออกจากตัวโค้ดหลัก ทำให้โปรแกรมเมอร์ต้องติดตั้ง plug-in แยกต่างหาก ซึ่งก็มีข้อดีและข้อยุ่งยาก ข้อดีที่ผมเห็นก็คือ นักพัฒนาสามารถเลือกที่จะเพิ่ม ลบ อัพเดท plug-in ให้กับโปรเจคของตนเองได้ โดยไม่ต้องมี plug-in ทั้งหมดอยู่ด้วยกันเหมือนแต่ก่อน และทำให้ผู้ที่สนใจพัฒนา plug-in เองสามารถแลกเปลี่ยนและแจกจ่าย plug-in ได้ง่ายขึ้น ผ่านเว็บ http://plugins.cordova.io/

ส่วนข้อยุ่งยากคือ มันไม่สามารถติดตั้ง plug-in เองได้ง่ายๆ จริงแล้ว plug-in หลักๆสามารถไปดาวน์โหลดได้ที่ https://www.apache.org/dist/cordova/plugins/ แต่ผมลองพยายามติดตั้งแล้ว ไม่สำเร็จ ลองไปแกะโค้ดที่ติดตั้งผ่านเครื่องมืออื่น ก็พบว่ายุ่งยากพอสมควร

เลยตัดสินใจกลับมาทำตามคู่มือ
วิธีแรก ถ้าเราติดตั้ง Cordova แบบแรก (คือเลือก platform) ให้ใช้ plugman เข้าช่วย
วิธีที่สอง ถ้าเราติดตั้ง Cordova แบบที่สองคือผ่าน npm ก็ติดตั้ง plug-in ง่ายๆได้เลย

สรุปแล้ว ถ้าติดตั้งแบบเลือก platform ต้องติดตั้ง plugman ต่อ ซึ่งตัวนี้ก็ต้องติดตั้งผ่าน npm อยู่ดี สรุปแล้วยังไงก็ต้องทำกระบวนการติดตั้งแบบวิธีที่สองโดยติดตั้ง npm และ plugman ให้เสร็จก่อน ตามนี้ (ไม่ต้องติดตั้ง cordova ก็ได้)

จากนั้น
กรณีแรก
ไม่ติดตั้ง Cordova แต่ดาวน์โหลดตัว platform มา เช่น Android ก็เปิด command prompt เรียก setpath.bat ที่เคยทำไว้ในบทความก่อนหน้านี้ สมมติว่าโปรเจคเราอยู่ที่ D:\mobile\code\hello

จากนั้นใช้คำสั่งในรูปแบบ
plugman install --platform --project --plugin
เช่น ถ้าต้องการติดตั้ง plugin ชื่อ geolocation สำหรับบอกพิกัดของอุปกรณ์ ก็จะใช้คำสั่ง
plugman install --platform android --project D:\mobile\code\hello --plugin org.apache.cordova.geolocation
ก็เป็นอันเรียบร้อยแล้วครับ

กรณีที่สอง
ติดตั้ง Cordova แล้ว เปิด command prompt เรียก setpath.bat ที่เคยทำไว้ในบทความก่อนหน้านี้ ย้ายไปยังโฟลเดอร์ของโปรเจค เช่น D:\mobile\code\hello แล้วก็ใช้คำสั่งง่ายๆ คือ
cordova plugin add org.apache.cordova.geolocation
ก็เสร็จแล้วครับ

ติดตั้ง Apache Cordova (PhoneGap) แบบเกือบ portable บน Windows (วิธีที่สอง: ลองทดสอบโค้ด jQuery Mobile)

ต่อจากตอนที่แล้ว หลังจากสร้าง Cordova Project แบบ multi-platform และได้ทดสอบกับ Android platform แล้ว ตอนนี้เราจะลองทำการเปลี่ยนโค้ด โดยเพิ่ม jQuery Mobile เหมือนกับ ตัวอย่างนี้ กันครับ

ไปที่โปรเจค D:\mobile\code\multi\www แล้วแก้ไขไฟล์ index.html ดังต่อไปนี้

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <meta name="msapplication-tap-highlight" content="no" />
        <!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
 <link rel="stylesheet" href="css/jquery.mobile-1.4.4.min.css">
        <script src="js/jquery-2.1.1.min.js"></script>
        <script src="js/jquery.mobile-1.4.4.min.js"></script>
        <script src="cordova.js"></script>
 <script src="js/index.js"></script>
    </head>
 
    <body>
        <div data-role="page" id="pageHome">
            <div data-role="header">
                <h3>Header</h3>
            </div>
            <div data-role="main" class="ui-content">
                <button id="bttOK" class="ui-btn ui-btn-inline">OK</button>
            </div>
            <div data-role="footer">
                <h3>Footer</h3>
            </div>
        </div>       
    </body>
</html>


และแก้ไขไฟล์ index.js ในโฟลเดอร์ js ดังนี้
$(document).on("pagecreate","#pageHome",function(){
 document.addEventListener("deviceready", onDeviceReady, false);
});

function onDeviceReady(){
 $("#bttOK").on("tap",function(){
  alert("Hello World!");
 });
}

อย่าลืมคัดลอกไฟล์ jquery และ jquery mobile ทั้ง .js และ .css ไปไว้ยังโฟลเดอร์ js และ css ตามลำดับด้วยครับ

จากนั้นลองทดสอบ run เลยก็ได้ครับ สมมติว่าตอนนี้เราอยู่ที่โฟลเดอร์ของโปรเจค เช่น D:\mobile\code\multi ก็ใช้คำสั่ง
cordova run android

ก็น่าจะได้ผลลัพธ์เหมือนตัวอย่างก่อนหน้านี้เช่นเดียวกัน

Sunday, November 2, 2014

ติดตั้ง Apache Cordova (PhoneGap) แบบเกือบ portable บน Windows (วิธีที่สอง: ลองสร้างโปรเจค)

ตอนที่ผ่านมาเราติดตั้ง Cordova แบบ multi-platform ซึ่งจะสามารถสร้างโปรเจคได้โดยใช้ Command Line Interface (CLI)

ก่อนอื่นขอลองอธิบายรูปแบบการสร้างโปรเจคของวิธีนี้ก่อน ว่าทำไมมันถึงสนับสนุน multi-platform

หลักการคือเมื่อสร้างโปรเจคด้วย CLI มันจะสร้างโปรเจคกลางๆไว้ ไม่มี platform เลย เราต้องเพิ่ม platform เข้าไปเอง การเพิ่ม platform ก็คือการสำเนาโปรเจคหลักไปเป็นโปรเจคสำหรับ platform นั้นๆ เช่น Android, iOS เป็นต้น

เราเริ่มด้วยการเปิด command prompt แล้วไปที่ D:\mobile แล้วเรียกไฟล์ setpath.bat ที่เคยสร้างไว้ก่อนนี้

ในที่นี้เราจะสร้างโปรเจคไว้ที่ D:\mobile\code ให้อยู่ในโฟลเดอร์ multi และมีชื่อโปรเจคว่า MyMulti จึงพิมพ์ว่า
cordova create D:\mobile\code\multi com.example.multi MyMulti

กระบวนการนี้ต้องต่อเน็ตเพื่อให้ cordova ดาวน์โหลด template มา ใช้เวลาแป๊บนึงครับ ก็จะมีโฟลเดอร์ D:\mobile\code\multi เกิดขึ้น

ต่อไปก็ต้องเพิ่ม platform ที่ต้องการเข้าไปครับ จะกี่ platform ก็ได้แล้วแต่ว่าเครื่องคอมเรารองรับไหม ในที่นี้จะทดสอบเฉพาะ Android ครับ

เพื่อความสะดวก เราจะใช้ command prompt ย้ายไปที่โฟลเดอร์ของโปรเจคที่เราพึ่งสร้างขึ้น โดยพิมพ์ cd D:\mobile\code\multi แล้วพิมพ์
 cordova platform add android
ซึ่งในที่นี้อาจจะเจอข้อผิดพลาดระบุว่า "Error: Please install Android target "android-19"." ทั้งนี้เนื่องจากไฟล์ template ของ Android ถูกกำหนดไว้ที่ level 19 (KitKat) แต่ Android SDK ของเราเป็น level 20 ซึ่งเป็นปัญหาเดียวกับบทความตอนที่ 2 วิธีแก้คือ
1. เรียก SDK Manager เพื่อเพิ่ม API level 19
หรือ
2. แก้ที่เครื่องเราเอง ไปที่ C:\Users\user\.cordova\lib\npm_cache\cordova-android\3.6.4\package\framework แล้วแก้ไขไฟล์ project.properties โดยเปลี่ยนบรรทัด target=android-19 เป็น target=android-20
ในที่นี้เราจะใช้วิธีที่ 2 ครับ

เมื่อแก้ไขไฟล์และบันทึกแล้ว เรียกคำสั่งเดิม คือ
cordova platform add android
อีกครั้งครับ

ในโฟลเดอร์ D:\mobile\code\multi ที่มีโปรเจคที่เราสร้างขึ้น โค้ดหลักจะอยู่ใต้โฟลเดอร์ www ครับ ส่วนโค้ดของแต่ละ platform จะอยู่ในโฟลเดอร์ platforms อีกทีหนึ่ง

ตามคู่มือ หากต้องการแก้ไขไฟล์ให้แก้เฉพาะที่โฟลเดอร์ www เพราะไฟล์จะถูกสำเนาไปให้แต่ละ platform ตอน build โปรเจคโดยอัตโนมัติ

หากเราต้องการ build โปรเจคโดยใช้ CLI สำหรับ Android แล้วเราต้องการ Apache Ant เพิ่มด้วยครับ ซึ่งดาวน์โหลดได้ที่ http://ant.apache.org/bindownload.cgi พอได้ไฟล์แล้วคลายไว้ที่ D:\mobile แล้วเปลี่ยนชื่อให้ง่ายๆเป็น D:\mobile\ant
แล้วไปแก้ไขไฟล์ setpath.bat เพื่อเพิ่ม path ให้กับ ant ดังนี้

set ANDROID_HOME=%~dp0adt-bundle\sdk
set NODE_PATH=%~dp0nodejs
set NODE_MODULES=%NODE_PATH%\node_modules
set NPM_CONFIG_PREFIX=%NODE_PATH%
set ANT_HOME=%~dp0ant
:: If JVM memory is not enough for building project by ANT
set _JAVA_OPTIONS=-Xmx512M
set PATH=%PATH%;%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\build-tools;%NODE_PATH%;%NODE_MODULES%;%ANT_HOME%\bin
แล้วเรียกไฟล์ D:\mobile\setpath.bat บน command prompt อีกครั้ง

จากนั้นไปที่ D:\mobile\code\multi แล้วใช้คำสั่ง
cordova build
ซึ่งจะ build ให้ทุก platform
หรือ ถ้าต้องการ build เฉพาะ Android ให้พิมพ์
cordova build android
ซึ่งขั้นตอนนี้จะเป็นการสำเนาไฟล์จากโฟลเดอร์ www ไปยังโฟลเดอร์ platforms\android\assets\www ซึ่งเป็น Android platform ตามที่เราสั่งด้วย

แล้วถ้าจะ run เพื่อดูผลลัพธ์
สำหรับ emulator เช่น AVD ให้ใช้
cordova emulate android
สำหรับ เครื่องจริง หรือ emulator เช่น genymotion ให้ใช้
cordova run android

หมายเหตุ คำสั่ง run จะ build โปรเจคใหม่เสมอ ถ้าไม่ต้องการ build แต่ต้องการรันเฉยๆ ให้ใช้คำสั่ง
cordova run android -- --nobuild

ตอนต่อไป เราจะลองเพิ่ม jQuery mobile ครับ

อ้างอิง
http://cordova.apache.org/docs/en/4.0.0/guide_cli_index.md.html#The%20Command-Line%20Interface