jodit
Version:
Jodit is awesome and usefully wysiwyg editor with filebrowser
227 lines (183 loc) • 5.02 kB
text/typescript
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Licensed under GNU General Public License version 2 or later or a commercial license;
* Copyright 2013-2019 Valeriy Chupurnov https://xdsoft.net
*/
import { IBound } from '../../types/types';
import { IViewBased } from '../../types/view';
import { Dom } from '../Dom';
import { css, offset, throttle } from '../helpers/';
import { Component } from '../Component';
import { IControlTypeStrong } from '../../types';
export class Popup extends Component {
private calcPosition() {
if (!this.isOpened || this.isDestructed) {
return;
}
const popup: HTMLElement = this.container;
const offsetContainer: IBound = offset(
this.jodit.container as HTMLDivElement,
this.jodit,
this.jodit.ownerDocument,
true
);
const offsetPopup: IBound = offset(
popup,
this.jodit,
this.jodit.ownerDocument,
true
);
const marginLeft: number = (css(popup, 'marginLeft') as number) || 0;
offsetPopup.left -= marginLeft;
let diffLeft: number = marginLeft;
let width: number | string = 'auto';
if (offsetPopup.left < offsetContainer.left) {
diffLeft = offsetContainer.left - offsetPopup.left;
} else if (
offsetPopup.left + offsetPopup.width >=
offsetContainer.left + offsetContainer.width
) {
diffLeft = -(
offsetPopup.left +
offsetPopup.width -
(offsetContainer.left + offsetContainer.width)
);
} else {
diffLeft = 0;
}
if (offsetPopup.width >= offsetContainer.width) {
diffLeft = offsetContainer.left - offsetPopup.left;
width = offsetContainer.width;
}
if (diffLeft !== marginLeft) {
try {
popup.style.setProperty(
'margin-left',
diffLeft + 'px',
'important'
);
} catch {
popup.style.marginLeft = diffLeft + 'px'; // fallback for ie9
}
}
const triangle: HTMLSpanElement | null = popup.querySelector(
'.jodit_popup_triangle'
);
if (triangle) {
triangle.style.marginLeft = -diffLeft + 'px';
}
css(popup, 'width', width);
}
private throttleCalcPosition = throttle(
this.calcPosition,
this.jodit.defaultTimeout
);
protected doOpen(content: string | HTMLElement | IControlTypeStrong) {
if (!content) {
return;
}
Dom.detach(this.container);
this.container.innerHTML = '<span class="jodit_popup_triangle"></span>';
this.container.appendChild(
Dom.isNode(content, this.jodit.ownerWindow)
? content
: this.jodit.create.fromHTML(content.toString())
);
this.container.style.display = 'block';
this.container.style.marginLeft = null;
}
protected doClose() {
// do nothing
}
isOpened: boolean = false;
/**
* @param {HTMLElement} content
* @param {boolean} [rightAlign=false] Open popup on right side
* @param {boolean} [noStandartActions=false] No call standarts action
*/
open(
content: string | HTMLElement | IControlTypeStrong,
rightAlign?: boolean,
noStandartActions: boolean = false
) {
Jodit.fireEach('beforeOpenPopup closeAllPopups', this, content); // close popups in another editors too
noStandartActions || this.jodit.events.on('closeAllPopups', this.close);
this.container.classList.add(this.className + '-open');
this.doOpen(content);
this.target.appendChild(this.container);
if (this.jodit.options.textIcons) {
this.firstInFocus();
}
if (rightAlign !== undefined) {
this.container.classList.toggle('jodit_right', rightAlign);
}
if (!noStandartActions && this.container.parentNode) {
this.jodit.events.fire(
this.container.parentNode,
'afterOpenPopup',
this.container
);
}
this.isOpened = true;
!noStandartActions && this.calcPosition();
}
close = (current?: HTMLElement | Popup) => {
if (!this.isOpened && !this.isDestructed) {
return;
}
if (
!current ||
!Dom.isOrContains(
this.container,
current instanceof Popup ? current.target : current
)
) {
this.isOpened = false;
this.jodit.events.off('closeAllPopups', this.close);
this.doClose();
Dom.safeRemove(this.container);
this.jodit.events.fire('removeMarkers');
this.jodit.events.fire(this, 'afterClose');
}
};
public container: HTMLElement;
constructor(
jodit: IViewBased,
readonly target: HTMLElement,
readonly current?: HTMLElement,
readonly className: string = 'jodit_toolbar_popup'
) {
super(jodit);
this.container = this.jodit.create.div(className, {
'data-editor_id': jodit.id
});
this.jodit.events
.on(
this.container,
'mousedown touchstart touchend',
(e: MouseEvent) => {
e.stopPropagation();
}
)
.on(
[this.jodit.ownerWindow, this.jodit.events],
'resize',
this.throttleCalcPosition
);
}
firstInFocus() {}
destruct() {
if (this.isDestructed) {
return;
}
this.jodit.events.off(
[this.jodit.ownerWindow, this.jodit.events],
'resize',
this.throttleCalcPosition
);
Dom.safeRemove(this.container);
delete this.container;
super.destruct();
}
}
import { Jodit } from '../../Jodit';