UNPKG

suneditor

Version:

Pure JavaScript based WYSIWYG web editor

761 lines (635 loc) 37.4 kB
/* * wysiwyg web editor * * suneditor.js * Copyright 2017 JiHong Lee. * MIT license. */ 'use strict'; export default { name: 'resizing', add: function (core) { const context = core.context; context.resizing = { _resizeClientX: 0, _resizeClientY: 0, _resize_plugin: '', _resize_w: 0, _resize_h: 0, _origin_w: 0, _origin_h: 0, _rotateVertical: false, _resize_direction: '', _move_path: null, _isChange: false }; /** resize controller, button */ let resize_div_container = this.setController_resize.call(core); context.resizing.resizeContainer = resize_div_container; context.resizing.resizeDiv = resize_div_container.querySelector('.se-modal-resize'); context.resizing.resizeDot = resize_div_container.querySelector('.se-resize-dot'); context.resizing.resizeDisplay = resize_div_container.querySelector('.se-resize-display'); let resize_button = this.setController_button.call(core); context.resizing.resizeButton = resize_button; resize_button.addEventListener('mousedown', function (e) { e.stopPropagation(); }, false); let resize_handles = context.resizing.resizeHandles = context.resizing.resizeDot.querySelectorAll('span'); context.resizing.resizeButtonGroup = resize_button.querySelector('._se_resizing_btn_group'); context.resizing.rotationButtons = resize_button.querySelectorAll('._se_resizing_btn_group ._se_rotation'); context.resizing.percentageButtons = resize_button.querySelectorAll('._se_resizing_btn_group ._se_percentage'); context.resizing.alignMenu = resize_button.querySelector('.se-resizing-align-list'); context.resizing.alignMenuList = context.resizing.alignMenu.querySelectorAll('button'); context.resizing.alignButton = resize_button.querySelector('._se_resizing_align_button'); context.resizing.alignButtonIcon = context.resizing.alignButton.querySelector('i'); context.resizing.autoSizeButton = resize_button.querySelector('._se_resizing_btn_group ._se_auto_size'); context.resizing.captionButton = resize_button.querySelector('._se_resizing_caption_button'); /** add event listeners */ resize_handles[0].addEventListener('mousedown', this.onMouseDown_resize_handle.bind(core)); resize_handles[1].addEventListener('mousedown', this.onMouseDown_resize_handle.bind(core)); resize_handles[2].addEventListener('mousedown', this.onMouseDown_resize_handle.bind(core)); resize_handles[3].addEventListener('mousedown', this.onMouseDown_resize_handle.bind(core)); resize_handles[4].addEventListener('mousedown', this.onMouseDown_resize_handle.bind(core)); resize_handles[5].addEventListener('mousedown', this.onMouseDown_resize_handle.bind(core)); resize_handles[6].addEventListener('mousedown', this.onMouseDown_resize_handle.bind(core)); resize_handles[7].addEventListener('mousedown', this.onMouseDown_resize_handle.bind(core)); resize_button.addEventListener('click', this.onClick_resizeButton.bind(core)); /** append html */ context.element.relative.appendChild(resize_div_container); context.element.relative.appendChild(resize_button); /** empty memory */ resize_div_container = null, resize_button = null, resize_handles = null; }, /** resize controller, button (image, iframe) */ setController_resize: function () { const resize_container = this.util.createElement('DIV'); resize_container.className = 'se-resizing-container'; resize_container.style.display = 'none'; resize_container.innerHTML = '' + '<div class="se-modal-resize"></div>' + '<div class="se-resize-dot">' + '<span class="tl"></span>' + '<span class="tr"></span>' + '<span class="bl"></span>' + '<span class="br"></span>' + '<span class="lw"></span>' + '<span class="th"></span>' + '<span class="rw"></span>' + '<span class="bh"></span>' + '<div class="se-resize-display"></div>' + '</div>'; return resize_container; }, setController_button: function () { const lang = this.lang; const resize_button = this.util.createElement("DIV"); resize_button.className = "se-controller se-controller-resizing"; resize_button.innerHTML = '' + '<div class="se-arrow se-arrow-up"></div>' + '<div class="se-btn-group _se_resizing_btn_group">' + '<button type="button" data-command="percent" data-value="1" class="se-tooltip _se_percentage">' + '<span>100%</span>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.resize100 + '</span></span>' + '</button>' + '<button type="button" data-command="percent" data-value="0.75" class="se-tooltip _se_percentage">' + '<span>75%</span>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.resize75 + '</span></span>' + '</button>' + '<button type="button" data-command="percent" data-value="0.5" class="se-tooltip _se_percentage">' + '<span>50%</span>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.resize50 + '</span></span>' + '</button>' + '<button type="button" data-command="auto" class="se-tooltip _se_auto_size">' + '<i class="se-icon-auto-size"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.autoSize + '</span></span>' + '</button>' + '<button type="button" data-command="rotate" data-value="-90" class="se-tooltip _se_rotation">' + '<i class="se-icon-rotate-left"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.rotateLeft + '</span></span>' + '</button>' + '<button type="button" data-command="rotate" data-value="90" class="se-tooltip _se_rotation">' + '<i class="se-icon-rotate-right"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.rotateRight + '</span></span>' + '</button>' + '</div>' + '<div class="se-btn-group">' + '<button type="button" data-command="mirror" data-value="h" class="se-tooltip">' + '<i class="se-icon-mirror-horizontal"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.mirrorHorizontal + '</span></span>' + '</button>' + '<button type="button" data-command="mirror" data-value="v" class="se-tooltip">' + '<i class="se-icon-mirror-vertical"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.mirrorVertical + '</span></span>' + '</button>' + '<button type="button" data-command="onalign" class="se-tooltip _se_resizing_align_button">' + '<i class="se-icon-align-justify"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.toolbar.align + '</span></span>' + '</button>' + '<div class="se-btn-group-sub sun-editor-common se-list-layer se-resizing-align-list">' + '<div class="se-list-inner">' + '<ul class="se-list-basic">' + '<li><button type="button" class="se-btn-list se-tooltip" data-command="align" data-value="basic">' + '<i class="se-icon-align-justify"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.dialogBox.basic + '</span></span>' + '</button></li>' + '<li><button type="button" class="se-btn-list se-tooltip" data-command="align" data-value="left">' + '<i class="se-icon-align-left"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.dialogBox.left + '</span></span>' + '</button></li>' + '<li><button type="button" class="se-btn-list se-tooltip" data-command="align" data-value="center">' + '<i class="se-icon-align-center"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.dialogBox.center + '</span></span>' + '</button></li>' + '<li><button type="button" class="se-btn-list se-tooltip" data-command="align" data-value="right">' + '<i class="se-icon-align-right"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.dialogBox.right + '</span></span>' + '</button></li>' + '</ul>' + '</div>' + '</div>' + '<button type="button" data-command="caption" class="se-tooltip _se_resizing_caption_button">' + '<i class="se-icon-caption"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.dialogBox.caption + '</span></span>' + '</button>' + '<button type="button" data-command="revert" class="se-tooltip">' + '<i class="se-icon-revert"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.dialogBox.revertButton + '</span></span>' + '</button>' + '<button type="button" data-command="update" class="se-tooltip">' + '<i class="se-icon-modify"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.edit + '</span></span>' + '</button>' + '<button type="button" data-command="delete" class="se-tooltip">' + '<i class="se-icon-delete"></i>' + '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + lang.controller.remove + '</span></span>' + '</button>' + '</div>'; return resize_button; }, _module_getSizeX: function (contextPlugin, element, cover, container) { if (!element) element = contextPlugin._element; if (!cover) cover = contextPlugin._cover; if (!container) container = contextPlugin._container; if (!container || !cover || !element) return ''; return !/%$/.test(element.style.width) ? element.style.width : (this.util.getNumber(container.style.width, 2) || 100) + '%'; }, _module_getSizeY: function (contextPlugin, element, cover, container) { if (!element) element = contextPlugin._element; if (!cover) cover = contextPlugin._cover; if (!container) container = contextPlugin._container; if (!container || !cover || !element) return ''; return this.util.getNumber(cover.style.paddingBottom) > 0 && !this.context.resizing._rotateVertical ? cover.style.height : (!/%$/.test(element.style.height) || !/%$/.test(element.style.width) ? element.style.height : (this.util.getNumber(container.style.height, 2) || 100) + '%'); }, _module_setModifyInputSize: function (contextPlugin, currentModule) { const percentageRotation = contextPlugin._onlyPercentage && this.context.resizing._rotateVertical; contextPlugin.proportion.checked = contextPlugin._proportionChecked = contextPlugin._element.getAttribute('data-proportion') !== 'false'; let x = percentageRotation ? '' : this.plugins.resizing._module_getSizeX.call(this, contextPlugin); if (x === contextPlugin._defaultSizeX) x = ''; if (contextPlugin._onlyPercentage) x = this.util.getNumber(x, 2); contextPlugin.inputX.value = x; currentModule.setInputSize.call(this, 'x'); if (!contextPlugin._onlyPercentage) { let y = percentageRotation ? '' : this.plugins.resizing._module_getSizeY.call(this, contextPlugin); if (y === contextPlugin._defaultSizeY) y = ''; if (contextPlugin._onlyPercentage) y = this.util.getNumber(y, 2); contextPlugin.inputY.value = y; } contextPlugin.inputX.disabled = percentageRotation ? true : false; contextPlugin.inputY.disabled = percentageRotation ? true : false; contextPlugin.proportion.disabled = percentageRotation ? true : false; currentModule.setRatio.call(this); }, _module_setInputSize: function (contextPlugin, xy) { if (contextPlugin._onlyPercentage) { if (xy === 'x' && contextPlugin.inputX.value > 100) contextPlugin.inputX.value = 100; return; } if (contextPlugin.proportion.checked && contextPlugin._ratio && /\d/.test(contextPlugin.inputX.value) && /\d/.test(contextPlugin.inputY.value)) { const xUnit = contextPlugin.inputX.value.replace(/\d+|\./g, '') || contextPlugin.sizeUnit; const yUnit = contextPlugin.inputY.value.replace(/\d+|\./g, '') || contextPlugin.sizeUnit; if (xUnit !== yUnit) return; const dec = xUnit === '%' ? 2 : 0; if (xy === 'x') { contextPlugin.inputY.value = this.util.getNumber(contextPlugin._ratioY * this.util.getNumber(contextPlugin.inputX.value, dec), dec) + yUnit; } else { contextPlugin.inputX.value = this.util.getNumber(contextPlugin._ratioX * this.util.getNumber(contextPlugin.inputY.value, dec), dec) + xUnit; } } }, _module_setRatio: function (contextPlugin) { const xValue = contextPlugin.inputX.value; const yValue = contextPlugin.inputY.value; if (contextPlugin.proportion.checked && /\d+/.test(xValue) && /\d+/.test(yValue)) { const xUnit = xValue.replace(/\d+|\./g, '') || contextPlugin.sizeUnit; const yUnit = yValue.replace(/\d+|\./g, '') || contextPlugin.sizeUnit; if (xUnit !== yUnit) { contextPlugin._ratio = false; } else if (!contextPlugin._ratio) { const x = this.util.getNumber(xValue); const y = this.util.getNumber(yValue); contextPlugin._ratio = true; contextPlugin._ratioX = x / y; contextPlugin._ratioY = y / x; } } else { contextPlugin._ratio = false; } }, _module_sizeRevert: function (contextPlugin) { if (contextPlugin._onlyPercentage) { contextPlugin.inputX.value = contextPlugin._origin_w > 100 ? 100 : contextPlugin._origin_w; } else { contextPlugin.inputX.value = contextPlugin._origin_w; contextPlugin.inputY.value = contextPlugin._origin_h; } }, _module_saveCurrentSize: function (contextPlugin) { const x = this.plugins.resizing._module_getSizeX.call(this, contextPlugin); const y = this.plugins.resizing._module_getSizeY.call(this, contextPlugin); contextPlugin._element.setAttribute('data-size', x + ',' + y); if (!!contextPlugin._videoRatio) contextPlugin._videoRatio = y; }, call_controller_resize: function (targetElement, plugin) { const contextResizing = this.context.resizing; const contextPlugin = this.context[plugin]; contextResizing._resize_plugin = plugin; const resizeContainer = contextResizing.resizeContainer; const resizeDiv = contextResizing.resizeDiv; const offset = this.util.getOffset(targetElement, this.context.element.wysiwygFrame); const isVertical = contextResizing._rotateVertical = /^(90|270)$/.test(Math.abs(targetElement.getAttribute('data-rotate')).toString()); const w = isVertical ? targetElement.offsetHeight : targetElement.offsetWidth; const h = isVertical ? targetElement.offsetWidth : targetElement.offsetHeight; const t = offset.top; const l = offset.left - this.context.element.wysiwygFrame.scrollLeft; resizeContainer.style.top = t + 'px'; resizeContainer.style.left = l + 'px'; resizeContainer.style.width = w + 'px'; resizeContainer.style.height = h + 'px'; resizeDiv.style.top = '0px'; resizeDiv.style.left = '0px'; resizeDiv.style.width = w + 'px'; resizeDiv.style.height = h + 'px'; let align = targetElement.getAttribute('data-align') || 'basic'; align = align === 'none' ? 'basic' : align; // text const container = this.util.getParentElement(targetElement, this.util.isComponent); const cover = this.util.getParentElement(targetElement, 'FIGURE'); const displayX = this.plugins.resizing._module_getSizeX.call(this, contextPlugin, targetElement, cover, container) || 'auto'; const displayY = contextPlugin._onlyPercentage && plugin === 'image' ? '' : ', ' + (this.plugins.resizing._module_getSizeY.call(this, contextPlugin, targetElement, cover, container) || 'auto'); this.util.changeTxt(contextResizing.resizeDisplay, this.lang.dialogBox[align] + ' (' + displayX + displayY + ')'); // resizing display contextResizing.resizeButtonGroup.style.display = contextPlugin._resizing ? '' : 'none'; const resizeDotShow = contextPlugin._resizing && !contextPlugin._resizeDotHide && !contextPlugin._onlyPercentage ? 'flex' : 'none'; const resizeHandles = contextResizing.resizeHandles; for (let i = 0, len = resizeHandles.length; i < len; i++) { resizeHandles[i].style.display = resizeDotShow; } if (contextPlugin._resizing) { const rotations = contextResizing.rotationButtons; rotations[0].style.display = rotations[1].style.display = contextPlugin._rotation ? '' : 'none'; } // align icon const alignList = contextResizing.alignMenuList; this.util.removeClass(contextResizing.alignButtonIcon, 'se-icon-align\\-[a-z]+'); this.util.addClass(contextResizing.alignButtonIcon, 'se-icon-align-' + (align === 'basic' ? 'justify' : align)); for (let i = 0, len = alignList.length; i < len; i++) { if (alignList[i].getAttribute('data-value') === align) this.util.addClass(alignList[i], 'on'); else this.util.removeClass(alignList[i], 'on'); } // percentage active const pButtons = contextResizing.percentageButtons; const value = /%$/.test(targetElement.style.width) && /%$/.test(container.style.width) ? (this.util.getNumber(container.style.width) / 100) + '' : '' ; for (let i = 0, len = pButtons.length; i < len; i++) { if (pButtons[i].getAttribute('data-value') === value) { this.util.addClass(pButtons[i], 'active'); } else { this.util.removeClass(pButtons[i], 'active'); } } // caption display, active if (!contextPlugin._captionShow) { contextResizing.captionButton.style.display = 'none'; } else { contextResizing.captionButton.style.display = ''; if (this.util.getChildElement(targetElement.parentNode, 'figcaption')) { this.util.addClass(contextResizing.captionButton, 'active'); contextPlugin._captionChecked = true; } else { this.util.removeClass(contextResizing.captionButton, 'active'); contextPlugin._captionChecked = false; } } this._resizingName = plugin; this.controllersOn(contextResizing.resizeContainer, contextResizing.resizeButton); // button group const overLeft = this.context.element.wysiwygFrame.offsetWidth - l - contextResizing.resizeButton.offsetWidth; contextResizing.resizeButton.style.top = (h + t + 60) + 'px'; contextResizing.resizeButton.style.left = (l + (overLeft < 0 ? overLeft : 0)) + 'px'; if (overLeft < 0) { contextResizing.resizeButton.firstElementChild.style.left = (20 - overLeft) + 'px'; } else { contextResizing.resizeButton.firstElementChild.style.left = '20px'; } contextResizing._resize_w = w; contextResizing._resize_h = h; const originSize = (targetElement.getAttribute('origin-size') || '').split(','); contextResizing._origin_w = originSize[0] || targetElement.naturalWidth; contextResizing._origin_h = originSize[1] || targetElement.naturalHeight; return { w: w, h: h, t: t, l: l }; }, _closeAlignMenu: null, openAlignMenu: function () { this.util.addClass(this.context.resizing.alignButton, 'on'); this.context.resizing.alignMenu.style.display = 'inline-table'; this.plugins.resizing._closeAlignMenu = function () { this.util.removeClass(this.context.resizing.alignButton, 'on'); this.context.resizing.alignMenu.style.display = 'none'; this.removeDocEvent('mousedown', this.plugins.resizing._closeAlignMenu); this.plugins.resizing._closeAlignMenu = null; }.bind(this); this.addDocEvent('mousedown', this.plugins.resizing._closeAlignMenu); }, create_caption: function () { const caption = this.util.createElement('FIGCAPTION'); caption.setAttribute('contenteditable', true); caption.innerHTML = '<div>' + this.lang.dialogBox.caption + '</div>'; return caption; }, set_cover: function (element) { const cover = this.util.createElement('FIGURE'); cover.appendChild(element); return cover; }, set_container: function (cover, className) { const container = this.util.createElement('DIV'); container.className = 'se-component ' + className; container.setAttribute('contenteditable', false); container.appendChild(cover); return container; }, onClick_resizeButton: function (e) { e.stopPropagation(); const target = e.target; const command = target.getAttribute('data-command') || target.parentNode.getAttribute('data-command'); if (!command) return; const value = target.getAttribute('data-value') || target.parentNode.getAttribute('data-value'); const pluginName = this.context.resizing._resize_plugin; const currentContext = this.context[pluginName]; const contextEl = currentContext._element; const currentModule = this.plugins[pluginName]; e.preventDefault(); if (typeof this.plugins.resizing._closeAlignMenu === 'function') { this.plugins.resizing._closeAlignMenu(); if (command === 'onalign') return; } switch (command) { case 'auto': currentModule.setAutoSize.call(this); currentModule.onModifyMode.call(this, contextEl, this.plugins.resizing.call_controller_resize.call(this, contextEl, pluginName)); break; case 'percent': let percentY = this.plugins.resizing._module_getSizeY.call(this, currentContext); if (this.context.resizing._rotateVertical) { const percentage = contextEl.getAttribute('data-percentage'); if (percentage) percentY = percentage.split(',')[1]; } this.plugins.resizing.resetTransform.call(this, contextEl); currentModule.setPercentSize.call(this, (value * 100), percentY); currentModule.onModifyMode.call(this, contextEl, this.plugins.resizing.call_controller_resize.call(this, contextEl, pluginName)); break; case 'mirror': const r = contextEl.getAttribute('data-rotate') || '0'; let x = contextEl.getAttribute('data-rotateX') || ''; let y = contextEl.getAttribute('data-rotateY') || ''; if ((value === 'h' && !this.context.resizing._rotateVertical) || (value === 'v' && this.context.resizing._rotateVertical)) { y = y ? '' : '180'; } else { x = x ? '' : '180'; } contextEl.setAttribute('data-rotateX', x); contextEl.setAttribute('data-rotateY', y); this.plugins.resizing._setTransForm(contextEl, r, x, y); break; case 'rotate': const contextResizing = this.context.resizing; const slope = (contextEl.getAttribute('data-rotate') * 1) + (value * 1); const deg = this._w.Math.abs(slope) >= 360 ? 0 : slope; contextEl.setAttribute('data-rotate', deg); contextResizing._rotateVertical = /^(90|270)$/.test(this._w.Math.abs(deg).toString()); this.plugins.resizing.setTransformSize.call(this, contextEl, null, null); currentModule.onModifyMode.call(this, contextEl, this.plugins.resizing.call_controller_resize.call(this, contextEl, pluginName)); break; case 'onalign': this.plugins.resizing.openAlignMenu.call(this); break; case 'align': const alignValue = value === 'basic' ? 'none' : value; currentModule.setAlign.call(this, alignValue, null, null, null); currentModule.onModifyMode.call(this, contextEl, this.plugins.resizing.call_controller_resize.call(this, contextEl, pluginName)); break; case 'caption': const caption = !currentContext._captionChecked; currentModule.openModify.call(this, true); currentContext._captionChecked = currentContext.captionCheckEl.checked = caption; if (pluginName === 'image') { currentModule.update_image.call(this, false, false, false); } else if (pluginName === 'video') { this.context.dialog.updateModal = true; currentModule.submitAction.call(this); } if (caption) { const captionText = this.util.getChildElement(currentContext._caption, function (current) { return current.nodeType === 3; }); if (!captionText) { currentContext._caption.focus(); } else { this.setRange(captionText, 0, captionText, captionText.textContent.length); } this.controllersOff(); } else { currentModule.onModifyMode.call(this, contextEl, this.plugins.resizing.call_controller_resize.call(this, contextEl, pluginName)); currentModule.openModify.call(this, true); } break; case 'revert': currentModule.setOriginSize.call(this); currentModule.onModifyMode.call(this, contextEl, this.plugins.resizing.call_controller_resize.call(this, contextEl, pluginName)); break; case 'update': currentModule.openModify.call(this); this.controllersOff(); break; case 'delete': currentModule.destroy.call(this); break; } // history stack this.history.push(false); }, resetTransform: function (element) { const size = (element.getAttribute('data-size') || element.getAttribute('data-origin') || '').split(','); this.context.resizing._rotateVertical = false; element.style.maxWidth = ''; element.style.transform = ''; element.style.transformOrigin = ''; element.setAttribute('data-rotate', ''); element.setAttribute('data-rotateX', ''); element.setAttribute('data-rotateY', ''); this.plugins[this.context.resizing._resize_plugin].setSize.call(this, size[0] ? size[0] : 'auto', size[1] ? size[1] : '', true); }, setTransformSize: function (element, width, height) { let percentage = element.getAttribute('data-percentage'); const isVertical = this.context.resizing._rotateVertical; const deg = element.getAttribute('data-rotate') * 1; let transOrigin = ''; if (percentage && !isVertical) { percentage = percentage.split(','); if (percentage[0] === 'auto' && percentage[1] === 'auto') { this.plugins[this.context.resizing._resize_plugin].setAutoSize.call(this); } else { this.plugins[this.context.resizing._resize_plugin].setPercentSize.call(this, percentage[0], percentage[1]); } } else { const cover = this.util.getParentElement(element, 'FIGURE'); const offsetW = width || element.offsetWidth; const offsetH = height || element.offsetHeight; const w = (isVertical ? offsetH : offsetW) + 'px'; const h = (isVertical ? offsetW : offsetH) + 'px'; this.plugins[this.context.resizing._resize_plugin].cancelPercentAttr.call(this); this.plugins[this.context.resizing._resize_plugin].setSize.call(this, offsetW + 'px', offsetH + 'px', true); cover.style.width = w; cover.style.height = (!!this.context[this.context.resizing._resize_plugin]._caption ? '' : h); if (isVertical) { let transW = (offsetW/2) + 'px ' + (offsetW/2) + 'px 0'; let transH = (offsetH/2) + 'px ' + (offsetH/2) + 'px 0'; transOrigin = deg === 90 || deg === -270 ? transH : transW; } } element.style.transformOrigin = transOrigin; this.plugins.resizing._setTransForm(element, deg.toString(), element.getAttribute('data-rotateX') || '', element.getAttribute('data-rotateY') || ''); if (isVertical) element.style.maxWidth = 'none'; else element.style.maxWidth = ''; this.plugins.resizing.setCaptionPosition.call(this, element); }, _setTransForm: function (element, r, x, y) { let width = (element.offsetWidth - element.offsetHeight) * (/-/.test(r) ? 1 : -1); let translate = ''; if (/[1-9]/.test(r) && (x || y)) { translate = x ? 'Y' : 'X'; switch (r) { case '90': translate = x && y ? 'X' : y ? translate : ''; break; case '270': width *= -1; translate = x && y ? 'Y' : x ? translate : ''; break; case '-90': translate = x && y ? 'Y' : x ? translate : ''; break; case '-270': width *= -1; translate = x && y ? 'X' : y ? translate : ''; break; default: translate = ''; } } if (r % 180 === 0) { element.style.maxWidth = ''; } element.style.transform = 'rotate(' + r + 'deg)' + (x ? ' rotateX(' + x + 'deg)' : '') + (y ? ' rotateY(' + y + 'deg)' : '') + (translate ? ' translate' + translate + '(' + width + 'px)' : ''); }, setCaptionPosition: function (element) { const figcaption = this.util.getChildElement(this.util.getParentElement(element, 'FIGURE'), 'FIGCAPTION'); if (figcaption) { figcaption.style.marginTop = (this.context.resizing._rotateVertical ? element.offsetWidth - element.offsetHeight : 0) + 'px'; } }, // resizing onMouseDown_resize_handle: function (e) { const contextResizing = this.context.resizing; const direction = contextResizing._resize_direction = e.target.classList[0]; e.stopPropagation(); e.preventDefault(); const pluginName = this.context.resizing._resize_plugin; const contextEl = this.context[pluginName]._element; const currentModule = this.plugins[pluginName]; contextResizing._resizeClientX = e.clientX; contextResizing._resizeClientY = e.clientY; this.context.element.resizeBackground.style.display = 'block'; contextResizing.resizeButton.style.display = 'none'; contextResizing.resizeDiv.style.float = /l/.test(direction) ? 'right' : /r/.test(direction) ? 'left' : 'none'; const closureFunc_bind = function closureFunc(e) { if (e.type === 'keydown' && e.keyCode !== 27) return; const change = contextResizing._isChange; contextResizing._isChange = false; this.removeDocEvent('mousemove', resizing_element_bind); this.removeDocEvent('mouseup', closureFunc_bind); this.removeDocEvent('keydown', closureFunc_bind); if (e.type === 'keydown') { this.controllersOff(); this.context.element.resizeBackground.style.display = 'none'; this.plugins[this.context.resizing._resize_plugin].init.call(this); } else { // element resize this.plugins.resizing.cancel_controller_resize.call(this); // history stack if (change) this.history.push(false); } currentModule.onModifyMode.call(this, contextEl, this.plugins.resizing.call_controller_resize.call(this, contextEl, contextResizing._resize_plugin)); }.bind(this); const resizing_element_bind = this.plugins.resizing.resizing_element.bind(this, contextResizing, direction, this.context[contextResizing._resize_plugin]); this.addDocEvent('mousemove', resizing_element_bind); this.addDocEvent('mouseup', closureFunc_bind); this.addDocEvent('keydown', closureFunc_bind); }, resizing_element: function (contextResizing, direction, plugin, e) { const clientX = e.clientX; const clientY = e.clientY; let resultW = plugin._element_w; let resultH = plugin._element_h; const w = plugin._element_w + (/r/.test(direction) ? clientX - contextResizing._resizeClientX : contextResizing._resizeClientX - clientX); const h = plugin._element_h + (/b/.test(direction) ? clientY - contextResizing._resizeClientY : contextResizing._resizeClientY - clientY); const wh = ((plugin._element_h / plugin._element_w) * w); if (/t/.test(direction)) contextResizing.resizeDiv.style.top = (plugin._element_h - (/h/.test(direction) ? h : wh)) + 'px'; if (/l/.test(direction)) contextResizing.resizeDiv.style.left = (plugin._element_w - w) + 'px'; if (/r|l/.test(direction)) { contextResizing.resizeDiv.style.width = w + 'px'; resultW = w; } if (/^(t|b)[^h]$/.test(direction)) { contextResizing.resizeDiv.style.height = wh + 'px'; resultH = wh; } else if (/^(t|b)h$/.test(direction)) { contextResizing.resizeDiv.style.height = h + 'px'; resultH = h; } contextResizing._resize_w = resultW; contextResizing._resize_h = resultH; this.util.changeTxt(contextResizing.resizeDisplay, this._w.Math.round(resultW) + ' x ' + this._w.Math.round(resultH)); contextResizing._isChange = true; }, cancel_controller_resize: function () { const isVertical = this.context.resizing._rotateVertical; this.controllersOff(); this.context.element.resizeBackground.style.display = 'none'; let w = this._w.Math.round(isVertical ? this.context.resizing._resize_h : this.context.resizing._resize_w); let h = this._w.Math.round(isVertical ? this.context.resizing._resize_w : this.context.resizing._resize_h); if (!isVertical && !/%$/.test(w)) { const padding = 16; const limit = this.context.element.wysiwygFrame.clientWidth - (padding * 2) - 2; if (this.util.getNumber(w) > limit) { h = this._w.Math.round((h / w) * limit); w = limit; } } this.plugins[this.context.resizing._resize_plugin].setSize.call(this, w, h, false); this.plugins[this.context.resizing._resize_plugin].init.call(this); } };