Category: การพัฒนา Web Application

  • django – as a Dialogflow Webhook #03

    บทความนี้ จะกล่าวถึง การใช้ django ทำหน้าที่เป็น Webhook จาก Dialogflow ผ่าน Fulfillment ทาง HTTP Post Request ด้วย JSON object และ ทำการประมวลผล แล้วตอบกลับไปเป็น JSON Object เช่นกัน เพื่อให้ Dialogflow ตอบสนองต่อผู้ใช้ได้ตามต้องการ เช่น อาจจะให้ไปค้นข้อมูลจากฐานข้อมูลในองค์กรมาตอบ เป็นต้น

    Source: https://dialogflow.com/docs/intro/fulfillment

    ในมุมของ django django (ดี)จังโก้ ดีอย่างไร #01 ได้กล่าวถึงการสร้าง Web Application จาก Model โดยกำหนด Fields ต่าง ๆ จากนั้น django ก็จะสร้าง Web Form ต่าง ๆ ให้อัตโนมัติ และยังสามารถสร้าง Users ของระบบ พร้อมทั้ง กำหนดสิทธิ์การเข้าถึงของแต่ละคนได้อีกด้วย แล้วนำไปผูกกับส่วน Admin เพื่อให้ผู้ใช้ทำการ Authentication ก่อนเข้าจัดการกับข้อมูลต่างได้ และในบทความ django – Deploy to Production #02 ได้แนะนำวิธีการ Deploy ระบบที่สร้างขึ้นสู่ Production ตามลำดับ

    ในบทความนี้ จะใช้ “view” ซึ่งเป็นอีกส่วนของ django ตามขั้นตอนต่อไปนี้

    ใน myproject สร้าง App ใหม่ ชื่อ fulfillment

    python manage.py startapp fulfillment

    เพิ่ม ‘fulfillment’ app ลงใน myproject/settings.py ที่ INSTALLED_APPS
    ( ในตัวอย่างก่อนหน้า เราเพิ่ม worklog app ไว้แล้ว) 

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'worklog',
        'fulfillment'
    ]

    จากนั้น แก้ไขไฟล์ myproject/fulfillment/views.py ตามนี้

    from django.http import HttpRequest, HttpResponse
    from django.views.decorators.csrf import csrf_exempt
    import json
    # Create your views here.
    @csrf_exempt
    def sayHi(request):
        j = json.loads(request.body)
        x = {  "fulfillmentText": "This is a text response"
            }
        return HttpResponse(json.dumps(x))

    ในส่วนนี้ จะ import packages ต่อไปนี้

    • HttpRequest เพื่อรับ Input ผ่าน HTTP
    • HttpResponse เพื่อตอบ Output ผ่าน HTTP
    • csrf_exempt เพื่อบอกว่า ยอมให้ทำงานผ่าน HTTP POST โดยไม่ต้องมี CSRF Token (ถ้าไม่ใส่ อยู่ ๆ จะส่ง POST เข้ามาไม่ได้ )
    • json เพื่อจัดการ JSON object

    จากนั้น สร้าง Function ชื่อ “sayHi” มี function ที่เรียกใช้งานดังนี้

    • json.loads(request.body) ทำหน้าที่แปลง JSON Object จาก HTTP Request เข้ามาอยู่ในรูป Python Object ในที่นี้ จะนำข้อมูลจาก Dialogflow Fulfillment ที่ได้จาก Intent Matching และ Parameter Extraction ส่งมา
    • json.dumps(x) ทำหน้าที่แปลงข้อมูล จาก Python Object (ในรูปแบบ dict) ไปเป็น JSON Object ในที่นี้ แปลง { “fulfillmentText” : “This is a text response” } ไปเป็น JSON Object แล้วตอบกลับไปทาง HTTP Response

    ต่อไป สร้างไฟล์ myproject/fulfillment/urls.py เพื่อกำหนด URL ที่จะเรียกใช้ function ดังนี้

    from django.urls import path
    from . import views
    urlpatterns = [    
    	path('hi', views.sayHi )
    ]

    ในส่วนนี้ import package “path” เข้ามา และ import views ที่สร้างขึ้นใน ‘fulfillment’ app และกำหนดว่า เมื่อการเรียก “hi” ให้ไปเรียก function “sayHi” ซึ่งเป็น views

    สุดท้าย แก้ไขไฟล์ myproject/urls.py เพื่อเพิ่ม URL path ให้ fulfillment

    from django.contrib import admin
    from django.urls import path, include
    urlpatterns = [
    	path('admin/', admin.site.urls),
    	path('fulfillment/', include('fullfillment.urls'))
    ]
    

    เมื่อมีการเรียก http://server-domain/fulfillment/ ก็จะส่งไปให้ views ใน fulfillment ทำงาน โดย Include fulfillment.urls เข้ามา

    เมื่อเรียก  http://server-domain/fulfillment/hi ก็จะไปเรียก function sayHi ที่เขียนข้างต้นนั่นเอง

    Dialogflow Fulfillment

    ใน Dialogflow Console คลิกที่ Fulfillment แล้ว Enable Webhook จากนั้นใส่ URL ของ django production server ที่เราสร้างขึ้น ในตัวอย่างจะเป็น

    https://xxxxxxxxx.psu.ac.th/fulfillment/hi

    จากนั้น กดปุ่ม Save ด้านล่าง (ในทางปฏิบัติจริง ๆ ต้องมีเรื่อง Authentication/Authorization อีกพอสมควร แต่ในตัวอย่างนี้ ทำแบบง่าย ๆ ก่อน)

    ต่อไป สร้าง Intent ชุดที่ต้องการให้ส่งให้ Fulfillment ทำงาน แล้วก็คลิกที่ Fulfillment > Enable webhook call for this intent แล้ว Save

    จากนั้น ลองทดสอบดู จะเห็นได้ว่า Default Response จะแสดงข้อความ “This is a text response” แทนที่จะเป็น Text Response ที่กำหนดใน Intent นั้น

    ลองคลิก Diagnostic Info

    จะเห็นว่า มี fulfillmentText เป็น “This is a text response” ตามที่เขียนไว้ เป็นอันว่า Dialogflow สามารถเชื่อมต่อไปยัง django Webhook ที่สร้างขึ้นได้แล้ว

    หวังว่าจะเป็นประโยชน์ครับ

  • django – Deploy to Production #02

    ต่อจาก django #01

    Development Environment

    เริ่มจาก ไปที่ command prompt แล้วใช้คำสั่งต่อไปนี้ เพื่อ เก็บรายละเอียดของ Package และ Version ที่ใช้ในการพัฒนา ไว้ในไฟล์ myenv.txt และ เก็บไฟล์ myproject ทั้งหมดไว้ในไฟล์ myproject.tar.gz (บน Windows อาจจะใช้ 7zip สร้าง)

    pip freeze > myenv.txt
    tar -zxvf myproject.tar.gz myproject

    แล้ว Upload ไฟล์ myenv.txt และ myproject.tar.gz ขึ้นบน Projection Server

    Production Server

    ในที่นี้ ลองไปใช้ Google Compute Engine สร้าง Instance ขึ้นมา เป็น Ubuntu 18.04 และ ได้ Upload ไฟล์ myenv.txt และ myproject.tar.gz จาก Development ขึ้นไว้แล้ว (ใน /home/user01)

    ติดตั้ง Python3, PIP, Apache2, และ mod_wsgi

    sudo apt update
    sudo apt install python3 python3-pip apache2 libapache2-mod-wsgi-py3

    ติดตั้ง virtualenv

    pip3 install virtualenv

    สร้าง Virtual Environment ชื่อ production

    virtualenv production
    source production/bin/activate

    ติดตั้ง Package ต่าง ๆ ตามที่สร้างไว้จาก Development Environment (จากไฟล์ myenv.txt)

    pip install -r myenv.txt

    แตกไฟล์ myproject.tar.gz ออกมา

    tar -zxvf myproject.tar.gz

    สร้าง Apache Site Configuration ที่ /etc/apache2/sites-available/001-myproject.conf

    เนื้อหาตามนี้

    <VirtualHost *:80>
        Alias /static /home/user01/myproject/static
        <Directory /home/user01/myproject/static>
            Require all granted
        </Directory>
        <Directory /home/user01/myproject/myproject>
            <Files wsgi.py>
                Require all granted
            </Files>
        </Directory>
    
        WSGIDaemonProcess myproject python-home=/home/user01/production python-path=/home/user01/myproject
        WSGIProcessGroup myproject
        WSGIScriptAlias / /home/user01/myproject/myproject/wsgi.py
    </VirtualHost>

    จากนั้น สร้าง Symbolic Link จาก /home/user01/production/lib/python3.6/site-packages/django/contrib/admin/static มาที่ /home/user01/myproject/static

    ln -s /home/user01/production/lib/python3.6/site-packages/django/contrib/admin/static /home/user01/myproject/static

    ปรับ Permission ให้ www-data สามารถแก้ไข Database ได้ (เพราะในที่นี้ใช้ SQLite)

    sudo chown :www-data /home/user01/myproject/db.sqlite3
    sudo chown :www-data /home/user01/myproject

    สั่ง Apache ให้เอา Default Site ออก และ นำ myproject ขึ้นแทน และ ทำการ Reload

    sudo a2dissite 000-default
    sudo a2ensite 001-myproject
    sudo systemctl reload apache2

    ก็จะใช้ได้แล้ว

    มีหน้า Admin ให้ใช้
    admin เข้าใช้งานได้
    User ก็สามารถเข้าใช้งานได้

    หวังว่าจะเป็นประโยชน์ครับ

  • django (ดี)จังโก้ ดีอย่างไร #01

    ขอไม่ลงรายละเอียดว่า อะไรคือ Web Framework, MVC, MVT พวกนั้นนะครับ อ่านเองที่ https://www.djangoproject.com/ และ เขียนวิธีติดตั้งบน Windows ไว้คร่าว ๆ ที่ ขั้นตอนการติดตั้ง django บน Windows และในที่นี้ใช้ Visual Studio Code เป็น Editor (สั่งด้วยคำสั่ง code …)

    โจทย์

    สมมุติในทีม มีคน 10 คน ต้องการ ระบบบันทึกการปฏิบัติงาน

    1. จัดเก็บข้อูล วันเวลาของงานที่ทำ, ประเภทของงงาน (ตาม TOR), รายละเอียดของงานที่ทำ, ระยะเวลาที่ใช้ไป (ชั่วโมง)
    2. แต่ละคน ต้อง Login เข้ามาก่อน จึงจะบันทึกปฏิบัติงานได้

    วิถีแบบ django

    สร้าง project ชื่อ myproject

    django-admin startproject myproject

    สร้าง App ชื่อ worklog

    cd myproject
    python manage.py startapp worklog

    สร้าง Model ว่าจะเก็บข้อมูลอะไรบ้าง

    แก้ไขไฟล์

    code worklog/models.py

    แล้วสร้าง Class ชื่อ Worklog เพื่อกำหนด Field เป็นช่องทางการเก็บค่าตามโจทย์ (Reference: https://docs.djangoproject.com/en/2.1/ref/models/fields/)
    –> ขั้นตอนนี้ เขียนใน Visual Studio Code เสร็จแล้ว Save and Exit

    from django.db import models
    from django.utils.timezone import now
    
    # Create your models here.
    class Worklog(models.Model):
        timestamp = models.DateTimeField(default = now())
        typeOfWork = models.ForeignKey('TypeOfWork', on_delete=models.CASCADE)
        work_text = models.TextField(default="")
        manhour = models.FloatField(default=0)
        def __str__(self):
            return self.work_text
    
    class TypeOfWork(models.Model):
        typeOfWork_text = models.CharField(max_length=200)
        def __str__(self):
            return self.typeOfWork_text

    บอกให้ django สร้างโครงสร้างฐานข้อมูลตามโมเดล (จาก Command Prompt)

    python manage.py migrate

    เพิ่ม App ‘worklog’ เข้าสู่ myproject

    แก้ไขไฟล์

    code myproject/settings.py

    เพิ่ม ‘worklog’ ในส่วนของ INSTALLED_APPS
    –> ขั้นตอนนี้ เขียนใน Visual Studio Code เสร็จแล้ว Save and Exit

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'worklog'
    ]

    สร้าง Super User สักคนนึง

    python manage.py createsuperuser

    ตั้งชื่อว่า admin และ รหัสผ่านตามต้องการ

    เพิ่มโมเดล TypeOfWork และ WorkLog เข้าสู่หน้าของ Admin โดยการแก้ไขไฟล์
    –> ขั้นตอนนี้ เขียนใน Visual Studio Code เสร็จแล้ว Save and Exit

    code worklog/admin.py

    ดังนี้

    from django.contrib import admin
    
    # Register your models here.
    from .models import TypeOfWork, Worklog
    admin.site.register(TypeOfWork)
    admin.site.register(Worklog)

    สั่ง Run Server

    สั่งที่ Command Prompt

    python manage.py runserver

    แล้วเปิด Web Browser ไปที่
    http://127.0.0.1:8000/admin/

    ใส่ Login และ Password ของ admin ทั้งตั้งไว้ก่อนหน้านี้

    เริ่มต้นใช้งาน

    เพิ่มประเภทของงาน

    คลิก Type of works — django พยายามใส่ s ให้ด้วยอัตโนมัติ
    คลิกที่ปุ่ม ADD TYPE OF WORK
    เพิ่มประเภทของงาน วนไป
    เสร็จแล้วได้ผลประมาณนี้ อยากจะ Edit Delete ได้หมด

    เพิ่มบันทึกการปฏิบัติงาน

    คลิกที่ Add ในส่วนของ Worklogs

    มี Form สำหรับ Input ทันที

    สวยงาม ไม่ต้องทำอะไรเพิ่ม เลือก Type of works ได้ ช่องวันที่ เวลา ก็มี Widget ให้เรียบร้อย
    แก้ไขไป มี History ให้ด้วย

    จากนั้น ก็เพิ่มคนเข้าทีม ด้วยเมนู Users ได้

    ระบบ Security พร้อม

    User01 ตั้งค่าให้เป็น Worklog > Can Add Worklog
    ก็จะทำได้แค่เข้ามาบันทึกปฏิบัติงานเท่านั้น

    สรุป

    จะเห็นได้ว่า ด้วยการสร้างโมเดลเล็กน้อย django ก็สามารถสร้างระบบ User Entry ง่าย ๆ ที่มาพร้อม Security Features มากมายได้แล้ว ยังมีรายละเอียดอีกเยอะ โดยเฉพาะในส่วนของ View/Template ที่จะสร้าง User Input และการออกรายงานต่าง ๆ รวมถึง การสร้าง API และ RESTful API หรือ จะผูกกับ OAuth2 ก็ยังได้

    หวังว่าเป็นประโยชน์ครับ

  • Stencil : Web component compiler

    Stencil เป็น compiler ที่ทำหน้าที่สร้าง standards-based web component (custom element) ซึ่งรวบรวมแนวคิดที่ดีของ framework ต่างๆที่ได้รับความนิยมสูง มาไว้ใน component โดย build-time tool ที่ใช้งานง่าย เช่น

    • Virtual DOM
    • Async rendering (inspired by React Fiber)
    • Reactive data-binding
    • TypeScript
    • JSX

    web component ที่ได้จาก Stencil เป็น standards-based web component ทำให้สามารถใช้งานร่วมกับ framework ต่างๆที่ได้รับความนิยม และสามารถใช้ได้โดยไม่มี framework ก็ได้ จากเดิมเมื่อพัฒนาด้วย framework หนึ่งแล้ว ไม่สามารถนำไปใช้ร่วมกับ framework อื่นได้

    Stencil มี APIs เช่น Virtual DOM, JSX, และ async rendering  ที่ทำให้สามารถพัฒนา web component ที่ทำงานได้เร็ว มีประสิทธิภาพดีกว่า และสร้างได้ง่ายกว่าเมื่อเปรียบเทียบกับการเขียน custom element โดยตรงโดยไม่ใช้ Stencil  และใน Stencil ยังมี small dev server พร้อมความสามารถ live reload อยู่ด้วย

    เริ่มต้นสร้าง project กับ Stencil

    การสร้าง component ทำได้โดยเริ่มต้นจาก component starter ดังนี้

    git clone https://github.com/ionic-team/stencil-component-starter my-component
    cd my-component
    git remote rm origin
    npm install
    

    จากนั้น ถ้าต้องการ start  live-reload server สำหรับการพัฒนา ให้ใช้คำสั่ง

    npm start

    Updating Stencil
    ถ้าต้องการ update Stencil เป็น version ล่าสุดให้ใช้คำสั่ง

    npm install @stencil/core@latest --save-exact

    Stencil components

    component ถูกสร้างโดยการสร้าง file .tsx ใน “src/components” directory เขียน component ด้วย JSX และ Typescript  ซึ่ง component ที่สร้างมาจาก component starter คือ my-component.tsx

    import { Component, Prop } from '@stencil/core';
    
    @Component({
      tag: 'my-first-component',
      styleUrl: 'my-first-component.scss'
    })
    export class MyComponent {
    
      @Prop() name: string;
    
      render() {
        return (My name is {this.name}); 
      } 
    }
    

    เมื่อ compile แล้วเสร็จ สามารถนำ component ไปใช้ใน HTML page ได้เช่นเดียวกับ tag อื่นๆ Web Components จะต้องมี “-” ภายใน tag (“myFirstComponent” เป็นชื่อที่ไม่สามารถใช้งานได้)

    <my-first-component name="Max"></my-first-component> 
    

    เมื่อเปิดผ่าน browser จะแสดงผล My name is Max

     

    อ้างอิง : https://stenciljs.com

  • การบริหารโครงการโดยใช้เครื่องมือ Team Foundation Server (Phase 4 : การวางแผนงาน)

    จาก บทความ “การบริหารโครงการโดยใช้เครื่องมือ Team Foundation Server (Phase 3 : ขั้นตอนการคัดเลือกความต้องการ และความหมายของ State)” ทำให้เราทราบแล้วว่าในรอบการพัฒนา (Sprint) เราจะต้องดำเนินการตามความต้องการ หรือ Backlog item ใดบ้างแล้วนั้น ต่อไปเราจะมาดูเรื่องการกำหนดทรัพยากรบุคคล และมอบหมายงานต่อไป


    ขั้นตอนการกำหนดทรัพยากรบุคคล ที่จะมาทำโครงการ

    เป็นขั้นตอนของการสร้าง Team และการเลือกคนเข้ามาอยู่ในทีมนั้นเอง ซึ่งแต่ละโครงการทีมงานอาจจะเป็นคนละคนกันได้ ในการสร้าง Team และกำหนดบุคลากร สามารถดำเนินการได้ตามขั้นตอนดังนี้

    จาก TFS เลือก หมายเลข 1 ตามรูปที่ 1

    รูปที่ 1

    ทำการสร้าง Team โดยทำตามขั้นตอนตามรูปที่ 2

    รูปที่ 2

    จะปรากฎหน้าจอ เพื่อให้ใส่ข้อมูลรายละเอียดต่างๆ เกี่ยวกับข้อมูล Team ที่จะสร้าง ดังรูปที่ 3

    รูปที่ 3

    โดย

    หมายเลข 1 คือ ชื่อของ Team ที่ต้องการเพิ่ม

    หมายเลข 2 รายละเอียดเพิ่มเติม เกี่ยวกับ Team

    หมายเลข 3 ประเภทของการตั้ง Team เพื่อจุดประสงค์ ใด โดย TFS มีให้เลือก ดังรูปที่ 4

    รูปที่ 4

    เมื่อเราได้ Team แล้ว เราจะมา Add สมาชิก หรือทรัพยากรบุคคล ใน Team ที่สร้าง โดยทำตามขั้นตอน ในรูปที่ 5

    รูปที่ 5

    จะปรากฎหน้าจอ ดังรูปที่ 6 จากนั้น จะทำการ Add Members หรือสมาชิกในทีม โดยทำตามขั้นตอน ข้อ 1 ในรูปที่ 6

    รูปที่ 6

    จะปรากฎหน้าจอ เพื่อให้การพิมพ์ชื่อ เพื่อจะ Add Member ดังรูปที่ 7 โดยสามารถ ได้ ทีละหลายๆ คน และทำการ Save changes เพียงครั้งเดียว

    รูปที่ 7

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


    ขั้นตอนการกำหนดงานย่อย (Tasks) และมอบหมายงาน

    จากบทความก่อนหน้า นั้น เราได้มีการสร้างรอบการพัฒนา ที่เรียกว่า Sprint ไว้แล้ว และได้ตกลงกับผู้ใช้เพื่อเลือกความต้องการ หรือ Backlog items ที่จะทำให้แล้วเสร็จในรอบการพัฒนาที่สร้างไว้ ซึ่งจะทำให้เห็นว่ามีความต้องการอะไรบ้างที่จะต้องทำให้เสร็จ จากนี้ Project Manager จะต้องทำการแตกงาน หรือ Task ลงไปว่าในแต่ละ Backlog item แต่ละตัวนั้น จะมีงานย่อย หรือ Task อะไร บ้าง ซึ่ง Project Manager จะต้องวางแผนไว้ และสามารถมาบันทึกใน TFS ได้ ดังขั้นตอนต่อไปนี้

     

    จาก TFS เลือกโครงการที่ต้องการสร้าง Task ย่อย ตามหมายเลข 1 รูปที่ 8

    รูปที่ 8

    คลิกเลือก ตามรูปที่ 9 เพื่อไปสู่การบันทึก Task

    รูปที่ 9

    เมื่อทำตามขั้นตอนข้างต้น ทำการเลือก Sprint และ Backlog ในขั้นตอนที่ 1 และ 2 ของรูปที่ 10 จะได้หน้าจอเหมือนรูปที่ 10

    รูปที่ 10

    จากรูปที่ 10 จะแสดงรายละเอียดของ Backlog Items ทั้งหมด ในรอบ  Sprint 5 ที่ได้ตกลงกับผู้ใช้ แล้วว่าจะดำเนินการเรื่องใดบ้างนั่นเอง

     

    จากนั้น ให้ทำตามขั้นตอนในรูปที่ 11

    รูปที่ 11

    จากรูปที่ 11 ทำการกดเลือกหมายเลข 1 ก็จะปรากฎข้อมูลดังหน้าจอ ในรูปที่ 11 ขึ้นมา

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

     

    ในกรณีที่ต้องการสร้าง Task หรืองานย่อย ผู้เขียนขอยกตัวอย่าง ใน Backlog item ที่ เป็น “รายงาน งบกระแสเงินสด” นะค่ะ หากต้องการสร้าง Task ย่อย ให้กดที่เครื่องหมายบวก (+) ดังขั้นตอนที่ 3 ในรูปที่ 11 ค่ะ ซึ่งจะได้หน้าจอ ดังรูปที่ 12

     

    ก่อนอื่นเลย Project Manager จะต้อง List มาก่อนว่าจะมี Task ย่อย ๆ อะไรบ้าง ก่อนจะมาบันทึกใน TFS ซึ่งในกรณีนี้ สำหรับงานพัฒนาระบบ ก็จะหนีไม่พ้น ตามกระบวนการ SDLC นั่นเอง ซึ่งหลักๆ จะประกอบไปด้วย

    • Desgin and Analysis
    • Develop
    • Review Develop
    • ส่งมอบเพื่อทดสอบ
    • System Test
    • Review System Test
    • Delpyment    เป็นต้น

    รูปที่ 12

    สำหรับรูปที่ 12 เป็นตัวอย่างของการสร้าง Task โดยมีรายละเอียดดังนี้

    หมายเลข 1 : ชื่อ Task ย่อย

    หมายเลข 2 : รอบการพัฒนาที่จะให้ดำเนินการ ซึ่งจะ Default ตาม Backlog item นั้นๆ

    หมายเลข 3 : ทำการ Assign ให้ใครดำเนินการ

    หมายเลข 4 : ระยะเวลาที่มอบหมายงานให้ ซึ่งชื่อจะปรากฎตามที่ ได้ Add ไปในขั้นตอนการกำหนดทรัพยากรบุคคล

    หมายเลข 5 : เป็นขั้นตอนใด ซึ่งประกอบด้วย

    Design

    Development

    Documentation

    Requirements

    Testing

    Deployment

    หมายเลข 6 : เป็นการอธิบายรายละเอียดของ Task ว่าจะดำเนินการ หรือมีเงื่อนไขอย่างไรบ้าง

    และกดหมายเลข 7 เพื่อทำการบันทึกข้อมูล

     

    หลังจากที่ทำการบันทึกข้อมูล Task ทั้งหมดเข้าสู่ TFS เรียบร้อยแล้ว Project Manager สามารถตรวจสอบ หรือดูภาพรวม ได้ทำตามขั้นตอน ในรูปที่ 13 คือ

    ขั้นตอน 1 จาก TFS เลือก Backlog

    ขั้นตอน 2 สำหรับส่วนที่ 2 จะแสดงรายละเอียด Task ย่อยต่างๆ ในแต่ะ Backlog item ทำให้ใเห็นว่ามี Activity ใดบ้าง Assign ให้ใคร และต้องใช้เวลาเท่าไหร่

    ขั้นตอน 3 สำหรับส่วนที่ 3 แสดงให้ว่า

    Work : จำนวนชั่วโมงที่ใช้ในเวลาทำงาน

    Work By Activity : จำนวนชั่วโมงของแต่ละ Activity

    Work By Assign To : จำนวนชั่วโมงที่ได้มอบหมายให้แต่ละบุคคล

    รูปที่ 13

    ถึงตอนนี้ ก็จะทำให้เห็นปริมาณของงาน และระยะเวลาที่ต้องใช้ทั้งในภาพรวมของรอบการพัฒนานั้นๆ ภาพรวมของแต่ละ Activity และยังสามารถเห็นในภาพรวมของการมอบหมาย หรือ Assign ให้แต่ละคนภายในทีมงานด้วย


    ในครั้งต่อไป จะมาอธิบายขั้นตอนในการ บันทึกผลการปฏิบัติงาน และการติดตามงานโดยใช้เครื่องมือ TFS กันต่อนะค่ะ อย่าลืมติดตามกันนะค่ะ ขอบคุณค่า ^____^

     

  • การบริหารโครงการโดยใช้เครื่องมือ Team Foundation Server (Phase 3 : ขั้นตอนการคัดเลือกความต้องการ และความหมายของ State)

    จากบทความ การบริหารโครงการโดยใช้เครื่องมือ Team Foundation Server (Phase 2 : การบันทึกความต้องการ)

    ผู้เขียนได้กล่าวถึงการบันทึกความต้องการโดยใช้เครื่องมือ TFS ไปแล้ว สำหรับบทความครั้งนี้ ผู้เขียนจะกล่าวถึงขั้นตอนหลังจากรับความต้องการเข้ามา และจะเข้าสู่ขั้นตอนการคัดเลือกความต้องการ และการกำหนด State ในเครื่องมือ TFS


    การคัดเลือก Backlog items (Backlog items)


    หลังจากขั้นตอนการรวบรวมความต้องการ หรือ Backlog items จากลูกค้ามาแล้วนั้น Backlog items ที่ได้ทุกข้อจะถูกบันทึกเข้าสู่ TFS ซึ่ง Backlog items ที่ได้มาทั้งหมด อาจจะไม่ถูกเลือกให้ดำเนินการ หรือไม่ต้องดำเนินการด้วยเหตุผลต่างๆ ขึ้นอยู่กับการตกลงกันระหว่างผู้จัดโครงการ กับลูกค้า

    สำหรับเครื่องมือ TFS นำมาช่วย Project Manager ในขั้นตอนการคัดเลือก Backlog Items โดยการ Update State ของแต่ละ Backlog Items เพื่อให้ทราบว่า  Backlog item อยู่ใน State ใด ตามความหมายดังนี้

    รูปที่ 1

    จากรูปที่ 1 นะค่ะ

    1. New : คือ Backlog items ที่เข้ามาใหม่ ยังไม่ผ่านการพิจารณา หรือยังไม่ผ่านขั้นตอนการคัดเลือก
    2. Approved คือ Backlog items ที่ผ่านการคัดเลือก แต่ยังไม่ดำเนินการในรอบปัจจุบัน ซึ่งอาจจะรอในรอบการพิจารณาถัดไปเพื่อให้ดำเนินการ
    3. Commited คือ Backlog items ที่ผ่านการคัดเลือก และตกลงให้แล้วเสร็จในรอบปัจจุบัน ซึ่งจะต้องประเมินเรื่องของความเหมาะสมของเวลาด้วย ว่าสามารถดำเนินการได้กี่ Backlog items
    4. Done คือ Backlog items ที่ผ่านการคัดเลือก และดำเนินการเสร็จเรียบร้อยแล้ว หรือ คือ Backlog items ที่ผ่านการคัดเลือกแต่ไม่ถูกให้ดำเนินการให้ทำ (ซึ่งจะมีการบันทึกไว้ใน หมายเหตุ หรือ History)

    ในบทบาทของ Project Manager คือ

    1. หลังจากได้ตกลงกับลูกค้าและร่วมกันคัดเลือกความต้องการแล้วแล้ว Project Manager จะทำการ Update State ของ Backlog item แต่ละข้อตามข้อตกลง
    2. สร้างรอบการพัฒนา หรือ Iteration
    3. ระบุ Backlog items ที่ทำการ Commited เข้าสู่รอบ Iteration ที่ต้องการ
    4. ทำการวางแผนย่อย (Tasks) ต่อไป

    วิธีการสร้างรอบการพัฒนา หรือ Iteration

    จาก Link ของ TFS

     

    รูปที่ 2

    เลือก Configuration หมายเลข 1 ในรูปที่ 2 เพื่อเข้าไปจัดการเกี่ยวกับโครงการ จะปรากฎหน้าจอดังรูปที่ 3 

    รูปที่ 3

    ในรูปที่ 3 จะแสดงโครงการ หรือ Project ทั้งหมดที่รับผิดชอบ ให้ทำตามขั้นตอน คือ

    • เลือกโครงการ ตามหมายเลข 1
    • จะปรากฎรายละเอียดด้านขวา เลือก Link ตามหมายเลข 2 เพื่อเข้าไปทำการจัดการเกี่ยวกับรายละเอียดของโครงการที่เลือก
    • จะปรากฎหน้าจอดังรูปที่ 4

     

    รูปที่ 4

    จากรูปที่ 4 ทำตามขั้นตอนเพื่อสร้างรอบการพัฒนา หรือ Iteration ดังนี้

    • กดเลือก หมายเลข 1 Iterations เพื่อจัดการเกี่ยวกับรอบการพัฒนา หรือ Iterations
    • กดเลือกหมายเลข 2 เพื่อเลือก Release ที่ต้องการ ซึ่งอาจจะมีหลาย Release ขึ้นอยู่กับข้อตกลงกับลูกค้า หรือขึ้นอยู่กับความต้องการที่ได้รับ
    • กดเลือกหมายเลข 3 เพื่อทำการสร้างรอบการพัฒนา ของ Release 1 โดยจะปรากฎหน้าจอขึ้นมา เพื่อให้กำหนดรายละเอียดของรอบการพัฒนา
    • หมายเลข 4 Iteration name ให้ใส่ชื่อรอบของการพัฒนา ขึ้นอยู่กับ Project Manager  แต่ละท่าน เพื่อใช้ในการสื่อสานภายในทีมพัฒนา
    • หมายเลข 5 ให้ระบุ วันที่เริ่มต้นรอบการพัฒนา (Start date) และวันที่สิ้นสุดรอบการพัฒนา (End date)
    • กดเลือกหมายเลข 6 เพื่อบันทึกรายละเอียดที่ได้กำหนดไป

    หลังจากได้ทำการสร้างรอบการพัฒนา ไปแล้วเราสามารถตรวจสอบ หรือดูรอบการพัฒนาที่เพิ่มไปได้ โดย ทำตามขั้นตอน ในรูปที่ 5 ดังนี้

    รูปที่ 5

    • หมายเลข 1 เข้าไปยัง TFS
    • หมายเลข 2 เลือกโครงการที่ได้กำหนดรอบการพัฒนาไปข้างต้น
    • จะปรากฎหน้าจอดังรูปที่ 6 โดย

    รูปที่ 6

    • กดเลือกหมายเลข 1 เพื่อดูงาน ทั้งหมด
    • กดเลือกหมายเลข 2 คือ รอบการพัฒนา ที่เราได้ทำการเพิ่มเติมนั้นเองค่ะ

    ขั้นตอนการระบุ Backlog items ที่ทำการ Commited กับผู้ใช้หรือลูกค้าว่าจะดำเนินการในรอบนี้ เข้าสู่รอบการพัฒนา หรือ Iteration ที่ต้องการ

    มีขั้นตอนดังนี้

    รูปที่ 7

    จากรูปที่ 7

    หมายเลข 1 เลือก Backlog items เลือก Board

    หมายเลข 2 ในช่อง Approved คือ Backlog items ที่ได้ตกลงกับผู้ใช้ว่าจะดำเนินการ แต่ยังไม่ได้ระบุว่าจะดำเนินการในรอบใด ให้เลือก Backlog item ที่ตกลงว่าจะทำในรอบนี้

    หมายเลข 3 Double click ที่ Backlog item ที่จะกำหนดรอบการพัฒนา จะได้หน้าจอดังรูปที่ 8

    รูปที่ 8

    จากรูปที่ 8

    หมายเลข 1 เลือกรอบการพัฒนา (Iteration) ที่ได้ตกลงกับผู้ใช้ หรือลูกค้า

    หมายเลข 2 ระบุ State เป็น Commited คือตกลงจะทำให้แล้วเสร็จในรอบการพัฒนาที่กำหนด

    หมายเลข 3 กดปุ่ม Ave and Close เพื่อบันทึกข้อมูล

    โดยข้อมูล Backlog item จะไปอยู่ในช่อง Commited ดังรูปที่ 9

    รูปที่ 9

     

    รูปที่ 10

    จากรูปที่ 10 เราสามารถตรวจสอบข้อมูล ในมุมมองว่าในรอบการพัฒนานั้นๆ มี Backlog items อะไรบ้างที่เราต้องทำ โดย

    หมายเลข 1 เลือกเมนู Work

    หมายเลข 2 เลือก Iteration ที่ต้องการ

    หมายเลข 3 จะแสดง Backlog items ที่เรากำหนดให้ commited ในรอบการพัฒนาดังกล่าวนั่นเอง


    กล่าวโดยสรุป

    ในมุมมองของ Project Manager ในการนำเครื่องมือ TFS มาใช้ในกระบวนการคัดเลือกความต้องการ และกำหนดรอบการพัฒนา ทำให้เห็นภาพรวมของ Backlog Items ทั้งหมด ว่ามีความต้องการของระบบนี้ทั้งหมดกี่เรื่อง และมีการแบ่งรอบการพัฒนาขึ้นกี่รอบ เพื่อให้สามารถพัฒนาระบบให้ได้ครบทุกความต้องการ และแต่ละรอบการพัฒนา จะมีความต้องการใดบ้างที่จะต้องดำเนินการ ซึ่งเครื่องมือดังกล่าวสามารถแสดงให้ Project Manager เห็นได้ และสามารถติดตามได้นั่นเอง

     

    สำหรับขั้นตอนการวางแผนย่อย (Tasks) เพื่อให้แต่ละความต้องการ หรือแต่ละ Backlog item ทำได้สำเร็จ หรือเสร็จทันนั้นผู้เขียนขอกล่าวในรอบถัดไปนะค่ะ เนื้อหายาวไปเกรงว่าผู้อ่านจะเบื่อกันซะก่อน อยากให้ติดตามกันต่อนานๆ ค่ะ

     

    ขอบคุณค่ะ ^___^

  • การเรียกใช้งาน (Register) Bootbox.js ด้วย C#.NET

    ในการออกแบบเว็บฟอร์มบันทึกข้อมูลลงฐานข้อมูลนั้น นักพัฒนาเว็บแอ๊พปลิเคชั่นส่วนใหญ่จะออกแบบเป็นลำดับขั้นตอนการทำงานประมาณนี้

    1. ผู้ใช้เปิดเว็บฟอร์มขึ้นมาด้วยเว็บบราวเซอร์
    2. ผู้ใช้กรอกข้อมูลลงในเว็บฟอร์ม
    3. ผู้ใช้กดปุ่มบันทึกข้อมูล
    4. ระบบตรวจสอบ (Validate) ข้อมูลที่ผู้ใช้กรอกเข้ามา
      1. ถ้าผ่านก็บันทึกข้อมูลลงฐานข้อมูล
      2. ถ้าไม่ผ่านก็จะแจ้งข้อความแจ้งเตือนผู้ใช้งานให้ตรวจสอบข้อมูลใหม่อีกครั้ง
    5. ระบบจะแจ้งผลการบันทึกข้อมูลว่า
      1. “บันทึกข้อมูลสำเร็จ” กรณีที่บันทึกสำเร็จ หรือ
      2. “เกิดข้อผิดพลาดในการบันทึกข้อมูล” ในกรณีที่มีข้อผิดพลาด

    การพัฒนาเว็บด้วย ASP.NET นั้นในขั้นตอนที่ 4 จะถูกเขียนด้วยโค้ด C#.NET ซึ่งเป็น Server Side Script ส่วนขั้นตอนที่ 5 นั้นเราสามารถใช้ Dialog ของ Bootbox.js ซึ่งเป็น Client Side Script มาช่วยได้ ซึ่งในบทความนี้จะแสดงวิธีการเขียนโค้ด C#.NET ให้เรียกใช้ Bootbox Dialog ได้เลย  (อ่านบทความ การสร้าง JavaScript Dialog ด้วย Bootbox.js ได้ที่นี่) และสร้างเป็นฟังก์ชั่นสำเร็จรูปไว้เรียกใช้งานใหม่ได้ (Reuse)

     

    การรันคำสั่ง Bootbox.js ซึ่งเป็น JavaScript ผ่าน C#.NET นั้นจะต้องใช้ ScriptManager ช่วยลงทะเบียนสคริปต์ (Register Script) ดังนี้

    รูปที่ 1 การ Register Script ด้วย ScriptManager

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

    รูปที่ 2 การแสดงข้อความแจ้งผู้ใช้หลังการบันทึกข้อมูล

    ผลลัพธ์ที่ได้จากโค้ดข้างต้นจะเป็นดังรูปที่ 3

    รูปที่ 3 ผลลัพธ์ของข้อความแจ้งเตือนจากการบันทึกข้อมูล

    แน่นอนว่าในการพัฒนาเว็บแอ๊พปลิเคชัน 1 ครั้ง จะประกอบด้วยฟอร์มบันทึกข้อมูลมากมาย ทำให้ต้องเขียนโค้ดซ้ำๆ กันหลายครั้ง จากโค้ดข้างต้นเราสามารถ Optimize โค้ดได้อีกโดยให้สามารถเรียกใช้งานและแก้ไขโค้ดในภายหลังได้ง่ายขึ้น โดยการย้ายส่วนลงทะเบียนสคริปต์ไปไว้ในฟังก์ชั่นกลางสร้างเป็น Library (ในที่นี้จะตั้งชื่อว่า CoreBLL) สำเร็จรูปไว้ใช้ต่อไปดังนี้

    รูปที่ 4 CoreBLL

    หลังจากที่สร้าง CoreBLL เสร็จแล้วให้แก้ไขโค้ดบันทึกข้อมูลดังรูปที่ 5

    รูปที่ 5 โค้ดบันทึกข้อมูลลงฐานข้อมูล

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

     

  • การสร้าง JavaScript Dialog ด้วย Bootbox.js

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

    JavaScript Confirm บน Google Chrome

     

    JavaScript Confirm บน Mozilla Firefox

    ตัวอย่างโค้ดเรียกใช้งาน JavaScript Confirm

    จากรูปจะเห็นว่า JavaScript Confirm บน Google Chrome และ Mozilla Firefox หน้าตาไม่เหมือนกัน ทั้งๆที่ใช้โค้ดเดียวกัน และปัญหาอีกอย่างหนึ่งที่พบคือ หากเราต้องการให้ข้อความ “คุณต้องการลบข้อมูลรายการนี้ใช่หรือไม่?” มีการขึ้นบรรทัดใหม่ ใส่สี เพิ่มขนาดฟอนต์ จัดตัวหนา ตัวเอียงก็ไม่สามารถทำได้เลย แต่ถ้าต้องการให้แก้ปัญหาเหล่านี้ได้ก็ต้องใช้ตัวช่วย นั่นคือ Bootbox.js ซึ่งเป็น JavaScript library ที่ใช้งานร่วมกับ Bootstrap โดยใช้ Bootstrap modal มาทำหน้าที่แทน JavaScript Dialog ต่างๆ ทั้ง Alert, Confirm, Prompt และรวมถึง Custom Dialog ด้วย ทำให้หน้าตาของ Dialog จะเหมือนกันทุก Browser และสามารถจัดรูปแบบการแสดงผลได้ตามต้องการโดยใช้ CSS

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

    1. เข้าไปที่เว็บไซต์ http://bootboxjs.com และเลือกดาวน์โหลดไฟล์ชื่อ bootbox.min.js หรือถ้าไม่ต้องการดาวน์โหลดก็สามารถใช้ CDN (https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js) ได้เช่นกัน
    2. ใส่โค้ดอ้างอิงไปยัง bootbox.min.js ใน header tag ดังนี้
      <script src=”path/to/script/bootbox.min.js”></script>
      หรือ
      <script src=https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js></script>

    ตัวอย่างการใช้งาน Confirm Dialog

    1. กำหนดชื่อ CSS class ให้กับปุ่มลบ ในที่ตั้งชื่อว่า “confirm”

      กำหนดชื่อ CSS Class ให้กับปุ่มลบ
    2. แทรกโค้ด JavaScript ใน HTML ดังนี้

      JavaScript สำหรับ Confirm Dialog
    3. ลองเปิดเว็บด้วย Google Chrome และ Mozilla Firefox ก็จะได้ผลลัพธ์เหมือนกันดังรูป

      Confirm Dialog ที่สร้างขึ้นด้วย Bootbox.js

    นอกจาก Confirm Dialog แล้ว ท่านสามารถดูตัวอย่าง Dialog แบบอื่นๆ ได้จากที่นี่ เพียงเท่านี้ก็จะสามารถสร้าง Dialog สวยๆ และมีความยืดหยุ่นไว้ใช้งานได้แล้ว

     

  • การดึงค่าละติจูดและลองจิจูดของสถานที่ด้วย Places search box บน Google Maps

           ก่อนจะพูดถึงเนื้อหาของบทความนี้ ผู้เขียนขอท้าวความไปถึงบทความก่อนหน้าที่เป็นเนื้อหาที่เกี่ยวข้องกับการดึงค่าละติจูด-ลองจิจูดของสถานที่ เพื่อมากำหนดจุดพิกัดบนแผนที่ หรือที่เรารู้จักกันดีในนามของ Google maps (ซึ่งสามารถหาอ่านได้จากลิงค์ ทำอย่างไรให้สามารถกำหนดจุดพิกัดบนแผนที่ Google map แบบจุดเดียวและหลายจุดจากฐานข้อมูลได้ด้วย ASP.NET C# (ภาคต่อ) และหากท่านต้องการศึกษาเกี่ยวกับวิธีการกำหนดพิกัดบนแผนที่เพิ่มเติมสามารถหาอ่านได้จากลิงค์ ทำอย่างไรให้สามารถกำหนดจุดพิกัดบนแผนที่ Google map แบบจุดเดียวและหลายจุดจากฐานข้อมูลได้ด้วย ASP.NET C# เช่นกัน) แต่หลังจากที่ผู้เขียนได้นำไปทดลองใช้งานการดึงค่าพิกัดที่ค้นหา พบว่าเกิดปัญหาในการค้นหาพิกัดของสถานที่ในบางกรณี คือ ไม่สามารถค้นหาพิกัดของบางสถานที่ที่ต้องการได้ และในบางครั้งผู้ใช้เลือกสถานที่ที่จะดึงค่าพิกัดมาใช้งานผิด เนื่องจากชื่อสถานที่อาจคล้ายกัน แต่ตั้งอยู่กันคนละประเทศ หรือทวีป โดยผู้ใช้อาจไม่เห็นภาพว่าสถานที่ดังกล่าวอยู่ส่วนใดของแผนที่ จึงทำให้พิกัดที่ได้มีความผิดพลาดหรือคลาดเคลื่อนได้ ผู้เขียนจึงได้ลองศึกษาเพิ่มเติม และปรับเปลี่ยนวิธีการ เพื่อให้การดึงค่าพิกัดเป็นไปได้ง่าย และอำนวยความสะดวกต่อผู้ใช้งานมากขึ้น รวมทั้งเพิ่มช่องทางในการค้นหาข้อมูลพิกัดได้มากขึ้นและมีความถูกต้องแม่นยำขึ้น

    ตัวอย่างภาพการทำงานของการดึงค่าพิกัดที่ผู้เขียนเคยเขียนไว้ก่อนหน้านี้

    แบบที่ 1 การเรียกใช้เซอร์วิสของ Google Geocoding API โดยการส่งพารามิเตอร์เป็นที่อยู่ของสถานที่ดังกล่าว

       

    แบบที่ 2 แบบใช้ place Autocomplete ซึ่งเป็น feature ของ Google Places API ที่จะช่วยในการค้นหาที่อยู่จากชื่อสถานที่ได้และประยุกต์เพิ่มเติมเพื่อดึงค่ามาแสดงเมื่อมีการเลือกรายการสถานที่นั้นๆ

         

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

    • ส่วนของสไตล์ชีทในการแสดงผล ขึ้นกับการตกแต่งของผู้พัฒนาแต่ละท่าน
    <!—ส่วนของ Style Sheets-->
    <style>
    html, body {
     height: 100%;
     margin: 0;
     padding: 0;
    }
    #map {
     width: 100%;
     height: 400px;
    }
    .controls {
     margin-top: 10px;
     border: 1px solid transparent;
     border-radius: 2px 0 0 2px;
     box-sizing: border-box;
     -moz-box-sizing: border-box;
     height: 32px;
     outline: none;
     box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
    }
    #searchInput {
     background-color: #fff;
     font-family: Roboto;
     font-size: 15px;
     font-weight: 300;
     margin-left: 12px;
     padding: 0 11px 0 13px;
     text-overflow: ellipsis;
     width: 50%;
    }
    #searchInput:focus {
     border-color: #4d90fe;
    }
    
    </style>
    
    • ส่วนของการอ้างอิง libraries เพื่อใช้งาน Google API
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCRbMoDPc_mTv3D3QPqe0Ar84nSvRhA8nk&libraries=places&callback=initMap" async defer></script>
    
    • ส่วนของการประกาศค่าเริ่มต้นและตัวแปร รวมถึงการเรียกใช้งานฟังก์ชั่นเพื่อใช้ในการแสดงผล
    <script>
    /***** function ในการประกาศค่าเริ่มต้นให้กับแผนที่*****/
     function initMap() {
     
     /***** กำหนดรายละเอียดคุณสมบัติของแผนที่*****/
     var map = new google.maps.Map(document.getElementById('map'), {
     center: {lat: -33.8688, lng: 151.2195},
     zoom: 13
     });
    
     /***** กำหนดตำแหน่งที่ตั้งของ control ที่จะวางในแผนที่*****/
     var input = document.getElementById('searchInput');
     map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
    
     /***** เพิ่ม Feature ให้กับ textbox ให้สามารถพิมพ์ค้นหาสถานที่ได้*****/
     var autocomplete = new google.maps.places.Autocomplete(input);
     autocomplete.bindTo('bounds', map);
    
     var infowindow = new google.maps.InfoWindow();
     
     /***** กำหนดคุณสมบัติให้กับตัวพิกัดจุดหรือ marker *****/
     var marker = new google.maps.Marker({
     map: map,
     anchorPoint: new google.maps.Point(0, -29)
     });
    
     /***** ทำงานกับ event place_changed หรือเมื่อมีการเปลี่ยนแปลงค่าสถานที่ที่ค้นหา*****/
     autocomplete.addListener('place_changed', function() {
     infowindow.close();
     marker.setVisible(false);
     var place = autocomplete.getPlace();
     if (!place.geometry) {
     window.alert("ไม่ค้นพบพิกัดจากสถานที่ดังกล่าว");
     return;
     }
    
     /***** แสดงผลบนแผนที่เมื่อพบข้อมูลที่ต้องการค้นหา *****/
     if (place.geometry.viewport) {
     map.fitBounds(place.geometry.viewport);
     } else {
     map.setCenter(place.geometry.location);
     map.setZoom(17);
     }
     marker.setIcon(({
     url: place.icon,
     size: new google.maps.Size(71, 71),
     origin: new google.maps.Point(0, 0),
     anchor: new google.maps.Point(17, 34),
     scaledSize: new google.maps.Size(35, 35)
     }));
     marker.setPosition(place.geometry.location);
     marker.setVisible(true);
     
     /***** แสดงรายละเอียดผลลัพธ์การค้นหา *****/
     var address = '';
     if (place.address_components) {
     address = [
     (place.address_components[0] && place.address_components[0].short_name || ''),
     (place.address_components[1] && place.address_components[1].short_name || ''),
     (place.address_components[2] && place.address_components[2].short_name || '')
     ].join(' ');
     }
     /***** แสดงรายละเอียดผลลัพธ์การค้นหาเป็น popup โดยมีชื่อและสถานที่ดังกล่าว *****/
     infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
     infowindow.open(map, marker);
    
     /***** แสดงรายละเอียดผลลัพธ์การค้นหา ซึ่งประกอบด้วย ที่อยู่ รหัสไปรษณีย์ ประเทศ ละติจูดและลองจิจูด *****/
     for (var i = 0; i < place.address_components.length; i++) {
     if(place.address_components[i].types[0] == 'postal_code'){
     document.getElementById('postal_code').innerHTML = place.address_components[i].long_name;
     }
     if(place.address_components[i].types[0] == 'country'){
     document.getElementById('country').innerHTML = place.address_components[i].long_name;
     }
     }
     document.getElementById('location').innerHTML = place.formatted_address;
     document.getElementById('lat').innerHTML = place.geometry.location.lat();
     document.getElementById('lon').innerHTML = place.geometry.location.lng();
     });
    }
    </script>
    • ส่วนของการแสดงผล (ใน tag body)
    <body>
    <!--ส่วนของ Element ที่ใช้ในการแสดงผล-->
    <input id="searchInput" class="controls" type="text" placeholder="Enter a location">
    <div id="map"></div>
    <!--ส่วนของการแสดงรายละเอียดผลลัพธ์ที่ได้-->
    <ul id="geoData">
     <li>ที่อยู่: <span id="location"></span></li>
     <li>รหัสไปรษณีย์: <span id="postal_code"></span></li>
     <li>ประเทศ: <span id="country"></span></li>
     <li>ละติจูด: <span id="lat"></span></li>
     <li>ลองจิจูด: <span id="lon"></span></li>
    </ul>
    
    <!--ส่วนของการประกาศค่าเริ่มต้นและตัวแปร รวมถึงการเรียกใช้งานฟังก์ชั่นเพื่อใช้ในการแสดงผลที่กล่าวไว้ก่อนหน้านี้-->
                                                                
    <script>
    /***** function ในการประกาศค่าเริ่มต้นให้กับแผนที่ และอื่นๆตามที่กล่าวไว้แล้วข้างต้น*****/
    </script>
    <!--สิ้นสุดส่วนของการประกาศค่าเริ่มต้นและตัวแปร รวมถึงการเรียกใช้งานฟังก์ชั่นเพื่อใช้ในการแสดงผล->
     </body>

    ผลลัพธ์ที่ได้

    1. เมื่อพิมพ์ชื่อสถานที่ เช่น มหาวิทยาลัยสงขลานครินทร์ จะมีรายการชื่อสถานที่ให้ผู้ใช้เลือก

    2. เมื่อเลือกชื่อสถานที่ที่ต้องการ เช่น มหาวิทยาลัยสงขลานครินทร์ จะมีการแสดงรายละเอียดของสถานที่ดังกล่าวดังภาพตามหมายเลข 1,2 และ 3 ตามลำดับ

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

    แหล่งข้อมูลอ้างอิง :

    https://www.tutorialspoint.com/google_maps/google_maps_symbols.htm

    http://www.codexworld.com/autocomplete-places-search-box-google-maps-javascript-api/