วันเสาร์ที่ 17 ตุลาคม พ.ศ. 2558

Tip5 : Linux , Git , Nginx command ที่ใช้บ่อยๆ

 ======Linux=========
ls -all     ดูรายชื่อโฟลเดอร์และไฟล์ทั้งหมด ณ ตำแหน่งที่เราอยู่
cd ..      ย้อนกลับโฟล์เดอร์ไป 1 ขั้น
cd [folder_name]    เข้าโฟล์เดอร์นั้น
top       ดู service ทั้งหมดที่กำลังรันอยู่ และกินเมมโมรี่ไปเท่าไหร่ เมมที่เหลือมีเท่าไหร่
df -h      ดูว่าพื้นที่ Storage เหลือเท่าไหร่ ****ถ้าพื้นที่ไม่พอ database ที่อยู่บนเซิฟนั้นจะ error****
du -h --max-depth=1    ดูพื้นที่ของแต่ล่ะไฟล์ โฟลเดอร์
sar    ดู IO activity ใน 24ชม ที่ผ่านมา
tail -n 100 [log_name]     ดูไฟล์ log 100บรรทัดสุดท้าย
grep -n [find_keyword] [log_name]    ดูไฟล์ log ตัดมาเฉพาะบรรทัดที่มีคำ find_keyword อยู่
tail -n 100 [log_name] | grep [keyword]   ดูไฟล์ log 100 บรรทัดสุดท้ายที่มี keyword อยู่
sudo chmod 777 [file_name]    เปลี่ยน permission file 
rm -rf [folder_name]    ลบโฟลเดอร์แบบหมดจดแม้จะไม่ใช่โฟลเดอร์ว่าง
iftop -n   ดูกิจกรรม network bandwidth (ต้องติดตั้งตัวคำสั่งก่อนถึงใช้ได้) 

======My SQL======
mysqld --console         เริ่มระบบ
Ctrl+c             ออกจากระบบ
mysql -u root -p         เข้าสู่ระบบด้วย username = root
mysql -h localhost -u root    เข้า localhost ด้วย username = root
show databases        แสดงลิตต์ database

======NGINX======
nginx -c C:\nginx\conf\nginx.conf    เริ่มระบบ สามารถเข้า localhost ได้หลังใช้

service nginx restart
service php-fpm restart
service memcached restart


======GIT======
git branch                เช็คว่าอยู่ brach ไหน
sudo git pull origin     ดึง brach   
sudo git checkout     ย้าย brach
sudo git commit -a -m 'commit_name'    comit git

$ git checkout -b [name_of_your_new_branch]
$ git push origin [name_of_your_new_branch]
$ git remote add [name_of_your_remote] 
$ git push origin [name_of_your_remote]
$ git fetch [name_of_your_remote]
$ git merge [name_of_your_remote]/develop
$ git branch -d [name_of_your_branch]    ลบ local branch
$ git branch -D [name_of_your_branch]    ลบ local branch แบบบังคับ


==========PHPMYADMIN remote database=========
ทำให้ phpmyadmin สามารถ access เข้า database จากที่อื่น server อื่นได้ (ปกติลงแล้วมันจะเข้าใช้ localhost)

The settings are stored in config.inc.php at the root of phpMyAdmin's installation directory; e.g. /usr/share/webapps/phpMyAdmin/config.inc.php. Do not dig deeper than that.
(It's the same place where you can find files config.sample.inc.php, ChangeLog, favicon.ico, and such.)

$i++;
$cfg['Servers'][$i]['host'] = 'yourhost.com:3306'; //provide hostname and port if other than default
$cfg['Servers'][$i]['user'] = 'root';   //user name for your remote server
$cfg['Servers'][$i]['password'] = '123456';  //password
$cfg['Servers'][$i]['auth_type'] = 'config';       // keep it as config

Tip4 : Yii and Php จากประสบการณ์

**************PHP***************
1.ทำให้อัพโหลดไฟล์ได้มากกว่า 5mb
http://www.sutenm.com/%E0%B9%81%E0%B8%81%E0%B9%89%E0%B9%84%E0%B8%82%E0%B9%83%E0%B8%AB%E0%B9%89-wordpress-upload-file/

2.ส่ง post data ไปหน้า page ที่ต้องการ พร้อมรับผลลัพท์ด้วย file_get_content
http://stackoverflow.com/questions/2445276/how-to-post-data-in-php-using-file-get-contents

3.ระบบแจ้งเตือน
http://www.thaicreate.com/community/php-mysql-alert-notify-new-message-notification.html

4.add element to array list
$list = array();
array_push($list, $objWillAdd);

5.การ lmport excel ไฟล์ csv เข้า php
< form enctype="multipart/form-data" method="POST" >
    < input name="userfile" type="file" >
    < input type="submit" value="Upload" >
  < /form >



 สำหรับตัวรับไฟล์ก็จะเป็น ภาษา php ดังนี้

if ( isset( $_FILES['userfile'] ) )
{
  $csv_file = $_FILES['userfile']['tmp_name'];

  if ( ! is_file( $csv_file ) )
    exit('File not found.');

  if (($handle = fopen( $csv_file, "r")) !== FALSE)
  {
      while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
      {
            echo $data[0];
            echo $data[1];
            echo $data[2];
      }
      fclose($handle);
  }
  exit( "Complete!" );
}

6.แก้ปัญหาเปิดไฟล์ภาษาไทยแล้วเพี้ยน ครอบด้วย iconv() ด้วยการแปลงจาก TIS-620 เป็น UTF-8 ได้ดังนี้
fopen( iconv('TIS-620',"UTF-8",$file_or_string), "r"))

