Search code examples
javascriptasync-awaitpromisehtml2canvas

html2canvas not working inside a php loop


I have a javascript function print(). It is called by a php loop. It shows 2 copies of an image on a page.

If I run it 1 time, nothing is wrong and below function works. But If I run it more than 1 time, due to promise nature of hmtl2canvas, it corrupts.

I searched for making html2canvas work sync but not much solutions

Also I tried to put it inside a async/await, but none of them works.

function print(html_string){

  let leftPanel = 'left'+Date.now(); //create Unique ID
  let rightPanel = 'right'+Date.now(); //create Unique ID

  document.body.innerHTML += "<div style='display:flex;'><div id='"+leftPanel+"'></div><div id='"+rightPanel+"'></div></div>";
  var iframe=document.createElement('iframe');
  document.body.appendChild(iframe);

  var iframedoc=iframe.contentDocument||iframe.contentWindow.document;
  iframedoc.body.innerHTML=html_string;

  html2canvas(iframedoc.body).then(canvas => {
      jQuery("#"+leftPanel).append(canvas);
  });
  html2canvas(iframedoc.body).then(canvas => {
      jQuery("#"+rightPanel).append(canvas);
      document.body.removeChild(iframe);
  });
}

EDIT:

Above javascript function is called by below php loop:

foreach($InvoiceNos as $row){
  $downloadedInvoiceHtml = requestInvoice($row->UUID);
  ?><script>print('<?=$downloadedInvoiceHtml?>');</script><?php
}

Solution

  • Use an array

    <script>
    const html = [];
    <?php 
     foreach($InvoiceNos as $row){
      $downloadedInvoiceHtml = requestInvoice($row->UUID);
      ?>html.push('<?=$downloadedInvoiceHtml?>');<?php
    } ?>
    
    let cnt = 0;
    function print(){
      if (cnt >= html.length) return; // stop
      $("body").append(`<div style='display:flex;'><div></div><div></div></div>`);
      const div = document.createElement("div");
      div.innerHTML = html[cnt]
      html2canvas(div).then(canvas => {
        $("body div:last-child div").append(canvas);
        cnt++;
        print()
      });
    }
    print()
    </script>
    

    Alternatively

    <?php 
     foreach($InvoiceNos as $row){
      $downloadedInvoiceHtml = requestInvoice($row->UUID);
      ?><div style="display:flex"><div class="html"><?=$downloadedInvoiceHtml?></div></div>
      } ?>
    <script>
    let cnt = 0;
    const $html = $(".html");
    function print(){
      if (cnt >= $html.length) return; // stop
      $current = $html[cnt]
      html2canvas($html).then(canvas => {
        $current.empty().append(canvas);
        $current.after($current.clone(true);
        cnt++;
        print()
      });
    }
    print()
    </script>