There is a Window called “caption” in calculation & fiel where you can add some information. That info is written below the main topic or calculation. You allready tried to minimize that by offering a much smaller text. But it would be way better if people like me could use the “caption” field and the option to hide the text behind a small “info” button like that . Position of that should be behind the main topic/calculation in the right top corner … like m². By tapping or mouse over effect on the info, the text will appear and the whole calc is way easier to read. Looking forward to see it. Dimitri
Hi there, @user23793
Interesting idea, thanks for sharing! If more users support this request, we’ll try to think it over in the future.
As for now, our devs will be happy to create a custom solution for you. I’ve forwarded your request to them and let you know once it’s done
Hi there, @user23793
This code should be added to the Custom JS field on the Settings tab of your widget’s settings:
const INFO_LIST = ['Eigenkapital', 'Monatliche Kosten ⁉️'];
function listener(selector, callback) {
const target = document.querySelector(selector);
if (target) return callback(target);
const observer = new MutationObserver(() => {
const node = document.querySelector(selector);
if (node) {
observer.disconnect();
callback(node);
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
function normalizedString(str) {
return str.toLowerCase().trim();
}
function createElement(tag, options = {}) {
return Object.assign(document.createElement(tag), options);
}
function createInfo(size) {
const container = createElement('div', {
className: 'result-info-container',
style: `
display: flex;
align-items: center;
justify-content: center;
opacity: 0.7;
font-size: ${Math.floor((size * 2) / 3)}px;
width: ${size}px;
height: ${size}px;
border: 1px solid rgb(17, 17, 17);
border-radius: 50%;
`
});
const block = createElement('div', {
className: 'result-info',
textContent: 'i'
});
container.appendChild(block);
return container;
}
function mapResultBlocks(container) {
const resultList = container.querySelectorAll('[class^="result"]');
const map = new Map();
for (const block of resultList) {
const isSecondary = block.className.includes('secondary');
const labelWrapper = (() => {
if (isSecondary) {
return block.querySelector(
'[class*="result-secondary__SecondaryLabel-sc"]'
);
}
return block;
})();
if (!labelWrapper) continue;
const label = labelWrapper.firstElementChild;
const caption = labelWrapper.lastElementChild;
const labelText = label?.textContent;
if (!labelText) continue;
const value = (() => {
if (isSecondary) {
return block.querySelector('[class*="result-secondary__Value-sc"]');
}
return block.querySelector('[class*="result-primary__Value-sc"]');
})();
map.set(normalizedString(labelText), {
label,
container: block,
caption: label === caption ? null : caption,
value,
isSecondary
});
}
return map;
}
function attachHoverBehavior(value, infoSize) {
let isHovering = false;
let isTouched = false;
const { value: valueNode, caption, container, isSecondary } = value;
if (!caption || !valueNode) return;
const info = createInfo(infoSize);
valueNode.appendChild(info);
valueNode.style.display = 'flex';
valueNode.style.alignItems = 'center';
if (isSecondary) {
const animatedValue = valueNode.querySelector(
'[class*="animated-number__Content-sc"]'
);
const hiddenValue = valueNode.querySelector(
'[class*="result-secondary__HiddenValue-sc"]'
);
if (animatedValue) animatedValue.style.position = 'relative';
if (hiddenValue) hiddenValue.style.display = 'none';
valueNode.style.minWidth =
parseInt(window.getComputedStyle(valueNode).minWidth || '0') +
infoSize +
'px';
valueNode.style.justifyContent = 'end';
}
container.style.position = 'relative';
container.style.overflow = 'unset';
caption.style.cssText = `
margin-top: 0;
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
background-color: #fff;
z-index: 2;
opacity: 1;
padding: 8px 12px;
border-radius: 4px;
box-shadow: 0px 2px 8px 0px #00000040;
`;
function show() {
isHovering = true;
caption.style.display = 'block';
}
function hide() {
isHovering = false;
setTimeout(() => {
if (!isHovering) caption.style.display = 'none';
}, 100);
}
valueNode.addEventListener('mouseenter', show);
valueNode.addEventListener('mouseleave', hide);
caption.addEventListener('mouseenter', show);
caption.addEventListener('mouseleave', hide);
valueNode.addEventListener('touchstart', (e) => {
e.stopPropagation();
isTouched = !isTouched;
if (isTouched) {
show();
} else {
hide();
}
});
document.addEventListener('touchstart', (e) => {
if (!valueNode.contains(e.target) && !caption.contains(e.target)) {
isTouched = false;
hide();
}
});
}
listener('[class*="results__Container-sc"]', (container) => {
const mappedBlocks = mapResultBlocks(container);
INFO_LIST.forEach((title) => {
const value = mappedBlocks.get(normalizedString(title));
if (!value || !value.value) return;
const fontSize = parseInt(
window.getComputedStyle(value.value).fontSize || '14'
);
const infoSize = Math.floor(fontSize / 2);
attachHoverBehavior(value, infoSize);
});
});
In the 1st line, you should add the calculation names where the captions should appear on hover:
Please try it out and let me know if you like the result
Hi,
it works almost perfectly. Small things to adjust…
- the hover Info should be connected to the title, not to the result.
- if using the view of „secondary result“, the i hover button is way to small.
- works only in the „calculations“ not in „ fields“
But in general it’s a cool calc!!!
One more thing: has nothing to do with hover. In the window caption there is only a distribution possible. It would be cool if users could reference to a field or to results of calculations , highlighted in in the text by a different color. That’s how it works in fillout, wich is in term of grafics worse and has no AI what helped me to get the results in some day instead in weeks > way faster, so keep the AI!!
Dimitri Geizenräder
Otto-Brenner-Strasse 86
D-45549 Sprockhövel
phone 49 (0)176 22 36 11 83
von unterwegs gesendet