7.หา sting "are" ใน string $a
strpos($a,'are') !== false //ถ้าเจอคืน true
substr_count($a, 'are') > 0 //ถ้าเจอคืนตำแหน่ง



8.microtime(true) is current time in micro second.

9.class ใดๆก็ตามที่มีการสร้าง Object ด้วยการ .getInstance()
จะเรียก class เหล่านั้นว่ามีการเขียนแบบ Singleton 
ซึ่งการเขียนลักษณะนี้จะเป็นการสร้าง instance ของ object นั้นขึ้นมาเพียงครั้งเดียวตอนเริ่มโปรแกรม
และให้ class อื่นๆที่ต้องการเรียกใช้ instance ของมันเองเรียกผ่านทาง .getInstance() ครับ

เหตุผลที่ต้องมี singleton เพราะในบางสถานการณ์ การสร้าง object เพียง
ตัวเดียวแล้วให้โปรแกรมทั้งหมดมาใช้ Object ตัวนั้นเพียงตัวเดียวจะมีประโยชน์มากกว่าครับ
เช่น การสร้าง Object ของการเชื่อมต่อฐานข้อมูลที่ต้องใช้พลังงานมากในตอนสร้าง
พอสร้างเสร็จแล้วก็ทำเป็น singleton ไว้ให้ Class อื่นๆ มาเรียกใช้ได้อีกเรื่อยๆครับ

