UIAPPDEVELOPER
UIAPPDEVELOPER

Reputation: 649

Not getting proper value or elements with Document​.query​SelectorAll() in javascript/jquery

I am using an "export to .ppt" application where I have used some charts and want to print those charts with the help of a plugin. I need to get all the chart ids in the form of an array and get those ids through document​.query​SelectorAll() but I am not getting the proper element ("chart3"). I am getting only first element/chart ("chart1") even though I used the 3rd chart id in the selection array. Here is the code below and a demo link also. On clicking the button you can get the .ppt download.

https://plnkr.co/edit/ROzjhJvOQA1wUoo6XoYI?p=preview

var id = ['chart1', 'chart2', 'chart3'];
$(document).ready(function() {
  var index = 0;


  Highcharts.chart('chart1', {
    title: {
      text: 'Chart1'
    },
    exporting: {
      showTable: true
    },
    series: [{
      data: [1, 2, 3]
    }]
  });

  Highcharts.chart('chart2', {
    title: {
      text: 'Chart2'
    },
    exporting: {
      showTable: true
    },
    series: [{
      data: [3, 2, 3]
    }]
  });

  Highcharts.chart('chart3', {
    title: {
      text: 'Chart3'
    },
    exporting: {
      showTable: true
    },
    series: [{
      data: [3, 2, 7]
    }]
  });
});

function doDemo() {
  console.log(id);
  var DOMURL = window.URL || window.webkitURL || window;
  var elements = id;
  var doc = new PptxGenJS();
  for (let i in elements) {
    let svg = document.querySelectorAll('svg');
    let canvas = document.createElement('canvas');
    let canvasIE = document.createElement('canvas');
    let context = canvas.getContext('2d');
    let data1 = (new XMLSerializer()).serializeToString(svg[i]);
    canvg(canvas, data1);
    let svgBlob = new Blob([data1], {
      type: 'image/svg+xml;charset=utf-8'
    });
    let url = DOMURL.createObjectURL(svgBlob);
    let img = new Image();
    img.src = url;
    img.onload = function() {
      context.canvas.width = $("#" + elements[i]).find('svg').width();
      context.canvas.height = $("#" + elements[i]).find('svg').height();

      context.drawImage(img, 0, 0);
      // freeing up the memory as image is drawn to canvas
      DOMURL.revokeObjectURL(url);
      var dataUrl;
      dataUrl = canvas.toDataURL('image/png');
      doc.addNewSlide().addImage({
        data: dataUrl,
        x: 3.0,
        y: 0,
        w: 6.0,
        h: 3.0
      });
    }
  }
  setTimeout(function() {
    doc.save('Demo-Images');
  }, 1000);
}
div {
  width: 25%;
  float: left;
  margin-right: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="canvg.js"></script>
<script src="rgbcolor.js"></script>

<script src="https://cdn.jsdelivr.net/gh/gitbrent/[email protected]/dist/pptxgen.bundle.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gitbrent/[email protected]/libs/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gitbrent/[email protected]/libs/jszip.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gitbrent/[email protected]/dist/pptxgen.min.js"></script>
<div id="chart1"></div>
<div id="chart2"></div>
<div id="chart3"></div>

Upvotes: 1

Views: 212

Answers (1)

OXiGEN
OXiGEN

Reputation: 2399

I took the liberty of refactoring and formatting some of your code for readability. Functionality stays the same, just with the fixes to make it work like you wanted.

Fixes:

  • Added let el = elements[i]; to avoid redundant elements[i] calls.
  • Replaced document.querySelectorAll('svg') with document.querySelectorAll('#' + el + ' svg') since you just want the specific div's svg in each loop, not all the svg elements in the doc.
  • Replaced .serializeToString(svg[i]) with .serializeToString(svg[0]) since there is only 1 element in the array per loop, which will always be the element you want.
  • Replaced $("#" + elements[i]).find('svg') with $('#' + el + ' svg') for some efficiency increase. If we did not have to use svg = document.querySelectorAll() per your requirements, we could just use the jQuery selector to assign the variable and reuse the variable again for both .width() and .height().

Runnable snippet with external libs at https://next.plnkr.co/edit/mHtNH9DIzhmWOV1U

var id = ['chart3'];

function doDemo() {
  let DOMURL = window.URL || window.webkitURL || window,
    elements = id,
    doc = new PptxGenJS();

  for (let i in elements) {
    let el = elements[i];
    let svg = document.querySelectorAll('#' + el + ' svg');
    let canvas = document.createElement('canvas');
    let canvasIE = document.createElement('canvas');
    let context = canvas.getContext('2d');
    let data1 = (new XMLSerializer()).serializeToString(svg[0]);
    canvg(canvas, data1);

    let svgBlob = new Blob([data1], {
      type: 'image/svg+xml;charset=utf-8'
    });
    let url = DOMURL.createObjectURL(svgBlob);
    let img = new Image();

    img.src = url;
    img.onload = function() {
      context.canvas.width = $('#' + el + ' svg').width();
      context.canvas.height = $('#' + el + ' svg').height();

      context.drawImage(img, 0, 0);
      // freeing up the memory as image is drawn to canvas
      DOMURL.revokeObjectURL(url);

      let dataUrl = canvas.toDataURL('image/png');

      doc.addNewSlide().addImage({
        data: dataUrl,
        x: 3.0,
        y: 0,
        w: 6.0,
        h: 3.0
      });
    }

  };
  setTimeout(function() {
    doc.save('Demo-Images');
  }, 1000);
}

$(document).ready(function() {
  Highcharts.chart('chart1', {
    title: {
      text: 'Chart1'
    },
    exporting: {
      showTable: true
    },
    series: [{
      data: [1, 2, 3]
    }]
  });
  Highcharts.chart('chart2', {
    title: {
      text: 'Chart2'
    },
    exporting: {
      showTable: true
    },
    series: [{
      data: [3, 2, 3]
    }]
  });
  Highcharts.chart('chart3', {
    title: {
      text: 'Chart3'
    },
    exporting: {
      showTable: true
    },
    series: [{
      data: [3, 2, 7]
    }]
  });
});
.chart {
  border: 1px solid black;
  margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="canvg.js"></script>
<script src="rgbcolor.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gitbrent/[email protected]/dist/pptxgen.bundle.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gitbrent/[email protected]/libs/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gitbrent/[email protected]/libs/jszip.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gitbrent/[email protected]/dist/pptxgen.min.js"></script>

<div class="btntn">
  <button type="button" class="btn btn-success my-4 w-50" onclick="doDemo()">Generate Demo PowerPoint</button>
</div>
<div class="container">
  <div class="chart" id="chart1"></div>
  <div class="chart" id="chart2"></div>
  <div class="chart" id="chart3"></div>
</div>

Upvotes: 1

Related Questions