watch-options.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. /*!
  2. * (C) Ionic http://ionicframework.com - MIT License
  3. */
  4. const watchForOptions = (containerEl, tagName, onChange) => {
  5. if (typeof MutationObserver === 'undefined') {
  6. return;
  7. }
  8. const mutation = new MutationObserver((mutationList) => {
  9. onChange(getSelectedOption(mutationList, tagName));
  10. });
  11. mutation.observe(containerEl, {
  12. childList: true,
  13. subtree: true,
  14. });
  15. return mutation;
  16. };
  17. const getSelectedOption = (mutationList, tagName) => {
  18. let newOption;
  19. mutationList.forEach((mut) => {
  20. // eslint-disable-next-line @typescript-eslint/prefer-for-of
  21. for (let i = 0; i < mut.addedNodes.length; i++) {
  22. newOption = findCheckedOption(mut.addedNodes[i], tagName) || newOption;
  23. }
  24. });
  25. return newOption;
  26. };
  27. /**
  28. * The "value" key is only set on some components such as ion-select-option.
  29. * As a result, we create a default union type of HTMLElement and the "value" key.
  30. * However, implementers are required to provide the appropriate component type
  31. * such as HTMLIonSelectOptionElement.
  32. */
  33. const findCheckedOption = (node, tagName) => {
  34. /**
  35. * https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
  36. * The above check ensures "node" is an Element (nodeType 1).
  37. */
  38. if (node.nodeType !== 1) {
  39. return undefined;
  40. }
  41. // HTMLElement inherits from Element, so we cast "el" as T.
  42. const el = node;
  43. const options = el.tagName === tagName.toUpperCase() ? [el] : Array.from(el.querySelectorAll(tagName));
  44. return options.find((o) => o.value === el.value);
  45. };
  46. export { watchForOptions as w };