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.
1 Answer 1
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.
-
\$\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\$Dan– Dan2016年09月07日 06:45:57 +00:00Commented 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\$Niet the Dark Absol– Niet the Dark Absol2016年09月07日 10:43:40 +00:00Commented Sep 7, 2016 at 10:43
Explore related questions
See similar questions with these tags.
getElementsByTagName
is a live list, so removing the elements in the loop will not work as intended unless I iterate backwards... \$\endgroup\$