accessibility-comms
Version:
add accessibility to your website
540 lines (500 loc) • 23.8 kB
text/typescript
import { IAccessibility } from './interfaces/accessibility.interface';
import { IMenuInterface } from './interfaces/menu.interface';
export class MenuInterface implements IMenuInterface {
private _acc: IAccessibility;
private readBind: any;
private _dialog: HTMLDialogElement;
constructor(accessibility: IAccessibility) {
this._acc = accessibility;
this.readBind = this._acc.read.bind(this._acc);
}
increaseText() {
this._acc.alterTextSize(true);
}
decreaseText() {
this._acc.alterTextSize(false);
}
increaseTextSpacing() {
this._acc.alterTextSpace(true);
}
decreaseTextSpacing() {
this._acc.alterTextSpace(false);
}
invertColors(destroy: boolean) {
if (typeof this._acc.stateValues.html.backgroundColor === 'undefined')
this._acc.stateValues.html.backgroundColor = getComputedStyle(this._acc.html).backgroundColor;
if (typeof this._acc.stateValues.html.color === 'undefined')
this._acc.stateValues.html.color = getComputedStyle(this._acc.html).color;
if (destroy) {
this._acc.resetIfDefined(this._acc.stateValues.html.backgroundColor, this._acc.html.style, 'backgroundColor');
this._acc.resetIfDefined(this._acc.stateValues.html.color, this._acc.html.style, 'color');
document.querySelector('._access-menu [data-access-action="invertColors"]').classList.remove('active');
this._acc.stateValues.invertColors = false;
this._acc.sessionState.invertColors = this._acc.stateValues.invertColors;
this._acc.onChange(true);
this._acc.html.style.filter = '';
return;
}
if (this._acc.stateValues.invertColors && this._acc.stateValues.textToSpeech) {
this._acc.textToSpeech('Colors Set To Normal');
}
document.querySelector('._access-menu [data-access-action="invertColors"]').classList.toggle('active');
this._acc.stateValues.invertColors = !this._acc.stateValues.invertColors;
this._acc.sessionState.invertColors = this._acc.stateValues.invertColors;
this._acc.onChange(true);
if (this._acc.stateValues.invertColors) {
if (this._acc.stateValues.grayHues)
this._acc.menuInterface.grayHues(true);
this._acc.html.style.filter = 'invert(1)';
if (this._acc.stateValues.textToSpeech) {
this._acc.textToSpeech('Colors Inverted');
}
}
else {
this._acc.html.style.filter = '';
}
}
grayHues(destroy: boolean) {
if (typeof this._acc.stateValues.html.filter === 'undefined')
this._acc.stateValues.html.filter = getComputedStyle(this._acc.html).filter;
if (typeof this._acc.stateValues.html.webkitFilter === 'undefined')
this._acc.stateValues.html.webkitFilter = getComputedStyle(this._acc.html).webkitFilter;
if (typeof this._acc.stateValues.html.mozFilter === 'undefined')
this._acc.stateValues.html.mozFilter = (getComputedStyle(this._acc.html) as any).mozFilter;
if (typeof this._acc.stateValues.html.msFilter === 'undefined')
this._acc.stateValues.html.msFilter = (getComputedStyle(this._acc.html) as any).msFilter;
if (destroy) {
document.querySelector('._access-menu [data-access-action="grayHues"]').classList.remove('active');
this._acc.stateValues.grayHues = false;
this._acc.sessionState.grayHues = this._acc.stateValues.grayHues;
this._acc.onChange(true);
this._acc.resetIfDefined(this._acc.stateValues.html.filter, this._acc.html.style, 'filter');
this._acc.resetIfDefined(this._acc.stateValues.html.webkitFilter, this._acc.html.style, 'webkitFilter');
this._acc.resetIfDefined(this._acc.stateValues.html.mozFilter, this._acc.html.style, 'mozFilter');
this._acc.resetIfDefined(this._acc.stateValues.html.msFilter, this._acc.html.style, 'msFilter');
return;
}
document.querySelector('._access-menu [data-access-action="grayHues"]').classList.toggle('active');
this._acc.stateValues.grayHues = !this._acc.stateValues.grayHues;
this._acc.sessionState.grayHues = this._acc.stateValues.grayHues;
this._acc.onChange(true);
if (this._acc.stateValues.textToSpeech && !this._acc.stateValues.grayHues)
this._acc.textToSpeech('Gray Hues Disabled.');
let val;
if (this._acc.stateValues.grayHues) {
val = 'grayscale(1)';
if (this._acc.stateValues.invertColors) {
this.invertColors(true);
}
if (this._acc.stateValues.textToSpeech) {
this._acc.textToSpeech('Gray Hues Enabled.');
}
} else {
val = '';
}
this._acc.html.style.webkitFilter = val;
(this._acc.html.style as any).mozFilter = val;
(this._acc.html.style as any).msFilter = val;
this._acc.html.style.filter = val;
}
underlineLinks(destroy: boolean) {
let className = '_access-underline';
let remove = () => {
let style = document.querySelector('.' + className);
if (style) {
style.parentElement.removeChild(style);
this._acc.common.deployedObjects.remove('.' + className);
}
};
if (destroy) {
this._acc.stateValues.underlineLinks = false;
this._acc.sessionState.underlineLinks = this._acc.stateValues.underlineLinks;
this._acc.onChange(true);
document.querySelector('._access-menu [data-access-action="underlineLinks"]').classList.remove('active');
return remove();
}
document.querySelector('._access-menu [data-access-action="underlineLinks"]').classList.toggle('active');
this._acc.stateValues.underlineLinks = !this._acc.stateValues.underlineLinks;
this._acc.sessionState.underlineLinks = this._acc.stateValues.underlineLinks;
this._acc.onChange(true);
if (this._acc.stateValues.underlineLinks) {
let css = `
body a {
text-decoration: underline !important;
}
`;
this._acc.common.injectStyle(css, { className: className });
this._acc.common.deployedObjects.set('.' + className, true);
if (this._acc.stateValues.textToSpeech) {
this._acc.textToSpeech('Links UnderLined');
}
}
else {
if (this._acc.stateValues.textToSpeech) {
this._acc.textToSpeech('Links UnderLine Removed');
}
remove();
}
}
bigCursor(destroy: boolean) {
if (destroy) {
this._acc.html.classList.remove('_access_cursor');
document.querySelector('._access-menu [data-access-action="bigCursor"]').classList.remove('active');
this._acc.stateValues.bigCursor = false;
this._acc.sessionState.bigCursor = false;
this._acc.onChange(true);
return;
}
document.querySelector('._access-menu [data-access-action="bigCursor"]').classList.toggle('active');
this._acc.stateValues.bigCursor = !this._acc.stateValues.bigCursor;
this._acc.sessionState.bigCursor = this._acc.stateValues.bigCursor;
this._acc.onChange(true);
this._acc.html.classList.toggle('_access_cursor');
if (this._acc.stateValues.textToSpeech && this._acc.stateValues.bigCursor) this._acc.textToSpeech('Big Cursor Enabled');
if (this._acc.stateValues.textToSpeech && !this._acc.stateValues.bigCursor) this._acc.textToSpeech('Big Cursor Disabled');
}
readingGuide(destroy: boolean) {
if (destroy) {
if (document.getElementById('access_read_guide_bar')) {
document.getElementById('access_read_guide_bar').remove();
}
document.querySelector('._access-menu [data-access-action="readingGuide"]').classList.remove('active');
this._acc.stateValues.readingGuide = false;
this._acc.sessionState.readingGuide = this._acc.stateValues.readingGuide;
this._acc.onChange(true);
document.body.removeEventListener('touchmove', this._acc.updateReadGuide, false);
document.body.removeEventListener('mousemove', this._acc.updateReadGuide, false);
if (this._acc.stateValues.textToSpeech) this._acc.textToSpeech('Reading Guide Enabled');
return;
}
document.querySelector('._access-menu [data-access-action="readingGuide"]').classList.toggle('active');
this._acc.stateValues.readingGuide = !this._acc.stateValues.readingGuide;
this._acc.sessionState.readingGuide = this._acc.stateValues.readingGuide;
this._acc.onChange(true);
if (this._acc.stateValues.readingGuide) {
let read = document.createElement('div');
read.id = 'access_read_guide_bar';
read.classList.add('access_read_guide_bar');
document.body.append(read);
document.body.addEventListener('touchmove', this._acc.updateReadGuide, false);
document.body.addEventListener('mousemove', this._acc.updateReadGuide, false);
} else {
if (document.getElementById('access_read_guide_bar') !== undefined) {
document.getElementById('access_read_guide_bar').remove();
}
document.body.removeEventListener('touchmove', this._acc.updateReadGuide, false);
document.body.removeEventListener('mousemove', this._acc.updateReadGuide, false);
if (this._acc.stateValues.textToSpeech) this._acc.textToSpeech('Reading Guide Disabled');
}
}
textToSpeech(destroy: boolean) {
// this.sessionState.textToSpeech = typeof destroy === 'undefined' ? true : false;
const tSpeechList = document.querySelector('._access-menu [data-access-action="textToSpeech"]');
if (!tSpeechList) return;
let step1 = document.getElementsByClassName('screen-reader-wrapper-step-1');
let step2 = document.getElementsByClassName('screen-reader-wrapper-step-2');
let step3 = document.getElementsByClassName('screen-reader-wrapper-step-3');
this._acc.onChange(false);
const className = '_access-text-to-speech';
let remove = () => {
let style = document.querySelector('.' + className);
if (style) {
style.parentElement.removeChild(style);
document.removeEventListener('click', this.readBind, false);
document.removeEventListener('keyup', this.readBind, false);
this._acc.common.deployedObjects.remove('.' + className);
}
if (window.speechSynthesis)
window.speechSynthesis.cancel();
this._acc.isReading = false;
};
if (destroy) {
tSpeechList.classList.remove('active');
step1[0].classList.remove('active');
step2[0].classList.remove('active');
step3[0].classList.remove('active');
this._acc.stateValues.textToSpeech = false;
window.speechSynthesis.cancel();
return remove();
}
if (this._acc.stateValues.speechRate === 1 && !tSpeechList.classList.contains('active')) {
this._acc.stateValues.textToSpeech = true;
this._acc.textToSpeech('Screen Reader enabled. Reading Pace - Normal');
tSpeechList.classList.add('active');
step1[0].classList.add('active');
step2[0].classList.add('active');
step3[0].classList.add('active');
}
else if (this._acc.stateValues.speechRate === 1 && tSpeechList.classList.contains('active')) {
this._acc.stateValues.speechRate = 1.5;
this._acc.textToSpeech('Reading Pace - Fast');
step1[0].classList.remove('active');
}
else if (this._acc.stateValues.speechRate === 1.5 && tSpeechList.classList.contains('active')) {
this._acc.stateValues.speechRate = 0.7;
this._acc.textToSpeech('Reading Pace - Slow');
step2[0].classList.remove('active');
} else {
this._acc.stateValues.speechRate = 1;
this._acc.textToSpeech('Screen Reader - Disabled');
tSpeechList.classList.remove('active');
step3[0].classList.remove('active');
let timeout: ReturnType<typeof setInterval> = setInterval(() => {
if (this._acc.isReading) {
return;
}
this._acc.stateValues.textToSpeech = false;
remove();
clearTimeout(timeout);
}, 500);
return;
}
let css = `
*:hover {
box-shadow: 2px 2px 2px rgba(180,180,180,0.7);
}
`;
if (tSpeechList.classList.contains('active') && this._acc.stateValues.speechRate === 1) {
this._acc.common.injectStyle(css, { className: className });
this._acc.common.deployedObjects.set('.' + className, true);
document.addEventListener('click', this.readBind, false);
document.addEventListener('keyup', this.readBind, false);
}
}
speechToText(destroy: boolean) {
// this.sessionState.speechToText = typeof destroy === 'undefined' ? true : false;
const sTextList = document.querySelector('._access-menu [data-access-action="speechToText"]');
if (!sTextList) return;
this._acc.onChange(false);
let className = '_access-speech-to-text';
let remove = () => {
if (this._acc.recognition) {
this._acc.recognition.stop();
this._acc.body.classList.remove('_access-listening');
}
let style = document.querySelector('.' + className);
if (style) {
style.parentElement.removeChild(style);
this._acc.common.deployedObjects.remove('.' + className);
}
let inputs = document.querySelectorAll('._access-mic');
for (let i = 0; i < inputs.length; i++) {
inputs[i].removeEventListener('focus', this._acc.listen.bind(this._acc), false);
inputs[i].classList.remove('_access-mic');
}
sTextList.classList.remove('active');
};
if (destroy) {
this._acc.stateValues.speechToText = false;
return remove();
}
this._acc.stateValues.speechToText = !this._acc.stateValues.speechToText;
if (this._acc.stateValues.speechToText) {
let css = `
body:after {
content: ${!this._acc.options.icon.useEmojis ? '"mic"' : '"🎤"'};
${!this._acc.options.icon.useEmojis ? `font-family: '` + this._acc.options.icon.fontFamily + `';` : ''}
position: fixed;
z-index: 1100;
top: 1vw;
right: 1vw;
width: 36px;
height: 36px;
font-size: 30px;
line-height: 36px;
border-radius: 50%;
background: rgba(255,255,255,0.7);
display: flex;
justify-content: center;
aling-items: center;
}
body._access-listening:after {
animation: _access-listening-animation 2s infinite ease;
}
_access-listening-animation {
0% {background-color: transparent;}
50% {background-color: #EF9A9A;}
}
`;
this._acc.common.injectStyle(css, { className: className });
this._acc.common.deployedObjects.set('.' + className, true);
let inputs = document.querySelectorAll('input[type="text"], input[type="search"], textarea, [contenteditable]');
for (let i = 0; i < inputs.length; i++) {
inputs[i].addEventListener('blur', () => {
if (typeof this._acc.recognition === 'object' && typeof this._acc.recognition.stop === 'function')
this._acc.recognition.stop();
}, false);
inputs[i].addEventListener('focus', this._acc.listen.bind(this._acc), false);
inputs[i].parentElement.classList.add('_access-mic');
}
sTextList.classList.add('active');
}
else
remove();
}
disableAnimations(destroy: boolean) {
const className = '_access-disable-animations', autoplayStopped = 'data-autoplay-stopped';
const remove = () => {
document.querySelector('._access-menu [data-access-action="disableAnimations"]').classList.remove('active');
this._acc.stateValues.disableAnimations = false;
let style = document.querySelector('.' + className);
if (style) {
style.parentElement.removeChild(style);
this._acc.common.deployedObjects.remove('.' + className);
}
let allImages = document.querySelectorAll('[data-org-src]') as NodeListOf<HTMLImageElement>;
allImages.forEach(async i => {
const screenshot = i.src;
i.setAttribute('src', i.getAttribute('data-org-src'));
i.setAttribute('data-org-src', screenshot);
});
const allVideos = document.querySelectorAll(`video[${autoplayStopped}]`) as NodeListOf<HTMLVideoElement>;
allVideos.forEach(v => {
v.setAttribute('autoplay', '');
v.removeAttribute(autoplayStopped);
v.play();
});
};
if (destroy) {
remove();
return;
}
this._acc.stateValues.disableAnimations = !this._acc.stateValues.disableAnimations;
if (!this._acc.stateValues.disableAnimations) {
remove();
return;
}
document.querySelector('._access-menu [data-access-action="disableAnimations"]').classList.add('active');
let css = `
body * {
animation-duration: 0.0ms !important;
transition-duration: 0.0ms !important;
}
`;
this._acc.common.injectStyle(css, { className: className });
this._acc.common.deployedObjects.set('.' + className, true);
const allImages = document.querySelectorAll('img');
allImages.forEach(async i => {
let ext = this._acc.common.getFileExtension(i.src);
if (ext && ext.toLowerCase() === 'gif') {
let screenshot = i.getAttribute('data-org-src');
if (!screenshot)
screenshot = await this._acc.common.createScreenshot(i.src);
i.setAttribute('data-org-src', i.src);
i.src = screenshot;
}
});
const allVideos = document.querySelectorAll('video[autoplay]') as NodeListOf<HTMLVideoElement>;
allVideos.forEach(v => {
v.setAttribute(autoplayStopped, '');
v.removeAttribute('autoplay');
v.pause();
});
}
iframeModals(destroy?: boolean, button?: HTMLElement) {
if (!button)
destroy = true;
const close = () => {
if (this._dialog) {
this._dialog.classList.add('closing');
setTimeout(() => {
this._dialog.classList.remove('closing');
this._dialog.close();
this._dialog.remove();
}, 350);
detach();
}
if (button)
button.classList.remove('active');
};
const onClose = () => {
close();
};
const detach = () => {
this._dialog.querySelector('button').removeEventListener('click', onClose, false);
this._dialog.removeEventListener('close', onClose);
};
if (destroy) {
close();
}
else {
button.classList.add('active');
if (!this._dialog)
this._dialog = document.createElement('dialog');
this._dialog.classList.add('_access');
this._dialog.innerHTML = '';
this._dialog.appendChild(this._acc.common.jsonToHtml({
type: 'div',
children: [
{
type: 'div',
children: [
{
type: 'button',
attrs: {
role: 'button',
'class': this._acc.options.icon.useEmojis ? '' : 'material-icons',
style: `position: absolute;
top: 5px;
cursor: pointer;
font-size: 24px !important;
font-weight: bold;
background: transparent;
border: none;
left: 5px;
color: #d63c3c;
padding: 0;`
},
children: [
{
type: '#text',
text: this._acc.options.icon.useEmojis ? 'X' : 'close'
}
]
}
]
},
{
type: 'div',
children: [
{
type: 'iframe',
attrs: {
src: button.getAttribute('data-access-url'),
style: 'width: 50vw;height: 50vh;padding: 30px;'
}
}
]
}
]
}));
document.body.appendChild(this._dialog);
this._dialog.querySelector('button').addEventListener('click', onClose, false);
this._dialog.addEventListener('close', onClose);
this._dialog.showModal();
}
}
customFunctions(destroy?: boolean, button?: HTMLElement) {
if (!button)
return;
const cf = this._acc.options.customFunctions[parseInt(button.getAttribute('data-access-custom-index'))];
if (cf.toggle && button.classList.contains('active'))
destroy = true;
if (destroy) {
if (cf.toggle)
button.classList.remove('active');
cf.method(cf, false);
}
else {
if (cf.toggle)
button.classList.add('active');
cf.method(cf, true);
}
}
increaseLineHeight() {
this._acc.alterLineHeight(true);
}
decreaseLineHeight() {
this._acc.alterLineHeight(false);
}
}