แต่ singleton ก็มีข้อเสียที่เห็นได้ชัดคือ object life time ครับ เพราะ
Object ที่ถูกสร้างขึ้นโดยวิธีนี้จะไม่ถูกทำลายจนกว่าโปรแกรมจะหยุดทำงาน
(ข้อ9อันนี้ไม่ได้เขียนเองครับ นำมาจาก http://www.narisa.com/forums/index.php?showtopic=34733 )

10.public function __construct(...) เป็น constructure ของ class ใน php

11.Redis คือ key-value database เหมือนกับ Memcache แต่ต่างกันตรงที่ Redis
นั้นจะทำการบันทึกข้อมูลต่างๆ ลง storage ส่วน memcache จะอยู่ใน ram

12.How to use regular expression for
preg_match('/^(?=.*([0-9]))(?=.*([A-z]))[A-z0-9]{6,12}$/' , $password)

13.เราสามารถเรียกใช้ function ใน class ที่เรา extend เข้ามาได้
โดยการเรียกใช้นั้นเสมือนเราเรียกใช้ function ในคลาสที่เรียก นั้นคือ
function ใน class ที่ extend มานั้น สามารถเรียกใช้ function ใน class ของเราที่เป็นคนเรียกใช้ได้
เช่น SerialCodeAbstract ที่ extends TableMapper
ใน SerialCodeAbstract เรียกใช้ static::find() ซึ่งเป็น function ใน TableMapper
จะเสมือนนำ function find() นั้นมารันที่ SerialCodeAbstract นั้นเอง ซึ่งทั้ง 2 คลาสนี้เวลา
เรียกใช้ fuction นั้น จะทำการค้นหา function ในคลาสของผู้ที่เรียก extends ก่อน ในที่นี้คือ
SerialCodeAbstract นั้นเอง ซึ่งหากไม่มีก็จะไปทำใน fuction ของ TableMapper แทน
(ในตัวอย่าง static:find() นั้นไม่มีใน SerialCodeAbstract แต่มีใน TableMapper
แต่ถ้ามีทั้งคู่ มันจะใช้ในคลาสผู้ที่ extend คือ SerialCodeAbstract นั้นเอง)


*************YII*****************
1.นับจำนวน tuple ที่ค้นได้ใน db
    $count = Notification::model()->countByAttributes(array(
            'user_id'=> Yii::app()->user->uid
        ));

2.การเพิ่ม FK ใน model
    public function relations()
    {
        return array(       
            'memberIdMember' => array(self::BELONGS_TO, 'Member', 'member_id_member'),
            // 'ชื่อที่ใช้เรียกFK' => array(self::BELONGS_TO, 'Modelของปลายทาง', 'ค่าAtrributeที่ชี้ไปFK'),
        );
    }
    ตัวอย่างเรียกใช้โดย เช่น $advisor->memberIdMember->username

3.get ค่าเป็น array ตามเงื่อนไข
Advisor::model()->findAllByAttributes(array('curriculum_id_curriculum'=>$value));


*************OTHER*************
ปลดล็อค gmail ให้ส่งเมลล์ผ่าน smtp ได้    https://support.google.com/mail/answer/14257

Tip3 : HTML , CSS , Javascript

**************HTML***************
DROP/DOWN MENU        http://www.w3schools.com/tags/att_option_value.asp
ROOT URL    ใส่ ../ หน้าลิงค์ เช่น "../images/ajax-loader.gif"
Form ถ้าไม่มี action เมื่อ Submit มันจะเรียกตัวมันเองซ้ำ

ทำให้ Input form รองรับเฉพาะไฟล์นามสกุลที่กำหนด
< input type="file" name="file[]" id="filename" accept="image/gif, image/jpeg, image/png, application/pdf, .xlsx, .xls, .doc, .docx" multiple >





************CSS****************
FADEIN/FADEOUT for div    http://stackoverflow.com/questions/11679567/using-css-for-fade-in-effect-on-page-load

ทำให้ใส (where 1 is not transparant at all, 0.5 is 50% see-through, and 0 is completely transparent.)
div {
    opacity: 0.5;



 *************JAVA SCRIPT**************
ปัญหาการพัฒนาเว็บส่วนมาก คือ การไม่สามารถโหลดไฟล์ JQuery หรือ .js ได้
(Failed to load resource: the server responded with a status of 404)

ปกติจะเรียกกันแบบ
< script src="js/jquery.min.js" >< /script >

ให้เราเปลี่ยนมาใช้
< script src="<%=ResolveClientUrl("~/js/")%>jquery.min.js" type="text/javascript" >< /script >


1.FADEIN/FADEOUT for id element    http://stackoverflow.com/questions/6121203/how-to-do-fade-in-and-fade-out-with-javascript-and-css
2.CHECK FORM VALIDATE(ajax)     http://jqueryfordesigners.com/index.html%3Fp=6.html
3.Upload multiple file            http://stackoverflow.com/questions/19295746/how-to-upload-multiple-files-using-php-jquery-and-ajax
4.Upload multiple file with interface    https://github.com/blueimp/jQuery-File-Upload/wiki

5.Detect when select file in upload buttom
$("#file").change(function(){
         //submit the form here
 });

6.Auto click buttom
$('#cancel').trigger('click');

7.Click button to do function
< button onclick="myFunction()" >Click me< /button >

8.ส่งค่า POST จาก jquery ให้ไฟล์ php
    $('#send').click(function(){
       // var clickBtnValue = $(this).val();
        var ajaxurl = 'http://mis.cp.eng.chula.ac.th/u54isi/indexTest.php', //ปลายทางรับ post
        data =  {'action': 'clickBtnValue','fromName':'poo'}; //ข้อมูลที่จะส่งไป post
        $.post(ajaxurl, data, function (response) {
            // Response div goes here.
            alert(response);
        });
    })

9. เรียกใช้ function ตลอดเวลา ทุกๆ 10000ms หรือ 10วิ
setInterval(functionName, 10000);

10.get ค่าใน html ของ id ต่างๆ
   var bar = $('#idname').html();

11.ส่งค่าด้วย post ไปเรียก method ใน url (php) ที่กำหนด ตัวอย่างเรียก get_info แล้วอ่านคืนมาเป็น info
    $.ajax({
                            url: 'ajax',
                            data: 'action=get_info&value=' + $('#curriculum').val() ,
                            dataType: 'json',
                            type: 'post',
                            success: function (info) {
                                depart.value = info.depart;
                                degree.value = info.degree;
                                fu.value = info.fu;
                            }
                        });
12.Foreach ใน javascript
http://blog.levelup.in.th/2010/06/30/javascripts-foreach-foreach-%E0%B9%83%E0%B8%99-javascript/

13.จับว่าเลิก focus element นี้แล้ว
$('#newPassword,#confirmPassword').focusout(function () {
        alert('kuy');
         if($('#newPassword').val() != $('#confirmPassword').val()) {
         //    $('#saveChange').disabled = true;
            }
    });

14.การ disabled ปุ่ม
 $("#saveChange").prop('disabled',true);

15.ทำให้ค่าภายใน element เป็น html ที่ต้องการ
$('#sa').html(str_html); 

16.
$(document).ready(function () {
    //function ที่ต้องการ
});

17.การทำปุ่มอัพไฟล์แบบสวยๆ โดย boostrap
 < div class="col-md-2" >
                            < form enctype="multipart/form-data" method="POST" >
                                < span class="btn btn-default fileinput-button" style="width: 100%" >
                                    < i class="glyphicon glyphicon-cloud-upload" aria-hidden="true" >< /i>
                                    < span>Import data< /span >
                                  < input type="file" name="studentfile" id="studentfile"/ >
                                < /span>        
                            < /form>
< /div>

< style>
.fileinput-button {
  position: relative;
  overflow: hidden;
}
.fileinput-button input {
  position: absolute;
  top: 0;
  right: 0;
  margin: 0;
  opacity: 0;
  -ms-filter: 'alpha(opacity=0)';
  font-size: 200px;
  direction: ltr;
  cursor: pointer;
}

/* Fixes for IE < 8 */
@media screen\9 {
  .fileinput-button input {
    filter: alpha(opacity=0);
    font-size: 100%;
    height: 100%;
  }
}
< /style>

18.เรียกใช้ฟังก์ชั่นเมื่อเวลาผ่านไป 3000ms
setTimeout(function(){ alert("Hello"); }, 3000);

19.ไม่ให้ form จำรหัส ใส่นี้ในส่วน
 < ?php
                echo '$("#password").attr("autocomplete", "off");';
                echo 'setTimeout('."'".'$("#password").val("");'."'".', 500);';
        ? >

19. reload
< script type="text/javascript" >
location.reload();
< /script >

Tip2 : Android รวมคำสั่ง และปัญหาที่พบบ่อยๆ จากประสบการณ์

============ ERROR ที่พบบ่อย ===============
1 . Gradle DSL method not found: 'runProguard()'
ที่ไฟล์ build.gradle เปลี่ยนดังนี้
runProguard false >> minifyEnabled false
..........................................................................................................................
2.SecurityException: Permission denied (missing INTERNET permission?)
เพิ่มบรรทัดนี้ลงไปที่ AndroidManifest.xml

..........................................................................................................................
3.FATAL EXCEPTION: main android.os.NetworkOnMainThreadException at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork
1) Don't write network call in Main UI Thread, Use Async Task for that.
2) Write below code into your MainActivity file after setContentView(R.layout.activity_main);

if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}
..........................................................................................................................
4. Error:(10, 8) error: class MyPageAdapter is public, should be declared in a file named MyPageAdapter.java
ตั้งชื่อไฟล์ java ไม่ตรงกับชื่อ class ให้แก้ให้ตรงกันซะ (ตรง
MyPageAdapter ของท่านจะปรากฏไม่เหมือนกัน แล้วแต่ชื่อ)
 ..........................................................................................................................
