Add accessibility features: high contrast, blue filter, grayscale, image toggle, and cursor size adjustments
- Implemented high contrast mode toggle with state persistence. - Added blue filter toggle with visual effect and state persistence. - Introduced grayscale mode toggle with state persistence. - Included option to hide/show images with state persistence. - Added functionality to increase/decrease cursor size with visual feedback. - Enhanced font size controls with increment, decrement, and reset options. - Updated accessibility panel UI and button labels for clarity. - Ensured all new features are accessible and maintain user preferences across sessions.
This commit is contained in:
2
.vscode/ftp-kr.sync.cache.json
vendored
2
.vscode/ftp-kr.sync.cache.json
vendored
@@ -98,7 +98,7 @@
|
||||
},
|
||||
"google-merchant_id-1.xml": {
|
||||
"type": "-",
|
||||
"size": 18879143,
|
||||
"size": 18781656,
|
||||
"lmtime": 0,
|
||||
"modified": true
|
||||
},
|
||||
|
||||
@@ -1 +1 @@
|
||||
#accessibility-button{position:fixed;bottom:20px;right:20px;background:#6366f1;color:#fff;border-radius:50%;width:50px;height:50px;font-size:24px;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:9999;box-shadow:0 0 10px rgba(0,0,0,.2)}#accessibility-panel{position:fixed;top:0;right:0;width:280px;height:100%;background:#f9f9f9;box-shadow:-2px 0 10px rgba(0,0,0,.1);transform:translateX(100%);transition:transform .3s ease;z-index:9998;display:flex;flex-direction:column}#accessibility-panel #close-accessibility-panel{border:0;height:30px;width:30px;border-radius:6px}#accessibility-panel.open{transform:translateX(0)}.panel-header{display:flex;justify-content:space-between;align-items:center;background:#6366f1;color:#fff;padding:1rem;font-weight:bold}.panel-body{padding:1rem;display:flex;flex-direction:column;gap:10px}#toggle-contrast{padding:10px;font-size:16px;cursor:pointer}/*# sourceMappingURL=accessibility.css.map */
|
||||
#accessibility-button{position:fixed;bottom:20px;right:20px;background:#6366f1;color:#fff;border-radius:50%;width:50px;height:50px;font-size:24px;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:9999;box-shadow:0 0 10px rgba(0,0,0,.2)}#accessibility-panel{position:fixed;top:0;right:0;width:280px;height:100%;background:#f9f9f9;box-shadow:-2px 0 10px rgba(0,0,0,.1);transform:translateX(100%);transition:transform .3s ease;z-index:9998;display:flex;flex-direction:column}#accessibility-panel #close-accessibility-panel{border:0;height:30px;width:30px;border-radius:6px}#accessibility-panel.open{transform:translateX(0)}.panel-header{display:flex;justify-content:space-between;align-items:center;background:#6366f1;color:#fff;padding:1rem;font-weight:bold}.panel-body{padding:1rem;display:flex;flex-direction:column;gap:10px}#toggle-contrast,#toggle-blue-filter,#toggle-grayscale,#toggle-images,#toggle-cursor{padding:10px;font-size:16px;cursor:pointer}body.hide-images img,body.hide-images picture,body.hide-images svg,body.hide-images video{display:none !important}html.grayscale{filter:grayscale(100%)}body.big-cursor-active,body.big-cursor-active *{cursor:none !important}#a11y-cursor{will-change:transform}.font-size-controls{display:grid;grid-auto-flow:column;gap:8px;align-items:center;margin-top:10px}.font-size-controls button{padding:6px 10px;border-radius:8px;border:1px solid #dcdcdc;background:#f7f7f7;cursor:pointer;font-weight:600}.font-size-controls button:hover{background:#efefef}.font-size-controls button:disabled{opacity:.55;cursor:not-allowed}#font-inc{font-size:1.05em}#font-dec{font-size:.95em}/*# sourceMappingURL=accessibility.css.map */
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"sources":["accessibility.scss"],"names":[],"mappings":"AAAA,sBACE,cAAA,CACA,WAAA,CACA,UAAA,CACA,kBAAA,CACA,UAAA,CACA,iBAAA,CACA,UAAA,CACA,WAAA,CACA,cAAA,CACA,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CACA,YAAA,CACA,kCAAA,CAGF,qBACE,cAAA,CACA,KAAA,CACA,OAAA,CACA,WAAA,CACA,WAAA,CACA,kBAAA,CACA,qCAAA,CACA,0BAAA,CACA,6BAAA,CACA,YAAA,CACA,YAAA,CACA,qBAAA,CAEA,gDACE,QAAA,CACA,WAAA,CACA,UAAA,CACA,iBAAA,CAIJ,0BACE,uBAAA,CAGF,cACE,YAAA,CACA,6BAAA,CACA,kBAAA,CACA,kBAAA,CACA,UAAA,CACA,YAAA,CACA,gBAAA,CAGF,YACE,YAAA,CACA,YAAA,CACA,qBAAA,CACA,QAAA,CAGF,iBACE,YAAA,CACA,cAAA,CACA,cAAA","file":"accessibility.css","sourcesContent":["#accessibility-button {\r\n position: fixed;\r\n bottom: 20px;\r\n right: 20px;\r\n background: #6366f1;\r\n color: white;\r\n border-radius: 50%;\r\n width: 50px;\r\n height: 50px;\r\n font-size: 24px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n z-index: 9999;\r\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n#accessibility-panel {\r\n position: fixed;\r\n top: 0;\r\n right: 0;\r\n width: 280px;\r\n height: 100%;\r\n background: #f9f9f9;\r\n box-shadow: -2px 0 10px rgba(0, 0, 0, 0.1);\r\n transform: translateX(100%);\r\n transition: transform 0.3s ease;\r\n z-index: 9998;\r\n display: flex;\r\n flex-direction: column;\r\n\r\n #close-accessibility-panel {\r\n border: 0;\r\n height: 30px;\r\n width: 30px;\r\n border-radius: 6px;\r\n }\r\n}\r\n\r\n#accessibility-panel.open {\r\n transform: translateX(0);\r\n}\r\n\r\n.panel-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n background: #6366f1;\r\n color: white;\r\n padding: 1rem;\r\n font-weight: bold;\r\n}\r\n\r\n.panel-body {\r\n padding: 1rem;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 10px;\r\n}\r\n\r\n#toggle-contrast {\r\n padding: 10px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n}"]}
|
||||
{"version":3,"sources":["accessibility.scss"],"names":[],"mappings":"AAAA,sBACE,cAAA,CACA,WAAA,CACA,UAAA,CACA,kBAAA,CACA,UAAA,CACA,iBAAA,CACA,UAAA,CACA,WAAA,CACA,cAAA,CACA,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CACA,YAAA,CACA,kCAAA,CAGF,qBACE,cAAA,CACA,KAAA,CACA,OAAA,CACA,WAAA,CACA,WAAA,CACA,kBAAA,CACA,qCAAA,CACA,0BAAA,CACA,6BAAA,CACA,YAAA,CACA,YAAA,CACA,qBAAA,CAEA,gDACE,QAAA,CACA,WAAA,CACA,UAAA,CACA,iBAAA,CAIJ,0BACE,uBAAA,CAGF,cACE,YAAA,CACA,6BAAA,CACA,kBAAA,CACA,kBAAA,CACA,UAAA,CACA,YAAA,CACA,gBAAA,CAGF,YACE,YAAA,CACA,YAAA,CACA,qBAAA,CACA,QAAA,CAGF,qFAKE,YAAA,CACA,cAAA,CACA,cAAA,CAMA,0FAIE,uBAAA,CAKJ,eACE,sBAAA,CAMA,gDAEE,sBAAA,CAKJ,aACE,qBAAA,CAIF,oBACE,YAAA,CACA,qBAAA,CACA,OAAA,CACA,kBAAA,CACA,eAAA,CAEA,2BACE,gBAAA,CACA,iBAAA,CACA,wBAAA,CACA,kBAAA,CACA,cAAA,CACA,eAAA,CAEA,iCACE,kBAAA,CAGF,oCACE,WAAA,CACA,kBAAA,CAMN,UACE,gBAAA,CAGF,UACE,eAAA","file":"accessibility.css","sourcesContent":["#accessibility-button {\r\n position: fixed;\r\n bottom: 20px;\r\n right: 20px;\r\n background: #6366f1;\r\n color: white;\r\n border-radius: 50%;\r\n width: 50px;\r\n height: 50px;\r\n font-size: 24px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n z-index: 9999;\r\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n#accessibility-panel {\r\n position: fixed;\r\n top: 0;\r\n right: 0;\r\n width: 280px;\r\n height: 100%;\r\n background: #f9f9f9;\r\n box-shadow: -2px 0 10px rgba(0, 0, 0, 0.1);\r\n transform: translateX(100%);\r\n transition: transform 0.3s ease;\r\n z-index: 9998;\r\n display: flex;\r\n flex-direction: column;\r\n\r\n #close-accessibility-panel {\r\n border: 0;\r\n height: 30px;\r\n width: 30px;\r\n border-radius: 6px;\r\n }\r\n}\r\n\r\n#accessibility-panel.open {\r\n transform: translateX(0);\r\n}\r\n\r\n.panel-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n background: #6366f1;\r\n color: white;\r\n padding: 1rem;\r\n font-weight: bold;\r\n}\r\n\r\n.panel-body {\r\n padding: 1rem;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 10px;\r\n}\r\n\r\n#toggle-contrast,\r\n#toggle-blue-filter,\r\n#toggle-grayscale,\r\n#toggle-images,\r\n#toggle-cursor {\r\n padding: 10px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n}\r\n\r\n/* Ukrywanie obrazów */\r\nbody.hide-images {\r\n\r\n img,\r\n picture,\r\n svg,\r\n video {\r\n display: none !important;\r\n }\r\n}\r\n\r\n/* Szarość */\r\nhtml.grayscale {\r\n filter: grayscale(100%);\r\n}\r\n\r\n/* Duży kursor – chowamy natywny kursor dopiero po pierwszym ruchu */\r\nbody.big-cursor-active {\r\n\r\n &,\r\n * {\r\n cursor: none !important;\r\n }\r\n}\r\n\r\n/* Overlay kursora */\r\n#a11y-cursor {\r\n will-change: transform;\r\n}\r\n\r\n/* Kontrolki rozmiaru czcionki */\r\n.font-size-controls {\r\n display: grid;\r\n grid-auto-flow: column;\r\n gap: 8px;\r\n align-items: center;\r\n margin-top: 10px;\r\n\r\n button {\r\n padding: 6px 10px;\r\n border-radius: 8px;\r\n border: 1px solid #dcdcdc;\r\n background: #f7f7f7;\r\n cursor: pointer;\r\n font-weight: 600;\r\n\r\n &:hover {\r\n background: #efefef;\r\n }\r\n\r\n &:disabled {\r\n opacity: .55;\r\n cursor: not-allowed;\r\n }\r\n }\r\n}\r\n\r\n/* Drobne różnice optyczne dla przycisków A− / A+ */\r\n#font-inc {\r\n font-size: 1.05em;\r\n}\r\n\r\n#font-dec {\r\n font-size: 0.95em;\r\n}"]}
|
||||
@@ -59,8 +59,78 @@
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#toggle-contrast {
|
||||
#toggle-contrast,
|
||||
#toggle-blue-filter,
|
||||
#toggle-grayscale,
|
||||
#toggle-images,
|
||||
#toggle-cursor {
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Ukrywanie obrazów */
|
||||
body.hide-images {
|
||||
|
||||
img,
|
||||
picture,
|
||||
svg,
|
||||
video {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Szarość */
|
||||
html.grayscale {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
/* Duży kursor – chowamy natywny kursor dopiero po pierwszym ruchu */
|
||||
body.big-cursor-active {
|
||||
|
||||
&,
|
||||
* {
|
||||
cursor: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Overlay kursora */
|
||||
#a11y-cursor {
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
/* Kontrolki rozmiaru czcionki */
|
||||
.font-size-controls {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
|
||||
button {
|
||||
padding: 6px 10px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #dcdcdc;
|
||||
background: #f7f7f7;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
|
||||
&:hover {
|
||||
background: #efefef;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: .55;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Drobne różnice optyczne dla przycisków A− / A+ */
|
||||
#font-inc {
|
||||
font-size: 1.05em;
|
||||
}
|
||||
|
||||
#font-dec {
|
||||
font-size: 0.95em;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1607,4 +1607,12 @@ body.high-contrast {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.blue-filter {
|
||||
filter: sepia(20%) hue-rotate(180deg) brightness(90%);
|
||||
}
|
||||
|
||||
html.grayscale {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
@@ -1,64 +1,275 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Tworzenie przycisku
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 1) Przycisk otwierający panel
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
const accessBtn = document.createElement('div');
|
||||
accessBtn.id = 'accessibility-button';
|
||||
accessBtn.setAttribute('aria-label', 'Opcje dostępności');
|
||||
accessBtn.innerHTML = `
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="24" height="24">
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
|
||||
<g id="SVGRepo_iconCarrier">
|
||||
<circle cx="12" cy="12" r="10" stroke="#ffffff" stroke-width="1.5"></circle>
|
||||
<path d="M14 7C14 8.10457 13.1046 9 12 9C10.8954 9 10 8.10457 10 7C10 5.89543 10.8954 5 12 5C13.1046 5 14 5.89543 14 7Z" stroke="#ffffff" stroke-width="1.5"></path>
|
||||
<path d="M18 10C18 10 14.4627 11.5 12 11.5C9.53727 11.5 6 10 6 10" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round"></path>
|
||||
<path d="M12 12V13.4522M12 13.4522C12 14.0275 12.1654 14.5906 12.4765 15.0745L15 19M12 13.4522C12 14.0275 11.8346 14.5906 11.5235 15.0745L9 19" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<circle cx="12" cy="12" r="10" stroke="#ffffff" stroke-width="1.5"></circle>
|
||||
<path d="M14 7C14 8.10457 13.1046 9 12 9C10.8954 9 10 8.10457 10 7C10 5.89543 10.8954 5 12 5C13.1046 5 14 5.89543 14 7Z" stroke="#ffffff" stroke-width="1.5"></path>
|
||||
<path d="M18 10C18 10 14.4627 11.5 12 11.5C9.53727 11.5 6 10 6 10" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round"></path>
|
||||
<path d="M12 12V13.4522M12 13.4522C12 14.0275 12.1654 14.5906 12.4765 15.0745L15 19M12 13.4522C12 14.0275 11.8346 14.5906 11.5235 15.0745L9 19" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
`;
|
||||
document.body.appendChild(accessBtn);
|
||||
|
||||
|
||||
// Tworzenie panelu
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 2) Panel opcji dostępności
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
const accessPanel = document.createElement('div');
|
||||
accessPanel.id = 'accessibility-panel';
|
||||
accessPanel.innerHTML = `
|
||||
<div class="panel-header">
|
||||
<span>Opcje dostępności</span>
|
||||
<button id="close-accessibility-panel">×</button>
|
||||
<button id="close-accessibility-panel" aria-label="Zamknij">×</button>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<button id="toggle-contrast">Wysoki kontrast: OFF</button>
|
||||
<button id="toggle-blue-filter">Filtr niebieski: OFF</button>
|
||||
<button id="toggle-grayscale">Tryb szarości: OFF</button>
|
||||
<button id="toggle-images">Ukryj obrazy</button>
|
||||
<button id="toggle-cursor">Zwiększ kursor</button>
|
||||
|
||||
<div class="font-size-controls" role="group" aria-label="Rozmiar czcionki">
|
||||
<button id="font-dec" aria-label="Zmniejsz czcionkę" title="Zmniejsz czcionkę">A−</button>
|
||||
<button id="font-reset" aria-label="Resetuj rozmiar czcionki" title="Resetuj rozmiar czcionki">A</button>
|
||||
<button id="font-inc" aria-label="Zwiększ czcionkę" title="Zwiększ czcionkę">A+</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(accessPanel);
|
||||
|
||||
// Logika
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 3) Referencje
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
const panel = document.getElementById('accessibility-panel');
|
||||
const contrastBtn = document.getElementById('toggle-contrast');
|
||||
const blueFilterBtn = document.getElementById('toggle-blue-filter');
|
||||
const grayscaleBtn = document.getElementById('toggle-grayscale');
|
||||
const imagesBtn = document.getElementById('toggle-images');
|
||||
const cursorBtn = document.getElementById('toggle-cursor');
|
||||
const fontIncBtn = document.getElementById('font-inc');
|
||||
const fontDecBtn = document.getElementById('font-dec');
|
||||
const fontResetBtn = document.getElementById('font-reset');
|
||||
|
||||
accessBtn.addEventListener('click', () => {
|
||||
panel.classList.toggle('open');
|
||||
});
|
||||
|
||||
document.getElementById('close-accessibility-panel').addEventListener('click', () => {
|
||||
panel.classList.remove('open');
|
||||
});
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 4) Panel open/close
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
accessBtn.addEventListener('click', () => panel.classList.toggle('open'));
|
||||
document.getElementById('close-accessibility-panel').addEventListener('click', () => panel.classList.remove('open'));
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 5) Helpery etykiet
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
function updateContrastButton() {
|
||||
const isOn = document.body.classList.contains('high-contrast');
|
||||
contrastBtn.textContent = isOn ? 'Wyłącz wysoki kontrast' : 'Włącz wysoki kontrast';
|
||||
}
|
||||
function updateBlueFilterButton() {
|
||||
const isOn = !!document.getElementById('eyeAble-Bluefilter');
|
||||
blueFilterBtn.textContent = isOn ? 'Wyłącz filtr niebieski' : 'Włącz filtr niebieski';
|
||||
}
|
||||
function updateGrayscaleButton() {
|
||||
const isOn = document.documentElement.classList.contains('grayscale');
|
||||
grayscaleBtn.textContent = isOn ? 'Wyłącz tryb szarości' : 'Włącz tryb szarości';
|
||||
}
|
||||
function updateImagesButton() {
|
||||
const isOn = document.body.classList.contains('hide-images');
|
||||
imagesBtn.textContent = isOn ? 'Pokaż obrazy' : 'Ukryj obrazy';
|
||||
}
|
||||
function updateCursorButton() {
|
||||
const isOn = document.body.classList.contains('big-cursor');
|
||||
cursorBtn.textContent = isOn ? 'Przywróć kursor' : 'Zwiększ kursor';
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 6) Akcje – istniejące
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
contrastBtn.addEventListener('click', () => {
|
||||
document.body.classList.toggle('high-contrast');
|
||||
const isHigh = document.body.classList.contains('high-contrast');
|
||||
localStorage.setItem('highContrast', isHigh ? '1' : '0');
|
||||
localStorage.setItem('highContrast', document.body.classList.contains('high-contrast') ? '1' : '0');
|
||||
updateContrastButton();
|
||||
});
|
||||
|
||||
if (localStorage.getItem('highContrast') === '1') {
|
||||
document.body.classList.add('high-contrast');
|
||||
blueFilterBtn.addEventListener('click', () => {
|
||||
const shader = document.getElementById('eyeAble-Bluefilter');
|
||||
if (shader) {
|
||||
shader.remove();
|
||||
localStorage.setItem('blueFilter', '0');
|
||||
} else {
|
||||
const s = document.createElement('eye-able-shader');
|
||||
s.id = 'eyeAble-Bluefilter';
|
||||
s.setAttribute('aria-hidden', 'true');
|
||||
s.style.cssText = `
|
||||
background: rgba(255, 147, 41, 0.43);
|
||||
z-index: 2147483646;
|
||||
margin: 0; border-radius: 0; padding: 0; pointer-events: none;
|
||||
position: fixed; top: -10%; right: -10%; bottom: -10%; left: -10%;
|
||||
width: auto; height: auto; mix-blend-mode: multiply; display: block !important;`;
|
||||
document.body.appendChild(s);
|
||||
localStorage.setItem('blueFilter', '1');
|
||||
}
|
||||
updateBlueFilterButton();
|
||||
});
|
||||
|
||||
grayscaleBtn.addEventListener('click', () => {
|
||||
document.documentElement.classList.toggle('grayscale');
|
||||
localStorage.setItem('grayscaleMode', document.documentElement.classList.contains('grayscale') ? '1' : '0');
|
||||
updateGrayscaleButton();
|
||||
});
|
||||
|
||||
imagesBtn.addEventListener('click', () => {
|
||||
document.body.classList.toggle('hide-images');
|
||||
localStorage.setItem('hideImages', document.body.classList.contains('hide-images') ? '1' : '0');
|
||||
updateImagesButton();
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 7) DUŻY KURSOR – overlay z INLINE SVG (CSP-safe), z aktywacją po pierwszym ruchu
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
let overlay = null; // <div id="a11y-cursor">
|
||||
let mmHandler = null;
|
||||
let leaveHandler = null;
|
||||
let enteredOnce = false;
|
||||
|
||||
const ARROW_SVG = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="100" height="100" viewBox="0 0 80 80">
|
||||
<path d="M 22 8.734375 L 22 64.328125 L 36.34375 54.273438 L 45.605469 72.628906 L 54.722656 67.921875 L 45.140625 50.1875 L 63.054688 46.230469 L 61.632813 44.933594 Z M 24 13.265625 L 58.859375 45.109375 L 42.125 48.800781 L 51.996094 67.078125 L 46.480469 69.925781 L 37.089844 51.308594 L 24 60.484375 Z M 28 24 C 27.449219 24 27 24.449219 27 25 C 27 25.550781 27.449219 26 28 26 C 28.550781 26 29 25.550781 29 25 C 29 24.449219 28.550781 24 28 24 Z M 28 28 C 27.449219 28 27 28.449219 27 29 C 27 29.550781 27.449219 30 28 30 C 28.550781 30 29 29.550781 29 29 C 29 28.449219 28.550781 28 28 28 Z M 28 32 C 27.449219 32 27 32.449219 27 33 C 27 33.550781 27.449219 34 28 34 C 28.550781 34 29 33.550781 29 33 C 29 32.449219 28.550781 32 28 32 Z M 28 36 C 27.449219 36 27 36.449219 27 37 C 27 37.550781 27.449219 38 28 38 C 28.550781 38 29 37.550781 29 37 C 29 36.449219 28.550781 36 28 36 Z M 28 40 C 27.449219 40 27 40.449219 27 41 C 27 41.550781 27.449219 42 28 42 C 28.550781 42 29 41.550781 29 41 C 29 40.449219 28.550781 40 28 40 Z M 28 44 C 27.449219 44 27 44.449219 27 45 C 27 45.550781 27.449219 46 28 46 C 28.550781 46 29 45.550781 29 45 C 29 44.449219 28.550781 44 28 44 Z M 28 48 C 27.449219 48 27 48.449219 27 49 C 27 49.550781 27.449219 50 28 50 C 28.550781 50 29 49.550781 29 49 C 29 48.449219 28.550781 48 28 48 Z M 28 52 C 27.449219 52 27 52.449219 27 53 C 27 53.550781 27.449219 54 28 54 C 28.550781 54 29 53.550781 29 53 C 29 52.449219 28.550781 52 28 52 Z"/>
|
||||
</svg>`;
|
||||
const HAND_SVG = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="100" height="100" viewBox="0 0 80 80">
|
||||
<path d="M 29.5 5 C 26.472656 5 24 7.472656 24 10.5 L 24 42.160156 L 19.976563 45.453125 C 16.941406 47.941406 16.125 52.261719 18.050781 55.683594 L 24.75 67.585938 L 24.699219 67.484375 C 26.0625 70.726563 29.273438 73 33 73 L 53 73 C 57.957031 73 62 68.957031 62 64 L 62 36.5 C 62 33.472656 59.527344 31 56.5 31 C 55.066406 31 53.777344 31.585938 52.796875 32.496094 C 52.304688 29.960938 50.167969 28 47.5 28 C 45.820313 28 44.371094 28.804688 43.359375 30 L 43.324219 30 C 42.402344 28.242188 40.613281 27 38.5 27 C 37.152344 27 35.957031 27.546875 35 28.355469 L 35 10.5 C 35 7.472656 32.527344 5 29.5 5 Z M 29.5 7 C 31.445313 7 33 8.554688 33 10.5 L 33 36 L 35 36 L 35 32.5 C 35 30.554688 36.554688 29 38.5 29 C 40.445313 29 42 30.554688 42 32.5 L 42 36 L 44 36 L 44 33.5 C 44 31.554688 45.554688 30 47.5 30 C 49.445313 30 51 31.554688 51 33.5 L 51 36.5 L 53 36.5 C 53 34.554688 54.554688 33 56.5 33 C 58.445313 33 60 34.554688 60 36.5 L 60 64 C 60 67.878906 56.878906 71 53 71 L 33 71 C 30.085938 71 27.601563 69.226563 26.546875 66.707031 L 26.519531 66.65625 L 19.792969 54.703125 C 18.339844 52.117188 18.949219 48.878906 21.246094 47 L 26 43.109375 L 26 10.5 C 26 8.554688 27.554688 7 29.5 7 Z M 34 41 C 33.449219 41 33 41.449219 33 42 C 33 42.550781 33.449219 43 34 43 C 34.550781 43 35 42.550781 35 42 C 35 41.449219 34.550781 41 34 41 Z M 43 41 C 42.449219 41 42 41.449219 42 42 C 42 42.550781 42.449219 43 43 43 C 43.550781 43 44 42.550781 44 42 C 44 41.449219 43.550781 41 43 41 Z M 52 41 C 51.449219 41 51 41.449219 51 42 C 51 42.550781 51.449219 43 52 43 C 52.550781 43 53 42.550781 53 42 C 53 41.449219 52.550781 41 52 41 Z M 34 45 C 33.449219 45 33 45.449219 33 46 C 33 46.550781 33.449219 47 34 47 C 34.550781 47 35 46.550781 35 46 C 35 45.449219 34.550781 45 34 45 Z M 43 45 C 42.449219 45 42 45.449219 42 46 C 42 46.550781 42.449219 47 43 47 C 43.550781 47 44 46.550781 44 46 C 44 45.449219 43.550781 45 43 45 Z M 52 45 C 51.449219 45 51 45.449219 51 46 C 51 46.550781 51.449219 47 52 47 C 52.550781 47 53 46.550781 53 46 C 53 45.449219 52.550781 45 52 45 Z M 34 49 C 33.449219 49 33 49.449219 33 50 C 33 50.550781 33.449219 51 34 51 C 34.550781 51 35 50.550781 35 50 C 35 49.449219 34.550781 49 34 49 Z M 43 49 C 42.449219 49 42 49.449219 42 50 C 42 50.550781 42.449219 51 43 51 C 43.550781 51 44 50.550781 44 50 C 44 49.449219 43.550781 49 43 49 Z M 52 49 C 51.449219 49 51 49.449219 51 50 C 51 50.550781 51.449219 51 52 51 C 52.550781 51 53 50.550781 53 50 C 53 49.449219 52.550781 49 52 49 Z M 34 53 C 33.449219 53 33 53.449219 33 54 C 33 54.550781 33.449219 55 34 55 C 34.550781 55 35 54.550781 35 54 C 35 53.449219 34.550781 53 34 53 Z M 43 53 C 42.449219 53 42 53.449219 42 54 C 42 54.550781 42.449219 55 43 55 C 43.550781 55 44 54.550781 44 54 C 44 53.449219 43.550781 53 43 53 Z M 52 53 C 51.449219 53 51 53.449219 51 54 C 51 54.550781 51.449219 55 52 55 C 52.550781 55 53 54.550781 53 54 C 53 53.449219 52.550781 53 52 53 Z"/>
|
||||
</svg>`;
|
||||
|
||||
const CURSORS = {
|
||||
arrow: { svg: ARROW_SVG, hotspotX: 6, hotspotY: 6 },
|
||||
hand: { svg: HAND_SVG, hotspotX: 26, hotspotY: 12 },
|
||||
};
|
||||
let current = 'arrow';
|
||||
|
||||
function ensureOverlay() {
|
||||
if (overlay) return;
|
||||
overlay = document.createElement('div');
|
||||
overlay.id = 'a11y-cursor';
|
||||
overlay.setAttribute('aria-hidden', 'true');
|
||||
overlay.style.cssText = [
|
||||
'position:fixed','left:0','top:0','width:48px','height:48px',
|
||||
'pointer-events:none','z-index:2147483647','transform:translate3d(-9999px,-9999px,0)',
|
||||
'opacity:1','display:block'
|
||||
].join(';');
|
||||
document.body.appendChild(overlay);
|
||||
}
|
||||
function setOverlay(name){ current = name; if (!overlay) return; overlay.innerHTML = CURSORS[name].svg; }
|
||||
function moveOverlay(x,y){ if(!overlay) return; const c = CURSORS[current]; overlay.style.transform = `translate3d(${x-c.hotspotX}px, ${y-c.hotspotY}px, 0)`; }
|
||||
function isInteractive(el){ return el && el.closest && el.closest('a[href],button,[role="button"],input[type="button"],input[type="submit"],input[type="checkbox"],input[type="radio"],select,.clickable,[onclick]'); }
|
||||
function isTextInput(el){ return el && el.closest && el.closest('input[type="text"],input[type="search"],input[type="email"],input[type="url"],input[type="tel"],input[type="password"],textarea,[contenteditable=""],[contenteditable="true"]'); }
|
||||
|
||||
function enableBigCursor(){
|
||||
ensureOverlay();
|
||||
setOverlay('arrow');
|
||||
document.body.classList.add('big-cursor');
|
||||
document.body.classList.remove('big-cursor-active');
|
||||
enteredOnce = false;
|
||||
|
||||
mmHandler = (e)=>{
|
||||
const t = e.target;
|
||||
if (!enteredOnce) { enteredOnce = true; document.body.classList.add('big-cursor-active'); }
|
||||
if (isTextInput(t)) { overlay.style.opacity = '0'; return; } else { overlay.style.opacity = '1'; }
|
||||
setOverlay(isInteractive(t) ? 'hand' : 'arrow');
|
||||
moveOverlay(e.clientX, e.clientY);
|
||||
};
|
||||
leaveHandler = ()=>{ if(overlay) overlay.style.opacity='0'; };
|
||||
document.addEventListener('mousemove', mmHandler);
|
||||
document.addEventListener('mouseleave', leaveHandler);
|
||||
}
|
||||
function disableBigCursor(){
|
||||
document.body.classList.remove('big-cursor','big-cursor-active');
|
||||
if (mmHandler) document.removeEventListener('mousemove', mmHandler);
|
||||
if (leaveHandler) document.removeEventListener('mouseleave', leaveHandler);
|
||||
mmHandler = leaveHandler = null;
|
||||
if (overlay) { overlay.remove(); overlay = null; }
|
||||
}
|
||||
|
||||
cursorBtn.addEventListener('click', () => {
|
||||
const willEnable = !document.body.classList.contains('big-cursor');
|
||||
localStorage.setItem('bigCursor', willEnable ? '1' : '0');
|
||||
if (willEnable) enableBigCursor(); else disableBigCursor();
|
||||
updateCursorButton();
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 8) KONTROLKI ROZMIARU CZCIONKI – działają także dla px w CSS
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
const FONT_STEP = 0.1; // 10%
|
||||
const FONT_MIN = 0.7; // 70%
|
||||
const FONT_MAX = 2.0; // 200%
|
||||
const TEXT_SELECTOR = 'h1,h2,h3,h4,h5,h6,p,span,li,dt,dd,blockquote,figcaption,small,strong,em,mark,code,pre,a,button,input,select,textarea,label,td,th,caption,legend';
|
||||
|
||||
function clamp(n, min, max){ return Math.min(Math.max(n, min), max); }
|
||||
function getScale(){ const v = parseFloat(localStorage.getItem('a11yFontScale') || '1'); return isNaN(v) ? 1 : clamp(v, FONT_MIN, FONT_MAX); }
|
||||
function updateFontButtons(){
|
||||
const s = getScale();
|
||||
fontDecBtn.disabled = s <= FONT_MIN;
|
||||
fontIncBtn.disabled = s >= FONT_MAX;
|
||||
fontResetBtn.textContent = s === 1 ? 'A' : `A (${Math.round(s*100)}%)`;
|
||||
}
|
||||
function applyFontScale(scale){
|
||||
const nodes = document.querySelectorAll(TEXT_SELECTOR);
|
||||
nodes.forEach(el => {
|
||||
if (el.closest('#accessibility-panel, #accessibility-button')) return; // nie skaluj UI panelu
|
||||
if (el.hasAttribute('data-no-scale')) return; // wykluczenia opcjonalne
|
||||
let base = el.getAttribute('data-font-base');
|
||||
if (!base) {
|
||||
const comp = getComputedStyle(el).fontSize;
|
||||
const px = parseFloat(comp);
|
||||
if (!isNaN(px) && px > 0) {
|
||||
el.setAttribute('data-font-base', String(px));
|
||||
base = String(px);
|
||||
}
|
||||
}
|
||||
if (base) {
|
||||
const b = parseFloat(base);
|
||||
if (scale === 1) {
|
||||
el.style.removeProperty('font-size');
|
||||
} else {
|
||||
const newPx = Math.round(b * scale * 100) / 100;
|
||||
el.style.setProperty('font-size', newPx + 'px', 'important');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function setScale(s){ s = clamp(s, FONT_MIN, FONT_MAX); localStorage.setItem('a11yFontScale', String(s)); applyFontScale(s); updateFontButtons(); }
|
||||
|
||||
fontIncBtn.addEventListener('click', () => setScale(getScale() + FONT_STEP));
|
||||
fontDecBtn.addEventListener('click', () => setScale(getScale() - FONT_STEP));
|
||||
fontResetBtn.addEventListener('click', () => setScale(1));
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 9) Przywracanie stanu
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
if (localStorage.getItem('highContrast') === '1') document.body.classList.add('high-contrast');
|
||||
if (localStorage.getItem('blueFilter') === '1') {
|
||||
const s = document.createElement('eye-able-shader');
|
||||
s.id = 'eyeAble-Bluefilter'; s.setAttribute('aria-hidden','true');
|
||||
s.style.cssText = 'background:rgba(255,147,41,0.43);z-index:2147483646;margin:0;border-radius:0;padding:0;pointer-events:none;position:fixed;top:-10%;right:-10%;bottom:-10%;left:-10%;width:auto;height:auto;mix-blend-mode:multiply;display:block!important;';
|
||||
document.body.appendChild(s);
|
||||
}
|
||||
if (localStorage.getItem('grayscaleMode') === '1') document.documentElement.classList.add('grayscale');
|
||||
if (localStorage.getItem('hideImages') === '1') document.body.classList.add('hide-images');
|
||||
if (localStorage.getItem('bigCursor') === '1') { enableBigCursor(); }
|
||||
|
||||
// Zastosuj i zainicjuj przyciski rozmiaru czcionki
|
||||
setScale(getScale());
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 10) Inicjalizacja etykiet
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
updateContrastButton();
|
||||
updateBlueFilterButton();
|
||||
updateGrayscaleButton();
|
||||
updateImagesButton();
|
||||
updateCursorButton();
|
||||
updateFontButtons();
|
||||
});
|
||||
Reference in New Issue
Block a user