Search code examples
javascripthtmlflaskjinja2

Trouble displaying escaped text with Flask and JavaScript


So I'm trying to make a website whose front page consists of "cards", each of which has a unique pop-up when clicked:

  <div class="format-rows">
    {% for row in cartelles|reverse %}
    <div><img class="card-image" src="{{ url_for('static', filename=row.img_url) }}">
      <div class="text-box">
        <p onclick='popupAction("{{row.full_text}}")'>{{row.question}}</p>
      </div>
    </div>
    {% endfor %}
  </div>
  <div id="grey-blur"></div>
  <div id="popup">
    <div>
      <button class="close" onclick="closePopup()"></button>
      <img id="popup-image"
        src="https://images.unsplash.com/photo-1543207564-1271b510019d?crop=entropy&cs=srgb&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2ODI3NjY4ODM&ixlib=rb-4.0.3&q=85">
    </div>
    <div id="popup-textbox"></div>
  </div>

The popupAction code being:

function popupAction(text){

  let popup = document.getElementById('popup');
  popup.classList.add('active');

  let greyBlur = document.getElementById('grey-blur');
  greyBlur.classList.add('active');

  let popupText = document.getElementById('popup-textbox');
  popupText.innerHTML = text;

}

I've escaped my code already on my app.py file as I retrieve it from my MySQL account, but when I attempt to display the "{{row.full_text}}", which is the following(in greek):

<span>Τί εν το αγαπημένο σας πράμα για τη ζωή σας στην Κύπρο;</span> <br><br> Λοιπον, το πιο αγαπημενο μου πραγμα στην Κυπρο εν το ότι μπορώ οποιαδήποτε στιγμή θελήσω να μπώ στο αυτοκηνιτο μου τζιαι να παω θάλασσα. Ειδικά τον χειμώνα. Εν το αγαπημένο μου κομμάτι της Κύπρου. <br><br> <span>Γιατί εν σου αρέσκει να ζεις στην Κύπρο;</span> <br><br> Το οτι εν μπορώ να πάω κάπου τζιαι να είμαι ανάμεσα σε αγνώστους. Δηλαδή ακόμα τζιαν εχω επιλογη να μεν συναντησω καποιο γνωστο.. το πιο πιθανο... εννοω ακομα τζιαι αν εχω αναγκη να ειμαι μονη μου εν θα μπορεσω να ειμαι καπου μονη μου. Συνηθως βρισκεις ατομα που τουσ ξερεις τζιαι ξερουν σε. Ναι, νομιζω εσχιει αναγκη ο ανδρωπος την...το να γινει αορατος μεσα στην πολη του. Τζιαι ισως το αλλο που με ενοχλει παρα πολλα τζιαι εν θεμα επιλογης δικης μου εν το κινητο. Το οτι με το κινητο εν εσχεις την ελευθερια να αρνηθεις να μιλησεις σε καποιον γιατι, επιαννα σε, εν μου απαντησες. Τζιαι εννα επιμενει να  πιασει τζιαι δευτερη φορα η να στιλει μυνημα, οποταν ναι, ακομα τζιαν θελεις να αποφυγεις καποιον, εν μπορεις ευκολα(...) Η σκεφτου πιο σοφον ηταν να ηταν τζινον που θα ελεγες, η ποσον ποσον πολλα ηταν να φκεννει που μεσα σου αν, αντι για να του μιλησεις που το κινητο, εγγραφες του μιαν επιστολη. Μπορει να επερνε μιαν εβδομαδα να παει τζιαι μιαν εβδομαδα ναρτει, ποσον ηταν να κατασταλαξουν τα συναισθηματα, γιατι, ξερεις, λεστο την βρα που εισαι μεστον θυμο, η μεσα στην θλιψη,  η μεσα στην απόγνωση, ενω μπορει δεκα λεπτα μετα να μενι νιωθεις ακριβως ετσι. Ενω αν τα εβαλλες σε λεξεις ναταν λίο διαφορετικα. Ναι, η αληθκεια, ισχυει. Τζιαι το αλλο που με ενοχλει με το κινητο ειναι το "που εισαι;" Εν σε αφορά ρε φίλε. Εννοώ, τι σημαινει "που εισαι"; [γελιο]"Τι κάμνεις;"[γελιο]. Ειμαστεν παντελως αδιακριτοι. <br><br>

the console log comes up with the following error: SyntaxError: Unexpected EOF, pointing to this line:

")'>What&#39;s your favourite thing about living in Cyprus?</p>

referring to this line in my code:

<p onclick='popupAction("{{row.full_text}}")'>{{row.question}}</p>

I understand that there's something weird going on with the quotes between the end of the input to my popupAction() function and the rest of the code,")'>, but I can't figure out how to get JS/jinja to parse this properly. I've tried combinations of JSON.parse on JS and safe/escape/tojson on the ninja side, resulting again in incorrect parsing in one form or another. Can anyone help?


Solution

  • I suggest something like this instead of fighting the quotes

    <p class="fullText"><span hidden>{{row.full_text}}</span>{{row.question}}</p> 
    

    using this code

    document.getElementById("rowContainer").addEventListener("click", (e) => { 
      const tgt = e.target; 
      if (!tgt.matches(".fullText")) return; 
      popupAction(tgt.querySelector('span').innerHTML); 
    });
    

    change rowContainer to whatever the ID or selector is for the nearest common container of all rows