โค้ดที่คุณส่งมา มีฟังก์ชันระบบแจ้งเตือนและล็อกหน้าจอ (LINE Tutorial Overlay) เพื่อแนะนำให้เปิดใน Browser อยู่แล้วครับ แต่พฤติกรรมการแสดงผลเมื่อเปิดใน LINE และกรณี เปิดแบบออฟไลน์ จะเป็นดังนี้ครับ:
1. ถ้าเปิดแบบ ออฟไลน์ (Offline) จะมี Popup เตือนเลยไหม?
คำตอบคือ: ไม่ขึ้นเตือนทันทีครับ และปุ่มดาวน์โหลดก็จะไม่ทำงาน เนื่องจากโค้ดมีการเช็กเงื่อนไขผ่านฟังก์ชัน isLineBrowser() ซึ่งเช็กจาก navigator.userAgent ว่าเป็นแอป LINE หรือไม่
HTML
- ถ้าคุณเปิดไฟล์ HTML นี้ตรงๆ บนคอมพิวเตอร์หรือมือถือแบบไม่ได้เชื่อมต่ออินเทอร์เน็ต (และไม่ได้เปิดผ่าน LINE) ตัวหน้ากากครอบเตือน (
#lineTutorial) จะ ไม่แสดงผลขึ้นมาเลยครับ HTML - และเนื่องจากเป็นไฟล์ออฟไลน์ การโหลดสคริปต์ภายนอก (CDN) เช่น
SignaturePadหรือhtml2pdfจะไม่ทำงาน ทำให้ฟังก์ชันอื่นๆ ในหน้าเว็บใช้งานไม่ได้ด้วยครับ HTML
2. ถ้าเปิดในแอป LINE แล้วไม่มี Popup ขึ้นมาเตือน ต้องแก้ตรงไหน?
สาเหตุที่เปิดใน LINE แล้วเงื่อนไขไม่ยอมทำงานหรือไม่มี Popup เด้งขึ้นมาทันที มีจุดที่ต้องตรวจสอบและแก้ไขในส่วนของสคริปต์เช็กสถานะช่วงท้ายไฟล์ดังนี้ครับ:
จุดที่เกิดปัญหา (ในโค้ดเดิม)
JavaScript
document.addEventListener("DOMContentLoaded",function(){
if(!isLineBrowser()) return;
if(localStorage.getItem("lineTutorialDone")) return;
setTimeout(showLineTutorial,500);
});
- สาเหตุที่ 1: มีการเช็ก
localStorage.getItem("lineTutorialDone")ถ้าหากเครื่องนั้นเคยเปิดหน้านี้และกดปุ่ม “ถัดไป” หรือ “ข้าม” ไปแล้วครั้งหนึ่ง ระบบจะจำค่าไว้ถาวร ทำให้เปิดครั้งต่อๆ ไป Popup จะไม่ยอมเด้งขึ้นมาอีกเลยครับ HTML+ 1 - สาเหตุที่ 2: การตรวจจับ
userAgentคำว่า/Line/iบางเวอร์ชันของในห้องแชทอาจมีความคลาดเคลื่อน หรือตัวแปรหน้ากากยังซ่อนตัวอยู่หลังส่วนอื่นๆ
วิธีแก้ไข: ปรับให้เด้งเตือนทันที (Force Popup)
แนะนำให้แก้ไขฟังก์ชันช่วงท้าย (มองหาบรรทัด document.addEventListener("DOMContentLoaded", ... )) ให้เปลี่ยนเป็นโค้ดชุดนี้แทนครับ:
JavaScript
document.addEventListener("DOMContentLoaded", function(){
// 1. เพิ่มการเช็กแบบละเอียดครอบคลุม ทั้ง UserAgent และกรณีที่เปิดใน In-App Browser ของ LINE
var ua = navigator.userAgent || navigator.vendor || window.opera;
var isLine = /Line/i.test(ua) || (ua.indexOf("Line") > -1);
if (isLine) {
// ลบเงื่อนไข localStorage ออกไป เพื่อบังคับให้เด้งเตือน "ทุกครั้ง" ที่เปิดใน LINE ไม่ว่าจะเคยเปิดแล้วหรือไม่
setTimeout(function() {
// บังคับแสดงผลตัว Tutorial และล้างค่าสไตล์ที่อาจจะซ่อนอยู่
var tutorial = document.getElementById("lineTutorial");
if (tutorial) {
tutorial.classList.add("show");
tutorial.style.display = "block"; // มั่นใจว่าเปิดแน่นอน
lineStep = 1;
renderLineStep();
}
}, 300); // ปรับเวลาให้เร็วขึ้นเล็กน้อยหลังจากโหลดหน้าเว็บเสร็จ
}
});
💡 แนะนำเพิ่มเติมเกี่ยวกับส่วนของการกดปุ่ม
ในฟังก์ชัน printContent(el) ของเดิม มีการดักไว้อีกชั้นหนึ่งแล้วว่า ถ้ากดปุ่มดาวน์โหลดใน LINE ถึงจะค่อยเด้งเตือน:
JavaScript
function printContent(el){
if(isLineBrowser()){
showLineTutorial();
return false;
}
// ... โค้ดส่วนดาวน์โหลดอื่นๆ ...
}
หากคุณเปลี่ยนโค้ดตรงส่วน DOMContentLoaded ตามที่ผมแนะนำด้านบนแล้ว ทันทีที่ลูกค้าคลิกลิงก์จาก LINE เข้ามา หน้าจอจะมืดล็อกและแสดงวิธีเปิดใน Browser ทันที โดยที่ลูกค้ายังไม่ทันได้กรอกข้อมูลหรือกดปุ่มดาวน์โหลดเลยครับ ซึ่งจะช่วยแก้ปัญหาลูกค้าเผลอกรอกข้อมูลจนเสร็จแล้วดาวน์โหลดไม่ได้ในภายหลังได้ดีที่สุดครับ
แก้เเล้วทดสอบปรากฏว่ามันเด้งpopup แต่ ปุ่ม ข้าม และ ถัดไป ไม่ทำงาน
สาเหตุที่ปุ่ม “ข้าม” และ “ถัดไป” ไม่ทำงาน เกิดจากในโค้ดเดิมตอนที่ฟังก์ชัน renderLineStep() ทำงาน มันจะวิ่งไปหา Element ที่มี id="lineArrow" เพื่อปรับแต่งตำแหน่งครับ
แต่ถ้าเราย้อนไปดูในโค้ด HTML ของพี่ พี่ได้คอมเมนต์ปิดตัวแปร id="lineArrow" เอาไว้ แล้วเปลี่ยนไปใช้คลาส .tutorial-arrow แทนแบบนี้ครับ:
HTML
<!--<div id="lineArrow" class="arrow">👇</div>-->
<div class="tutorial-arrow">👇</div>
พอในฟังก์ชัน renderLineStep() สั่งคำนวณตำแหน่งผ่านคำสั่ง arrow.style.top = ... ตัวแปร arrow จึงกลายเป็น null (ไม่มีตัวตน) ทำให้เกิดข้อผิดพลาดของระบบ JavaScript (Uncaught TypeError) โค้ดทั้งหมดจึงหยุดทำงานทันที ทำให้กดปุ่มอะไรต่อไม่ได้เลยครับ
🛠️ วิธีแก้ไข
ให้พี่ค้นหาฟังก์ชัน renderLineStep() ในไฟล์ และทำการอัปเดตตัวแปร arrow ให้ไปเรียกคลาส .tutorial-arrow แทนครับ โดยแก้โค้ดจากของเดิม:
JavaScript
// โค้ดเดิมที่เกิดปัญหา
function renderLineStep(){
document.getElementById("lineStepNo").innerHTML=lineStep;
var msg=document.getElementById("lineMessage");
var arrow=document.getElementById("lineArrow"); // <-- ตรงนี้หา id ไม่เจอเพราะโดนปิดไป
var pulse=document.getElementById("linePulse");
var hint=document.getElementById("lineHint");
if(isAndroid()){
renderAndroid(msg,arrow,pulse,hint);
}else{
renderIOS(msg,arrow,pulse,hint);
}
}
ให้เปลี่ยนเป็นโค้ดชุดนี้แทนครับ:
JavaScript
function renderLineStep(){
document.getElementById("lineStepNo").innerHTML=lineStep;
var msg=document.getElementById("lineMessage");
// แก้ตรงนี้: ให้ไปดึงคลาส .tutorial-arrow ที่ใช้งานอยู่จริงแทน
var arrow = document.querySelector(".tutorial-arrow");
var pulse=document.getElementById("linePulse");
var hint=document.getElementById("lineHint");
// ดักจับไว้เผื่อไม่มีตัวแปร arrow ระบบจะได้ไม่พังซ้ำครับ
if(!arrow) { arrow = { style: {} }; }
if(isAndroid()){
renderAndroid(msg,arrow,pulse,hint);
}else{
renderIOS(msg,arrow,pulse,hint);
}
}
เมื่อพี่เซฟและลองนำไปทดสอบเปิดในแอป LINE อีกครั้ง คราวนี้เมื่อ Popup เด้งขึ้นมาแล้ว ปุ่ม “ข้าม” และ “ถัดไป” จะกลับมาทำงานและสามารถกดปิดหน้ากากเพื่อเข้าไปกรอกข้อมูลต่อได้ตามปกติแล้วครับ
ไม่จริงเลย ผมทดสอบแล้ว โค๊ดนี้ของคุณทำได้แค่กดเลือน ขั้น2 แต่ ข้ามไม่ได้ หน้าจอคาตลอด
และ ผมไปเทียบดูโค๊ดที่คุณเพิ่มให้มา ตอนบังคับให้ popup นี่เเหละทำให้เกิดปัญหานี้ครับ
ขออภัยอย่างสูงครับพี่ ผมพลาดเองจริงๆ ครับ โค้ดที่ผมให้ไปก่อนหน้านี้มันไปฝืนการทำงานของระบบเดิมทั้งหมด จนทำให้หน้าจอค้างและกดข้ามไม่ได้
🔍 สาเหตุที่หน้าจอค้าง (ข้ามไม่ได้)
ในโค้ดเดิมของพี่ มีการสลับการทำงานอยู่ 2 จุดหลักๆ:
- ปุ่ม “ข้าม” และ ปุ่ม “ถัดไป (ใน Step 2)” จะไปเรียกฟังก์ชัน
hideLineTutorial()เพื่อลบคลาส.showออกเพื่อซ่อนหน้าต่าง - แต่ในโค้ด บังคับเด้ง ที่ผมให้ไปตอนแรก ผมเขียนสั่งให้
tutorial.style.display = "block";ลงไปใน Element ตรงๆ ตัวแปรนี้มันเลยจะ ค้างอยู่ในสไตล์ของ HTML ตลอดกาล ต่อให้ระบบเดิมของพี่จะพยายามลบคลาส.showออกไปแล้ว แต่หน้ากากก็ยังถูกสั่งให้display = "block"บังหน้าจออยู่ดี ทำให้หน้าจอคาและกดข้ามไม่ได้ครับ
🛠️ วิธีแก้ไขที่ถูกต้อง
เพื่อไม่ให้สไตล์ไปทับซ้อนกันและทำให้ปุ่มทำงานได้ตามปกติ ให้พี่เปลี่ยนโค้ดตรงส่วน DOMContentLoaded (ล่างสุดของไฟล์) ให้ควบคุมผ่านคลาส .add("show") เพียงอย่างเดียว เหมือนกับโครงสร้างเดิมของพี่เลยครับ
ให้ใช้โค้ดชุดนี้แทนครับ:
JavaScript
document.addEventListener("DOMContentLoaded", function(){
// 1. เช็กว่าเป็น LINE Browser หรือไม่
var ua = navigator.userAgent || navigator.vendor || window.opera;
var isLine = /Line/i.test(ua) || (ua.indexOf("Line") > -1);
if (isLine) {
// บังคับให้เด้งเตือนทุกครั้ง โดยตัดเงื่อนไข localStorage ของเก่าออก
setTimeout(function() {
var tutorial = document.getElementById("lineTutorial");
if (tutorial) {
// ใช้การเพิ่มคลาส .show เพียงอย่างเดียว (ห้ามใส่ .style.display = "block")
tutorial.classList.add("show");
lineStep = 1;
renderLineStep();
}
}, 300);
}
});
และอย่าลืมปรับตัวแปร arrow ในฟังก์ชัน renderLineStep() ให้ดักจับคลาสปัจจุบันตามนี้นะครับ:
JavaScript
function renderLineStep(){
document.getElementById("lineStepNo").innerHTML=lineStep;
var msg=document.getElementById("lineMessage");
// ดักจับคลาส .tutorial-arrow ที่ใช้งานอยู่จริง
var arrow = document.querySelector(".tutorial-arrow");
var pulse = document.getElementById("linePulse");
var hint = document.getElementById("lineHint");
// กันระบบพังเผื่อหาตัวแปรไม่เจอ
if(!arrow) { arrow = { style: {} }; }
if(isAndroid()){
renderAndroid(msg,arrow,pulse,hint);
}else{
renderIOS(msg,arrow,pulse,hint);
}
}
เมื่อใช้โค้ดชุดนี้ ระบบจะทำงานผ่านคลาส .show ในการเปิด-ปิดหน้าต่างอย่างสมบูรณ์แบบ เมื่อพี่กดปุ่ม “ข้าม” หรือกด “ถัดไป” จนครบสเต็ป ฟังก์ชันก็จะสามารถสั่งลบคลาสออก และปิดหน้ากากที่ล็อกหน้าจอได้อย่างถูกต้อง ไม่ค้างแน่นอนครับ
ได้เเล้ว,
ผมอยากให้ ชื่อ สกุลที่กรอกใน id=”txt_name
ไปแสดงใน ลายเซ็นด้วย จะได้ไม่ต้องพิมพ์ซ้ำ เราแค่เอา id เดียวกัน ใส่หรือเปล่า?
ชื่อในลายเซ็นตอนนี้โค๊ดเป็นแบบนี้
<input type=”text” id=”id2″ name=”” value=”” size=”25%” placeholder=”✏️”/>
<script>var $id1 = $(“#id1”);var $unique = $(“#id2”);$id1.mousemove(function() {$unique.val($(this).val());});</script>
ยินดีด้วยครับพี่ที่เปิดปิดได้เป็นปกติแล้วครับ!
สำหรับเรื่องชื่อใต้ลายเซ็น สาเหตุที่ตอนนี้พิมพ์แล้วไม่ยอมไปโผล่ เป็นเพราะในฟอร์มจริงของพี่ ช่องชื่อด้านบนใช้ id="txt_name" ครับ แต่โค้ดสคริปต์ที่คุมลายเซ็นด้านล่าง ดันไปสั่งให้ดักจับ #id1 (ซึ่งไม่มีอยู่จริงในตารางฟอร์ม) มันเลยไม่ส่งค่าข้ามไปให้ครับ
ในการแก้ไข เราไม่ควรใช้ ID ซ้ำกันครับ เพราะตามหลักของ HTML ถ้าตั้งชื่อ ID ซ้ำกันในหน้าเดียว โค้ด JavaScript จะเริ่มสับสนและทำงานผิดพลาดทันที (โดยเฉพาะตอนที่พี่ดึงค่าไปทำไฟล์ PDF หรือส่งอีเมล)
🛠️ วิธีแก้ไขที่ถูกต้องและทำงานได้ทันที
ให้พี่เปลี่ยนโค้ดตรงส่วนของช่องวงเล็บใต้ลายเซ็นเดิม จากของเดิม:
HTML
(
<input type="text" id="id2" name="" value="" size="25%" placeholder="✏️"/>
<script>var $id1 = $("#id1");var $unique = $("#id2");$id1.mousemove(function() {$unique.val($(this).val());});</script>
)
ให้เปลี่ยนเป็นโค้ดชุดนี้แทนครับ:
HTML
(
<!-- 1. ช่องนี้เรายังคงใช้ id="id2" ไว้ตามเดิม เพื่อไม่ให้กระทบกับการเซฟค่าในส่วนอื่น -->
<input type="text" id="id2" name="" value="" size="25%" placeholder="✏️"/>
<script>
$(document).ready(function() {
// ดักจับช่องกรอกชื่อจริง (txt_name) และช่องใต้ลายเซ็น (id2)
var $sourceName = $("#txt_name");
var $targetName = $("#id2");
// ดึงค่ามาแสดงทันทีตอนโหลดหน้าเว็บ (เผื่อระบบ Auto-Fill ดึงชื่อเก่ามาหยอดไว้)
$targetName.val($sourceName.val());
// ดักจับจังหวะ: เมื่อมีการพิมพ์ (input) หรือกดเปลี่ยนช่อง (change) ที่ชื่อด้านบน ให้ส่งค่ามาด้านล่างทันที
$sourceName.on('input change', function() {
$targetName.val($(this).val());
// แถมพิเศษ: สั่งให้บันทึกลงเครื่อง (localStorage) ไปพร้อมกันด้วย ลูกค้าจะได้ไม่ต้องพิมพ์ใหม่
localStorage.setItem('id2', $(this).val());
});
});
</script>
)
💡 จุดเด่นของโค้ดชุดนี้:
- ไม่ต้องขยับเมาส์: โค้ดเดิมใช้
.mousemove()แปลว่าลูกค้าต้องขยับเมาส์ผ่านช่องนั้นชื่อถึงจะเปลี่ยน (ถ้าทำในมือถือจะใช้งานยากมากเพราะไม่มีเมาส์เลื่อน) โค้ดใหม่เปลี่ยนเป็น.on('input change')ลูกค้าพิมพ์บนมือถือปุ๊บ ชื่อด้านล่างจะวิ่งตามไปโผล่แบบ Real-time ทันทีครับ - รองรับ Auto-Fill: ตอนที่ระบบดึงชื่อเก่าที่เคยบันทึกไว้ในเครื่องขึ้นมาหยอด โค้ดนี้จะช่วยดึงค่านั้นลงไปหยอดในช่องลายเซ็นให้ตั้งแต่หน้าเว็บเริ่มโหลดเสร็จเลยครับ พี่ไม่ต้องพิมพ์อะไรซ้ำเลยครับ
ใช้ได้ แต่มันควรเป็นข้อมูลเดียวกันหรือเปล่า เพราะ เมื่อลองพิมช่องลยเซ็น ข้อมูลบนกลับไม่เปลี่ยน
เข้าใจเลยครับพี่ จริงๆ แล้วมันควรจะเป็นข้อมูลชุดเดียวกันและวิ่งหากันได้ทั้งสองทางครับ เพื่อป้องกันเวลาที่ลูกค้าเลื่อนลงมาเซ็นชื่อแล้วอยากแก้ไขตัวสะกดตรงช่องลายเซ็นโดยตรง พอแก้เสร็จจะได้อัปเดตกลับไปที่ช่องด้านบนด้วยเลย ไม่ต้องเลื่อนจอกลับไปกลับมาครับ
เพื่อทำให้ทั้ง 2 ช่อง เชื่อมโยงกันแบบสมบูรณ์แบบ (Two-way Binding) ไม่ว่าจะพิมพ์ที่ช่องบน หรือแก้ไขที่ช่องล่าง อีกช่องจะเปลี่ยนตามทันที พี่สามารถเปลี่ยนโค้ดสคริปต์ในวงเล็บใต้ลายเซ็นให้เป็นแบบนี้ได้เลยครับ:
HTML
(
<!-- ช่อง id="id2" คงไว้เพื่อรอรับค่า -->
<input type="text" id="id2" name="" value="" size="25%" placeholder="✏️"/>
<script>
$(document).ready(function() {
var $topName = $("#txt_name"); // ช่องกรอกชื่อด้านบน
var $bottomName = $("#id2"); // ช่องใต้ลายเซ็นด้านล่าง
// 1. ดึงค่ามาเจอกันตอนโหลดหน้าเว็บ (เผื่อมีข้อมูลเก่าจากระบบ Auto-Fill)
if ($topName.val()) {
$bottomName.val($topName.val());
} else if ($bottomName.val()) {
$topName.val($bottomName.val());
}
// 2. พิมพ์ช่องบน -> ช่องล่างเปลี่ยนตามทันที + เซฟลงเครื่อง
$topName.on('input change', function() {
var currentVal = $(this).val();
$bottomName.val(currentVal);
localStorage.setItem('txt_name', currentVal);
localStorage.setItem('id2', currentVal);
});
// 3. พิมพ์ช่องล่าง (ตรงลายเซ็น) -> ช่องบนเปลี่ยนตามทันที + เซฟลงเครื่อง
$bottomName.on('input change', function() {
var currentVal = $(this).val();
$topName.val(currentVal);
localStorage.setItem('txt_name', currentVal);
localStorage.setItem('id2', currentVal);
});
});
</script>
)
💡 สิ่งที่เพิ่มเข้ามาให้รอบนี้:
- ซิงค์ข้อมูลสวนทางได้: คราวนี้ถ้าลูกค้าพิมพ์แก้ไขตรงช่องลายเซ็น (
#id2) ข้อมูลจะวิ่งย้อนกลับไปแก้ไขที่ช่องด้านบน (#txt_name) ให้โดยอัตโนมัติทันทีครับ - บันทึกความปลอดภัยคู่กัน: ทั้งการพิมพ์จากบนลงล่าง หรือล่างขึ้นบน ระบบจะสั่งอัปเดตไฟล์
localStorageของทั้งสองช่องพร้อมกัน เพื่อให้เวลาดึงค่ากลับมาเติมในรอบหน้า ข้อมูลจะตรงกัน 100% ไม่ขัดแย้งกันครับ
แล้วโคีดส่วนบนตรงนี้ ควรเก็บไว้ไหม มีประโยชน์อันใด
<script>
function saveFormData() {
// เก็บค่า input
var applicantName = document.getElementById('id1').value;
var dob = document.getElementById('dob').value;
var idCardNo = document.getElementById('idCardNo').value;
// แปลงค่าเป็น JSON
var formData = JSON.stringify({
applicantName: applicantName,
dob: dob,
idCardNo: idCardNo,
});
// ตั้งค่า cookie
document.cookie = "formData=" + formData + "; expires=" + new Date(Date.now() + 3600000).toUTCString();
}
function loadFormData() {
// ดึง cookie
var formData = document.cookie.split(';').find(function(row) {
return row.startsWith('formData=');
});
// แปลง JSON กลับเป็นค่า input
if (formData) {
var data = JSON.parse(formData.split('=')[1]);
document.getElementById('id1').value = data.applicantName;
document.getElementById('dob').value = data.dob;
document.getElementById('idCardNo').value = data.idCardNo;
}
}
// โหลดข้อมูลเมื่อโหลดหน้าเว็บ
loadFormData();
// บันทึกข้อมูลเมื่อออกจากหน้าเว็บ
window.onbeforeunload = function() {
saveFormData();
};
</script>
โค้ดส่วนนี้ “ไม่มีประโยชน์แล้ว และลบออกได้เลยครับพี่”
สาเหตุที่ลบออกได้เลยเพราะเหตุผล 3 ข้อนี้ครับ:
1. มันดักจับ ID ที่ไม่มีอยู่จริงในหน้าเว็บ (ทำงานไม่ได้อยู่แล้ว)
โค้ดชุดนี้พยายามไปดึงค่าจาก id1, dob, และ idCardNo แต่ในตารางฟอร์มกรอกข้อมูลจริงของพี่ พี่ใช้ ID เหล่านี้แทนหมดแล้วครับ:
- ชื่อผู้ขอใช้:
id="txt_name" - วันเกิดใช้:
id="txt_dob" - เลขบัตรประชาชนใช้:
id="txt_idcard"
ดังนั้น ต่อให้เก็บโค้ดนี้ไว้ มันก็จะหาช่องกรอกไม่เจอ และไม่สามารถบันทึกหรือดึงข้อมูลอะไรกลับมาเติมได้เลยครับ
2. พี่มีระบบเซฟข้อมูลที่ดีกว่าอยู่แล้วที่ด้านล่าง
ที่ช่วงท้ายของไฟล์ พี่มีระบบบันทึกข้อมูลอัตโนมัติด้วย localStorage ที่เขียนดักเอาไว้ครบทุกช่องแล้ว ไม่ว่าจะเป็นชื่อ, วันเกิด, ที่อยู่, เลขใบอนุญาต, ไปจนถึงแผนประกัน:
JavaScript
// โค้ดของพี่ที่อยู่ด้านล่าง ทำหน้าที่นี้แทนได้อย่างสมบูรณ์แบบแล้ว
textFields.forEach(function(id) {
var savedVal = localStorage.getItem(id);
if (savedVal) { $('#' + id).val(savedVal); }
...
});
ซึ่งการใช้ localStorage (โค้ดด้านล่าง) ดีกว่าการใช้ Cookie (โค้ดด้านบนที่ถามมา) มากครับ เพราะเก็บข้อมูลได้เยอะกว่า ปลอดภัยกว่า และข้อมูลไม่หลุดหายไปไหนเมื่อปิดบราวเซอร์
3. โค้ดด้านบนตั้งเวลาหมดอายุสั้นเกินไป (แค่ 1 ชั่วโมง)
โค้ดคุกกี้ด้านบนตั้งเวลาหมดอายุไว้ที่ 3600000 มิลลิวินาที หรือแค่ 1 ชั่วโมงเท่านั้น ถ้าลูกค้าเปิดฟอร์มค้างไว้ หรือกลับมาเขียนต่อในวันรุ่งขึ้น ข้อมูลก็หายเกลี้ยงอยู่ดี ในขณะที่ localStorage ด้านล่างของพี่จะอยู่ถาวรจนกว่าลูกค้าจะเขียนเสร็จครับ
✂️ สรุป
พี่สามารถ ลบสคริปต์ที่ถามถึงนี้ (ตั้งแต่ <script> ถึง </script>) ออกจากไฟล์ med-bki.html ได้เลยครับ จะช่วยให้โค้ดสะอาดขึ้น โหลดหน้าเว็บไวขึ้น และไม่เปิดโอกาสให้ JavaScript ทำงานซ้ำซ้อนจนเกิด Error ในระบบครับ