ว่าด้วยเรื่องของการ window.print() ของ Javascript

วันนี้ผมขอแนะนำคำสั่ง window.print(); เป็นคำสั่งที่ง่ายๆ แต่ให้ได้ผลลัพธ์ที่ดีนั้นทำค่อนข้างยาก ปัญหาที่ผมเจอนั้นก็มีหลากหลาย ยกตัวอย่างเช่น

  1. ปัญหาต้องการจะ Print เพียงบางส่วน แต่คำสั่งนี้มันดันออกมาหมด
  2. print แล้วไม่ต้องการให้ print  button หรือ control อื่นๆ ติดมาด้วย
  3. print แล้วออกมาไม่สวยเหมือนหน้าจอ
  4. print Table แล้วขึ้นหน้าใหม่แล้วอยากให้มี Header ใหม่ทุกหน้า (ปัญหา  Classic)

วันนี้ผมมีวิธีและแนวทางการแก้ไขมาให้ดูกันครับ

โดยปกติแล้วคำสั่ง window.print(); จะเป็นการ สั่ง print ทุกอย่างที่อยู่บน Page ออกมา

ตัวอย่างเช่น  (ลองเลือกที่ icon print)


แล้วเราสั่ง print แล้วเราจะได้ผลลัพธ์มาทั้งหน้าดังรูปด้านล่าง
print result

ซึ่งถ้าหากเราต้องการเพียงส่วนที่เป็น Table เพียงอย่างเดียวเราก็สามารถทำได้สองวิธีคือ

  1. ใช้ stylesheet CSS เป็นตัวกำหนด
  2. ใช้ JavaScript เข้ามาช่วยซึ่งวิธีนี้เป็นวิธีที่ผมค่อนข้างชอบส่วนตัวครับ

วิธีที่ 1 ใช้stylesheet ค่อนข้างง่ายครับ
ใช้ Code CSS ในการซ่อน Control นั้นตอน Print ตัวอย่างตาม Code ด้านล่างครับ
#DivSerach คือ ชื่อ ID ของ Search Panel ที่เป็นสีเขียวด้านบน

@media print {
  #DivSerach {
  	display: none;
  }
}

โดย CSS ด้านบนจะสั่งให้ Control นี้เมื่อวเลา Print

ลองดูผลลัพธ์ใหม่หลังจากแก้ CSSตามด้านล่างครับ

จะเห็นว่า แท๊ป Search หายไป ซึ่งวิธีนี้ดูแล้วอาจจะง่ายหากเรามี Ui ที่ไม่สับซ้อน  เรามาดูวิธีต่อไปกันครับ

วิธีที่ 2 .ใช้ JavaScript
แนวคิดก็คือ อ่าน Tag ที่เราต้องการจะ print มาวาดใหม่บน Popup เพื่อ print เพียงส่วนที่ต้องการ วิธีนี้ก็ให้เขียน function ขึ้นมา 1 function  ถ้าหากเราใช้ jQuery เราก็ใช้ Tag อย่างเช่น $(“div.demo-container”).html(); อ่าน html เพื่อเอามาทำการ print หากไม่ได้ใช้ jQuery ก็ใช้ Tag พื้นฐานอย่างเช่น document.getElementById(“myHeader”);   ในที่นี่ผมขอยกตัวอย่าง document.getElementById(“”);  ละกันนะครับเพราะมันเป็น function พื้นฐานดี

function PrintPanel(tableId) {
    var divContents = document.getElementById(tableId).outerHTML;

    var printWindow = window.open('', '', 'height=400,width=1050,scrollbars=1');        
//สร้าง popup
    printWindow.document.write('<html><head><title>Business Trends Report</title>');

    printWindow.document.write('</head><body onLoad="self.print();self.close();">'); 
// สั่ง Print เมื่อ reder เสร็จ
    printWindow.document.write(divContents);
    printWindow.document.write('</body></html>');
    printWindow.document.close();
//printWindow.print();   print แบบนี้มีปัญหา run ไม่ได้ทุก Browser
}

//เรียกใช้งาน
function JsPrint(tableId) {
    PrintPanel(tableId);
}

เสริมคำสั่ง 

innerHTML VS outerHTML
<p id="explain">Hello</p>

innerHTML of element "explain" == Hello
outerHTML of element "explain" == <p id="explain">Hello</p>

