Ho bisogno di cambiare singole istanze di icone in tutto il sito. Non voglio usare replaceIcon() e sovrascrivere tutte le istanze di quell’icona. Vedo che in passato hanno reso possibile questo per aree specifiche del sito, o almeno così sembra, ma non per tutto il sito.
Ad esempio, voglio cambiare UNA delle icone a forma di ingranaggio nella ricerca per riflettere meglio ciò che accade quando l’utente ci clicca sopra. Non voglio cambiare tutte le icone a forma di ingranaggio.
Quale icona è questa nello specifico (dove appare)? se sembra che ci sia un caso ragionevole in cui altri potrebbero trovarla utile, possiamo creare un alias per essa per consentirne la sostituzione separatamente.
Usiamo un’icona “sliders” qui per impostazione predefinita (ed è l’unica occorrenza di questa icona in Discourse per impostazione predefinita) — quindi sarebbe sicuro usare replaceIcon() in questo caso
Poiché non disponiamo di un’API per sostituire singole icone, il modo migliore per supportare questo oggi è valutare le richieste di aggiunta di nuovi alias che raggruppano casi d’uso simili.
Quindi, ad esempio, usiamo d-liked come alias per heart in modo che replaceIcon() possa essere utilizzato su d-liked per cambiarlo nel contesto “mi piace”, anziché sostituire ogni occorrenza dell’icona del cuore in tutta l’app.
Sarebbe bello sostituire qualsiasi occorrenza singola, che non è una situazione insolita nei temi — speriamo che un giorno avremo un’API per questo.
Va bene, ora capisco qual è il verdetto. Peccato sapere che non è disponibile fino a un aggiornamento dell’API, quindi per ora dovrò usare il metodo che ho adottato.
@awesomerobot Ecco un codice aggiornato di ciò che ho fatto per cambiare l’icona di creazione argomento che è un + senza modifiche globali a tutti i +
<script type="text/discourse-plugin" version="0.8">
api.onPageChange(() => {
const button = document.querySelector("#create-topic");
if (button) {
// Nascondi temporaneamente il pulsante mentre sostituiamo l'icona
button.style.display = "none";
// Cerca l'SVG all'interno del pulsante
const oldIcon = button.querySelector("svg");
if (oldIcon) {
// Rimuovi l'icona esistente (SVG)
oldIcon.remove();
}
// Crea un nuovo SVG per l'icona Font Awesome (fa-feather-pointed)
const newIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
newIcon.setAttribute("class", "fa d-icon d-icon-feather-pointed svg-icon svg-string");
newIcon.setAttribute("xmlns", "http://www.w3.org/2000/svg");
newIcon.innerHTML = '<use href="#feather-pointed"></use>';
// Inserisci la nuova icona all'interno del pulsante
button.insertBefore(newIcon, button.firstChild);
// Mostra di nuovo il pulsante dopo la sostituzione dell'icona
button.style.display = "block";
}
});
</script>
Devo perfezionarlo un po’ di più per modifiche multiple di icone
<script type="text/discourse-plugin" version="0.8">
api.onPageChange(() => {
// Elenco di selettori di pulsanti e relativi contenuti SVG personalizzati
const iconsToReplace = [
{ selector: "#create-topic", newSVG: `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M12 2L15 5H13V9H11V5H9L12 2ZM3 12L5 10V13H9V15H5V18L3 16V12ZM21 12L19 10V13H15V15H19V18L21 16V12Z" />
</svg>
` },
{ selector: "#some-other-button", newSVG: `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M21 3H3C2.44772 3 2 3.44772 2 4V20C2 20.5523 2.44772 21 3 21H21C21.5523 21 22 20.5523 22 20V4C22 3.44772 21.5523 3 21 3ZM20 19H4V5H20V19Z" />
</svg>
` },
{ selector: "#another-button", newSVG: `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M12 2L8 6H10V10H14V6H16L12 2ZM12 12L8 16H10V20H14V16H16L12 12Z" />
</svg>
` }
];
iconsToReplace.forEach(icon => {
const button = document.querySelector(icon.selector);
if (button) {
// Nascondi temporaneamente il pulsante mentre sostituiamo l'icona
button.style.display = "none";
// Cerca l'SVG esistente all'interno del pulsante
const oldIcon = button.querySelector("svg");
if (oldIcon) {
// Rimuovi l'icona esistente (SVG)
oldIcon.remove();
}
// Crea un nuovo elemento SVG e imposta il suo contenuto
const newIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
newIcon.innerHTML = icon.newSVG; // Imposta il contenuto SVG personalizzato
// Inserisci la nuova icona SVG all'interno del pulsante
button.insertBefore(newIcon, button.firstChild);
// Mostra di nuovo il pulsante dopo la sostituzione dell'icona
button.style.display = "block";
}
});
});
</script>
Sì, hai ragione! Non è molto stabile. Forse può essere più stabile con requestAnimationFrame o MutationObserver? ma sì, la cosa migliore sarebbe un’API dedicata come hai menzionato.
Grazie per avermelo fatto notare, hai assolutamente ragione. Usare solo api.onPageChange può essere inaffidabile poiché si attiva al cambio di rotta, non dopo il rendering del DOM. Ciò significa che c’è il rischio di una race condition in cui il pulsante #create-topic potrebbe non esistere ancora quando lo script tenta di accedervi.
api.onPageChange(() => {
const targetSelector = "#create-topic";
const tryEnhanceButton = () => {
const button = document.querySelector(targetSelector);
if (button) {
// Disconnette l'observer dopo aver trovato l'elemento
observer.disconnect();
// Nasconde temporaneamente il pulsante mentre sostituiamo l'icona
button.style.display = "none";
// Rimuove la vecchia icona se esiste
const oldIcon = button.querySelector("svg");
if (oldIcon) oldIcon.remove();
// Crea e inserisce la nuova icona SVG di Font Awesome
const newIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
newIcon.setAttribute("class", "fa d-icon d-icon-feather-pointed svg-icon svg-string");
newIcon.setAttribute("xmlns", "http://www.w3.org/2000/svg");
newIcon.innerHTML = '<use href="#feather-pointed"></use>';
button.insertBefore(newIcon, button.firstChild);
// Mostra di nuovo il pulsante
button.style.display = "block";
}
};
// Osserva le modifiche al DOM e tenta di migliorare il pulsante quando viene aggiunto
const observer = new MutationObserver(() => tryEnhanceButton());
observer.observe(document.body, { childList: true, subtree: true });
// Tenta immediatamente anche nel caso in cui sia già presente
tryEnhanceButton();
});
@Don Ho incluso MutationObserver per garantire che lo script venga eseguito solo una volta che l’elemento di destinazione esiste effettivamente, e si disconnette dopo aver svolto il suo compito per evitare overhead non necessari. Tenta comunque un controllo immediato nel caso in cui l’elemento esista già.
Non riesco a recuperare l’SVG che desidero dal sistema di icone di Discourse, anche se l’ho registrato come sottoinsieme di icone SVG per l’amministratore, poiché sembra essere in fontawesome ma non in discourse.