jodit
Version:
Jodit is awesome and usefully wysiwyg editor with filebrowser
420 lines (400 loc) • 7.96 kB
text/typescript
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Licensed under GNU General Public License version 2 or later or a commercial license or MIT;
* For GPL see LICENSE-GPL.txt in the project root for license information.
* For MIT see LICENSE-MIT.txt in the project root for license information.
* For commercial licenses see https://xdsoft.net/jodit/commercial/
* Copyright (c) 2013-2019 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/
import { Config } from '../Config';
import { KEY_DOWN, KEY_ENTER, KEY_LEFT, KEY_RIGHT, KEY_UP } from '../constants';
import { Alert, Dialog } from '../modules/dialog/';
import { IControlType } from '../types/toolbar';
import { IJodit } from '../types';
declare module '../Config' {
interface Config {
specialCharacters: string[];
usePopupForSpecialCharacters: boolean;
}
}
Config.prototype.usePopupForSpecialCharacters = false;
Config.prototype.specialCharacters = [
'!',
'"',
'#',
'$',
'%',
'&',
"'",
'(',
')',
'*',
'+',
'-',
'.',
'/',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
':',
';',
'<',
'=',
'>',
'?',
'@',
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'[',
']',
'^',
'_',
'`',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'{',
'|',
'}',
'~',
'€',
'‘',
'’',
'“',
'”',
'–',
'—',
'¡',
'¢',
'£',
'¤',
'¥',
'¦',
'§',
'¨',
'©',
'ª',
'«',
'»',
'¬',
'®',
'¯',
'°',
'²',
'³',
'´',
'µ',
'¶',
'·',
'¸',
'¹',
'º',
'¼',
'½',
'¾',
'¿',
'À',
'Á',
'Â',
'Ã',
'Ä',
'Å',
'Æ',
'Ç',
'È',
'É',
'Ê',
'Ë',
'Ì',
'Í',
'Î',
'Ï',
'Ð',
'Ñ',
'Ò',
'Ó',
'Ô',
'Õ',
'Ö',
'×',
'Ø',
'Ù',
'Ú',
'Û',
'Ü',
'Ý',
'Þ',
'ß',
'à',
'á',
'â',
'ã',
'ä',
'å',
'æ',
'ç',
'è',
'é',
'ê',
'ë',
'ì',
'í',
'î',
'ï',
'ð',
'ñ',
'ò',
'ó',
'ô',
'õ',
'ö',
'÷',
'ø',
'ù',
'ú',
'û',
'ü',
'ý',
'þ',
'ÿ',
'Œ',
'œ',
'Ŵ',
'Ŷ',
'ŵ',
'ŷ',
'‚',
'‛',
'„',
'…',
'™',
'►',
'•',
'→',
'⇒',
'⇔',
'♦',
'≈'
];
Config.prototype.controls.symbol = {
icon: 'omega',
hotkeys: ['ctrl+shift+i', 'cmd+shift+i'],
tooltip: 'Insert Special Character',
popup: (editor: IJodit, current, control, close): any => {
const container: HTMLElement | undefined = editor.events.fire(
'generateSpecialCharactersTable.symbols'
);
if (container) {
if (editor.options.usePopupForSpecialCharacters) {
const box: HTMLDivElement = editor.ownerDocument.createElement(
'div'
);
box.classList.add('jodit_symbols');
box.appendChild(container);
editor.events.on(container, 'close_dialog', close);
return box;
} else {
const dialog: Dialog = Alert(
container,
editor.i18n('Select Special Character'),
void 0,
'jodit_symbols'
);
const a: HTMLAnchorElement | null = container.querySelector(
'a'
);
a && a.focus();
editor.events.on('beforeDestruct', () => {
dialog && dialog.close();
});
}
}
}
} as IControlType;
/**
* The plugin inserts characters that are not part of the standard keyboard.
*/
export class symbols {
private countInRow: number = 17;
constructor(editor: IJodit) {
editor.events.on('generateSpecialCharactersTable.symbols', () => {
const container: HTMLDivElement = editor.create.fromHTML(
'<div class="jodit_symbols-container">' +
'<div class="jodit_symbols-container_table"><table><tbody></tbody></table></div>' +
'<div class="jodit_symbols-container_preview"><div class="jodit_symbols-preview"></div></div>' +
'</div>'
) as HTMLDivElement,
preview: HTMLDivElement = container.querySelector(
'.jodit_symbols-preview'
) as HTMLDivElement,
table: HTMLTableElement = container.querySelector(
'table'
) as HTMLTableElement,
body: HTMLTableSectionElement = table.tBodies[0],
chars: HTMLAnchorElement[] = [];
for (
let i: number = 0;
i < editor.options.specialCharacters.length;
) {
const tr: HTMLTableRowElement = editor.create.element('tr');
for (
let j: number = 0;
j < this.countInRow &&
i < editor.options.specialCharacters.length;
j += 1, i += 1
) {
const td: HTMLTableCellElement = editor.create.element(
'td'
),
a: HTMLAnchorElement = editor.create.fromHTML(
`<a
data-index="${i}"
data-index-j="${j}"
href="javascript:void(0)"
role="option"
tabindex="-1"
>${editor.options.specialCharacters[i]}</a>`
) as HTMLAnchorElement;
chars.push(a);
td.appendChild(a);
tr.appendChild(td);
}
body.appendChild(tr);
}
const self: symbols = this;
editor.events
.on(chars, 'focus', function(this: HTMLAnchorElement) {
preview.innerHTML = this.innerHTML;
})
.on(chars, 'mousedown', function(
this: HTMLAnchorElement,
e?: MouseEvent
) {
if (this && this.nodeName === 'A') {
editor.selection.focus();
editor.selection.insertHTML(this.innerHTML);
editor.events.fire(this, 'close_dialog');
e && e.preventDefault();
e && e.stopImmediatePropagation();
}
})
.on(chars, 'mouseenter', function(this: HTMLAnchorElement) {
if (this && this.nodeName === 'A') {
this.focus();
}
})
.on(chars, 'keydown', (e: KeyboardEvent) => {
const target: HTMLAnchorElement = e.target as HTMLAnchorElement;
if (target && target.nodeName === 'A') {
const index: number = parseInt(
target.getAttribute('data-index') || '0',
10
),
jIndex: number = parseInt(
target.getAttribute('data-index-j') || '0',
10
);
let newIndex: number;
switch (e.which) {
case KEY_UP:
case KEY_DOWN:
newIndex =
e.which === KEY_UP
? index - self.countInRow
: index + self.countInRow;
if (chars[newIndex] === undefined) {
newIndex =
e.which === KEY_UP
? Math.floor(
chars.length /
self.countInRow
) *
self.countInRow +
jIndex
: jIndex;
if (newIndex > chars.length - 1) {
newIndex -= self.countInRow;
}
}
chars[newIndex] && chars[newIndex].focus();
break;
case KEY_RIGHT:
case KEY_LEFT:
newIndex =
e.which === KEY_LEFT
? index - 1
: index + 1;
if (chars[newIndex] === undefined) {
newIndex =
e.which === KEY_LEFT
? chars.length - 1
: 0;
}
chars[newIndex] && chars[newIndex].focus();
break;
case KEY_ENTER:
editor.events.fire(target, 'mousedown');
e.stopImmediatePropagation();
e.preventDefault();
break;
}
}
});
return container;
});
}
}