1

Short version: How can I keep the contents of different <script> elements independent of each other?

Long version: I have a django template that looks a bit like this:

<div class="app-container">
  <script src="app.js"></script>
  <script>
    $(function() {
        app_init($('.app-container')); // app_init is defined in app.ja
    });
  </script>
</div>

The difficulty is that I want to be able to include this template multiple times in the same page. When I do this, the $('.app-container') selector matches all of the <div class="app-container"> elements on the page.

What's the best way of keeping these independent? Some options I can think of but can't quite see how to make them work:

  • Find the <div ...> tag that is the parent of the <script> tag. If the script was executed automatically then I can see how this would work, using document.scripts[-1] but I can't spot how to do this when the code is executing in $(function () { ... }).
  • Assign the class of the <div> tag programmatically, then figure out the same class programmatically in the javascript. But I can't figure out how to do this.
  • Something clever using anonymous functions and captures that, again, I can't quite figure out.

Edit I've seen people suggesting various variations on this:

<div class="app-container">
  <script>
    var thisscript = document.currentScript;
    $(function() {
      app_init($(thisscript).closest('.app-container'));
    });
  </script>
</div>

This doesn't work if the template is used multiple times in a page, as the thisscript variable is common between them all and so it is always the last div.app-container in the page that gets processed.

Tom
  • 7,269
  • 1
  • 42
  • 69
  • What is your ultimate goal? It seems like your code is doing what it should, but not what you want. What are you trying to achieve? If you need unique elements, you can use an id on each. – colecmc May 25 '15 at 04:11
  • Well, pretty much what it says on the tin. I want to be able to write a django template that includes some html tags and some scripts that manipulate those tags, without having to assign a unique ID to the tags each time the template is included. I could just require the user to add an edtra `unique_id` parameter each time they include the template, but that is annoying, fails silently if they forget to do it, and looks like it should be unnecessary - I should be able to get a reference to the `div` tag that encloses *this* script tag. – Tom May 25 '15 at 04:31

1 Answers1

0

Here is a technique that may work. You'll have to figure out the global variable issue.

<!DOCTYPE html>
<html>

<head>
  <script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<script>
  var thisScript = [];
</script>

<body>

  <div class="app-container">
    some text
    <p>one</p>
    <script src="app.js"></script>
    <script>
      thisScript.push(document.currentScript);
      console.log(1);
      $(function() {
        //app_init($('.app-container')); // app_init is defined in app.js
      });
    </script>
  </div>

  <div class="app-container">
    second instance
    <p>two</p>
    <script src="appy.js"></script>
    <script>
      thisScript.push(document.currentScript);
      console.log(2);
      $(function() {
        //alert( script );
        //app_init(script); // app_init is defined in app.js
      });
    </script>
  </div>

  <div class="app-container">
    here is poor html
    <p>last</p>
    <script src="appy.js"></script>
    <script>
      thisScript.push(document.currentScript);
      console.log(3);
      $(function() {
        /**/
      });
    </script>
  </div>

  <script>
    console.log(thisScript);
  </script>
</body>

</html>

Also, see this post for more options that may work in your case: How may I reference the script tag that loaded the currently-executing script?

Community
  • 1
  • 1
colecmc
  • 3,133
  • 2
  • 20
  • 33
  • See updates to the question; this only works once in a document, not if the same template is used multiple times. The 'global variable issue' is indeed the problem. – Tom May 25 '15 at 05:29
  • I'm not familiar with django. How are the templates getting added? – colecmc May 25 '15 at 05:36
  • Django's template system lets you include another template - `{% include 'other_template.html' %}` if that helps. At any rate, django is a distraction here. The problem is how to store a reference to the current script so that it can be used in the document onReady function in a way that can be repeated in a single page. – Tom May 25 '15 at 05:49
  • I pushed them all to an array. So you still have one global that houses the individual instances. Please let me know if that works. – colecmc May 25 '15 at 06:06
  • I'm not sure how that helps - then you have to know the array index to use each time the script is included, which is exactly the same problem. – Tom May 25 '15 at 08:51
  • Sorry, I guess I'm not getting the full picture. – colecmc May 25 '15 at 14:36