Tag Archive AJAX

Byphunsanit

jQuery: Ajax Cache

ต้องการเก็บข้อมูลส่วนที่ใช้บ่อยๆ ไว้ในฝั่ง user (browser) นั่นละ จะได้ลดการ query แต่ข้อมูลมันมีการเปลี่ยนแปลงด้วย ที่เก็บข้อมูลระยะยาวได้ในฝั่ง browser กลับออกแบบให้ localStorage เก็บข้อมูลถาวรโดยไม่มีการ expires เหมือน cookie ทำให้ต้องเขียน code จัดการเพิ่ม

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>Ajax: localStorage</title>
</head>

<body>
    <h1>localStorage</h1>
    <div class="col-sm-12" id="datasA"></div>
    <div class="col-sm-12" id="resultA"></div>
    <script src="../vendor/components/jquery/jquery.min.js"></script>
    <script>
        $(function() {

            function getDatas() {
                let cacheKey = 'memories';

                if (cacheKey in localStorage) {
                    let datas = JSON.parse(localStorage.getItem(cacheKey));

                    // if expired
                    if (datas['expires'] < Date.now()) {
                        localStorage.removeItem(cacheKey);

                        getDatas()
                    } else {
                        setDatas(datas);
                    }
                } else {
                    $.ajax({
                        "dataType": "json",
                        "success": function(datas, textStatus, jqXHR) {
                            let today = new Date();

                            datas['expires'] = today.setDate(today.getDate() + 7) // expires in next 7 days

                            setDatas(datas);

                            localStorage.setItem(cacheKey, JSON.stringify(datas));
                        },
                        "url": "http://localhost/phunsanit/snippets/PHP/json.json_encode.php",
                    });
                }
            }

            function setDatas(datas) {
                // display json as text
                $('#datasA').text(JSON.stringify(datas));

                // your code here
                let html = '';
                $.each(datas.datas, function(index, value) {
                    html += '<br>' + index + ' = ' + value;
                });
                $('#resultA').html(html);

            }

            // call
            getDatas();

        });
    </script>
</body>

</html>

ข้อมูลที่ call ผ่าน ajax จะโดนเก็บใน localStorage แต่เวลาใช้ก็จะเอามาเทียบ expires ก่อน ถ้ายังไม่หมดอายุก็เอามาใช้ ถ้าหมดอายุไปแล้วก็ call ใหม่ ลองดัดแปลงดูให้เหมาะกับงานดูครับ

Byphunsanit

Fetch API: Download

ที่นี้มาถึงการที่ใช้ fetch download file จาก server ซึ่งวิธีนี้ง่ายกว่าการใช้ jQuery ดึงไฟล์มามาก จากที่เคยเขียน jQuery ajax download file เอาไว้จะเห็นว่าวิธีนี้ง่ายกว่ามาก

เริ่มจากการที่โหลด download.js มาก่อน โดยใช้คำสั่ง npm i downloadjs
ไฟล์กลางที่ไว้ใช้ร่วมกัน

scripts.js

/*
pitt phunsanit
default fetch api options
version 1
*/
let fetchOptions = {
    "headers": {
        'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
    },
    "method": "post"
};

