4
\$\begingroup\$

I mostly just want to make sure I've understood the specs correctly with this code, but here goes:

var nums = document.getElementsByTagName('x-number');
var observer = new MutationObserver(replaceNumerics);
var config = { childList: true, subtree: true };
observer.observe(document.body, config);
replaceNumerics(); // initial load
function replaceNumerics() {
 var l = nums.length, i, span;
 for( i=l-1; i>=0; i--) { // node list is live so iterate backwards
 span = document.createElement('span');
 span.classList.add("x-number");
 span.textContent = parseFloat(nums[i].textContent).toLocaleString();
 nums[i].parentNode.replaceChild(span,nums[i]);
 }
}

The idea is to have a custom <x-number> tag that contains... a number, obviously. JavaScript will detect these tags, parse out the number, then render it according to the user's locale. I'm planning to do a similar thing for dates, which will be especially useful since <input type="date" /> already uses the user's locale.

My biggest concern is I think this will result in an infinite loop, as the replaceChild call will fire the MutationObserver again... but if I understand the spec correctly, this second firing will only happen if and when all <x-number> elements have been replaced (as opposed to the earlier DOMSubtreeModified event which would fire immediately), at which point there would be no more <x-number> elements to replace and the loop would end.

Honestly this is all very unfamiliar territory to me, but I believe this should work fine... But I figured I'd subject it to public opinion before going any further with it.

asked Sep 5, 2016 at 22:48
\$\endgroup\$
8
  • \$\begingroup\$ Have you tested your code to see if it actually works or not? \$\endgroup\$ Commented Sep 5, 2016 at 23:00
  • \$\begingroup\$ Yes, and it seems to work. But a lot of stuff I write "seems to work" :D \$\endgroup\$ Commented Sep 5, 2016 at 23:02
  • \$\begingroup\$ There won't be an infinite loop because you iterate over the custom tags only, so even though the observer callback will be invoked after modification it'll do nothing, and won't trigger subsequent invocation. \$\endgroup\$ Commented Sep 6, 2016 at 8:59
  • \$\begingroup\$ @wOxxOm And that's because the custom tags are removed in the process, so there's none left when it runs the second time, right? \$\endgroup\$ Commented Sep 6, 2016 at 9:04
  • \$\begingroup\$ Just remembered that getElementsByTagName is a live list, so removing the elements in the loop will not work as intended unless I iterate backwards... \$\endgroup\$ Commented Sep 6, 2016 at 9:10

1 Answer 1

3
\$\begingroup\$

One issue I'm seeing is that you're listening to the entire tree. While not an issue in small apps, it might be an issue for huge apps, with deep trees. Consider limiting it to the places where you expect your custom tag will exist.

If you are in control of the process of adding these elements to the DOM, consider doing this transformation there instead of listening to the entire DOM for you to change it. It will be easier to debug since the transformation is involved in the process of generating that element, instead of an indirect side-effect of some other operation.

You know that feeling when someone else's JavaScript re-arranges the HTML you rendered on the backend and you had to hunt it down? Same story.

answered Sep 6, 2016 at 23:36
\$\endgroup\$
2
  • \$\begingroup\$ One could argue that for huge trees this approach isn't going to scale up either way and OP would be best off leveraging something like Vue or Polymer and creating custom elements. Scanning the tree, as you mention, will cause huge performance issues. \$\endgroup\$ Commented Sep 7, 2016 at 6:45
  • \$\begingroup\$ I do like to keep the DOM tree relatively simple, but I can certainly see the potential for issues here. The main reason for the Observer at all is to avoid hooking into jQuery's .html(), but come to think of it I could extend my AJAX setup to handle the replacements in the returned data. You've certainly given me some options to think about. Thank you. (Also, I'm the only dev on this project, and an appropriate tag choice and documentation should make this a non-issue if I ever hire another dev) \$\endgroup\$ Commented Sep 7, 2016 at 10:43

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.