안녕하세요, 두 개의 이미지 중 하나를 무작위로 선택해 모든 페이지에 이미지 배너를 추가하려고 합니다. 테마의 Head 섹션에 추가하고 홈페이지를 강제로 새로고침하면 정상적으로 작동합니다:
수정: 해답에 더 가까워진 시도는 여기에 있습니다:
How to use api.onPageChange with api.createWidget? - #2 by rahim123
제가 어디서 잘못하고 있는지 혹시 아시는 분 계신가요? 감사합니다!
안녕하세요, 두 개의 이미지 중 하나를 무작위로 선택해 모든 페이지에 이미지 배너를 추가하려고 합니다. 테마의 Head 섹션에 추가하고 홈페이지를 강제로 새로고침하면 정상적으로 작동합니다:
수정: 해답에 더 가까워진 시도는 여기에 있습니다:
How to use api.onPageChange with api.createWidget? - #2 by rahim123
제가 어디서 잘못하고 있는지 혹시 아시는 분 계신가요? 감사합니다!
이것은 제가 더 적절하게 시도해 본 것입니다. api.onPageChange(() 함수 없이 실행하면 동작은 하지만, 하드 리프레시를 해야만 이미지가 무작위로 바뀝니다. api.onPageChange(() 함수를 추가하면 아예 이미지가 표시되지 않습니다. 제가 어디서 잘못되고 있는지 조언을 주실 수 있나요?
<script type="text/discourse-plugin" version="0.8">
api.onPageChange(() => {
doStuff();
});
function doStuff() {
const h = require("virtual-dom").h;
let banners = new Array();
banners[0]="https://example.com/uploads/default/original/1X/9d9762a4129c78c478d14ff857c3bd1f2be0322a.jpg";
banners[1]="https://example.com/uploads/default/original/1X/04ede2abd9ac117c64988a5b0bcf033474381527.jpg";
let GoTo = new Array();
GoTo[0]="https://google.com";
GoTo[1]="https://brave.com";
let Number = Math.round(1 * Math.random());
let TheLink = GoTo[Number];
let TheImage = banners[Number];
api.createWidget("top-banner-widget", {
tagName: "div.top-banner",
html() {
return h("div#top-banner", [
h(
"a.custom-ad-link",
{ href: TheLink },
h("img", { src: TheImage})
)
]);
}
});
}
</script>
<script type="text/x-handlebars" data-template-name="/connectors/above-main-container/inject-widget">
{{mount-widget widget="top-banner-widget"}}
</script>
결측된 부분이 위젯의 재렌더링을 트리거하는 것이었던 것 같습니다… 기억이 맞다면 위젯은 상호작용 시 재렌더링되므로, 페이지 변경 시 재렌더링이 일어나도록 this.scheduleRerender();를 추가했습니다.
제 로컬 환경에서는 정상적으로 동작합니다:
api.createWidget("top-banner-widget", {
tagName: "div.top-banner",
html() {
let Number = Math.round(1 * Math.random());
let banners = new Array();
banners[0]="https://placekitten.com/500/500";
banners[1]="https://placekitten.com/500/300";
let GoTo = new Array();
GoTo[0]="https://google.com";
GoTo[1]="https://brave.com";
let TheLink = GoTo[Number];
let TheImage = banners[Number];
api.onPageChange(() => {
this.scheduleRerender();
});
return h("div#top-banner", [
h(
"a.custom-ad-link",
{ href: TheLink },
h("img", { src: TheImage})
)
]);
}
});
정말 훌륭합니다! 덕분에 정말 감사합니다. 저 혼자서는 절대 알아낼 수 없었을 거예요!
테마 컴포넌트의 Head 코드 전체는 다음과 같습니다:
<script type="text/discourse-plugin" version="0.8">
const h = require("virtual-dom").h;
api.createWidget("top-banner-widget", {
tagName: "div.top-banner",
html() {
let Number = Math.round(1 * Math.random());
let banners = new Array();
banners[0]="https://example.com/uploads/default/original/1X/9d9762a4129c78c478d14ff857c3bd1f2be0322a.jpg";
banners[1]="https://example.com/uploads/default/original/1X/04ede2abd9ac117c64988a5b0bcf033474381527.jpg";
let GoTo = new Array();
GoTo[0]="https://google.com";
GoTo[1]="https://brave.com";
let TheLink = GoTo[Number];
let TheImage = banners[Number];
api.onPageChange(() => {
this.scheduleRerender();
});
return h("div#top-banner", [
h(
"a.custom-ad-link",
{ href: TheLink },
h("img", { src: TheImage})
)
]);
}
});
</script>
<script type="text/x-handlebars" data-template-name="/connectors/above-main-container/inject-widget">
{{mount-widget widget="top-banner-widget"}}
</script>
이것이 Ember 컴포넌트로 구현될 수도 있다는 점도 언급할 가치가 있습니다. 장기적으로 우리는 커스텀 위젯 시스템보다 Ember에 더 많이 의존하게 될 것입니다. 아직 Ember 업데이트 작업을 진행 중이므로, Discourse 커스터마이징에 대한 문서가 이 부분에서 다소 뒤처져 있습니다.
Ember 컴포넌트로 작동하는 방식을 보여주는 예시를 담은 테마 컴포넌트를 정리해 두었습니다: GitHub - awesomerobot/discourse-component-example · GitHub
여기에는 3개의 중요한 파일이 있습니다:
커넥터 (/javascripts/discourse/connectors/custom-header-banner-connector.hbs)
컴포넌트 (/javascripts/discourse/components/custom-header-banner.js)
컴포넌트 템플릿 (/javascripts/discourse/templates/components/custom-header-banner.hbs)
커넥터는 컴포넌트가 추가되는 위치이므로, 여기에는 <CustomHeaderBanner />만 포함하면 됩니다. 컴포넌트는 페이지 변경(라우트 변경)을 감지하고, 어떤 이미지/링크가 무작위로 표시될지에 대한 로직을 설정하는 곳입니다. 컴포넌트 템플릿은 데이터가 HTML로 표시되는 방식을 정의합니다.
아, 알겠습니다. 그것도 감사합니다. 제 사이트에서 해당 저장소의 테마 컴포넌트로 설치했을 때 정상적으로 작동하는 것을 확인했습니다.
대안으로, Customize > Install > Create New 인터페이스를 통해 수동으로 Ember 테마 컴포넌트로 추가한 다음 Edit CSS / HTML을 사용하는 것도 가능한가요? 그렇게 하면 이미지와 링크를 필요에 따라 빠르게 변경할 수 있어서 더 편할 것 같습니다. custom-header-banner.js의 내용은 Head 아래에, 그리고 <CustomHeaderBanner />는 After Header 또는 Body에 넣어야 할 것으로 생각되지만, custom-header-banner.hbs의 내용을 어디에 추가해야 하는지 확실하지 않습니다.
로컬에 설치된 테마 컴포넌트로 번역하는 것은 그보다 조금 더 복잡하지만, 원격 테마에 유연성을 더하는 방법 중 하나는 테마 설정을 사용하는 것입니다(Add settings to your Discourse theme).
이 방법은 settings.yml 파일을 추가하고 컴포넌트 및/또는 템플릿의 몇 가지 값을 업데이트하는 것을 포함합니다. 그러면 테마 컴포넌트 관리 페이지에 다음과 같은 설정이 표시됩니다:
위와 같은 위젯 구현 방식을 유지하고 관리 패널을 통해 업데이트하는 것도 괜찮지만, 가능한 경우 git 사용을 권장합니다. 문제 해결 시 공유하기가 쉽고, 변경 사항을 추적하기도 편리하기 때문입니다.
정말 훌륭합니다. 인내심을 갖고 명확하게 설명해 주셔서 감사합니다. 그 옵션도 사용할 수 있어서 정말 좋습니다.
다시 인사드립니다. 위젯이 특정 URL, 예를 들어 홈페이지에서만 표시되도록 하는 가장 좋은 방법을 찾고 있습니다.
가장 쉬운 방법은 홈페이지에만 존재하는 플러그인 아웃렛을 사용하는 것입니다. 현재 제가 필요한 것(구체적으로는 discovery-navigation-bar-above)에는 잘 작동합니다. 하지만 특정 페이지 URL에 민감하게 반응하면서 프로그래매틱하게 이 기능을 구현하는 방법에 대해서는 여전히 궁금합니다.
@awesomerobot 님이 작성한 이 매우 유용한 토픽을 찾았습니다:
이 내용을 이 게시물의 이전 솔루션에 맞게 적용해 보았습니다:
api.onPageChange((url) => {
if (url === "/" || url === homeRoute ){
this.scheduleRerender();
}
});
하지만 이 경우에도 이미지가 모든 페이지에 표시됩니다. 또한 변수와 무작위 선택 코드를 if 절 안에 넣어서 시도해 보았지만 전혀 작동하지 않습니다.
예제에는 <script type="text/x-handlebars" ... 섹션도 있지만, 여기서는 HTML만 허용되는 것 같고, 이전 스크립트에서 변수를 어떻게 가져와야 하는지 알지 못합니다.