Javascript added to theme header returns $ is not defined

Hi,

In Admin > Customize > Themes > in the header section I add the following but it returns
Uncaught ReferenceError: $ is not defined

<script>
$(document).ready(function() {
$('.topic-list .topic-excerpt[href="/t/urltobechanged/8"]').attr('href', "/t/newurltoset/17 ");
});
</script>

If I add the following though, then it it works fine without error.

<script>
  console.log("Hello, Discourse!");
</script>

Mostly this $ is not defined error occurs because jQuery is not loaded, however shouldn’t the header scripts be by default executed after jQuery is loaded?h.

Use native javascript, not jQuery.

(But even then be aware Discourse is a SPA PWA so you may have race conditions occuring if you are relying on certain elements having been rendered - and the solution to that is to use Ember Components rendered in specific plugin outlets in combination with modifiers)

2 Likes

Thanks but if this javascript this works fine when used in the developer console
document.querySelector('.topic-list .topic-excerpt[href="/t/urltobechanged/8"]').setAttribute('href', "/t/newurltoset/17");

Somehow when it is loaded from the discourse header, it is returned as “Uncaught TypeError: document.querySelector(…) is null”, no matter if I wrap it with :

function doSomething() {
or
document.addEventListener("DOMContentLoaded", function(event)

Any idea how this single line to change the href attribute should be run as it works fine in the dev console?

Since Discourse is an SPA, relying on the document “DOMContentLoaded” won’t be very helpful, since the document DOM is always “loaded” but the elements can be missing. Instead you’ll want to use Components as @merefield mentioned, or something like this: How do you force a script to refire on every page load in Discourse? - #5 by simon. This way every time the page changes, your code can check for the element you’re trying to change.

1 Like

Allright, I understand now, coming from wordpress/joomla developement, you think adding js to the header would work in the same way.

Your link provides indeed a solution, note that now the <script type='text/discourse-plugin> headers are deprecated Modernizing inline script tags for templates & JS API

To quickly solve the url situation I ended up doing a permalink directly from discourse admin though.

Thank you for the support and explanation !

1 Like