You are on the main content
Essenza Plus Cherry Red | Coffee Machine | Nespresso GR
Essenza Plus Cherry Red Coffee Machine Nespresso GR
We apologise but due to a technical error we are unable to complete your request. Please contact the Nespresso Club, specifying the error code 78-KJM, and one of our Coffee Specialists will be able to assist.
/gr/en/error/unexpected.jsp
CHANGE MY PREFERENCES
Pressing this button will close this page and redirect you to the My Account Contact Preferences section so that you can update your settings on how Nespresso can contact you
KEEP MY PREFERENCES
Pressing this button will confirm all your current settings on how Nespresso will contact you in the future and close this page
/**
* scroll-popups-hardened.js
* Hides chat/feedback popups on scroll down; shows on scroll up.
* Robust to late-loaded widgets, shadow DOM, and (to a degree) cross-origin iframes.
*/
const SELECTORS = [
'.pagetop',
'#nespresso-conversational-window',
'#QSIFeedbackButton-btn',
// Add any iframe wrappers you recognize below (examples):
// 'iframe[src*="qualtrics"]',
// 'iframe[src*="konnektive"]',
];
const ROOT_TOGGLE_CLASS = 'popups-hidden';
const MIN_DELTA = 8;
const ENABLE_ON_ALL_DEVICES = true; // set false to limit to mobile-like only
// ----- CSS (define visible + hidden, applied via class on ) -----
function ensureHiddenStyle() {
const id = `scroll-popups-style-${ROOT_TOGGLE_CLASS}`;
if (document.getElementById(id)) return;
const s = document.createElement('style');
s.id = id;
s.textContent = `
/* default visible state with transitions so late elements animate correctly */
${SELECTORS.join(', ')} {
opacity: 1;
transform: translateY(0);
visibility: visible;
transition: opacity 200ms ease, transform 200ms ease, visibility 200ms;
will-change: opacity, transform;
}
/* hidden state driven by a root toggle class so late-loaded nodes are affected automatically */
html.${ROOT_TOGGLE_CLASS} ${SELECTORS.join(', ')} {
opacity: 0 !important;
transform: translateY(14px) !important;
pointer-events: none !important;
visibility: hidden !important;
}
`;
document.head.appendChild(s);
}
// ----- Core decision (pure) -----
function decideVisibilityAction(prevY, currY, minDelta = MIN_DELTA) {
if (!Number.isFinite(prevY) || !Number.isFinite(currY)) return 'none';
const d = currY - prevY; // >0 when scrolling DOWN
if (Math.abs(d) < minDelta) return 'none';
if (currY <= 0) return 'show';
const doc = document.scrollingElement || document.documentElement;
if (doc && doc.scrollHeight - doc.clientHeight - currY < 4) return 'show';
return d > 0 ? 'hide' : 'show';
}
function isMobileLike() {
try {
if (window.matchMedia?.('(pointer: coarse)').matches) return true;
} catch {}
return window.innerWidth <= 768;
}
// ----- Visibility application -----
// We toggle a class on for CSS, and keep aria-hidden in sync on matching nodes, including late ones.
function setHiddenState(hidden) {
document.documentElement.classList.toggle(ROOT_TOGGLE_CLASS, hidden);
const aria = hidden ? 'true' : 'false';
// update current matches (light DOM + any open shadow roots we’re tracking)
queryAllDeep(SELECTORS).forEach((el) => {
try { el.setAttribute('aria-hidden', aria); } catch {}
});
}
function applyVisibility(action) {
if (action === 'hide') setHiddenState(true);
else if (action === 'show') setHiddenState(false);
}
// ----- Deep querying across light DOM + open shadow roots -----
// We maintain a small registry of open shadow roots to search as they appear.
const shadowRoots = new Set(); // Set
function queryAllDeep(selectors) {
// Search light DOM
const results = new Set([...document.querySelectorAll(selectors.join(','))]);
// Search tracked shadow roots
for (const root of shadowRoots) {
try {
root.host && results.add(root.host.matches && selectors.some((s) => root.host.matches(s)) ? root.host : null);
root.querySelectorAll && root.querySelectorAll(selectors.join(',')).forEach((el) => results.add(el));
} catch {}
}
// Remove potential nulls
results.delete(null);
return [...results];
}
// Track any open shadow roots dynamically
function tryTrackShadowRoot(node) {
// If an element exposes an *open* shadowRoot, track it
if (node && node.shadowRoot && node.shadowRoot.mode === 'open') {
if (!shadowRoots.has(node.shadowRoot)) {
shadowRoots.add(node.shadowRoot);
// Also observe inside it for nested additions
observer.observe(node.shadowRoot, { childList: true, subtree: true });
}
}
}
// ----- MutationObserver (light DOM + open shadow roots) -----
const observer = new MutationObserver((mutations) => {
const hidden = document.documentElement.classList.contains(ROOT_TOGGLE_CLASS);
const aria = hidden ? 'true' : 'false';
for (const m of mutations) {
// Newly added nodes: sync aria, discover shadow roots
m.addedNodes.forEach((n) => {
if (!(n instanceof Element)) return;
// If the added node itself matches, set aria
if (SELECTORS.some((sel) => n.matches?.(sel))) {
try { n.setAttribute('aria-hidden', aria); } catch {}
}
// Descendants that match
try {
n.querySelectorAll?.(SELECTORS.join(',')).forEach((el) => el.setAttribute('aria-hidden', aria));
} catch {}
// Track open shadow roots on this node and its descendants
tryTrackShadowRoot(n);
n.querySelectorAll?.('*').forEach(tryTrackShadowRoot);
});
}
});
// ----- Optional: slow poll as a belt-and-suspenders for flaky vendors -----
let pollStop = null;
function startPollingForMatches(timeoutMs = 15000, intervalMs = 500) {
const start = Date.now();
const t = setInterval(() => {
const matches = queryAllDeep(SELECTORS);
if (matches.length > 0 || Date.now() - start > timeoutMs) {
// Sync aria to current hidden state when the first ones appear
const hidden = document.documentElement.classList.contains(ROOT_TOGGLE_CLASS);
const aria = hidden ? 'true' : 'false';
matches.forEach((el) => { try { el.setAttribute('aria-hidden', aria); } catch {} });
clearInterval(t);
pollStop = null;
}
}, intervalMs);
pollStop = () => clearInterval(t);
}
// ----- Init -----
function initScrollPopupsHardened() {
ensureHiddenStyle();
// Observe entire document and any open shadow roots we discover
observer.observe(document.documentElement, { childList: true, subtree: true });
// Track currently open shadow roots (in case something already attached one)
document.querySelectorAll('*').forEach(tryTrackShadowRoot);
// Kick off polling to catch ultra-late vendors (optional but pragmatic)
startPollingForMatches();
const featureEnabled = ENABLE_ON_ALL_DEVICES || isMobileLike();
if (!featureEnabled) {
applyVisibility('show');
return () => {
observer.disconnect();
if (pollStop) pollStop();
};
}
let prevY = window.scrollY;
let ticking = false;
const controller = new AbortController();
const { signal } = controller;
const onScroll = () => {
if (ticking) return;
ticking = true;
requestAnimationFrame(() => {
try {
const currY = window.scrollY;
const action = decideVisibilityAction(prevY, currY, MIN_DELTA);
applyVisibility(action);
prevY = currY;
} finally {
ticking = false;
}
});
};
const onResize = () => {
if (!ENABLE_ON_ALL_DEVICES && !isMobileLike()) {
applyVisibility('show');
controller.abort();
observer.disconnect();
if (pollStop) pollStop();
}
};
window.addEventListener('scroll', onScroll, { passive: true, signal });
window.addEventListener('resize', onResize, { passive: true, signal });
window.addEventListener('orientationchange', onResize, { passive: true, signal });
return () => {
controller.abort();
observer.disconnect();
if (pollStop) pollStop();
};
}
// Auto-init
document.readyState !== 'loading'
? initScrollPopupsHardened()
: document.addEventListener('DOMContentLoaded', () => initScrollPopupsHardened());