5.no such table : message หรือขึ้นว่าไม่มี table
-ให้ตรวจสอบว่าสร้างแล้วยัง ถ้าคำสั่งถูกหมดให้ลองเปลี่ยนชื่อ table ใหม่
-ลองเปลี่ยนเวอร์ชั่น database sqllite ใหม่
..........................................................................................................................




===========TIP ใช้ประจำ=============
1.ส่งตัวแปรข้ามหน้า

ใน MainActivity.java
Intent in = new Intent(MainActivity.this,SecondActivity.class);    //มี class ปัจจุบันเป็น MainActivity.java และ class ปลายทาง SecondActivity.java
in.putExtra("key",value);    //ส่งตัวแปรพร้อมค่า
startActivity(in);     //เปลี่ยนหน้าไปปลายทาง

ใน SecondActivity.java
Intent in = getIntent();
String var = in.getStringExtra("key");    //รับตัวแปร
..........................................................................................................................
2.วันเวลา
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        long today = (new Date()).getTime();        //เวลาขณะนี้
        long bday = 0;
        String birthday = dpBirthday.getYear() + "-" + (dpBirthday.getMonth()+1) + "-" + dpBirthday.getDayOfMonth();
        try {
            bday = formatter.parse(birthday).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        long age = (today-bday)/(1000*60*60*24);
..........................................................................................................................
3.JSON
อ่านจากสตริงเดียว
String json = "{\"sName\":\"Sawatdee : Weerachai Nukitram\",\"sEmail\":\"Sawatdee : is_php@hotmail.com\"}";
JSONObject c = new JSONObject(json);
String strResultName = c.getString("sName");
String strResultEmail = c.getString("sEmail");

อ่านจาก array 2d
String strJSON = "[{\"MemberID\":\"1\",\"Name\":\"Weerachai\",\"Tel\":\"0819876107\"}" +
                 ",{\"MemberID\":\"2\",\"Name\":\"Win\",\"Tel\":\"021978032\"}" +
                 ",{\"MemberID\":\"3\",\"Name\":\"Eak\",\"Tel\":\"0876543210\"}]";

    JSONArray data = new JSONArray(strJSON);
   
    ArrayList> MyArrList = new ArrayList>();
    HashMap map;
   
    for(int i = 0; i < data.length(); i++){
              JSONObject c = data.getJSONObject(i);
             
              map = new HashMap();
              map.put("MemberID", c.getString("MemberID"));
              map.put("Name", c.getString("Name"));
              map.put("Tel", c.getString("Tel"));
              MyArrList.add(map);
             
    }

อ่านจากหลายมิติ
try
    {  
        String jsonString="";//your json string here
        JSONObject jObject= new JSONObject(jsonString).getJSONObject("categories");
        Iterator keys = jObject.keys();
        while( keys.hasNext() )
        {
            String key = keys.next();
            Log.v("**********", "**********");
            Log.v("category key", key);
            JSONObject innerJObject = jObject.getJSONObject(key);
            Iterator innerKeys = innerJObject.keys();
            while( innerKeys.hasNext() )
            {
                String innerKkey = keys.next();
                String value = innerJObject.getString(innerKkey);
                Log.v("key = "+key, "value = "+value);
            }
        }
    }
    catch (JSONException e)
    {   e.printStackTrace();    }
..........................................................................................................................
4.ใส่เส้นคั่นหน้า
                    android:layout_height="1dip"
            android:background="#CCCCCC" />
..........................................................................................................................
5.Layout ต่างๆ
1. Linear Layout เรียงเป็นเส้นตรง แนวนอน หรือ แนวตั้ง โดยใช้คำสั่ง
android:orientation = "horizontal"
android:orientation = "vertical"

2. Relative Layout เรียงตามตำแหน่งอ้างอิงกับ element อื่นๆ ในเลย์เอาต์ หรือ อ้างอิงกับเลย์เอาต์ที่ตัว element นั้นอยู่ โดยใช้คำสั่ง
android:layout_below = "@android:id/text1"
android:layout_toRightOf = "@android:id/checkbox"

3. Frame Layout เป็นการเรียงแบบ stack คือตัวที่สร้างทีหลังจะวางอยู่บนสุด

4. Absolute Layout เป็นการเรียงแบบที่เรากำหนดตำแหน่ง โดยใช้คำสั่ง
android:layout_x="100dp"
android:layout_y="50dp"

5. Table Layout เป็นการเรียงแบบตาราง โดยที่ control แต่ละตัวจะถือเป็น 1 คอลัมน์
โดยจะใช้ .. ครอบแต่ละแถวของตาราง

..........................................................................................................................
6.ใส่ background
android:background="@drawable/bg"
..........................................................................................................................
7.Full Screen app

เปลี่ยน extends เป็น Activity (ห้ามเป็น actionbarActivity) , เพิ่ม 3 บรรทัดนั้นก่อน setContent

public class FullScreen extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.main);
    }
}

หรือใช้วิธี
Alternatively you can add
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
to AndroidManifest.xml under
..........................................................................................................................
8.ทำให้ element ภายในพอดี
 android:scaleType="centerCrop"
..........................................................................................................................
9.ทำให้ปุ่มกระพริบเป็นอีกภาพเมื่อคลิก

 
                android:drawable="@drawable/button_pressed" />
                android:drawable="@drawable/button_focused" />
    
 

แล้ว save ไว้ใน drawable folder เช่น button.xml
ส่วนใน button activity เพิ่ม android:src="@drawable/button"
..........................................................................................................................
10.รับรู้เมื่อปุ่มถูกกด
 final Button button = (Button) findViewById(R.id.button_id);
         button.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 // Perform action on click
             }
         });
