Necesito cambiar instancias individuales de iconos en todo el sitio. No quiero usar replaceIcon() y anular todas las instancias de ese icono. Veo que en el pasado hicieron esto posible para áreas específicas del sitio, o eso es lo que parece, pero no en todo el sitio.
Por ejemplo, quiero cambiar UN icono de engranaje en la búsqueda para reflejar mejor lo que sucede cuando el usuario hace clic en él. No quiero cambiar todos los iconos de engranaje.
¿Qué icono es este específicamente (dónde aparece)? Si parece que hay un caso razonable en el que otros podrían encontrarlo útil, podemos crear un alias para él para permitir que se reemplace por separado.
Usamos un icono de “sliders” aquí por defecto (y es la única aparición de este icono en Discourse por defecto) — así que sería seguro usar replaceIcon() en este caso
Dado que no tenemos una API para reemplazar iconos individuales, la mejor manera en que podemos soportar esto hoy es evaluando solicitudes para agregar nuevos alias que agrupen casos de uso similares.
Así, por ejemplo, usamos d-liked como alias para heart para que replaceIcon() se pueda usar contra d-liked para cambiarlo en el contexto de “like”, en lugar de reemplazar cada aparición del icono de corazón en toda la aplicación.
Sería bueno reemplazar cualquier ocurrencia individual, esa no es una situación inusual en los temas — esperemos que algún día tengamos una API para eso.
Okay, ahora entiendo, ¿cuál es el veredicto sobre esto? Es triste saber que no está disponible hasta una actualización de la API, así que tendré que usar el método que he hecho por el momento.
@awesomerobot Aquí tienes un código actualizado de lo que he hecho para cambiar el icono de crear tema, que es un + sin cambio global a todos los +
<script type="text/discourse-plugin" version="0.8">
api.onPageChange(() => {
const button = document.querySelector("#create-topic");
if (button) {
// Ocultar temporalmente el botón mientras reemplazamos el icono
button.style.display = "none";
// Buscar el SVG dentro del botón
const oldIcon = button.querySelector("svg");
if (oldIcon) {
// Eliminar el icono existente (SVG)
oldIcon.remove();
}
// Crear un nuevo SVG para el icono de 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>';
// Insertar el nuevo icono dentro del botón
button.insertBefore(newIcon, button.firstChild);
// Mostrar el botón de nuevo después de reemplazar el icono
button.style.display = "block";
}
});
</script>
Tengo que refinarlo un poco más para múltiples cambios de icono
<script type="text/discourse-plugin" version="0.8">
api.onPageChange(() => {
// Lista de selectores de botones y contenido SVG personalizado correspondiente
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) {
// Ocultar temporalmente el botón mientras reemplazamos el icono
button.style.display = "none";
// Buscar el SVG existente dentro del botón
const oldIcon = button.querySelector("svg");
if (oldIcon) {
// Eliminar el icono existente (SVG)
oldIcon.remove();
}
// Crear un nuevo elemento SVG y establecer su contenido
const newIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
newIcon.innerHTML = icon.newSVG; // Establecer el contenido SVG personalizado
// Insertar el nuevo icono SVG dentro del botón
button.insertBefore(newIcon, button.firstChild);
// Mostrar el botón de nuevo después de reemplazar el icono
button.style.display = "block";
}
});
});
</script>
¡Sí, tienes razón! Esto no es muy estable. ¿Quizás podría ser más estable con requestAnimationFrame o MutationObserver? pero sí, lo mejor sería una API dedicada como mencionaste.
Gracias por señalarlo; tienes toda la razón. Usar solo api.onPageChange puede ser poco fiable, ya que se activa al cambiar de ruta, no después de que el DOM se haya renderizado. Esto significa que existe el riesgo de una condición de carrera en la que el botón #create-topic podría no existir todavía cuando el script intente acceder a él.
api.onPageChange(() => {
const targetSelector = "#create-topic";
const tryEnhanceButton = () => {
const button = document.querySelector(targetSelector);
if (button) {
// Desconectar el observador después de encontrar el elemento
observer.disconnect();
// Ocultar temporalmente el botón mientras reemplazamos el icono
button.style.display = "none";
// Eliminar el icono antiguo si existe
const oldIcon = button.querySelector("svg");
if (oldIcon) oldIcon.remove();
// Crear e insertar el nuevo icono SVG de 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);
// Volver a mostrar el botón
button.style.display = "block";
}
};
// Observar los cambios en el DOM e intentar mejorar el botón cuando se añada
const observer = new MutationObserver(() => tryEnhanceButton());
observer.observe(document.body, { childList: true, subtree: true });
// Intentar inmediatamente también en caso de que ya esté allí
tryEnhanceButton();
});
@Don He incluido MutationObserver para asegurar que el script solo se ejecute una vez que el elemento objetivo exista realmente, y se desconecta después de hacer su trabajo para evitar sobrecarga innecesaria. Aún así, intenta una comprobación inmediata en caso de que el elemento ya exista.
No puedo obtener el SVG que quiero del sistema de iconos de Discourse, aunque lo registré en el subconjunto de iconos SVG de administrador, ya que parece estar en fontawesome pero no en discourse.