เมื่อ Javascript อ่าน Element ผิดพลาด ด้วย firstChild
ก่อนอิ่น เรามาดูโค้ดต้นตอของปัญหากันก่อนนะครับ
จากโค้ดด้าน บน ถ้าดูตาม tag เผินๆ node ลูกอันแรก (img) ควรเป็น IMG หรือ tag img ใข่มั้ยครับ (เนื่องจาก node ลูกอันแรกของ div คือ รูปภาพนั่นเอง) แต่ถ้าได้ทดสอบโค้ดด้านบน (ตัวอย่าง) ผลลัพท์ที่ได้กลับเป็น undefined
เราลองมาดูกันนะครับว่าเกิดอะไรขึ้นกับโค้ดด้านบน โดยใช้ develop tools ของ IE กันครับ
ผลลัพท์ตามรูปด้านบนถ้าดูให้ดีจะเห็นว่าโหนดลูกอันแรก ไม่ใช่ img แต่เป็น "โหนดข้อความว่าง" แทน โหนดข้อความนี้มาจากตัวอักษรขึ้นบรรทัดใหม่นั่นเองครับ (ดูตามโค้ดด้านบนจะเห็นว่ามีการขึ้นบรรทัดใหม่) ทำให้คำสั่ง firstChild ให้ผลลัพท์แรกเป็น textNode ซึ่งไม่มี property tagName ผลลัพท์ที่ได้เลยเป็น undefined ครับ
การแก้ไขหรือวิธีที่ถูกต้องมีสองวิธีครับ
วิธีแรก เมื่อเรารู้ว่าปัญหาคือตัวอักษรขึ้นบรรทัดใหม่ ก็แก้ไขโดยการ เรียง element ต่อๆกันโดยไม่ขึ้นบรรทัดใหม่แทนครับ
วิธีที่สอง ปรับเปลี่ยนวิธีการอ่าน element ใหม่ด้วย ฟังก์ชั่นด้านล่าง
อธิบายกันสักนิดนะครับ เนื่องจากเรารู้ว่า เราได้ผลลัพท์เป็น textNode ซึ่งเราไม่ต้องการ ก็ให้ทำการข้ามผลลัพท์นี้ไป ด้วยการตรวจสอบด้วย nodeType ครับ ซึ่งถ้า nodeType เท่ากับ 3 (textNode) ก็ให้ข้าม element ไป และทำการอ่าน element ถัดไปแทน ตามโค้ดด้านบนครับ
<div id=test>
<img alt="" src="https://www.goragod.com/datas/users/goro/image/m7a3c3.jpg" />
<img alt="" src="https://www.goragod.com/datas/users/goro/image/m7a3c3.jpg" />
<img alt="" src="https://www.goragod.com/datas/users/goro/image/m7a3c3.jpg" />
<img alt="" src="https://www.goragod.com/datas/users/goro/image/m7a3c3.jpg" />
</div>
<script>
var el = document.getElementById('test'); // คืนค่า div id=test
var img = el.firstChild; // อ่าน node ลูกอันแรก
document.write(img.tagName); // แสดงผล ชื่อ tag ของ node ลูกอันแรก
</script>
จากโค้ดด้าน บน ถ้าดูตาม tag เผินๆ node ลูกอันแรก (img) ควรเป็น IMG หรือ tag img ใข่มั้ยครับ (เนื่องจาก node ลูกอันแรกของ div คือ รูปภาพนั่นเอง) แต่ถ้าได้ทดสอบโค้ดด้านบน (ตัวอย่าง) ผลลัพท์ที่ได้กลับเป็น undefined
เราลองมาดูกันนะครับว่าเกิดอะไรขึ้นกับโค้ดด้านบน โดยใช้ develop tools ของ IE กันครับ
ผลลัพท์ตามรูปด้านบนถ้าดูให้ดีจะเห็นว่าโหนดลูกอันแรก ไม่ใช่ img แต่เป็น "โหนดข้อความว่าง" แทน โหนดข้อความนี้มาจากตัวอักษรขึ้นบรรทัดใหม่นั่นเองครับ (ดูตามโค้ดด้านบนจะเห็นว่ามีการขึ้นบรรทัดใหม่) ทำให้คำสั่ง firstChild ให้ผลลัพท์แรกเป็น textNode ซึ่งไม่มี property tagName ผลลัพท์ที่ได้เลยเป็น undefined ครับ
การแก้ไขหรือวิธีที่ถูกต้องมีสองวิธีครับ
วิธีแรก เมื่อเรารู้ว่าปัญหาคือตัวอักษรขึ้นบรรทัดใหม่ ก็แก้ไขโดยการ เรียง element ต่อๆกันโดยไม่ขึ้นบรรทัดใหม่แทนครับ
<div id=test><img alt="" src="https://www.goragod.com/datas/users/goro/image/m7a3c3.jpg" /><img alt="" src="https://www.goragod.com/datas/users/goro/image/m7a3c3.jpg" /><img alt="" src="https://www.goragod.com/datas/users/goro/image/m7a3c3.jpg" /><img alt="" src="https://www.goragod.com/datas/users/goro/image/m7a3c3.jpg" /></div>
วิธีที่สอง ปรับเปลี่ยนวิธีการอ่าน element ใหม่ด้วย ฟังก์ชั่นด้านล่าง
function getfirstChild(id){
var img = document.getElementById(id).firstChild;
while (img && img.nodeType == 3) {
img = img.nextSibling;
}
return img;
}
document.getElementById('result2').innerHTML = getfirstChild('test').tagName;
อธิบายกันสักนิดนะครับ เนื่องจากเรารู้ว่า เราได้ผลลัพท์เป็น textNode ซึ่งเราไม่ต้องการ ก็ให้ทำการข้ามผลลัพท์นี้ไป ด้วยการตรวจสอบด้วย nodeType ครับ ซึ่งถ้า nodeType เท่ากับ 3 (textNode) ก็ให้ข้าม element ไป และทำการอ่าน element ถัดไปแทน ตามโค้ดด้านบนครับ