หรือ
android:onClick="selfDestruct"
แล้วเพิ่ม
 public void selfDestruct(View view) {
     // Kabloey
 }
..........................................................................................................................
11. เรียกใช้ JSON
JSONArray arr = new JSONArray(result);
JSONObject jObj = arr.getJSONObject(0);
String date = jObj.getString("NeededString");
..........................................................................................................................
12. ทำให้มีหลายแท็ป
http://www.thaicreate.com/mobile/android-tabhost.html
http://devahoy.com/2014/09/android-tab-with-tabhost-and-actionbar-tab/
http://www.akexorcist.com/2014/11/lets-fragment-view-pager-1.html
ใส่รูปใน tab ด้วย view
http://stackoverflow.com/questions/14535085/add-image-or-style-to-each-tab
..........................................................................................................................
13.การนำภาพมาใช้ เช่น button.jpg จากโฟลเดอร์ Drawable
getResources().getDrawable(R.drawable.button)
..........................................................................................................................
14.เพิ่มสี
Then declare gray in your res\values\strings.xml
#808080
แล้วเรียกใช้ผ่าน @color/grey ได้เลย
..........................................................................................................................
15.การเปลี่ยน string เป็น string[]
String[] ary = "abc".split("");
ary จะเป็น {"a","b","c"}
..........................................................................................................................
16.SQLLITE การลบ
// Delete Data
    public long DeleteData() {
        // TODO Auto-generated method stub
        try {
            SQLiteDatabase db;
            db = this.getWritableDatabase(); // Write Data
            db.delete(TABLE_MEMBER, null, null);
            return 0;
        } catch (Exception e) {
            return -1;
        }
    }
..........................................................................................................................
17.refresh activity ใหม่
finish();
startActivity(getIntent());
..........................................................................................................................
18.android life cycle
http://startandroid.ru/en/lessons/complete-list/232-lesson-24-activity-lifecycle-example-about-changing-states-with-two-activities.html
..........................................................................................................................
19.kill thread
myService.getThread().interrupt();
..........................................................................................................................
20.Custom list view
http://www.akexorcist.com/2012/09/android-code-custom-list-view.html
..........................................................................................................................
21.การอัพเดท listview
เอาโค้ดนี้ไว้ที่ไหนก็ได้ เช่น เมท็อตรีเฟชร ให้ Thread เรี่ยกใช้ หรือ onResume()
adapter.getData().clear();    //เข้าไปลบ data ใน adapter (ต้องทำ method getData() ไว้ที่ adapter ด้วย)
adapter.setData(m.SelectAllData());    //เข้าไปเพิ่ม data ใน adapter เป็นตัวใหม่ ต้องมีเมท็อตเหมือนกัน
adapter.notifyDataSetChanged();       
listView.invalidateViews();
listView.refreshDrawableState();
..........................................................................................................................
22.ทำให้ Thread สามารถเรียกเมท็อดได้ ให้ครอบด้วย handler
 handler.post(new Runnable() {
                public void run() {
                    f.refresh1(); //เมท็อดที่จะเรียก
                }
            });
..........................................................................................................................
23. Print to console
Log.d("array", a.size() + "");
..........................................................................................................................
24.สร้างตัวแจ้งเตือน
Toast.makeText(getApplicationContext(),
                                    "Sorry", Toast.LENGTH_SHORT).show();
..........................................................................................................................
25.ทำ popup แบบมีหลายตัวเลือก
http://devahoy.com/2014/04/android-dialog-and-custom-dialog-example/#multi-choice-dialog
..........................................................................................................................


=====================hot-key=====================
[[android : pc]]
Home = Home
Back = esc
Power = F7
Menu = F2
VolUp = Ctrl-F5
VolDown = Ctrl-F6
Press ALT+spacebar together, then release and press m. You are now in Move mode. press Enter to exit Move mode.

ออโต้อิมพอต
http://stackoverflow.com/questions/16615038/what-is-the-shortcut-to-auto-import-all-in-android-studio

วันอาทิตย์ที่ 11 ตุลาคม พ.ศ. 2558

Tip1 : Basic javascript animation PART2

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


1.คำสั่งที่ใช้ควบคุม javascript ที่จำเป็น

var t = setInterval(framerate,500);  เป็นการสั่งให้เรียกฟังค์ชั่น (ในที่นี้ชื่อ framerate) ทุกๆ 500ms ไปตลอด
จะหยุดได้ต้องใช้ clearInterval(t); และนี้คือเหตุผลที่ต้องมี var t มารับค่า เพราะจะได้นำมาใช้หยุดคำสั่งได้
note : คำสั่งจะเริ่มทำงานครั้งแรกเมื่อผ่านไป 500ms นับจากคำสั่งถูกรัน ไม่ใช่เริ่มทำงานทันที

คำสั่งต่อมาที่ใช้บ่อยเช่นกันคือ setTimeout(framerate,500); อันนี้ต่างกันคือเรียกใช้เพียงครั้งเดียว เริ่มทำงานหลัง 500ms 


สองคำสั่งนี้จำเป็นมากในการควบคุมเวลาที่ทำให้อนิเมชั่นเกิดการเปลี่ยนแปลงตามเวลา
สำหรับ setInterval นั้นนอกจากจะใส่เวลาเป็นตัวเลขเป็นเวลาที่แน่นอนคงที่แล้ว
ยังกำหนดเป็นแบบไม่คงที่ได้ เช่น นับเร็วขึ้นเรื่อยๆ ดูรายละเอียดได้ที่เว็บนี้เลย
http://javascript.info/tutorial/animation



2.คำสั่งเบสิกสุดๆ คือการเปลี่ยนค่า css ของแต่ล่ะ element  

