The chat with emotes
A chat message arrives in parts: text, emotes and cheer images. Widget.dom.renderMessage turns them
into a fragment ready to append, with emotes as <img> and text as text.
{ "events": ["Twitch.ChatMessage", "Twitch.ChatMessageDeleted"], "strings": { "es": {}, "en": {} }, "menu": { "sections": [ { "id": "chat", "title": { "es": "Chat", "en": "Chat" }, "fields": [ { "type": "number", "id": "maxMessages", "param": "maxMessages", "label": { "es": "Máximo de mensajes", "en": "Maximum messages" }, "default": 20, "min": 1, "max": 100, "step": 1 } ] } ] }}<div id="chat"></div>html,body { margin: 0; background: transparent;}
#chat { position: absolute; inset: auto 0 0 0; padding: 16px; font: 600 28px system-ui, sans-serif; color: #ffffff;}
.message { margin-top: 8px;}
.message img { height: 1.2em; vertical-align: middle;}const chat = document.querySelector("#chat");const maxMessages = Widget.parameters.int("maxMessages", 20);
Widget.on("Twitch.ChatMessage", (message) => { const row = document.createElement("div"); row.className = "message"; row.dataset.messageId = message.messageId;
const name = document.createElement("strong"); Widget.dom.text(name, message.user);
const text = document.createElement("span"); text.append(Widget.dom.renderMessage(message.parts));
row.append(name, " ", text); chat.append(row);
while (chat.children.length > maxMessages) chat.firstElementChild.remove();});
Widget.on("Twitch.ChatMessageDeleted", ({ messageId }) => { for (const row of chat.querySelectorAll(".message")) { if (row.dataset.messageId === messageId) row.remove(); }});How it works
Section titled “How it works”message.partsalready carries the message split up; there is nothing to parse by hand. Emote images only show if they are from an allowed CDN.- The name goes through
Widget.dom.text, neverinnerHTML: a name with HTML cannot sneak elements in. - The
whileloop caps the number of messages. Without it, a long chat would pile up elements endlessly and run out of memory (runtime_memory). messageIdidentifies each message: when a moderator deletes one,Twitch.ChatMessageDeletedarrives with the same id and you remove it.
Variations
Section titled “Variations”- More platforms:
Kick.ChatMessageandYoutube.Messagecarry the same fields, so the same function works: call it from threeWidget.on. - Name color: the event carries
color(the user’s on their platform):name.style.color = message.color. - Badges:
message.badgesis a list withnameandimageUrl; draw each one withWidget.dom.image(badge.imageUrl, { alt: badge.name }). - The Chat template in “New widget” carries all of this and a full parameter menu.