[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"article-mutation-observer-dom-change-detection":32,"code:js:true:fyhxgn":216,"code:js:true:1aj2eht":217,"code:js:true:1axlznm":218,"code:js:true:1971hew":219,"code:js:true:1o0qsoa":220},[4,20],{"id":5,"slug":6,"name":7,"tagline":8,"description":9,"accentFrom":10,"accentTo":11,"icon":12,"defaultLocale":13,"locales":14,"features":16,"position":19},"019fe637-3d33-714b-b57f-23e163ffca0c","dev","Web Development","Build. Learn. Ship.","Practical courses, engineering-grade articles and open-source tools for people who ship.","violet-500","cyan-400","◇","en",[13,15],"fa",{"courses":17,"paths":17,"articles":17,"exams":18,"flashcards":18,"packages":17,"community":17,"certificates":17,"teams":17,"commerce":17},true,false,0,{"id":21,"slug":22,"name":23,"tagline":24,"description":25,"accentFrom":26,"accentTo":10,"icon":27,"defaultLocale":13,"locales":28,"features":30,"position":31},"019fe637-3dc2-754c-8657-0f175bfee7c6","lang","Languages","Learn a language the way you learn a codebase.","Structured paths, listening drills and spaced repetition that actually sticks.","amber-400","⌘",[13,15,29],"es",{"courses":17,"paths":17,"articles":18,"exams":18,"flashcards":18,"packages":18,"community":17,"certificates":18,"teams":18,"commerce":17},2,{"id":33,"slug":34,"title":35,"subtitle":36,"excerpt":37,"coverUrl":38,"locale":13,"readingMinutes":39,"publishedAt":40,"viewCount":41,"likeCount":19,"commentCount":19,"author":42,"vertical":47,"topic":48,"tags":51,"_count":63,"playground":65,"body":67,"bodyMd":198,"seo":199,"translationGroupId":203,"thread":204,"assessments":206,"translations":212,"quiz":214},"019ff19b-f68d-77ea-9a2c-70e14c5c7a05","mutation-observer-dom-change-detection","You're polling setInterval to detect DOM changes. `MutationObserver` fires when they happen.",null,"Watching for DOM mutations with setInterval or custom event dispatch is fragile and imprecise. The MutationObserver API delivers a callback exactly when attributes, text content, or child elements change — with full control over which types of mutations you watch.","\u002Fmedia\u002Fcovers\u002Fmutation-observer-dom-change-detection.png",4,"2026-08-11T15:48:01.781Z",113,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":49,"name":50},"javascript","JavaScript",[52,54,57,60],{"slug":49,"name":53,"color":36},"Javascript",{"slug":55,"name":56,"color":36},"webdev","Webdev",{"slug":58,"name":59,"color":36},"frontend","Frontend",{"slug":61,"name":62,"color":36},"dom","Dom",{"assessments":64},1,{"slug":34,"title":66},"MutationObserver — interactive playground",{"blocks":68,"version":64},[69,73,77,83,86,89,92,96,99,103,106,109,112,115,119,122,126,129,132,135,142,145,148,151,154,157,160,163,166,169,172,175,178,181,184,187,190],{"id":70,"html":71,"type":72},"b1","\u003Cp>The DOM can change in ways your code didn&#39;t trigger — a third-party widget injects a node, a library adds a class, a rich text editor updates its content. The common response is polling: \u003Ccode>setInterval(() =&gt; checkIfThingChanged(), 100)\u003C\u002Fcode>. It works until it doesn&#39;t. You tune the interval, miss changes that happen between ticks, and pay CPU cost whether anything changes or not. \u003Ccode>MutationObserver\u003C\u002Fcode> is the built-in answer.\u003C\u002Fp>","paragraph",{"id":74,"html":75,"text":75,"type":76,"level":31},"b2","The API","heading",{"id":78,"code":79,"type":80,"language":81,"highlight":82},"b3","const observer = new MutationObserver((mutations) => {\n  for (const mutation of mutations) {\n    console.log(mutation.type);         \u002F\u002F 'attributes' | 'characterData' | 'childList'\n    console.log(mutation.target);       \u002F\u002F the node that changed\n    console.log(mutation.addedNodes);   \u002F\u002F NodeList (for childList mutations)\n    console.log(mutation.oldValue);     \u002F\u002F previous value (if requested)\n  }\n});\n\nobserver.observe(document.getElementById('app'), {\n  childList: true,              \u002F\u002F watch for added\u002Fremoved child nodes\n  subtree: true,                \u002F\u002F include all descendants, not just direct children\n  attributes: true,             \u002F\u002F watch attribute changes\n  characterData: true,          \u002F\u002F watch text node content changes\n  attributeOldValue: true,      \u002F\u002F record the previous attribute value\n  characterDataOldValue: true,  \u002F\u002F record the previous text content\n});\n\n\u002F\u002F Stop watching:\nobserver.disconnect();","code","js",[],{"id":84,"html":85,"type":72},"b4","\u003Cp>Two steps: create an observer with a callback, then call \u003Ccode>.observe(node, options)\u003C\u002Fcode>. The callback fires asynchronously after a batch of mutations completes — never mid-update — with an array of \u003Ccode>MutationRecord\u003C\u002Fcode> objects, one per change.\u003C\u002Fp>",{"id":87,"html":88,"text":88,"type":76,"level":31},"b5","What it replaces",{"id":90,"html":91,"type":72},"b6","\u003Cp>Here&#39;s the typical &quot;wait for a class to appear&quot; pattern using an interval:\u003C\u002Fp>",{"id":93,"code":94,"type":80,"language":81,"highlight":95},"b7","\u002F\u002F Before — fragile, always running\nlet seen = false;\nconst timer = setInterval(() => {\n  const el = document.querySelector('.widget-loaded');\n  if (el && !seen) {\n    seen = true;\n    clearInterval(timer);\n    initWidget(el);\n  }\n}, 50);",[],{"id":97,"html":98,"type":72},"b8","\u003Cp>The 50 ms interval means you catch changes up to 50 ms late, it burns CPU on every tick even when nothing is happening, and if you forget to \u003Ccode>clearInterval\u003C\u002Fcode>, it runs indefinitely. With \u003Ccode>MutationObserver\u003C\u002Fcode>:\u003C\u002Fp>",{"id":100,"code":101,"type":80,"language":81,"highlight":102},"b9","\u002F\u002F After — fires immediately when the node appears\nconst observer = new MutationObserver(() => {\n  const el = document.querySelector('.widget-loaded');\n  if (el) {\n    observer.disconnect();\n    initWidget(el);\n  }\n});\n\nobserver.observe(document.body, { childList: true, subtree: true });",[],{"id":104,"html":105,"type":72},"b10","\u003Cp>No timer, no polling overhead, no missed windows.\u003C\u002Fp>",{"id":107,"html":108,"text":108,"type":76,"level":31},"b11","Real-world use cases",{"id":110,"html":111,"type":72},"b12","\u003Cp>\u003Cstrong>Third-party widget lifecycle.\u003C\u002Fstrong> When you embed a chat widget or payment form from a third party, you have no hook into when it finishes rendering. \u003Ccode>MutationObserver\u003C\u002Fcode> on the container gives you that hook without touching the third-party script.\u003C\u002Fp>",{"id":113,"html":114,"type":72},"b13","\u003Cp>\u003Cstrong>Auto-resizing a textarea.\u003C\u002Fstrong> The \u003Ccode>input\u003C\u002Fcode> event doesn&#39;t fire on programmatic changes. Observing \u003Ccode>characterData\u003C\u002Fcode> on the textarea&#39;s text node catches every content change regardless of source:\u003C\u002Fp>",{"id":116,"code":117,"type":80,"language":81,"highlight":118},"b14","function autoResize(textarea) {\n  const resize = () => {\n    textarea.style.height = 'auto';\n    textarea.style.height = `${textarea.scrollHeight}px`;\n  };\n\n  resize();\n\n  const observer = new MutationObserver(resize);\n  observer.observe(textarea, { characterData: true, subtree: true });\n  textarea.addEventListener('input', resize);\n\n  return () => observer.disconnect();\n}",[],{"id":120,"html":121,"type":72},"b15","\u003Cp>\u003Cstrong>Accessible live announcements.\u003C\u002Fstrong> Screen readers miss DOM updates that don&#39;t go through an \u003Ccode>aria-live\u003C\u002Fcode> region. A \u003Ccode>MutationObserver\u003C\u002Fcode> on a dynamic feed can forward new content to an announcer element, making additions audible without a framework:\u003C\u002Fp>",{"id":123,"code":124,"type":80,"language":81,"highlight":125},"b16","const announcer = document.getElementById('sr-announcer'); \u002F\u002F aria-live=\"polite\"\n\nconst observer = new MutationObserver((mutations) => {\n  for (const mutation of mutations) {\n    for (const node of mutation.addedNodes) {\n      if (node.textContent?.trim()) {\n        announcer.textContent = node.textContent.trim();\n      }\n    }\n  }\n});\n\nobserver.observe(document.getElementById('feed'), { childList: true });",[],{"id":127,"html":128,"text":128,"type":76,"level":31},"b17","Batching and performance",{"id":130,"html":131,"type":72},"b18","\u003Cp>\u003Ccode>MutationObserver\u003C\u002Fcode> delivers changes in batches. If a loop adds 500 nodes in one synchronous operation, you get one callback with 500 records — not 500 callbacks. This is intentional: the observer is low-overhead even on large, active DOM trees.\u003C\u002Fp>",{"id":133,"html":134,"type":72},"b19","\u003Cp>A few things to keep in mind:\u003C\u002Fp>",{"id":136,"type":137,"items":138,"ordered":18},"b20","list",[139,140,141],"\u003Cstrong>Narrow the target.\u003C\u002Fstrong> Observing \u003Ccode>document.body\u003C\u002Fcode> with \u003Ccode>subtree: true\u003C\u002Fcode> watches every node in the page. Prefer the smallest relevant container.","\u003Cstrong>Always disconnect.\u003C\u002Fstrong> The observer holds a reference to the target node, which can delay garbage collection. Call \u003Ccode>observer.disconnect()\u003C\u002Fcode> when you&#39;re done.","\u003Cstrong>\u003Ccode>takeRecords()\u003C\u002Fcode> for early cleanup.\u003C\u002Fstrong> This flushes any pending, undelivered records synchronously — useful when you need to process remaining mutations before disconnecting without waiting for the next callback.",{"id":143,"html":144,"text":144,"type":76,"level":31},"b21","Browser support",{"id":146,"html":147,"type":72},"b22","\u003Cp>\u003Ccode>MutationObserver\u003C\u002Fcode> is \u003Cstrong>Baseline 2015\u003C\u002Fstrong>: Chrome 26 (2013), Firefox 14 (2012), Safari 7 (2013). It has shipped in every major browser and runtime for over a decade, including Web Workers.\u003C\u002Fp>",{"id":149,"html":150,"type":72},"b23","\u003C!-- playground:start -->",{"id":152,"html":153,"text":153,"type":76,"level":31},"b24","🎮 Try it yourself",{"id":155,"html":156,"type":72},"b25","\u003Cp>\u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-08-11-mutation-observer-dom-change-detection\u002Fplayground\u002F\">▶️ Open the interactive playground →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":158,"html":159,"type":72},"b26","\u003Cp>\u003Cem>Runs right in your browser — poke at it and watch the concept react live.\u003C\u002Fem>\u003C\u002Fp>",{"id":161,"html":162,"type":72},"b27","\u003C!-- playground:end -->",{"id":164,"html":165,"type":72},"b28","\u003C!-- quiz:start -->",{"id":167,"html":168,"text":168,"type":76,"level":31},"b29","🧠 Test yourself",{"id":170,"html":171,"type":72},"b30","\u003Cp>Think it clicked? \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-08-11-mutation-observer-dom-change-detection\">Take the 9-question quiz →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":173,"html":174,"type":72},"b31","\u003Cp>\u003Cem>Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.\u003C\u002Fem>\u003C\u002Fp>",{"id":176,"html":177,"type":72},"b32","\u003C!-- quiz:end -->",{"id":179,"html":180,"text":180,"type":76,"level":31},"b33","The takeaway",{"id":182,"html":183,"type":72},"b34","\u003Cp>Search your codebase for \u003Ccode>setInterval\u003C\u002Fcode> calls that check a DOM condition and clear themselves once it&#39;s true — that&#39;s polling for a DOM change. \u003Ccode>MutationObserver\u003C\u002Fcode> replaces the pattern with a callback that fires the moment the change occurs, with zero cost in between. It completes the browser&#39;s built-in observer trio: \u003Ccode>IntersectionObserver\u003C\u002Fcode> for element visibility, \u003Ccode>ResizeObserver\u003C\u002Fcode> for element size, and \u003Ccode>MutationObserver\u003C\u002Fcode> for everything the DOM itself changes. Once you know all three, most &quot;watch the DOM&quot; problems reduce to picking the right one.\u003C\u002Fp>",{"id":185,"type":186},"b35","divider",{"id":188,"html":189,"type":72},"b36","\u003Cp>\u003Cem>Thanks for reading! Let&#39;s stay connected:\u003C\u002Fem>\u003C\u002Fp>",{"id":191,"type":137,"items":192,"ordered":18},"b37",[193,194,195,196,197],"⭐ \u003Cstrong>GitHub\u003C\u002Fstrong> — follow me and star the projects: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fparsajiravand\">github.com\u002Fparsajiravand\u003C\u002Fa>","💬 \u003Cstrong>Discord\u003C\u002Fstrong> — join the frontend best-practices community: \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ\">discord.gg\u002Fd9KRhuAwQ\u003C\u002Fa>","📸 \u003Cstrong>Instagram\u003C\u002Fstrong> — frontend best practices, daily: \u003Ca href=\"https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F\">@bestpractice___\u003C\u002Fa>","💼 \u003Cstrong>LinkedIn\u003C\u002Fstrong> — \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F\">linkedin.com\u002Fin\u002Fparsa-jiravand\u003C\u002Fa>","✉️ \u003Cstrong>Email\u003C\u002Fstrong> (work &amp; contract inquiries): \u003Ca href=\"mailto:bestpractice2026@gmail.com\">bestpractice2026@gmail.com\u003C\u002Fa>","The DOM can change in ways your code didn't trigger — a third-party widget injects a node, a library adds a class, a rich text editor updates its content. The common response is polling: `setInterval(() => checkIfThingChanged(), 100)`. It works until it doesn't. You tune the interval, miss changes that happen between ticks, and pay CPU cost whether anything changes or not. `MutationObserver` is the built-in answer.\n\n## The API\n\n```js\nconst observer = new MutationObserver((mutations) => {\n  for (const mutation of mutations) {\n    console.log(mutation.type);         \u002F\u002F 'attributes' | 'characterData' | 'childList'\n    console.log(mutation.target);       \u002F\u002F the node that changed\n    console.log(mutation.addedNodes);   \u002F\u002F NodeList (for childList mutations)\n    console.log(mutation.oldValue);     \u002F\u002F previous value (if requested)\n  }\n});\n\nobserver.observe(document.getElementById('app'), {\n  childList: true,              \u002F\u002F watch for added\u002Fremoved child nodes\n  subtree: true,                \u002F\u002F include all descendants, not just direct children\n  attributes: true,             \u002F\u002F watch attribute changes\n  characterData: true,          \u002F\u002F watch text node content changes\n  attributeOldValue: true,      \u002F\u002F record the previous attribute value\n  characterDataOldValue: true,  \u002F\u002F record the previous text content\n});\n\n\u002F\u002F Stop watching:\nobserver.disconnect();\n```\n\nTwo steps: create an observer with a callback, then call `.observe(node, options)`. The callback fires asynchronously after a batch of mutations completes — never mid-update — with an array of `MutationRecord` objects, one per change.\n\n## What it replaces\n\nHere's the typical \"wait for a class to appear\" pattern using an interval:\n\n```js\n\u002F\u002F Before — fragile, always running\nlet seen = false;\nconst timer = setInterval(() => {\n  const el = document.querySelector('.widget-loaded');\n  if (el && !seen) {\n    seen = true;\n    clearInterval(timer);\n    initWidget(el);\n  }\n}, 50);\n```\n\nThe 50 ms interval means you catch changes up to 50 ms late, it burns CPU on every tick even when nothing is happening, and if you forget to `clearInterval`, it runs indefinitely. With `MutationObserver`:\n\n```js\n\u002F\u002F After — fires immediately when the node appears\nconst observer = new MutationObserver(() => {\n  const el = document.querySelector('.widget-loaded');\n  if (el) {\n    observer.disconnect();\n    initWidget(el);\n  }\n});\n\nobserver.observe(document.body, { childList: true, subtree: true });\n```\n\nNo timer, no polling overhead, no missed windows.\n\n## Real-world use cases\n\n**Third-party widget lifecycle.** When you embed a chat widget or payment form from a third party, you have no hook into when it finishes rendering. `MutationObserver` on the container gives you that hook without touching the third-party script.\n\n**Auto-resizing a textarea.** The `input` event doesn't fire on programmatic changes. Observing `characterData` on the textarea's text node catches every content change regardless of source:\n\n```js\nfunction autoResize(textarea) {\n  const resize = () => {\n    textarea.style.height = 'auto';\n    textarea.style.height = `${textarea.scrollHeight}px`;\n  };\n\n  resize();\n\n  const observer = new MutationObserver(resize);\n  observer.observe(textarea, { characterData: true, subtree: true });\n  textarea.addEventListener('input', resize);\n\n  return () => observer.disconnect();\n}\n```\n\n**Accessible live announcements.** Screen readers miss DOM updates that don't go through an `aria-live` region. A `MutationObserver` on a dynamic feed can forward new content to an announcer element, making additions audible without a framework:\n\n```js\nconst announcer = document.getElementById('sr-announcer'); \u002F\u002F aria-live=\"polite\"\n\nconst observer = new MutationObserver((mutations) => {\n  for (const mutation of mutations) {\n    for (const node of mutation.addedNodes) {\n      if (node.textContent?.trim()) {\n        announcer.textContent = node.textContent.trim();\n      }\n    }\n  }\n});\n\nobserver.observe(document.getElementById('feed'), { childList: true });\n```\n\n## Batching and performance\n\n`MutationObserver` delivers changes in batches. If a loop adds 500 nodes in one synchronous operation, you get one callback with 500 records — not 500 callbacks. This is intentional: the observer is low-overhead even on large, active DOM trees.\n\nA few things to keep in mind:\n\n- **Narrow the target.** Observing `document.body` with `subtree: true` watches every node in the page. Prefer the smallest relevant container.\n- **Always disconnect.** The observer holds a reference to the target node, which can delay garbage collection. Call `observer.disconnect()` when you're done.\n- **`takeRecords()` for early cleanup.** This flushes any pending, undelivered records synchronously — useful when you need to process remaining mutations before disconnecting without waiting for the next callback.\n\n## Browser support\n\n`MutationObserver` is **Baseline 2015**: Chrome 26 (2013), Firefox 14 (2012), Safari 7 (2013). It has shipped in every major browser and runtime for over a decade, including Web Workers.\n\n\n\u003C!-- playground:start -->\n\n## 🎮 Try it yourself\n\n**[▶️ Open the interactive playground →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-08-11-mutation-observer-dom-change-detection\u002Fplayground\u002F)**\n\n_Runs right in your browser — poke at it and watch the concept react live._\n\n\u003C!-- playground:end -->\n\n\u003C!-- quiz:start -->\n\n## 🧠 Test yourself\n\nThink it clicked? **[Take the 9-question quiz →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-08-11-mutation-observer-dom-change-detection)**\n\n_Instant feedback, a hint on every question, and an explanation for each answer — right or wrong._\n\n\u003C!-- quiz:end -->\n## The takeaway\n\nSearch your codebase for `setInterval` calls that check a DOM condition and clear themselves once it's true — that's polling for a DOM change. `MutationObserver` replaces the pattern with a callback that fires the moment the change occurs, with zero cost in between. It completes the browser's built-in observer trio: `IntersectionObserver` for element visibility, `ResizeObserver` for element size, and `MutationObserver` for everything the DOM itself changes. Once you know all three, most \"watch the DOM\" problems reduce to picking the right one.\n\n---\n\n*Thanks for reading! Let's stay connected:*\n\n- ⭐ **GitHub** — follow me and star the projects: [github.com\u002Fparsajiravand](https:\u002F\u002Fgithub.com\u002Fparsajiravand)\n- 💬 **Discord** — join the frontend best-practices community: [discord.gg\u002Fd9KRhuAwQ](https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ)\n- 📸 **Instagram** — frontend best practices, daily: [@bestpractice___](https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F)\n- 💼 **LinkedIn** — [linkedin.com\u002Fin\u002Fparsa-jiravand](https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F)\n- ✉️ **Email** (work & contract inquiries): [bestpractice2026@gmail.com](mailto:bestpractice2026@gmail.com)",{"title":200,"canonical":201,"description":202},"You're polling setInterval to detect DOM changes. `MutationObserver` f","https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fmutation-observer-dom-change-detection","Watching for DOM mutations with setInterval or custom event dispatch is fragile and imprecise. The MutationObserver API delivers a callback exactly when attributes, text content, o","019ff19b-f68d-77ea-9a2c-7638a5552195",{"id":205,"locked":18},"019ff19b-f6a7-740e-82a3-f42d6837c361",[207],{"id":208,"slug":34,"title":209,"_count":210},"019ff19b-f6c2-7399-adec-2ec63e233f15","MutationObserver — DOM change detection",{"questions":211},9,[213],{"locale":13,"slug":34},{"id":208,"slug":34,"title":209,"_count":215,"questionCount":211},{"questions":211},"\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003Cdiv>13\u003C\u002Fdiv>\u003Cdiv>14\u003C\u002Fdiv>\u003Cdiv>15\u003C\u002Fdiv>\u003Cdiv>16\u003C\u002Fdiv>\u003Cdiv>17\u003C\u002Fdiv>\u003Cdiv>18\u003C\u002Fdiv>\u003Cdiv>19\u003C\u002Fdiv>\u003Cdiv>20\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> observer \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">MutationObserver\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>mutations\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">for\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> mutation \u003Cspan class=\"shj-kwd\">of\u003C\u002Fspan> mutations\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    console\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>mutation\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>type\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;         \u003Cspan class=\"shj-cmnt\">\u002F\u002F 'attributes' | 'characterData' | 'childList'\n\u003C\u002Fspan>    console\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>mutation\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>target\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;       \u003Cspan class=\"shj-cmnt\">\u002F\u002F the node that changed\n\u003C\u002Fspan>    console\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>mutation\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>addedNodes\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;   \u003Cspan class=\"shj-cmnt\">\u002F\u002F NodeList (for childList mutations)\n\u003C\u002Fspan>    console\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>mutation\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>oldValue\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;     \u003Cspan class=\"shj-cmnt\">\u002F\u002F previous value (if requested)\n\u003C\u002Fspan>  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\nobserver\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">observe\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getElementById\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'app'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  childList\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>              \u003Cspan class=\"shj-cmnt\">\u002F\u002F watch for added\u002Fremoved child nodes\n\u003C\u002Fspan>  subtree\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>                \u003Cspan class=\"shj-cmnt\">\u002F\u002F include all descendants, not just direct children\n\u003C\u002Fspan>  attributes\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>             \u003Cspan class=\"shj-cmnt\">\u002F\u002F watch attribute changes\n\u003C\u002Fspan>  characterData\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>          \u003Cspan class=\"shj-cmnt\">\u002F\u002F watch text node content changes\n\u003C\u002Fspan>  attributeOldValue\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>      \u003Cspan class=\"shj-cmnt\">\u002F\u002F record the previous attribute value\n\u003C\u002Fspan>  characterDataOldValue\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>  \u003Cspan class=\"shj-cmnt\">\u002F\u002F record the previous text content\n\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F Stop watching:\n\u003C\u002Fspan>observer\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">disconnect\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F Before — fragile, always running\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">let\u003C\u002Fspan> seen \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">false\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> timer \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-func\">setInterval\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> el \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">querySelector\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'.widget-loaded'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-kwd\">if\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>el \u003Cspan class=\"shj-oper\">&#38;&#38;\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">!\u003C\u002Fspan>seen\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    seen \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>;\n    \u003Cspan class=\"shj-func\">clearInterval\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>timer\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n    \u003Cspan class=\"shj-func\">initWidget\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>el\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">50\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F After — fires immediately when the node appears\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> observer \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">MutationObserver\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> el \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">querySelector\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'.widget-loaded'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-kwd\">if\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>el\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    observer\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">disconnect\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n    \u003Cspan class=\"shj-func\">initWidget\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>el\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\nobserver\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">observe\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>body\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> childList\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> subtree\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003Cdiv>13\u003C\u002Fdiv>\u003Cdiv>14\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">function\u003C\u002Fspan> \u003Cspan class=\"shj-func\">autoResize\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>textarea\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-func\">resize\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    textarea\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>style\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>height \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'auto'\u003C\u002Fspan>;\n    textarea\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>style\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>height \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-str\">`\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">${\u003C\u002Fspan>textarea\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>scrollHeight\u003Cspan class=\"shj-kwd\">}\u003C\u002Fspan>\u003Cspan class=\"shj-str\">px`\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>;\n\n  \u003Cspan class=\"shj-func\">resize\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> observer \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">MutationObserver\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>resize\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  observer\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">observe\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>textarea\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> characterData\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> subtree\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  textarea\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">addEventListener\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'input'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> resize\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\n  \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> observer\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">disconnect\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003Cdiv>13\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> announcer \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getElementById\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'sr-announcer'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F aria-live=\"polite\"\n\u003C\u002Fspan>\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> observer \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">MutationObserver\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>mutations\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">for\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> mutation \u003Cspan class=\"shj-kwd\">of\u003C\u002Fspan> mutations\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    \u003Cspan class=\"shj-kwd\">for\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> node \u003Cspan class=\"shj-kwd\">of\u003C\u002Fspan> mutation\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>addedNodes\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n      \u003Cspan class=\"shj-kwd\">if\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>node\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>textContent\u003Cspan class=\"shj-oper\">?.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">trim\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n        announcer\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>textContent \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> node\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>textContent\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">trim\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n      \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n    \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\nobserver\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">observe\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getElementById\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'feed'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> childList\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>"]