เป็นการเปลี่ยนค่าวัตถุ เช่น ขนาด ตำแหน่ง ซ่อน แสดง ขอบ สี  โดยเมื่อออกแบบลำดับดีๆ
ก็จะทำให้เกิดการเปลี่ยนแปลงของวัตถุเป็นอนิเมชั่นที่สวยงามได้ โดยใน js เบื้องต้นจะเป็น
document.getElementById("id").style. แล้วตามด้วยคำสั่ง style ต่างๆ เช่น


document.getElementById("id").style.marginTop = "50%";
document.getElementById("id").style.border = "10px solid yellow";
document.getElementById("id".style.backgroundColor = "red";
document.getElementById("id").style.top = "30%";
document.getElementById("id").style.opacity = "0.9";

ถ้าของ Jquery ก็จะสั้นกว่า ตามนี้ http://www.w3schools.com/jquery/jquery_css.asp
ซึ่งคำสั่งเพิ่มเติมสามารถหาได้จาก google เลยครับ

ตัวอย่างโค้ดทำให้การ์ด (html element) เลื่อนขึ้นและโชว์ขอบ และเลื่อนลงซ่อนขอบ
function cardSlideUp(card) {
  document.getElementById(card).style.marginTop = "40" + "%";
  document.getElementById(card).style.border = "10px solid yellow";
  document.getElementById("frame").style.backgroundColor = "red";
  setTimeout(function(){ document.getElementById('raid').style.width = "98%"; },20);
  setTimeout(function(){ document.getElementById('raid').style.width = "100%"; },200);
}

function cardSlideDown(card) {
  document.getElementById(card).style.marginTop = "50" + "%";
  document.getElementById(card).style.border = "0px solid yellow";
  document.getElementById("frame").style.backgroundColor = "black";
}


เวลาเรียกใช้งานก็จะประมาณนี้

function onClick() { //คำสั่งนี้ถูกเรียกได้หลายวิธี สามารถดูได้ที่ tip part1 บทความที่แล้ว
  var scene = 0

  function framerate() {   
      scene++  


      switch(scene) {
      case 1:
          cardSlideUp("card"); //500ms แรก เรียกการ์ดขยับขึ้น เป็นการโจมตี โดยต้องมี html element ภาพการ์ดที่มี id = "card" ด้วยในการเรียก
          break;
      case 2:
          cardSlideDown("card"); //500ms ต่อมา โจมตีเสร็จขยับลง
          break;


      if (scene == 2) 
        clearInterval(t); //หยุดการทำงานของ setInterval
   }

    var t = setInterval(framerate,500); //ตั้งเวลาไว้ 500ms หรือครึ่งวินาทีต่อการเปลี่ยนแปลง 1 ครั้ง
}



3.คำสั่งจำพวก Canvas ใช้ร่วมกับ sprite sheet
ถ้าต้องการอนิเมชั่นที่ลื่นไหล สวยงาม สมจริง เช่นท่าเตะของตัวละคร effect สกิลโจมตีต่างๆ
ก็จำเป็นที่จะต้องใช้ sprite sheet ร่วมกับคำสั่ง canvas ล่ะครับ

sprite sheet ก็คือภาพๆนึง ที่รวมการเคลื่อนไหวของตัวละครหรือวัตถุต่างๆ ในทุกๆเฟรมไว้
นั้นเอง เฟรมๆนึงก็จะใช้รูปภาพนึง ดังนั้น sprite image จึงมีภาพเล็กๆหลายภาพ อยู่ในตำแหน่ง
ที่แน่นอน เพราะเวลานำไปใช้งานเราจะทำการดึงภาพเล็กๆนั้นแหละไปทีล่ะภาพ โดยจะเปลี่ยน
ตำแหน่งในการดึงทุกครั้ง เพื่อให้ได้ภาพเคลื่อนไหวที่สวยงามต่อเนื่อง




ตัวอย่างภาพ sprite sheet ของ effect ระเบิด 

(http://stackoverflow.com/questions/28201187/working-with-sprite-sheet-animations-in-android)


คราวนี้จะมาอธิบายพร้อม code นะครับ
ขั้นแรก เราต้องมี html element ให้มันแสดงผล canvas ก่อนนะครับ ง่ายๆเลยก็ตัวอย่างเช่น
< canvas id="show" width="640px" height="400px" >< /canvas >
ต่อมาก็เป็นรูปภาพ sprite sheet ซึ่งให้โหลดมาเป็น html img แล้วทำการซ่อนภาพ ก่อนปิดด้วยวงเล็บปีกกา เช่น
< img id="skill" src="sprite.png" style="display:none" />
สำหรับการโหลดภาพเข้ามาใช้ในงานนั้น เนื่องจาก javascript นั้นทำงานแบบไม่รอใคร ไม่รอคำสั่งบรรทัดบนประมวลผลเสร็จ
ก็ไปรันคำสั่งถัดไปแล้ว (async) ก็จะทำให้บางทีนั้นภาพอนิเมชั่นไม่ขึ้น เพราะไม่สามารถหาภาพเจอเนื่องจากโหลดไม่ทัน
วิธีแก้นั้นก็คือให้ทำเป็น img html แล้วโหลดมาไว้ก่อน พร้อมกับซ่อนไว้ ดังตัวอย่างข้างบน หรือถ้าจะใช้ javascript โหลดมาตรงๆล่ะก็ อาจจะต้องมีการหน่วงเวลาด้วยคำสั่ง setTimeout หรือจะใช้ window.onload = function () { ... } ในการรอให้โหลดเสร็จก่อนค่อยรันก็ได้


จากนั้นก็สร้าง javascript สำหรับเรนเดอร์ ดังนี้ 

function animation() {
  var mainAnimationFrame = 0; //เฟรมเริ่มต้นเป็น 0 เหมือนเดิม
 
   var c = document.getElementById("show"); //ต้องนำเข้า canvas html element ที่เราสร้างไว้ในขั้นแรกมาเป็นตัวแปรก่อน
    var ctx = c.getContext("2d"); //จากตัวแปร canvas นั้น ก็ใช้คำสั่ง getContext("2d") เพื่อเรียกส่วนการวาดของ canvas ขึ้นมา เก็บไว้ที่ตัวแปร ctx

    var skill_img = document.getElementById('skill'); //นำภาพ sprite sheet เข้ามาเก็บ


    //ต่อมากำหนดตำแหน่งจุดเริ่มต้นภาพที่จะให้ตัดรูปไปแสดงผลในแต่ล่ะเฟรม โดยสร้างเป็นอาเรย์ javascript
    var skill_list = [{'y': '5', 'x': '5'} ,
                    {'y': '5', 'x': '655'} ,
                    {'y': '5', 'x': '1305'} ,
                    {'y': '5', 'x': '1955'}];

    function run() {
       var id = mainAnimationFrame;
        ctx.clearRect(0, 0, 640, 400); //ลบภาพเก่าเฟรมที่แล้ว ถ้าไม่ใส่ภาพจะวาดทับกันไปเรื่อยๆ
        ctx.drawImage(
          skill_img, //ภาพ sprite ที่โหลดมาไว้ข้างบน
          skill_list[id].x, //จุดเริ่มต้นที่วาดภาพในแนวแกน x โดยดูจากอาเรย์ skill_list ตำแหน่งของอาเรย์ตามเฟรมภาพปัจจุบัน
          skill_list[id].y, 
//จุดเริ่มต้นที่วาดภาพในแนวแกน y โดยดูจากอาเรย์ skill_list ตำแหน่งของอาเรย์ตามเฟรมภาพปัจจุบัน        
          640,  //ขนาดรูปต้นฉบับที่จะ crop มาแสดงผล นับจากจุดเริ่มต้นแกน x
          400, 
//ขนาดรูปต้นฉบับที่จะ crop มาแสดงผล นับจากจุดเริ่มต้นแกน y         
          0, 0, //ตำแหน่ง x,y เริ่มต้นที่จะวาดใน html canvas element
          640, //ขนาดรูปแนวแกน x ที่จะวาดลงไปใน canvas
          400 //ขนาดรูปแนวแกน y ที่จะวาดลงไปใน canvas
          );
        mainAnimationFrame += 1; //เพิ่มเฟรมไปเรื่อยๆทีล่ะ 1

        if(mainAnimationFrame == 3) //ถ้าหมด sprite ที่จะแสดงผลแล้ว ในที่นี้มี 4 รูป เริ่มจาก 0 1 2 3 ดังนั้นเมื่อถึง 3 ก็คือรูปสุดท้าย จบแล้ว ให้ทำคำสั่งข้างล่าง
        {
            ctx.clearRect(0, 0, 640, 400); //ลบภาพเก่าที่วาดไว้
            clearInterval(r); //จบการแสดงผลโดยจบคำสั่ง setInterval ข้างล่าง
        }
    }

   var r = setInterval(run, 100); //ทำงานทุกๆ 100ms
    
}


ดูคำอธิบายโค้ดเพิ่มได้ที่
http://www.w3schools.com/tags/canvas_drawimage.asp    


จากการแสดงผลอนิเมชั่นด้วย canvas ที่ยกตัวอย่างให้เห็นนั้น เป็นการแสดงผล
อนิเมชั่นจาก sprite image ที่โหลดเข้ามา โดยตัดภาพแต่ล่ะส่วนของ sprite image 

(ตามตำแหน่ง x,y ที่เซตใน array skill_list) ไปแสดงผลที่ canvas element ทุกๆ 100ms 
ก็เลยจะได้ภาพที่ค่อนข้างลื่นไหล จะเห็นได้ว่าการทำงานนั้นคล้ายกับตัวอย่างโค้ดใน
PART1 อยู่มาก หลักๆคือให้รู้ว่าทุกๆครั้งที่เฟรมนับไปเรื่อยๆนั้นจะต้องทำอะไร อย่างไรบ้าง
จากตัวอย่าง canvas ในที่นี้คือ เฟรมแรกตัดภาพส่วนที่1 ไปแสดง เฟรมต่อไปก็ตัดภาพส่วนที่2 ไปแสดง 
ทำแบบนี้ไปเรื่อยๆจนหมดเฟรม ตรงส่วนนี้เราสามารถออกแบบโปรแกรมให้ทำงานตามที่เราต้องการได้

สำหรับการประยุกต์ใช้ตัวอย่างนึงคือ การใช้โค้ดใน part1 นั้น มาเรียกใช้
โค้ดในตัวอย่าง canvas นี้ เช่น 


function onClick() {
  var scene = 0

  function framerate() {   
      scene++  


      switch(scene) {
      case 1:
          cardSlideUp("card"); //500ms แรก เรียกการ์ดขยับขึ้น เป็นการโจมตี โดยต้องมี html element ภาพการ์ดที่มี id = "card" ด้วยในการเรียก          

          animation(); //สั่งให้วาดอนิเมชั่นด้วย canvas ที่เราได้ออกแบบไว้หลังการ์ดขยับโจมตี
          break;
      case 2:
          cardSlideDown("card"); //500ms ต่อมา โจมตีเสร็จขยับลง
          break;


      if (scene == 2) 
        clearInterval(t); //หยุดการทำงานของ setInterval
   }

    var t = setInterval(framerate,500); //ตั้งเวลาไว้ 500ms หรือครึ่งวินาทีต่อการเปลี่ยนแปลง 1 ครั้ง
}

 

วันจันทร์ที่ 5 ตุลาคม พ.ศ. 2558

Tip1 : Basic javascript animation PART1

สวัสดีครับ หายไปนานเพราะงานเข้าเยอะมากๆ ช่วงนี้ก็เลยได้เวลาปล่อยของ เอ้ย ปล่อย
ความรู้ที่ได้รับจากการทำงานเป็นโปรแกรมเมอร์ให้เกมๆนึงทางฝั่งญี่ปุ่น โดยส่วนที่ทำให้
ผมชะงักมากสุดก็คือส่วน javascript ที่เป็นอนิเมชั่นนั้นเอง (ปกติผมเป็น backend php)
เอาล่ะ ใน Part1 นี้ผมจะมาอธิบายในส่วนหลักการพื้นฐานที่ควรรู้ก่อน นั้นคือเรื่อง
เวลาที่อนิเมชั่นจะแสดงผล หรือ timeline frame นั้นเอง

Concept
ปกติการรันอนิเมชั่นก็จะมีการกำหนดไว้ว่า ที่เวลาเท่านั้นเท่านี้หลังจาก start จะให้
ทำอะไร วัตถุเคลื่อนไปทางไหน มีอะไรโผล่ขึ้นมา อะไรหายไป และอีกมากมายที่เป็น
การเปลี่ยนแปลงที่ทำให้เกิดเป็นการเคลื่อนไหว หรือ effect ต่างๆ ดังนั้นก็จะต้องมีการ
plan ว่าที่วินาที 1 จะให้ทำอะไร วินาทีต่อมาทำอะไรต่อ เพื่อให้เกิดเป็นภาพอนิเมชั่น
ขึ้นมาในที่สุด บางครั้งอาจเซตเป็น 0.5 วินาที, 0.1 วินาที หรือน้อยจนระดับ ms (millisecond)
แล้วแต่ความ smooth ของภาพ โดยถ้าเซตเป็น 0.5 วินาทีก็หมายความว่า ใน 1 วินาทีที่ผ่านไป
จะมีการเปลี่ยนแปลงเกิดขึ้น 2 ครั้ง และถ้าเซตเป็น 0.1 วินาทีก็มีการเปลี่ยนแปลงเกิดขึ้น 10 ครั้ง
ภาพก็จะ smooth ดูต่อเนื่องมากยิ่งขึ้น ตรงนี้ก็แล้วแต่จุดประสงค์ของแต่ล่ะคนเลยครับ

และนี้คือ basic code พื้นฐานที่เป็นหัวใจสำคัญในการรันอนิเมชั่นใน javascript ครับ

function animation() {  //ชื่อฟังค์ชั่นที่คุมเวลาแสดงอนิเมชั่น

  var scene = 0 //กำหนด scene หรือฉากแรกเป็น 0

  function framerate() {   

      scene++ //ให้ฉากเปลี่ยนไปเรื่อยๆ โดยเพิ่มทีล่ะ 1

      switch(scene) {

      case 1:
          //ใส่ function หรือ code ที่ต้องการให้ run เมื่อถึงวินาทีที่1 ตรงนี้
          break;
      case 2:
         //ใส่ function หรือ code ที่ต้องการให้ run เมื่อถึงวินาทีที่2 ตรงนี้
          break;
      case 3:
         //ใส่ function หรือ code ที่ต้องการให้ run เมื่อถึงวินาทีที่3 ตรงนี้
          break;

      if (scene == 3) 

        clearInterval(t);  //ถ้า scene มาถึงฉากสุดท้าย หรือในที่นี้คือ3 ให้หยุดการทำงาน
      
// กรณีที่อยากให้วน loop เรื่อยๆไม่หยุด ให้เซต scene = 0;

   }

    var t = setInterval(framerate,1000); //เรียกใช้ function framerate ทุกๆ1000ms

}

จากข้างบนจะเป็น code สำหรับรันอนิเมชั่น โดยเซตเวลาที่ทำอนิเมชั่นต่อครั้ง = 1 วินาที
(1000ms) และมี timeline การรันอนิเมชั่นอยู่ 3 ครั้ง (ในที่นี้ตามจำนวน case 1-3)
โดยฟังค์ชั่นข้างบนนั้นจะมีการเรียกใช้ได้หลายวิธี ตัวอย่าง เช่น

1.รันเมื่อโหลดหน้าเว็บ พวกรูปภาพ ไฟล์ต่างๆ เสร็จแล้ว
window.onload = function () {
     animation();  

}


2.รันจากฟังค์ชั่นอื่นๆ (สามารถรันจากฟังค์ชั่นอนิเมชั่นตัวอื่นซ้อนอีกทีก็ได้ จะอธิบาย part ต่อไป)
3.รันจาก html element เมื่อคลิก เช่น < img src="xxx.jpg" onclick="animation();">
4.รันจาก html element เมื่อเมาส์ชี้ เช่น < img src="xxx.jpg" onmouseover="animation();">
5.รันจาก html element เมื่อค่าเปลี่ยน เช่น < input type="text" onchange="animation();">


สำหรับวันนี้ก็จะเป็นการอธิบายในส่วนของ concept เบื้องต้นนะครับ
จริงๆในส่วนนี้ก็สามารถนำไปประยุกต์ใช้ได้เยอะ แต่ถ้ายังไม่หนำใจมีตอนหน้าครับ
จะเป็นตัวอย่างการใช้งานจริงแบบง่ายๆ และตอนถัดไปก็จะเป็นการประยุกต์มากขึ้นอีก

ขอบคุณที่ติดตามครับ