1

In a Djano project of mine, I have a JS file inside /project/static/js/. It needs access to a files stored at /project/templates/. I'm unable to access this location from the js file.

Can someone suggest a work around (short of keeping duplicates of the said files in the JS folder). I'd like to avoid duplication (since it doubles my maintenance down the road)

Task specifics: I have some HTML templates that display instructions. The JS I've written simply takes the same instruction text and displays it as text on a dynamic popup.

Note: The main wrinkle is that a non-JS fallback must exist for any JS solution. Some of the users of this project emanate from a forward proxy that strips all <script> tags. Think Unobtrusive JS.

j-i-l
  • 10,281
  • 3
  • 53
  • 70
Hassan Baig
  • 15,055
  • 27
  • 102
  • 205
  • what about simlinking it?!: `ln -s /project/templates/my_file /project/static/js/my_file` – j-i-l Dec 21 '18 at 12:59
  • 1
    @jojo, that wouldn't be the number 1 way I'd do it. Yes it'd work but I don't want to do something on the OS level to solve an issue with the application. – Hassan Baig Dec 21 '18 at 13:10
  • 1
    Sure. I wouldn't do it this way either. But I guess this is more of a design problem. The best solution is one where there is no need to access the template folder from within you static directory, I guess. – j-i-l Dec 21 '18 at 13:15
  • @jojo, precisely, that is the kind of solution I'm trying to figure out. – Hassan Baig Dec 21 '18 at 13:18
  • Any luck? Maybe, if you are more specific on what exactly the JS does you'll have more luck in getting an answer. – j-i-l Dec 21 '18 at 17:47
  • @jojo: I have some HTML templates that display instructions. The JS I've written simply takes the same instruction text and displays it as text on a dynamic popup. – Hassan Baig Dec 21 '18 at 19:17
  • 1
    Can you add views that serve up the templates and then have your js call the urls for those views? – jcfollower Dec 21 '18 at 21:26
  • 1
    @jcfollower: : I don't follow. Could you illustrate a bit more? – Hassan Baig Dec 22 '18 at 04:20

1 Answers1

1

There is no need to access projects/templates from the static folder.

You have several options how to display HTML content, like instructions, in a popup.

Here's an outline of 2 ways to do so:

1st Option: Load all content at once

This approach loads everything in one go and the js only changes the visibility of the instruction pop-up. If you are using Bootstrap then modal is what will make your life easier. You do not even need to write any js altogether. With Bootstrap this would look something like:

<!-- main_template.html -->
<!-- Don't forget to load the bootstrap library here -->
....
<!-- icon to trigger the popup -->
<a data-toggle="modal" data-target="#InstructionModal">
    <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>&nbsp;Show Instructions
</a>
....

<!-- the bootstrap modal -->
<div class="modal fade" id="InstructionModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="myModalLabel">Instructions</h4>
      </div>
      <div class="modal-body">
        {% include 'instruction.html' %}
      </div>
    <div class="modal-footer">
      <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
    </div>
  </div>
</div>

Then the instructions:

<!-- instruction.html -->
<p>
  This is an instruction - You must follow it!
</p>

2nd Option: Load additional content on request using ajax

In this case you would not load the additional HTML content in the beginning, but serve it only upon request, i.e. if someone clicks on the Show Instructions icon. Note that you'll need jQuery for this to work.

Here your instructions get a view (don't forget to update your urls.py as well):

# view.py
def get_instructions(request):
    return render(request, 'instruction.html')

The instructions template is still the same:

<!-- instruction.html -->
<p>
  This is an instruction - You must follow it!
</p>

The js:

<!-- get_instructions.js -->
....
<script>
$("#InstroductionModal").on("show.bs.modal", function(e) {
    var link = $(e.relatedTarget);
    $(this).find(".modal-body").load(link.attr("href"));
});
</script>

The the main template:

<!-- main_template.html -->
<!-- Don't forget to load get_instructions.js -->
....
<!-- icon to trigger the popup -->
<a href="{% url 'get_instructions' %}" data-remote="false" data-toggle="modal" data-target="#InstructionModal">
    <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>&nbsp;Show Instructions
</a>

<!-- the bootstrap modal -->
<div class="modal fade" id="InstructionModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
        <h4 class="modal-title" id="myModalLabel">Instructions</h4>
      </div>
      <div class="modal-body">
        <p> Instructions will follow </p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">
          Close
        </button>
      </div>
    </div>
  </div>
</div>

Hopefully one of those ways work for you. Unfortunately, I don't have a django project setup, so this code is untested.

j-i-l
  • 10,281
  • 3
  • 53
  • 70
  • I'd certainly prefer to use jQuery (method 2) but my issue is I need to support non-JS clients as well. Some of my users emanate from a forward-proxy that strips all ` – Hassan Baig Dec 22 '18 at 04:14
  • @HassanBaig but so you cannot use the ` – j-i-l Dec 22 '18 at 09:55