Calculator: How to add search for dropdowns with long option lists

Want to make searching the long lists of the dropdown fields in your Calculator widget simpler? We’ve got a solution!

Add this code to the Custom JS field on the Settings tab of your widget’s settings and the search will appear in dropdowns with more than 12 options:

const listenerBlock = (selector, callback) => {
  const uniqueBlocks = new Set();

  const initialTargetNode = document.querySelector(selector);
  if (initialTargetNode && !uniqueBlocks.has(initialTargetNode)) {
    uniqueBlocks.add(initialTargetNode);
    callback(initialTargetNode);
  }

  const mutationObserver = new MutationObserver((mutations, observer) => {
    for (const mutation of mutations) {
      for (const node of mutation.addedNodes) {
        if (node.nodeType === Node.ELEMENT_NODE) {
          const targetNode = node.querySelector(selector);
          if (targetNode && !uniqueBlocks.has(targetNode)) {
            uniqueBlocks.add(targetNode);
            observer.disconnect();
            callback(targetNode);
          }
        }
      }
    }
  });

  mutationObserver.observe(document.body, {
    childList: true,
    subtree: true
  });
};

const createInput = (placeholder) => {
  const input = document.createElement('input');
  input.type = 'text';
  input.placeholder = placeholder;

  input.style.cssText = `
    width: calc(100% - 24px) !important;
    box-sizing: border-box !important;
    padding: 10px 29px 10px 15px !important;
    margin: 0px 12px !important;
    border: 1px solid rgba(17, 17, 17, 0.6) !important;
    border-radius: 4px !important;
    position: fixed  !important;
    top: 10px !important;
    left: 0 !important;
    background: inherit !important;
    z-index: 2 !important;
	`;

  return input;
};

listenerBlock('[class*="form__Container-sc"]', (formContainer) => {
  const dropdowns = formContainer.querySelectorAll(
    '[class*="dropdown__Container-sc"]'
  );

  for (const dropdown of dropdowns) {
    const mutationObserver = new MutationObserver(([{ addedNodes }]) => {
      if (addedNodes.length) {
        const container = addedNodes[0];
        const dropdownContainer = container.querySelector(
          '[class*="Dropdown__DropdownContainer-sc"]'
        );

        const withFilters = dropdownContainer.childNodes.length > 12;

        if (withFilters) {
          const filter = createInput('Search...');
          dropdownContainer.prepend(filter);

          dropdownContainer.style.position = 'relative';
          dropdownContainer.style.paddingTop = '60px';

          filter.addEventListener('input', (e) => {
            const value = e.target.value.trim();

            if (value) {
              dropdownContainer.childNodes.forEach((node) => {
                if (node.nodeName === 'INPUT') {
                  return;
                }

                const isTarget = node.textContent
                  .toLowerCase()
                  .includes(value.toLowerCase());

                if (isTarget) {
                  node.style.display = 'flex';
                } else {
                  node.style.display = 'none';
                }
              });
            } else {
              dropdownContainer.childNodes.forEach((node) => {
                if (node.nodeName === 'INPUT') {
                  return;
                }

                return (node.style.display = 'flex');
              });
            }
          });
        }
      }
    });

    mutationObserver.observe(dropdown, { childList: true });
  }
});

Watch this video to see the code in action:


Note: Custom JS doesn’t function in the preview mode, so you can check the result right on your website or through the Share Link


Guys, was this solution helpful? Let us know in the comments :slightly_smiling_face:

3 Likes

Wow, this is super helpful! :grinning_face_with_smiling_eyes: The search for long dropdowns makes things way easier. Thanks for sharing the code and the explanation — definitely going to try it out on my widget!

3 Likes

Hey there and welcome to the Community, @user29397 :waving_hand:

Happy to see you’ve found this solution helpful - many thanks for sharing your feedback with us :heart: