Hi @Max,
the JS code works for the first dropdown. I have another one. How does the code need to be extended for this?
Hi @Sina
In your 2nd widget you’re using the ID of the 1st widget. So, you just should replace it with the ID of the 2nd widget:
Check it out and let me know if it worked
Hi @Max,
its not a second widget but a second dropdown in a widget.
Sorry, haven’t noticed the 2nd dropdown because of the conditional display!
I’ve passed it on to the devs and will update you once the solution is ready
Thank you for waiting, @Sina
We’ve adjusted the script in your widget and now everything is working fine:
const CUSTOM_SELECT_VALUE = 'Nuance wählen';
const WIDGET_CLASS = 'elfsight-app-95f91737-ccc2-4beb-8a81-cd3641c4f302';
const LISTEN_TYPES = {
one: {
select: (selector, root) => root.querySelector(selector),
validate: (node) => !!node,
},
all: {
select: (selector, root) => root.querySelectorAll(selector),
validate: (node) => node?.length > 0,
},
};
function listenStep(args) {
args.node = args.select(args.selector, args.root);
if (!args.validate(args.node)) {
args.step++;
if (args.step < args.limit)
setTimeout(() => {
listenStep(args);
}, args.delay);
else args.reject();
} else {
args.resolve(args.node);
}
}
async function asyncListenFor(selector, type = 'one', customArgs = {}) {
const args = {
root: document,
node: undefined,
selector,
delay: 100,
limit: 50,
step: 0,
select: LISTEN_TYPES[type].select,
validate: LISTEN_TYPES[type].validate,
...customArgs,
};
if (type === 'one' || type === 'all') {
return new Promise((resolve, reject) => {
listenStep({ ...args, resolve, reject });
});
}
}
const createInput = (placeholder) => {
const input = document.createElement('input');
input.type = 'text';
input.placeholder = placeholder;
input.style.cssText = `
width: calc(98% - 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;
};
const processDropdown = (dropdown) => {
if (dropdown.hasAttribute('data-processed')) {
return;
}
dropdown.setAttribute('data-processed', 'true');
const select = dropdown.querySelector("[class*='dropdown__Select-sc']");
select.textContent = CUSTOM_SELECT_VALUE;
const mutationObserver = new MutationObserver(([{ addedNodes }]) => {
if (addedNodes.length) {
const container = addedNodes[0];
const dropdownContainer = container.querySelector(
'[class*="Dropdown__DropdownContainer-sc"]'
);
const firstValue = dropdownContainer.querySelector(
"[class*='DropdownItem__ItemContainer-sc']:first-child [class*='DropdownItem__Item-sc']"
);
firstValue.textContent = CUSTOM_SELECT_VALUE;
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 });
};
asyncListenFor(`.${WIDGET_CLASS} [class*="form__Container-sc"]`).then((formContainer) => {
const dropdowns = formContainer.querySelectorAll('[class*="dropdown__Container-sc"]');
dropdowns.forEach(processDropdown);
const formObserver = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
setTimeout(function() {
const newDropdowns = node.querySelectorAll('[class*="dropdown__Container-sc"]');
newDropdowns.forEach(processDropdown);
}, 50);
}
});
}
}
});
formObserver.observe(formContainer, { childList: true, subtree: true });
});
Please check your widgets and let me know if it works
Hi @Max
I have the JS code for the translation and a CSS code scrollbar for the options list in the dropdown.
https://community.elfsight.com/t/add-scroll-for-the-options-list-in-the-dropdown/73343?u=sina
How can I set it up so that when I use the dropdown again it automatically scrolls to the already selected value?
Hi there, @Sina
Could you please elaborate on what you mean under “use the dropdown again”?
@Max ok. use the dropdown again to select another value.
this ist selected
and now I want to choose something else
now it should scroll to what is already selected
Got it, thank you!
I’ve forwarded your request to the devs and will let you know once the code is ready
Hi @Sina
Please try to use this code in the Custom JS section and let me know if it worked:
function observeChanges(containerSelector, callback) {
const observer = new MutationObserver((mutations) => {
mutations.forEach(({ addedNodes }) => {
addedNodes.forEach((node) => {
if (
node.nodeType === Node.ELEMENT_NODE &&
(node.matches(containerSelector) || node.querySelector(containerSelector))
) {
callback(node.matches(containerSelector) ? node : node.querySelector(containerSelector));
}
});
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
observeChanges('[class*="Dropdown__DropdownContainer-sc"]', (container) => {
requestAnimationFrame(() => {
const icon = container.querySelector(
'[class*="DropdownItem__ItemContainer-sc"] [class*="Icon__IconContainer-sc"] svg'
);
if (!icon) return;
const selectedItem = icon.closest('[class*="DropdownItem__ItemContainer-sc"]');
if (!selectedItem) return;
const containerRect = container.getBoundingClientRect();
const itemRect = selectedItem.getBoundingClientRect();
if (itemRect.top >= containerRect.top && itemRect.bottom <= containerRect.bottom) return;
container.scrollTo({
top: selectedItem.offsetTop,
behavior: 'auto'
});
});
});
Hi @Max ooohh thank you. Works perfect.
Amazing, you’re always welcome
My goodness, you guys are really good at what you’ve done, and in such a short time. I feel honored. My thanks also to the devs. Please pass them on!!
Wow, thanks a ton for such an amazing feedback
I’ll definitely pass your words to the dev team