/*
pitt phunsanit
get file name from fetch api
version 1
*/
function fetchGetFilename(response) {
    let filename = '';
    let disposition = response.headers.get('Content-Disposition');
    if (disposition && disposition.indexOf('attachment') !== -1) {
        let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
        let matches = filenameRegex.exec(disposition);
        if (matches != null && matches[1]) {
            filename = matches[1].replace(/['"]/g, '');
        }
    }
    return filename;
}

/*
pitt phunsanit
get status from fetch api
version 1
*/
function fetchStatus(Response) {
    if (Response.status >= 200 && Response.status < 300) {
        return Promise.resolve(Response);
    } else {
        return Promise.reject(new Error(Response.status + ' : ' + Response.statusText));
    }
}

ตัวอย่างการใช้ fetch download file โดยใช้ downloadjs ช่วยให้ทำงานได้ทุกบราวเซอร์ (ยกเว้น IE ถ้าจะใช้กลับไปอ่าน Fetch API)

JavaScript/fetch.download.html
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

      <meta name="author" content="Pitt Phunsanit">
      <title>fetch: download</title>
   </head>
   <body>
      <script src="../node_modules/downloadjs/download.min.js"></script>
      <script src="../scripts.js"></script>
      <script>
fetchOptions.body = 'file=ISO 3166-1 two aplha COUNTRY codes (01102009).xls&token=HH89VOiirgXlCdEqDrFs';

fetch('http://localhost/snippets/PHP/download.php', fetchOptions)
    .then(fetchStatus)
    .then(
        function(response) {
            if (response.ok) {
                let fileName = fetchGetFilename(response);
                let mimeType = response.headers.get('Content-Type');

                response.blob().then(function(blob) {
                    download(blob, fileName, mimeType);
                });
            }
        }
    )
    .catch(function(error) {
        alert(error);
    });
      </script>

</body></html>

อ่านเพิ่มเติม

Byphunsanit

Fetch API

Fetch API เป็นวิธีที่ใช้ทำ ajax แทน XMLHttpRequest (XHR) สามารถใช้ได้กับทุกบราวเซอร์ยกเว้น อ้ายอี (IE) แม้แต่ microsoft edge ก็ยังใช้ได้ แต่จริงๆ แล้วสามารถบังคับให้อ้ายอีใช้ได้โดยการเรียกใช้ github/fetch ช่วย

ไฟล์กลางที่ไว้ใช้ร่วมกัน

scripts.js

/*
pitt phunsanit
default fetch api options
version 1
*/
let fetchOptions = {
    "headers": {
        'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
    },
    "method": "post"
};

/*
pitt phunsanit
get status from fetch api
version 1
*/
function fetchStatus(Response) {
    if (Response.status >= 200 && Response.status < 300) {
        return Promise.resolve(Response);
    } else {
        return Promise.reject(new Error(Response.status + ' : ' + Response.statusText));
    }
}

ตัวอย่างการใช้ fetch แบบ GET

JavaScript/fetch.get.html
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

      <meta name="author" content="Pitt Phunsanit">
      <title>fetch: get</title>
   </head>
   <body>
      <script src="../scripts.js"></script>
      <script>
fetch('http://localhost/snippets/PHP/json.json_encode.php?name=pitt&surname=phunsanit')
    .then(fetchStatus)
    .then(
        function(response) {

            response.json()
                .then(function(data) {
                    alert(JSON.stringify(data));
                });

        }
    )
    .catch(function(error) {
        alert(error);
    });
      </script>

</body></html>

เมื่อต้องการส่งข้อมูลแบบ POST ก็เพิ่ม option ไปเล็กน้อย
ตัวอย่างการ fetch แบบ POST

JavaScript/fetch.post.html
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

      <meta name="author" content="Pitt Phunsanit">
      <title>fetch: post</title>
   </head>
   <body>
      <script src="../scripts.js"></script>
      <script>
fetchOptions.body = '[email protected]&name=pitt&surname=phunsanit';

fetch('http://localhost/snippets/PHP/json.json_encode.php', fetchOptions)
    .then(fetchStatus)
    .then(
        function(response) {

            response.json()
                .then(function(data) {
                    alert(JSON.stringify(data));
                });

        }
    )
    .catch(function(error) {
        alert(error);
    });
      </script>

</body></html>

อ่านเพิ่มเติม

Byphunsanit

joGet: AJAX Subform reload

ตัวอย่างการสร้าง ajax subform ในเรื่อง joGet: AJAX Subform มีโจทย์มาว่า input ที่ผูกกับซับฟอร์มถูกเปลี่ยนค่าจาก javascript ก็คิดว่าค่าใน subform จะเปลี่ยนตามไปด้วย แต่มันกลับไม่เปลี่ยนตาม เพราะ input ค่าเปลี่ยนก็จะทำให้มันโหลดข้อมูลมาใหม่ได้ไม่ยาก แต่มันไม่ทำงาน ลองศึกษาไฟล์ /jw/plugin/org.joget.plugin.enterprise.AjaxSubForm/js/jquery.ajaxsubform.js ดูก็พบว่ามันมีการสั่ง .off เอา event เก่าออกไปก่อน ทำให้แค่เปลี่ยนค่าเฉยๆ มันจะไม่ทำงาน

การสั่ง reload / refresh ajax subform โดยใช้ javascript ทำได้โดย

<button class="btn btn-info" id="refreshBtn" type="button">Reload form</button>
<script>
$(document).ready(function() {

$('#refreshBtn').on('click', function() {

let field1 = FormUtil.getField('field1');
field1.val('72817b0c-ac1430db-671b8000-37df4c8d');
field1.trigger('change');

});

});
</script>

แบบนี้เมื่อนเปลี่ยนค่า field1 subform จะถูกเปลี่ยนค่าตามไปด้วยแล้ว ลองดัดแปลงให้เหมาะกับงานดูนะครับ

Byphunsanit

joGet: AJAX Subform

AJAX Subform เป็น Form Element ที่ joget เตรียมไว้ให้สามารถใช้ ajax ดึงข้อมูลฟอร์มที่มีมาแสดงได้แบบไม่จำเป็นต้องโหลดทั้งหน้าใหม่ เหมือนระบบที่เราเขียนด้วยตัวเอง

การใช้งานทำได้ง่ายๆ โดยการ

    1. ในหน้า Form Builder ลาก AJAX Subform มาจากด้านซ้ายมือ
    2. คลิก Edit ไอค่อน
    3. กรอกข้อมูล
      ID
      id ของ ajax subform เช่น ajaxSubform
      Form
      เลือกฟอร์มที่ต้องการนำมาแทรกไว้ในหน้านี้
    4. คลิก Next >
    5. ติ๊ก
      Reload Subform when Parent Field value change?
      ติ๊กเพื่อจะให้ ajax ทำงานโหลด ฟอร์มใหม่เมื่อ input ที่ผูกไว้ เปลี่ยนค่า
    6. ผูกฟอร์มทั้งสองไว้ด้วยกัน
      Parent Field to keep Subform ID
      id input ในฟอร์มหลัก ที่จะใช้ลิงค์ให้ sub form ถูกดึงมาแทนที่โดยใช้ ajax
      Subform Field to keep Parent ID
      เป็น input ที่อยู่ใน subform ถ้าไม่มี การ load subform มาจาก server ก็ยังทำงานได้ตามปกติ

ทีนี้มาศึกษาการทำงานกันดูบ้าง

      1. joGet จะแทรกไฟล์ /jw/plugin/org.joget.plugin.enterprise.AjaxSubForm/js/jquery.ajaxsubform.js เพิ่มเข้ามาจากปกติ
      2. จะถูกเรียกใช้โดย javascript ที่เพิ่มเข้ามา เช่น
        <script type="text/javascript">
        $(document).ready(function() {
        $("#ajaxSubform_ajaxsubform_928").ajaxSubForm({
        contextPath: "/jw",
        id: "ajaxSubform",
        label: "",
        formDefId: "sendEmail",
        readOnly: "",
        readOnlyLabel: "",
        noframe: "",
        ajax: "true",
        parentSubFormId: "field1",
        prefix: "",
        hideEmpty: "",
        appId: "prototypes",
        appVersion: "1",
        processId: "",
        nonce: "%EF%BF%BD%00%3B%7D%28%EF%BF%BD%EF%BF%BD%EF%BF%BD",
        collapsible: "",
        collapsibleLabelExpanded: "Hide Details",
        collapsibleLabelCollapsed: "View Details",
        collapsibleExpanded: "true",
        collapsibleNoLoad: ""
        });
        });
        </script>

เมื่อไล่ดู code แล้วมันคือ plugin ที่ extended มาจาก jQuery ajax ตามปกติ ส่ง request ไปยัง /jw/web/json/plugin/org.joget.plugin.enterprise.AjaxSubForm/service โดยส่ง formDefId มีค่าเป็น form id ของ subform, parentSubFormId คือ field ในฟอร์มหลักที่ใช้ผูกกับซับฟอร์ม และจะคืนค่ากลับมาเป็น html ของฟอร์ม ในอนาคตคงได้ใช้เรียก ajax ไปโดยไม่ต้องสร้าง subform ก่อน

อ่านเพิ่มเติม