# Javascript in theme component only runs once?

**URL:** https://meta.discourse.org/t/javascript-in-theme-component-only-runs-once/106202
**Category:** Support
**Created:** [January 10, 2019, 3:52pm UTC](https://meta.discourse.org/t/javascript-in-theme-component-only-runs-once/106202 "2019-01-10T15:52:05Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![jtbayly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jtbayly/32/119510_2.png) [@jtbayly](https://meta.discourse.org/u/jtbayly)
#### Post date: [January 10, 2019, 3:52pm UTC](https://meta.discourse.org/t/javascript-in-theme-component-only-runs-once/106202/1 "2019-01-10T15:52:05Z")

</div>

Hi there, I’ve got a javascript snippet that I’m supposed to put before the closing body tag. It works, but just as described on [this very old topic](https://meta.discourse.org/t/what-is-the-best-way-to-inject-javascript-code/17485), it only seems to run on first page load. Because it is supposed to scan the contents of posts and create tooltips and links for certain phrases, it needs to run each time new content is loaded.

Because of the _huge_ combination of potential strings (any Bible passage reference) to be linked, it is impossible to use a solution such as the [Auto-Linkify Words](https://meta.discourse.org/t/linkify-words-in-post/82193) plugin.

Apparently this sort of thing is possible to pull off in a theme component, as linkify does, but in my case the snippet just loads the actual javascript file from an external server and tells it to run. Anybody have any idea how I can get this working on content loaded via ajax?

Here’s the javascript snippet:

```plaintext
    <script>
	var refTagger = {
		settings: {
			bibleVersion: "NASB",			
			socialSharing: []
		}
	};
	(function(d, t) {
		var g = d.createElement(t), s = d.getElementsByTagName(t)[0];
		g.src = "//api.reftagger.com/v2/RefTagger.js";
		s.parentNode.insertBefore(g, s);
	}(document, "script"));
    </script>

```

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [January 10, 2019, 4:11pm UTC](https://meta.discourse.org/t/javascript-in-theme-component-only-runs-once/106202/2 "2019-01-10T16:11:39Z")

</div>

Use the page tracker API to call the necessary function on page change. Here an example:

[https://github.com/discourse/discourse-matomo-analytics/blob/master/common/head\_tag.html](https://github.com/discourse/discourse-matomo-analytics/blob/master/common/head_tag.html)

---

<div class="post-metadata">

### Author: ![jtbayly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jtbayly/32/119510_2.png) [@jtbayly](https://meta.discourse.org/u/jtbayly)
#### Post date: [January 10, 2019, 6:25pm UTC](https://meta.discourse.org/t/javascript-in-theme-component-only-runs-once/106202/3 "2019-01-10T18:25:06Z")

</div>

Thanks. That got me on the right track. However, in looking at [How do you force a script to refire on every page load in Discourse? - #26 by vinothkannans](https://meta.discourse.org/t/how-do-you-force-a-script-to-refire-on-every-page-load-in-discourse/74856/26), and the code of the linkify component, I believe I need to use the api.decorateCooked rather than api.onPageChange. Does that sound right?

Problem is, I can’t figure out how to use either one. I was able to get it “working” without the API, but like the above mentioned issue, it fires 3 times on page load. Here’s the code that works:

```plaintext
<script>
	var refTagger = {
		settings: {
			bibleVersion: "NASB",			
			socialSharing: []
		}
	};
	(function(d, t) {
		var g = d.createElement(t), s = d.getElementsByTagName(t)[0];
		g.src = "//api.reftagger.com/v2/RefTagger.js";
		s.parentNode.insertBefore(g, s);
	}(document, "script"));

$(document).ajaxComplete(function() {
    refTagger.tag();
});

</script>

```

If I replace the ajaxComplete section with the following, there’s an error in the console: “ReferenceError: Can’t find variable: api”.

```plaintext
  api.decorateCooked($elem => {
    refTagger.tag();
  });

```

If I change the opening script tag as follows, the error changes to "“refTagger.tag is not a function. (In ‘refTagger.tag()’, ‘refTagger.tag’ is undefined)”

```plaintext
<script type="text/discourse-plugin" version="0.2">

```

I don’t know javascript, so I’m just lost now. I’d like to do this the “proper” way if anybody can help me fix it. Thanks much.

By the way, it’s also possible apparently to run refTagger on specific content (rather than the whole page, I guess). This is some example code I found:

```plaintext
var o_c = document.getElementById('comment');

o_c.innerHTML = "See [Romans 1:10](http://biblia.com/bible/esv/Rom%201.10) for details";

refTagger.tag(o_c);

```

Not sure if it would be possible to just do something like the following, which is similar to what linkify does. If so, it seems like this would be most efficient:

```plaintext
  api.decorateCooked($elem => {
    refTagger($elem[0]);
  });

```

Anyway, as I said, if anybody can help, I’d be grateful.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [January 10, 2019, 6:31pm UTC](https://meta.discourse.org/t/javascript-in-theme-component-only-runs-once/106202/4 "2019-01-10T18:31:50Z")

</div>

To use the api you will need to put the code inside a discourse-plugin block. (It’s still javascript, just with a sprinkling of Discourse added on top).

So something like:

```plaintext
<script type="text/discourse-plugin" version="0.2">
api.decorateCooked($elem => {
    refTagger.tag($elem[0]);
  });
</script>
```

---

<div class="post-metadata">

### Author: ![jtbayly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jtbayly/32/119510_2.png) [@jtbayly](https://meta.discourse.org/u/jtbayly)
#### Post date: [January 10, 2019, 6:35pm UTC](https://meta.discourse.org/t/javascript-in-theme-component-only-runs-once/106202/5 "2019-01-10T18:35:34Z")

</div>

I think you missed it, I already tried that exact code. It then tells me “refTagger.tag is not a function. (In ‘refTagger.tag($elem[0])’, ‘refTagger.tag’ is undefined)”

I feel like I’m just missing something basic about how to declare or call these scripts.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [January 10, 2019, 6:42pm UTC](https://meta.discourse.org/t/javascript-in-theme-component-only-runs-once/106202/6 "2019-01-10T18:42:30Z")

</div>

That means the script isn’t available. This isn’t really a Discourse question, but:

```plaintext
<script src="https://api.reftagger.com/v2/RefTagger.js"></script>

<script type="text/discourse-plugin" version="0.2">
  api.decorateCooked($elem => {
    refTagger.tag($elem[0]);
  });
</script>

```

should work.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [January 10, 2019, 6:54pm UTC](https://meta.discourse.org/t/javascript-in-theme-component-only-runs-once/106202/7 "2019-01-10T18:54:44Z")

</div>

Looks like `refTagger` requires a variable to be set on the `window` object before the script is loaded, which isn’t possible by using multiple script tags (any inline scripts are extracted and executed at the end). This method works - using our `loadScript` function:

```plaintext
<script type="text/discourse-plugin" version="0.2">
window.refTagger = {
	settings: {
		bibleVersion: "NASB",			
		socialSharing: []
	}
};

let loadScript = require('discourse/lib/load-script').default;

api.decorateCooked($elem => {
    loadScript("//api.reftagger.com/v2/RefTagger.js").then(()=>{
        window.refTagger.tag($elem[0]);    
    })
});
</script>

```

 ![28](https://global.discourse-cdn.com/meta/original/3X/7/6/7673d84869c178e09da766575063a56d00296ab1.png)

---

<div class="post-metadata">

### Author: ![jtbayly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jtbayly/32/119510_2.png) [@jtbayly](https://meta.discourse.org/u/jtbayly)
#### Post date: [January 10, 2019, 7:00pm UTC](https://meta.discourse.org/t/javascript-in-theme-component-only-runs-once/106202/9 "2019-01-10T19:00:17Z")

</div>

Thanks! It would have taken me a while to figure that out, not knowing javascript, much less the intricacies of Discourse. 🙂

It’s working like a charm.

I appreciate all the help you guys give.

---

<div class="post-metadata">

### Author: ![system](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/system/32/443519_2.png) [@system](https://meta.discourse.org/u/system)
#### Post date: [February 10, 2019, 9:03am UTC](https://meta.discourse.org/t/javascript-in-theme-component-only-runs-once/106202/12 "2019-02-10T09:03:23Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