ตัวอย่าง function การ print

ผลลัพที่ได้จาก Code Print javascript

ซึ่งผลลัพธ์ที่ได้แล้วทำไมมันไม่สวยเหมือนหน้าจอ ก็เป็นเพราะเวลาเราอ่าน Tag Table มันได้มาแต่เพียง

 <table  id="DataPanel" class="gridtable">
<tr>
	<th>A1</th>
	<th>A2</th>
	<th>A3</th>
	<th>A4</th>
</tr>
<tr>
	<td>Ciaran</td>
	<td>Ap #822-3249 Sapien Ave</td>
	<td>9303</td>
	<td>-85.03472, 44.05532</td>
</tr>
......
......
......
</table>

ซึ่ง stylesheet มันไม่มาด้วยเราก็ต้องทำส่วนของ popup ให้เหมือน page แม่โดยการเพิ่ม stylesheet

function PrintPanel(tableId) {
    var divContents = document.getElementById(tableId).outerHTML;

    var printWindow = window.open('', '', 'height=400,width=1050,scrollbars=1');        
//สร้าง popup
    printWindow.document.write('<html><head><title>Business Trends Report</title>');

    printWindow.document.write('<link href="TableCSS.css" rel="stylesheet" type="text/css" />'); //css path  

    printWindow.document.write('</head><body onLoad="self.print();self.close();">'); // สั่ง Print เมื่อ reder เสร็จ
    printWindow.document.write(divContents);

    printWindow.document.write('</body></html>');
    printWindow.document.close();

    //printWindow.print();   print แบบนี้มีปัญหา run ไม่ได้ทุก Browser
}

function JsPrint(tableId) {
    PrintPanel(tableId);
}

ลองดูทดสอบผลลัพธ์ใน page ด้านล่างได้ครับ

หมายเหตุการ ข้อจำกัดของ print ผ่าน Browser มันจะไม่ print background ของ Tag นั้น ๆ 

ซึ่งจะเห็นว่าทั้งสองวิธีให้ผลลัพธ์ที่เหมือนกันแต่แตกต่างกันที่วิธีการให้เลือกใช้ตามความเหมาะสมครับ

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


จากรูปด้านบนก็จะเห็นว่า Header มันหายไป และการตัดบรรทัดที่ ขาดๆ เกินๆ ดูแล้วไม่สวยงาม ปัญหานี้เป็นปัญหาที่ค่อนข้าง Classic เกิดขึ้นทุกยุคทุกสมัย ซึ่งมาถึงตอนนี้บางคนอาจถอดใจไปออกรายงาน โดยวิธีอื่นๆ แทนดีกว่า แต่ขอเสียของการออกรายงานด้วยวิธีอื่นมันจะเป็นการเพิ่มงานให้กับเราเป็นสองเท่าหากมีแก้ไขหน้าหลัก เราต้องจำเป็นที่จะต้องแก้ไขหน้ารายงานรายงานอีก ซึ่งมันค่อนข้างหน้าเบื่อ ซึ่งทางแก้ปัญหาการตกบรรทัดนี้เพียงแค่ใช้ stylesheet CSS ตาม code ด้านล่างเท่านั้นเอง

@media print
{
    table.gridtable     { page-break-after: auto; }
    table.gridtable   tr    { page-break-inside:avoid;page-break-after: auto; }
    table.gridtable   td    { page-break-inside:avoid; page-break-after:auto }
    table.gridtable   thead { display:table-header-group }
    table.gridtable   tfoot { display:table-footer-group }
}

Code ด้านบนเป็นการบอกให้ Print Header เวลาขึ้นหน้าใหม่ทุกครั้งและให้คำนวณการขึ้นหน้าใหม่แบบไม่ให้มีการตัดบรรทัดขาดๆ เกินลองทดสอบผลลัพธ์


ผลลัพธ์ที่ได้ครวออกมาตามรูปด้านล่าง

ซึ่งในตอนที่เขียน บทความนี้อยู่ CODE CSS นี้สามารถทำงานได้บน IE FIREFOX แต่มันยังเป็น Bug ของ Chome ที่รอการแก้ไขอยู่ครับหากสนใจติดตาม link ด้านล่างได้เลยครับ

Issue 24826: Repeating table headers on printed pages

ปัญหามากจริงๆครับผม

 source code

Loading Facebook Comments ...