UNPKG

suneditor

Version:

Vanilla JavaScript based WYSIWYG web editor

199 lines (173 loc) 5.66 kB
import { keyCodeMap } from '../../../../helper'; import { Figure } from '../../../../modules/contract'; import { SIZE_UNIT } from '../shared/image.constants'; /** * @class ImageSizeService * @description Handles image resizing, proportion calculations, and size input management. */ export class ImageSizeService { #main; #$; #state; #pluginOptions; #resizing; #origin_w; #origin_h; #ratio = { w: 0, h: 0 }; #proportion = null; #inputX = null; #inputY = null; /** * @param {import('../index').default} main - The main Image_ plugin instance. * @param {import('../render/image.html').ModalReturns_image} modalEl - Modal element */ constructor(main, modalEl) { this.#main = main; this.#$ = main.$; this.#state = main.state; this.#pluginOptions = main.pluginOptions; this.#resizing = this.#pluginOptions.canResize; this.#origin_w = this.#pluginOptions.defaultWidth === 'auto' ? '' : this.#pluginOptions.defaultWidth; this.#origin_h = this.#pluginOptions.defaultHeight === 'auto' ? '' : this.#pluginOptions.defaultHeight; if (this.#resizing) { this.#proportion = modalEl.proportion; this.#inputX = modalEl.inputX; this.#inputY = modalEl.inputY; this.#inputX.value = this.#pluginOptions.defaultWidth; this.#inputY.value = this.#pluginOptions.defaultHeight; const ratioChange = this.#OnChangeRatio.bind(this); this.#$.eventManager.addEvent(this.#inputX, 'keyup', this.#OnInputSize.bind(this, 'x')); this.#$.eventManager.addEvent(this.#inputY, 'keyup', this.#OnInputSize.bind(this, 'y')); this.#$.eventManager.addEvent(this.#inputX, 'change', ratioChange); this.#$.eventManager.addEvent(this.#inputY, 'change', ratioChange); this.#$.eventManager.addEvent(this.#proportion, 'change', ratioChange); this.#$.eventManager.addEvent(modalEl.revertBtn, 'click', this.#OnClickRevert.bind(this)); } } /** * @description Sets the width and height input values. * @param {string} w - Width value * @param {string} h - Height value */ setInputSize(w, h) { this.#inputX.value = w === 'auto' ? '' : w; if (this.#state.onlyPercentage) return; this.#inputY.value = h === 'auto' ? '' : h; } /** * @description Gets the current width and height input values. * @returns {{w: string, h: string}} */ getInputSize() { return { w: this.#inputX?.value || '', h: this.#inputY?.value || '', }; } /** * @description Sets the original width and height of the image. * @param {string} w - Original width * @param {string} h - Original height */ setOriginSize(w, h) { this.#origin_w = w; this.#origin_h = h; } /** * @description Applies the specified width and height to the image. * @param {string} w - Image width. * @param {string} h - Image height. */ applySize(w, h) { w ||= this.#inputX?.value || this.#pluginOptions.defaultWidth; h ||= this.#inputY?.value || this.#pluginOptions.defaultHeight; if (this.#state.onlyPercentage) { if (!w) w = '100%'; else if (!/%$/.test(w)) w += SIZE_UNIT.PERCENTAGE; } this.#main.figure.setSize(w, h); } /** * @description Called when the modal is opened. Resets size inputs to default. */ on() { if (!this.#resizing) return; const x = this.#pluginOptions.defaultWidth; const y = this.#pluginOptions.defaultHeight; this.setInputSize(x, y); this.setOriginSize(x, y); } /** * @description Prepares the size inputs and proportion state when an image is selected. * @param {SunEditor.Module.Figure.TargetInfo} figureInfo - Figure size information * @param {string} w - Current width * @param {string} h - Current height */ ready(figureInfo, w, h) { this.setInputSize(w, h); const percentageRotation = this.#state.onlyPercentage && this.#main.figure.isVertical; this.#proportion.checked = true; this.#inputX.disabled = percentageRotation; this.#inputY.disabled = percentageRotation; this.#proportion.disabled = percentageRotation; this.#ratio = this.#proportion.checked ? figureInfo.ratio : { w: 0, h: 0, }; } /** * @description Initializes the size service state. */ init() { this.#ratio = { w: 0, h: 0, }; if (this.#resizing) { this.setInputSize(this.#pluginOptions.defaultWidth, this.#pluginOptions.defaultHeight); this.#proportion.checked = true; } } /** * @description Handles keyup events on size inputs to calculate proportion. * @param {'x'|'y'} xy - Axis (`'x'` for width, `'y'` for height) * @param {KeyboardEvent} e - Event object */ #OnInputSize(xy, e) { if (keyCodeMap.isSpace(e.code)) { e.preventDefault(); return; } const target = /** @type {HTMLInputElement} */ (e.target); if (xy === 'x' && this.#state.onlyPercentage && Number(target.value) > 100) { target.value = '100'; } else if (this.#proportion.checked) { const ratioSize = Figure.CalcRatio(this.#inputX.value, this.#inputY.value, this.#state.sizeUnit, this.#ratio); if (xy === 'x') { this.#inputY.value = String(ratioSize.h); } else { this.#inputX.value = String(ratioSize.w); } } } /** * @description Updates the ratio based on current input values. */ #OnChangeRatio() { this.#ratio = this.#proportion.checked ? Figure.GetRatio(this.#inputX.value, this.#inputY.value, this.#state.sizeUnit) : { w: 0, h: 0 }; } /** * @description Reverts the size inputs to the original image size. */ #OnClickRevert() { if (this.#state.onlyPercentage) { this.#inputX.value = Number(this.#origin_w) > 100 ? '100' : this.#origin_w; } else { this.#inputX.value = this.#origin_w; this.#inputY.value = this.#origin_h; } } } export default ImageSizeService;