2

I would like to get some help to pass Django variable in HTML template into Javascript variable.

I believed it would be easy, but up to now, I don't overcome to do that. Especially with a Django for loop.

I have an HTML piece of code like this :

{% for document in publication.documents.all %}
    <table class="table table-condensed">
        <tbody>
            <tr>
                <td class="col-md-1">
                    <canvas id="test{{ document.id }}"></canvas>
                </td>
            </tr>
        </tbody>
    </table>
{% endfor %}

Then, I would like to use Javascript code to display the PDF for each document.

So, I have something like this with JS :

<script src="https://mozilla.github.io/pdf.js/build/pdf.js"></script>

<script type="text/javascript">

  var document_upload = "{{ document.upload }}"; //Django variable
  pdfjsLib.getDocument('http://localhost:8000/media/'+document_upload).then(function (pdf) {
    console.log("pdf loaded");
    pdf.getPage(1).then(function (page) {
        var scale = 0.30;
        var viewport = page.getViewport(scale);

        var canvases = document.getElementsByTagName('canvas');
        Array.from(canvases).forEach((canvas) => {
            var context = canvas.getContext('2d');
            canvas.height = viewport.height;
            canvas.width = viewport.width;

            var renderContext = {
                canvasContext: context,
                viewport: viewport
            };
            page.render(renderContext);
        });
    });
  });

</script>

But nothing appears in my template.

If I make a console.log() for these :

var document_upload = "{{ document.upload }}"; //returns blank
var document_upload = {{ document.upload }}    //returns Undefined

Maybe someone could help me? I don't know but I think I need to add a loop in my JS too according to this Django loop {% for document in publication.documents.all %} ?

Essex
  • 6,042
  • 11
  • 67
  • 139
  • https://stackoverflow.com/questions/8683922/how-can-i-pass-my-context-variables-to-a-javascript-file-in-django – Mohit Solanki Sep 26 '18 at 09:01
  • is JS code in the same HTML file? – BugHunter Sep 26 '18 at 09:02
  • @BugHunter Yes because I tried with external JS code but I read that I couldn't pass Django variable in this case. – Essex Sep 26 '18 at 09:03
  • 2
    But `document` is only in scope inside the loop, and your JS - even if it is in the same file - is not inside that loop. – Daniel Roseman Sep 26 '18 at 09:05
  • @MohitSolanki I already tried answers from this post and up to now I don't find the solution. I tried with `|escapejs` etc .. – Essex Sep 26 '18 at 09:05
  • @DanielRoseman Yes it's exactly what I'm thinking as you can see my tip to the end of my question. As I'm JS beginner, how I can add JS inside this loop ? – Essex Sep 26 '18 at 09:06
  • 1
    Why can't you just put it there? JS can go anywhere in your HTML file. – Daniel Roseman Sep 26 '18 at 09:09
  • 1
    Hum, I don't know because I believed that JS was executed only at the end, even if the JS script is placed at the beginning or at the end of HTML file. – Essex Sep 26 '18 at 09:11
  • @Deadpool, you can just create a js array of 'publication.documents.all' and use it. the way, you are doing, it will always be undefined, because document is outside loop. var publications = publication.documents.all call some function to consume this data. – BugHunter Sep 26 '18 at 09:18
  • @BugHunter You're right, but according to Daniel's answer, I set JS script just after my `html canvas` inside the loop. So I get a new issue because it takes too much time to load PDF and picture is strange. – Essex Sep 26 '18 at 09:21
  • 1
    probably you are overlapping all these documents. parse them one by one, by providing different viewport. – BugHunter Sep 26 '18 at 09:32

3 Answers3

0
<script>
   const document_upload = {{document | safe}}
   console.log(document.upload)
</script>

Check if there is some data

It should print data if you have or it will give you an empty array

Sunil Kumar
  • 61
  • 1
  • 12
  • I'm not sure that your code will work, because as said @DanielRoseman, I have to set my JS script inside the Django loop. If I print data from your code, the array will be always empty I assume. – Essex Sep 26 '18 at 09:32
  • i think you mean `console.log(document_upload)` – Vaibhav Vishal Sep 26 '18 at 09:50
0

Put your django variable inside html as data-element. Then run a loop to render pdf. Your variable is available inside your {% for %} loop only, so either you put your js inside the loop(don't do it) or do this.
Scripts I have added use jQuery, so don't forget to add it.

{% for document in publication.documents.all %}
<table class="table table-condensed">
    <tbody>
        <tr>
            <td class="col-md-1">
                <canvas class="my-canvas" data-upload="{{ document.upload }}" id="test{{ document.id }}"></canvas>
            </td>
        </tr>
    </tbody>
</table>

Script, preferably just before < /body>

<script src="https://mozilla.github.io/pdf.js/build/pdf.js"></script>
// add jQuery
<script type="text/javascript">
    $(document).ready(function(){
        $('.my-canvas').each(function(){
            var document_upload = $(this).data('upload'); // Django variable saved as data attribute
            console.log(document_upload);
            /* Do rest of your pdf.js stuff here */\
            pdfjsLib.getDocument('http://localhost:8000/media/' + document_upload).then(function (pdf) {
                console.log("pdf loaded");
                pdf.getPage(1).then(function (page) {
                    var scale = 0.30;
                    var viewport = page.getViewport(scale);

                    var canvases = document.getElementsByTagName('canvas');
                    Array.from(canvases).forEach((canvas) => {
                        var context = canvas.getContext('2d');
                        canvas.height = viewport.height;
                        canvas.width = viewport.width;

                        var renderContext = {
                            canvasContext: context,
                            viewport: viewport
                        };
                        page.render(renderContext);
                    });
                });
            });
        });
    });
</script>
Vaibhav Vishal
  • 6,576
  • 7
  • 27
  • 48
0

Thanks to Daniel Roseman, I found the answer and I overcome to display PDF cover page for each document.

This is my HTML file containing JS script :

{% for document in publication.documents.all %}
    <table class="table table-condensed">
        <tbody>
            <tr>
                <td class="col-md-1">
                    {% if document.format == 'pdf' %}

                            <script src="https://mozilla.github.io/pdf.js/build/pdf.js"></script>

                            <script type="text/javascript">
                            var document_upload = "{{ document.upload }}";
                            pdfjsLib.getDocument('http://localhost:8000/media/'+document_upload).then(function (pdf) {
                              pdf.getPage(1).then(function (page) {
                                  var scale = 0.30;
                                  var viewport = page.getViewport(scale);

                                  var canvas = document.getElementById('test{{ document.id }}');
                                  var context = canvas.getContext('2d');
                                  canvas.height = viewport.height;
                                  canvas.width = viewport.width;

                                  var renderContext = {
                                      canvasContext: context,
                                      viewport: viewport
                                  };
                                  page.render(renderContext);
                              });
                            });
                            </script>
                            <canvas id="test{{ document.id }}" style="border:1px solid #000000;"></canvas>
                          {% else %}
                            <span class="glyphicon glyphicon-blackboard"></span>
                          {% endif %}
                </td>
            </tr>
        </tbody>
    </table>
{% endfor %}

It takes just 3-4s to load all PDF (maybe there is another way to do that faster), but it works !

Essex
  • 6,042
  • 11
  • 67
  • 139