title: Wagtail streamfield block: injecting jQuery into the Wagtail Admin
body: <p>I'm creating a block for Wagtail streamfields which shows real-time code syntax highlighting using the Prism JS library. It is partially working; when I have a language selected and code in place on an existing page, the code shows up, highlighted as expected:</p>
  
  <p><a href="https://i.stack.imgur.com/OkpmV.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/OkpmV.png" alt="It works for already populated code."></a></p>
  
  <p>However, when I try to create a new Wagtail page with a new Code Block, I get a JavaScript error:</p>
  
  <p><a href="https://i.stack.imgur.com/mrsJO.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/mrsJO.png" alt="JavaScript error when starting a new page with a new code block."></a></p>
  
  <p>It seems like the library is being delayed on loading when there isn't content there for it to highlight. I've tried both <code>$(document).ready</code> and <code>$(window).load</code>, but this is a different situation since the template containing the Prism library is loaded dynamically when you click the "Code Snippet" button. Here's the ext of the error I'm getting:</p>
  
  <pre><code>VM730:2 Uncaught ReferenceError: Prism is not defined
      at prism_repaint (eval at globalEval (jquery-2.2.1.js:338), &lt;anonymous&gt;:2:5)
      at populate_target_code (eval at globalEval (jquery-2.2.1.js:338), &lt;anonymous&gt;:9:5)
      at HTMLDocument.eval (eval at globalEval (jquery-2.2.1.js:338), &lt;anonymous&gt;:2:29)
      at fire (jquery-2.2.1.js:3182)
      at Object.add [as done] (jquery-2.2.1.js:3241)
      at jQuery.fn.init.jQuery.fn.ready (jquery-2.2.1.js:3491)
      at eval (eval at globalEval (jquery-2.2.1.js:338), &lt;anonymous&gt;:1:13)
      at eval (&lt;anonymous&gt;)
      at Function.globalEval (jquery-2.2.1.js:338)
      at domManip (jquery-2.2.1.js:5285)
  </code></pre>
  
  <p>Here's the Django Wagtail code I'm using for the Wagtail block:</p>
  
  <pre><code>class CodeBlock(StructBlock):
      """
      Code Highlighting Block
      """
  
      WCB_LANGUAGES = get_language_choices()
  
      language = ChoiceBlock(choices=WCB_LANGUAGES)
      code = TextBlock()
  
      class Meta:
          icon = 'code'
          template = 'wagtailcodeblock/code_block.html'
          form_template = 'wagtailcodeblock/code_block_form.html'
  </code></pre>
  
  <p>...and the code for the form template for the Wagtail admin:</p>
  
  <pre><code>&lt;script&gt;
  function prism_repaint(target_class) {
      Prism.highlightElement($(target_class)[0]);
  }
  function populate_target_code(label) {
      target_class = '#target-element-' + label;
      code_text = $('#' + label).val();
      $(target_class).text(code_text);
      prism_repaint(target_class);
  }
  &lt;/script&gt;
  {% with prism_version="1.6.0" %}
      {% block extra_css %}
      &lt;link href="https://cdnjs.cloudflare.com/ajax/libs/prism/{{ prism_version }}/themes/prism.min.css" rel="stylesheet" /&gt;
      {% endblock extra_css %}
      {% block extra_js %}
      &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/prism/{{ prism_version }}/prism.min.js"&gt;&lt;/script&gt;
      {% endblock extra_js %}
      &lt;div class="{{ classname }}"&gt;
          {% if help_text %}
              &lt;div class="object-help help"&gt;{{ help_text }}&lt;/div&gt;
          {% endif %}
  
          &lt;ul class="fields"&gt;
              {% for child in children.values %}
                  &lt;li{% if child.block.required %} class="required"{% endif %}&gt;
                      {% if child.block.label %}
                          &lt;label{% if child.id_for_label %} for="{{ child.id_for_label }}"{% endif %}&gt;{{ child.block.label }}:&lt;/label&gt;
                      {% endif %}
                      {{ child.render_form }}
                  &lt;/li&gt;
                  {% if child.block.label == "Language" %}
                      {# As we loop through, load each language dialect #}
                      {% for language_choice, language_name in child.block.field.choices %}
                          {% if language_choice|length %}
                              &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/prism/{{ prism_version }}/components/prism-{{ language_choice }}.min.js"&gt;&lt;/script&gt;
                          {% endif %}
                      {% endfor %}
  
                      &lt;script&gt;
                          $(document).ready(function() {
                              // Set initial language class on load
                              target_class = '#target-element-{{ child.id_for_label }}'.replace('language', 'code');
                              {% if child.id_for_label|length %}
                                  $(target_class).addClass('language-' + $('#{{ child.id_for_label }}').val());
                              {% endif %}
                              // Change language being highlighted when dropdown is changed
                              $('#{{ child.id_for_label }}').bind('input propertychange', function() {
                                  language_class = 'language-' + $('#{{ child.id_for_label }}').val();
                                  $(target_class).removeClass().addClass(language_class);
                                  prism_repaint(target_class);
                              });
                          });
                      &lt;/script&gt;
                  {% endif %}
                  {% if child.block.label == "Code" %}
                      &lt;script&gt;
                          $(document).ready(function() {
                              populate_target_code('{{ child.id_for_label }}');
                              $('#{{ child.id_for_label }}').bind('input propertychange', function() {
                                  populate_target_code('{{ child.id_for_label }}');
                              });
                          });
                      &lt;/script&gt;
                      &lt;li&gt;
                          &lt;pre&gt;&lt;code id="target-element-{{ child.id_for_label }}"&gt;&lt;/code&gt;&lt;/pre&gt;
                      &lt;/li&gt;
                  {% endif %}
              {% endfor %}
          &lt;/ul&gt;
      &lt;/div&gt;
  {% endwith %}
  </code></pre>
  
  <p>I've verified that the CSS and JS are properly being injected into the code using the <code>extra_css</code> and <code>extra_js</code> template blocks. I've also attempted using the ".getScript" function, but haven't had any luck. I'm by no means a JavaScript expert, so any help would be appreciated. The entire source for the project can be found on GitHub, in case that helps: </p>
  
  <p><a href="https://github.com/FlipperPA/wagtailcodeblock" rel="nofollow noreferrer">https://github.com/FlipperPA/wagtailcodeblock</a></p>
  
  <p>Any help tracking fixing this would be appreciated! Thanks for your time.</p>