테마 헤더에 추가한 JavaScript에서 $ is not defined 오류 발생

안녕하세요,

관리자 > 사용자 정의 > 테마 > 헤더 섹션에 아래 코드를 추가했는데, 다음 오류가 발생합니다.

Uncaught ReferenceError: $ is not defined

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

하지만 아래 코드를 추가하면 오류 없이 정상적으로 동작합니다.

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

보통 이 $ is not defined 오류는 jQuery가 로드되지 않았을 때 발생하는데, 기본적으로 헤더 스크립트는 jQuery가 로드된 후에 실행되지 않나요?

jQuery가 아닌 네이티브 JavaScript를 사용하세요.

(그렇더라도 Discourse는 SPA PWA이므로 특정 요소가 렌더링되었음을 전제로 하는 경우 레이스 조건이 발생할 수 있습니다. 이 문제를 해결하려면 특정 플러그인 아웃렛에 렌더링되는 Ember 컴포넌트를 모디파이어와 함께 사용하는 것입니다)

감사합니다. 하지만 이 자바스크립트는 개발자 콘솔에서 실행하면 정상적으로 동작합니다.
document.querySelector('.topic-list .topic-excerpt[href="/t/urltobechanged/8"]').setAttribute('href', "/t/newurltoset/17");

어떤 이유로인지 discourse 헤더에서 로드되면 :로 감싸서 실행하든, 아니면:

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

으로 감싸서 실행하든, “Uncaught TypeError: document.querySelector(…) is null” 오류가 반환됩니다.

개발자 콘솔에서는 정상적으로 동작하는데, 이 href 속성을 변경하는 한 줄의 코드를 어떻게 실행해야 하는지 아이디어가 있을까요?

Discourse가 SPA(싱글 페이지 애플리케이션)이므로, 문서의 “DOMContentLoaded” 이벤트에 의존하는 것은 큰 도움이 되지 않습니다. 문서의 DOM은 항상 "로드"된 상태이지만, 필요한 요소가 실제로는 존재하지 않을 수 있기 때문입니다. 대신 @merefield님이 언급했듯이 Components를 사용하거나, 다음과 같은 방식을 사용하는 것이 좋습니다: How do you force a script to refire on every page load in Discourse? - #5 by simon. 이렇게 하면 페이지가 변경될 때마다 변경하려는 요소가 존재하는지 코드로 확인할 수 있습니다.

좋아요, 이제 이해했습니다. WordPress/Joomla 개발에서 넘어온 분이라면 헤더에 JS를 추가하는 방식이 동일한 방식으로 작동할 거라고 생각하셨겠네요.

링크하신 내용은 실제로 해결책이 됩니다. 다만, 현재 <script type='text/discourse-plugin> 헤더는 비추천(deprecated) 상태라는 점에 유의해 주세요: Modernizing inline script tags for templates & JS API

URL 문제를 빠르게 해결하기 위해 결국 Discourse 관리자에서 직접 영구 링크(permalink)를 설정했습니다.

도와주셔서 감사합니다. 설명도 잘 이해했습니다!