UNPKG

jodit

Version:

Jodit is awesome and usefully wysiwyg editor with filebrowser

307 lines (254 loc) 7.74 kB
/*! * 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 { IControlTypeStrong, IToolbarButton, IToolbarCollection } from '../../types/toolbar'; import { Dom } from '../Dom'; import { asArray, camelCase } from '../helpers/'; import { ToolbarElement } from './element'; import { PopupList } from '../popup/list'; import { Popup } from '../popup/popup'; import { ToolbarTooltip } from './tooltip'; import { IViewBased } from '../../types'; import { isJoditObject } from '../helpers/checker/isJoditObject'; import { KEY_ENTER } from '../../constants'; import { ToolbarIcon } from './icon'; export class ToolbarButton extends ToolbarElement implements IToolbarButton { set disable(disable: boolean) { this.__disabled = disable; this.container.classList.toggle('jodit_disabled', disable); if (!disable) { if (this.container.hasAttribute('disabled')) { this.container.removeAttribute('disabled'); } } else { if (!this.container.hasAttribute('disabled')) { this.container.setAttribute('disabled', 'disabled'); } } } get disable(): boolean { return this.__disabled; } set active(enable: boolean) { this.__actived = enable; this.container.classList.toggle('jodit_active', enable); } get active(): boolean { return this.__actived; } private __disabled: boolean = false; private __actived: boolean = false; private tooltip: ToolbarTooltip; readonly control: IControlTypeStrong; readonly target: HTMLElement | undefined; textBox: HTMLSpanElement; anchor: HTMLAnchorElement; isDisable(): boolean { return Boolean( this.parentToolbar && this.parentToolbar.buttonIsDisabled(this) ); } isActive(): boolean { return Boolean( this.parentToolbar && this.parentToolbar.buttonIsActive(this) ); } private onMouseDown = (originalEvent: MouseEvent | KeyboardEvent): false | void => { if (originalEvent.type === 'keydown' && originalEvent.which !== KEY_ENTER) { return; } originalEvent.stopImmediatePropagation(); originalEvent.preventDefault(); if (this.disable) { return false; } const control: IControlTypeStrong = this.control, getTarget = (): Node | false => (this.parentToolbar && this.parentToolbar.getTarget(this)) || this.target || false; if (control.list) { const list: PopupList = new PopupList( this.jodit, this.container, this.target ); list.open(control); this.jodit.events.fire('closeAllPopups', list.container); this.anchor.setAttribute('aria-expanded', 'true'); this.jodit.events.on(list, 'afterClose', () => { this.anchor.setAttribute('aria-expanded', 'false'); }); } else if (control.exec !== undefined && typeof control.exec === 'function') { control.exec(this.jodit, getTarget(), control, originalEvent, this.container as HTMLLIElement); this.jodit.events.fire('synchro'); if (this.parentToolbar) { this.parentToolbar.immedateCheckActiveButtons(); } /** * Fired after calling `button.exec` function * @event afterExec */ this.jodit.events.fire('closeAllPopups afterExec'); } else if ( control.popup !== undefined && typeof control.popup === 'function' ) { const popup: Popup = new Popup( this.jodit, this.container, this.target ); if ( this.jodit.events.fire( camelCase('before-' + control.name + '-OpenPopup'), getTarget(), control, popup ) !== false ) { const popupElm = control.popup( this.jodit, getTarget(), control, popup.close, this ); if (popupElm) { popup.open(popupElm); } } /** * Fired after popup was opened for some control button * @event after{CONTROLNAME}OpenPopup */ /** * Close all opened popups * * @event closeAllPopups */ this.jodit.events.fire( camelCase('after-' + control.name + '-OpenPopup') + ' closeAllPopups', popup.container ); } else { if (control.command || control.name) { if (isJoditObject(this.jodit)) { this.jodit.execCommand( control.command || control.name, (control.args && control.args[0]) || false, (control.args && control.args[1]) || null ); } else { this.jodit.ownerDocument.execCommand( control.command || control.name, (control.args && control.args[0]) || false, (control.args && control.args[1]) || null ); } this.jodit.events.fire('closeAllPopups'); } } }; get tooltipText(): string { if (!this.control.tooltip) { return ''; } return this.jodit.i18n(this.control.tooltip) + (this.control.hotkeys ? '<br>' + asArray(this.control.hotkeys).join(' ') : ''); } focus() { this.anchor.focus(); } constructor( parentToolbarOrView: IToolbarCollection | IViewBased, control: IControlTypeStrong, target?: HTMLElement ) { super(parentToolbarOrView); this.control = control; this.target = target; this.anchor = this.jodit.create.element('a', { "role": "button", "href": "javascript:void(0)" }); let tabIndex = '-1'; if (this.jodit.options.allowTabNavigation) { tabIndex = '0'; } this.anchor.setAttribute('tabindex', tabIndex); this.container.appendChild(this.anchor); if (this.jodit.options.showTooltip && control.tooltip) { if (!this.jodit.options.useNativeTooltip) { this.tooltip = new ToolbarTooltip(this); } else { this.anchor.setAttribute('title', this.tooltipText); } this.anchor.setAttribute('aria-label', this.tooltipText); } this.textBox = this.jodit.create.span(); this.anchor.appendChild(this.textBox); const clearName: string = control.name.replace(/[^a-zA-Z0-9]/g, '_'); if (control.getContent && typeof control.getContent === 'function') { Dom.detach(this.container); const content = control.getContent(this.jodit, control, this); this.container.appendChild( typeof content === 'string' ? this.jodit.create.fromHTML(content) : content ); } else { if (control.list && this.anchor) { const trigger = this.jodit.create.fromHTML(ToolbarIcon.getIcon('dropdown-arrow')); trigger.classList.add('jodit_with_dropdownlist-trigger'); this.container.classList.add('jodit_with_dropdownlist'); this.anchor.appendChild(trigger); } this.textBox.appendChild(this.createIcon(clearName, control)); } this.container.classList.add('jodit_toolbar_btn-' + clearName); if (this.jodit.options.direction) { const direction = this.jodit.options.direction.toLowerCase(); this.container.style.direction = direction === 'rtl' ? 'rtl' : 'ltr'; } if (control.isInput) { this.container.classList.add('jodit_toolbar-input'); } else { /** * You can emulate click on some button * * @event click-%buttonName%-btn * @example * ```javascript * var editor = new Jodit('#editor'); * editor.events.fire('click-image-btn'); // will open Image popup * ``` */ this.jodit.events .on(this.container, 'mousedown touchend keydown', this.onMouseDown) .on(`click-${clearName}-btn`, this.onMouseDown); } } destruct() { if (this.isDestructed) { return; } this.jodit && this.jodit.events && this.jodit.events.off(this.container); super.destruct(); if (this.tooltip) { this.tooltip.destruct(); delete this.tooltip; } } }