/*! * Jodit Editor (https://xdsoft.net/jodit/) * License GNU General Public License version 2 or later; * Copyright 2013-2019 Valeriy Chupurnov https://xdsoft.net */ import { Config } from '../Config'; import * as consts from '../constants'; import { IS_IE } from '../constants'; import { IBound } from '../types/types'; import { Dom } from '../modules/Dom'; import { $$ } from '../modules/helpers/selector'; import { debounce, setTimeout } from '../modules/helpers/async'; import { offset, innerWidth } from '../modules/helpers/size'; import { css } from '../modules/helpers'; import { IJodit } from '../types'; /** * The module creates a supporting frame for resizing of the elements img and table * @module Resizer * @params {Object} parent Jodit main object */ /** * @property{boolean} useIframeResizer=true Use true frame for editing iframe size */ declare module '../Config' { interface Config { useIframeResizer: boolean; useTableResizer: boolean; useImageResizer: boolean; resizer: { showSize: boolean; hideSizeTimeout: number; min_width: number; min_height: number; }; } } Config.prototype.useIframeResizer = true; /** * @property{boolean} useTableResizer=true Use true frame for editing table size */ Config.prototype.useTableResizer = true; /** * @property{boolean} useImageResizer=true Use true image editing frame size */ Config.prototype.useImageResizer = true; /** * @property {object} resizer * @property {int} resizer.min_width=10 The minimum width for the editable element * @property {int} resizer.min_height=10 The minimum height for the item being edited * @property {boolean} resizer.showSize=true Show size */ Config.prototype.resizer = { showSize: true, hideSizeTimeout: 1000, min_width: 10, min_height: 10, }; /** * Resize table and img * @param {Jodit} editor */ export function resizer(editor: IJodit) { const LOCK_KEY = 'resizer'; let handle: HTMLElement, currentElement: null | HTMLElement, resizeElementClicked: boolean = false, isResizing: boolean = false, start_x: number, start_y: number, width: number, height: number, ratio: number, new_h: number, new_w: number, diff_x: number, diff_y: number, resizerIsVisible: boolean = false, timeoutSizeViewer: number = 0; const resizerElm: HTMLElement = editor.create.fromHTML( '
' ), sizeViewer: HTMLSpanElement = resizerElm.getElementsByTagName( 'span' )[0], hideResizer = () => { isResizing = false; resizerIsVisible = false; currentElement = null; resizerElm.style.display = 'none'; }, hideSizeViewer = () => { sizeViewer.style.opacity = '0'; }, showSizeViewer = (w: number, h: number) => { if (!editor.options.resizer.showSize) { return; } if (w < sizeViewer.offsetWidth || h < sizeViewer.offsetHeight) { hideSizeViewer(); return; } sizeViewer.style.opacity = '1'; sizeViewer.innerHTML = `${w} x ${h}`; clearTimeout(timeoutSizeViewer); timeoutSizeViewer = setTimeout( hideSizeViewer, editor.options.resizer.hideSizeTimeout ); }, updateSize = () => { if (resizerIsVisible && currentElement && resizerElm) { const workplacePosition: IBound = offset( (resizerElm.parentNode || editor.ownerDocument .documentElement) as HTMLElement, editor, editor.ownerDocument, true ), pos: IBound = offset( currentElement, editor, editor.editorDocument ), left: number = parseInt(resizerElm.style.left || '0', 10), top: number = parseInt(resizerElm.style.top || '0', 10), w: number = resizerElm.offsetWidth, h: number = resizerElm.offsetHeight; // 1 - because need move border higher and toWYSIWYG the left than the picture // 2 - in box-sizing: border-box mode width is real width indifferent by border-width. const newTop: number = pos.top - 1 - workplacePosition.top, newLeft: number = pos.left - 1 - workplacePosition.left; if ( top !== newTop || left !== newLeft || w !== currentElement.offsetWidth || h !== currentElement.offsetHeight ) { resizerElm.style.top = newTop + 'px'; resizerElm.style.left = newLeft + 'px'; resizerElm.style.width = currentElement.offsetWidth + 'px'; resizerElm.style.height = currentElement.offsetHeight + 'px'; if (editor.events) { editor.events.fire(currentElement, 'changesize'); // check for first init. Ex. inlinePopup hides when it was fired if (!isNaN(left)) { editor.events.fire('resize'); } } } } }, showResizer = () => { if (editor.options.readonly) { return; } if (!resizerElm.parentNode) { editor.workplace.appendChild(resizerElm); } resizerIsVisible = true; resizerElm.style.display = 'block'; if (editor.isFullSize()) { resizerElm.style.zIndex = css( editor.container, 'zIndex' ).toString(); } updateSize(); }, /** * Bind an edit element toWYSIWYG element * @param {HTMLElement} element The element that you want toWYSIWYG add a function toWYSIWYG resize */ bind = (element: HTMLElement) => { let wrapper: HTMLElement; if (element.tagName === 'IFRAME') { const iframe = element; if ( element.parentNode && (element.parentNode as HTMLElement).getAttribute( 'data-jodit_iframe_wrapper' ) ) { element = element.parentNode as HTMLElement; } else { wrapper = editor.create.inside.fromHTML( '