feat:add select control
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
.select-control-popup {
|
||||||
|
max-width: 160px;
|
||||||
|
min-width: 69px;
|
||||||
|
max-height: 225px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 5px 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-control-popup ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 3px 0;
|
||||||
|
margin: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-control-popup ul li {
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 0 20px;
|
||||||
|
position: relative;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
color: #666;
|
||||||
|
height: 36px;
|
||||||
|
line-height: 36px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-control-popup ul li:hover {
|
||||||
|
background-color: #EEF2FD;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-control-popup ul li.active {
|
||||||
|
color: var(--COLOR-HOVER, #5175f4);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@import './control/select.css';
|
||||||
|
|
||||||
.inputarea {
|
.inputarea {
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { ControlComponent, ControlType } from '../../../dataset/enum/Control'
|
import { ControlComponent, ControlType } from '../../../dataset/enum/Control'
|
||||||
import { ElementType } from '../../../dataset/enum/Element'
|
import { ElementType } from '../../../dataset/enum/Element'
|
||||||
import { IControlInitOption, IControlInstance, IControlOption } from '../../../interface/Control'
|
import { IControlInitOption, IControlInstance, IControlOption } from '../../../interface/Control'
|
||||||
import { IElement } from '../../../interface/Element'
|
import { IElement, IElementPosition } from '../../../interface/Element'
|
||||||
import { RangeManager } from '../../range/RangeManager'
|
import { RangeManager } from '../../range/RangeManager'
|
||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
import { SelectControl } from './select/SelectControl'
|
||||||
import { TextControl } from './text/TextControl'
|
import { TextControl } from './text/TextControl'
|
||||||
|
|
||||||
interface IMoveCursorResult {
|
interface IMoveCursorResult {
|
||||||
@@ -40,14 +41,34 @@ export class Control {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getContainer(): HTMLDivElement {
|
||||||
|
return this.draw.getContainer()
|
||||||
|
}
|
||||||
|
|
||||||
public getElementList(): IElement[] {
|
public getElementList(): IElement[] {
|
||||||
return this.draw.getElementList()
|
return this.draw.getElementList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getPosition(): IElementPosition | null {
|
||||||
|
const positionList = this.draw.getPosition().getPositionList()
|
||||||
|
const { endIndex } = this.range.getRange()
|
||||||
|
return positionList[endIndex] || null
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPreY(): number {
|
||||||
|
const height = this.draw.getHeight()
|
||||||
|
const pageGap = this.draw.getPageGap()
|
||||||
|
return this.draw.getPageNo() * (height + pageGap)
|
||||||
|
}
|
||||||
|
|
||||||
public getRange() {
|
public getRange() {
|
||||||
return this.range.getRange()
|
return this.range.getRange()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public shrinkBoundary() {
|
||||||
|
this.range.shrinkBoundary()
|
||||||
|
}
|
||||||
|
|
||||||
public getActiveControl(): IControlInstance | null {
|
public getActiveControl(): IControlInstance | null {
|
||||||
return this.activeControl
|
return this.activeControl
|
||||||
}
|
}
|
||||||
@@ -58,23 +79,42 @@ export class Control {
|
|||||||
const element = elementList[range.startIndex]
|
const element = elementList[range.startIndex]
|
||||||
// 判断控件是否已经激活
|
// 判断控件是否已经激活
|
||||||
if (this.activeControl) {
|
if (this.activeControl) {
|
||||||
|
// 列举控件唤醒下拉弹窗
|
||||||
|
if (this.activeControl instanceof SelectControl) {
|
||||||
|
this.activeControl.awake()
|
||||||
|
}
|
||||||
const controlElement = this.activeControl.getElement()
|
const controlElement = this.activeControl.getElement()
|
||||||
if (element.controlId === controlElement.controlId) return
|
if (element.controlId === controlElement.controlId) return
|
||||||
}
|
}
|
||||||
// 销毁旧激活控件
|
// 销毁旧激活控件
|
||||||
this.destroyControl()
|
this.destroyControl()
|
||||||
// 激活控件
|
// 激活控件
|
||||||
if (element.control!.type === ControlType.TEXT) {
|
const control = element.control!
|
||||||
|
if (control.type === ControlType.TEXT) {
|
||||||
this.activeControl = new TextControl(element, this)
|
this.activeControl = new TextControl(element, this)
|
||||||
|
} else if (control.type === ControlType.SELECT) {
|
||||||
|
const selectControl = new SelectControl(element, this)
|
||||||
|
this.activeControl = selectControl
|
||||||
|
selectControl.awake()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public destroyControl() {
|
public destroyControl() {
|
||||||
if (this.activeControl) {
|
if (this.activeControl) {
|
||||||
|
if (this.activeControl instanceof SelectControl) {
|
||||||
|
this.activeControl.destroy()
|
||||||
|
}
|
||||||
this.activeControl = null
|
this.activeControl = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public repaintControl(curIndex: number) {
|
||||||
|
this.range.setRange(curIndex, curIndex)
|
||||||
|
this.draw.render({
|
||||||
|
curIndex
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
public moveCursor(position: IControlInitOption): IMoveCursorResult {
|
public moveCursor(position: IControlInitOption): IMoveCursorResult {
|
||||||
const { index, trIndex, tdIndex, tdValueIndex } = position
|
const { index, trIndex, tdIndex, tdValueIndex } = position
|
||||||
let elementList = this.draw.getOriginalElementList()
|
let elementList = this.draw.getOriginalElementList()
|
||||||
@@ -169,97 +209,12 @@ export class Control {
|
|||||||
}
|
}
|
||||||
nextIndex++
|
nextIndex++
|
||||||
}
|
}
|
||||||
if (!~leftIndex || !~rightIndex) return -1
|
if (!~leftIndex || !~rightIndex) return startIndex
|
||||||
// 删除元素
|
// 删除元素
|
||||||
elementList.splice(leftIndex + 1, rightIndex - leftIndex)
|
elementList.splice(leftIndex + 1, rightIndex - leftIndex)
|
||||||
return leftIndex
|
return leftIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
public shrinkBoundary() {
|
|
||||||
const elementList = this.getElementList()
|
|
||||||
const range = this.getRange()
|
|
||||||
const { startIndex, endIndex } = range
|
|
||||||
const startElement = elementList[startIndex]
|
|
||||||
const endElement = elementList[endIndex]
|
|
||||||
if (startIndex === endIndex) {
|
|
||||||
if (startElement.controlComponent === ControlComponent.PLACEHOLDER) {
|
|
||||||
// 找到第一个placeholder字符
|
|
||||||
let index = startIndex - 1
|
|
||||||
while (index > 0) {
|
|
||||||
const preElement = elementList[index]
|
|
||||||
if (
|
|
||||||
preElement.controlId !== startElement.controlId ||
|
|
||||||
preElement.controlComponent === ControlComponent.PREFIX
|
|
||||||
) {
|
|
||||||
console.log(index)
|
|
||||||
range.startIndex = index
|
|
||||||
range.endIndex = index
|
|
||||||
break
|
|
||||||
}
|
|
||||||
index--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 首、尾为占位符时,收缩到最后一个前缀字符后
|
|
||||||
if (
|
|
||||||
startElement.controlComponent === ControlComponent.PLACEHOLDER ||
|
|
||||||
endElement.controlComponent === ControlComponent.PLACEHOLDER
|
|
||||||
) {
|
|
||||||
let index = endIndex - 1
|
|
||||||
while (index > 0) {
|
|
||||||
const preElement = elementList[index]
|
|
||||||
if (
|
|
||||||
preElement.controlId !== endElement.controlId
|
|
||||||
|| preElement.controlComponent === ControlComponent.PREFIX
|
|
||||||
) {
|
|
||||||
range.startIndex = index
|
|
||||||
range.endIndex = index
|
|
||||||
return
|
|
||||||
}
|
|
||||||
index--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 向右查找到第一个Value
|
|
||||||
if (startElement.controlComponent === ControlComponent.PREFIX) {
|
|
||||||
let index = startIndex + 1
|
|
||||||
while (index < elementList.length) {
|
|
||||||
const nextElement = elementList[index]
|
|
||||||
if (
|
|
||||||
nextElement.controlId !== startElement.controlId
|
|
||||||
|| nextElement.controlComponent === ControlComponent.VALUE
|
|
||||||
) {
|
|
||||||
range.startIndex = index - 1
|
|
||||||
break
|
|
||||||
} else if (nextElement.controlComponent === ControlComponent.PLACEHOLDER) {
|
|
||||||
range.startIndex = index - 1
|
|
||||||
range.endIndex = index - 1
|
|
||||||
return
|
|
||||||
}
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 向左查找到第一个Value
|
|
||||||
if (endElement.controlComponent !== ControlComponent.VALUE) {
|
|
||||||
let index = startIndex - 1
|
|
||||||
while (index > 0) {
|
|
||||||
const preElement = elementList[index]
|
|
||||||
if (
|
|
||||||
preElement.controlId !== startElement.controlId
|
|
||||||
|| preElement.controlComponent === ControlComponent.VALUE
|
|
||||||
) {
|
|
||||||
range.startIndex = index
|
|
||||||
break
|
|
||||||
} else if (preElement.controlComponent === ControlComponent.PLACEHOLDER) {
|
|
||||||
range.startIndex = index
|
|
||||||
range.endIndex = index
|
|
||||||
return
|
|
||||||
}
|
|
||||||
index--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public removePlaceholder(startIndex: number) {
|
public removePlaceholder(startIndex: number) {
|
||||||
const elementList = this.getElementList()
|
const elementList = this.getElementList()
|
||||||
const startElement = elementList[startIndex]
|
const startElement = elementList[startIndex]
|
||||||
|
|||||||
@@ -1,3 +1,254 @@
|
|||||||
export class SelectControl {
|
import { EDITOR_COMPONENT } from '../../../../dataset/constant/Editor'
|
||||||
|
import { ControlComponent } from '../../../../dataset/enum/Control'
|
||||||
|
import { EditorComponent } from '../../../../dataset/enum/Editor'
|
||||||
|
import { KeyMap } from '../../../../dataset/enum/Keymap'
|
||||||
|
import { IControlInstance } from '../../../../interface/Control'
|
||||||
|
import { IElement } from '../../../../interface/Element'
|
||||||
|
import { Control } from '../Control'
|
||||||
|
|
||||||
|
export class SelectControl implements IControlInstance {
|
||||||
|
|
||||||
|
private element: IElement
|
||||||
|
private control: Control
|
||||||
|
private isPopup: boolean
|
||||||
|
private selectDom: HTMLDivElement | null
|
||||||
|
|
||||||
|
constructor(element: IElement, control: Control) {
|
||||||
|
this.element = element
|
||||||
|
this.control = control
|
||||||
|
this.isPopup = false
|
||||||
|
this.selectDom = null
|
||||||
|
}
|
||||||
|
|
||||||
|
public getElement(): IElement {
|
||||||
|
return this.element
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCode(): string | null {
|
||||||
|
return this.element.control?.code || null
|
||||||
|
}
|
||||||
|
|
||||||
|
public getValue(): IElement[] {
|
||||||
|
const elementList = this.control.getElementList()
|
||||||
|
const { startIndex } = this.control.getRange()
|
||||||
|
const startElement = elementList[startIndex]
|
||||||
|
const data: IElement[] = []
|
||||||
|
// 向左查找
|
||||||
|
let preIndex = startIndex
|
||||||
|
while (preIndex > 0) {
|
||||||
|
const preElement = elementList[preIndex]
|
||||||
|
if (
|
||||||
|
preElement.controlId !== startElement.controlId ||
|
||||||
|
preElement.controlComponent === ControlComponent.PREFIX
|
||||||
|
) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (preElement.controlComponent === ControlComponent.VALUE) {
|
||||||
|
data.unshift(preElement)
|
||||||
|
}
|
||||||
|
preIndex--
|
||||||
|
}
|
||||||
|
// 向右查找
|
||||||
|
let nextIndex = startIndex + 1
|
||||||
|
while (nextIndex < elementList.length) {
|
||||||
|
const nextElement = elementList[nextIndex]
|
||||||
|
if (
|
||||||
|
nextElement.controlId !== startElement.controlId ||
|
||||||
|
nextElement.controlComponent === ControlComponent.POSTFIX
|
||||||
|
) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (nextElement.controlComponent === ControlComponent.VALUE) {
|
||||||
|
data.push(nextElement)
|
||||||
|
}
|
||||||
|
nextIndex++
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
public setValue(): number {
|
||||||
|
const range = this.control.getRange()
|
||||||
|
return range.endIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
public keydown(evt: KeyboardEvent): number {
|
||||||
|
const elementList = this.control.getElementList()
|
||||||
|
const range = this.control.getRange()
|
||||||
|
// 收缩边界到Value内
|
||||||
|
this.control.shrinkBoundary()
|
||||||
|
const { startIndex, endIndex } = range
|
||||||
|
const startElement = elementList[startIndex]
|
||||||
|
const endElement = elementList[endIndex]
|
||||||
|
// backspace
|
||||||
|
if (evt.key === KeyMap.Backspace) {
|
||||||
|
// 清空选项
|
||||||
|
if (startIndex !== endIndex) {
|
||||||
|
return this.clearSelect()
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
startElement.controlComponent === ControlComponent.PREFIX ||
|
||||||
|
endElement.controlComponent === ControlComponent.POSTFIX ||
|
||||||
|
startElement.controlComponent === ControlComponent.PLACEHOLDER
|
||||||
|
) {
|
||||||
|
// 前缀、后缀、占位符
|
||||||
|
return this.control.removeControl(startIndex)
|
||||||
|
} else {
|
||||||
|
// 清空选项
|
||||||
|
return this.clearSelect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (evt.key === KeyMap.Delete) {
|
||||||
|
// 移除选区元素
|
||||||
|
if (startIndex !== endIndex) {
|
||||||
|
// 清空选项
|
||||||
|
return this.clearSelect()
|
||||||
|
} else {
|
||||||
|
const endNextElement = elementList[endIndex + 1]
|
||||||
|
if (startElement.controlComponent === ControlComponent.PREFIX ||
|
||||||
|
endNextElement.controlComponent === ControlComponent.POSTFIX ||
|
||||||
|
startElement.controlComponent === ControlComponent.PLACEHOLDER
|
||||||
|
) {
|
||||||
|
// 前缀、后缀、占位符
|
||||||
|
return this.control.removeControl(startIndex)
|
||||||
|
} else {
|
||||||
|
// 清空选项
|
||||||
|
return this.clearSelect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return endIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
public cut(): number {
|
||||||
|
this.control.shrinkBoundary()
|
||||||
|
const { startIndex, endIndex } = this.control.getRange()
|
||||||
|
if (startIndex === endIndex) {
|
||||||
|
return startIndex
|
||||||
|
}
|
||||||
|
// 清空选项
|
||||||
|
return this.clearSelect()
|
||||||
|
}
|
||||||
|
|
||||||
|
public clearSelect(): number {
|
||||||
|
const elementList = this.control.getElementList()
|
||||||
|
const { startIndex } = this.control.getRange()
|
||||||
|
const startElement = elementList[startIndex]
|
||||||
|
let leftIndex = -1
|
||||||
|
let rightIndex = -1
|
||||||
|
// 向左查找
|
||||||
|
let preIndex = startIndex
|
||||||
|
while (preIndex > 0) {
|
||||||
|
const preElement = elementList[preIndex]
|
||||||
|
if (
|
||||||
|
preElement.controlId !== startElement.controlId ||
|
||||||
|
preElement.controlComponent === ControlComponent.PREFIX
|
||||||
|
) {
|
||||||
|
leftIndex = preIndex
|
||||||
|
break
|
||||||
|
}
|
||||||
|
preIndex--
|
||||||
|
}
|
||||||
|
// 向右查找
|
||||||
|
let nextIndex = startIndex + 1
|
||||||
|
while (nextIndex < elementList.length) {
|
||||||
|
const nextElement = elementList[nextIndex]
|
||||||
|
if (
|
||||||
|
nextElement.controlId !== startElement.controlId ||
|
||||||
|
nextElement.controlComponent === ControlComponent.POSTFIX
|
||||||
|
) {
|
||||||
|
rightIndex = nextIndex - 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
nextIndex++
|
||||||
|
}
|
||||||
|
if (!~leftIndex || !~rightIndex) return -1
|
||||||
|
// 删除元素
|
||||||
|
elementList.splice(leftIndex + 1, rightIndex - leftIndex)
|
||||||
|
// 增加占位符
|
||||||
|
this.control.addPlaceholder(preIndex)
|
||||||
|
this.element.control!.code = null
|
||||||
|
return preIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSelect(code: string) {
|
||||||
|
const control = this.element.control!
|
||||||
|
const valueSets = control.valueSets
|
||||||
|
if (!Array.isArray(valueSets) || !valueSets.length) return
|
||||||
|
// 转换code
|
||||||
|
const valueSet = valueSets.find(v => v.code === code)
|
||||||
|
if (!valueSet) return
|
||||||
|
// 清空选项
|
||||||
|
const startIndex = this.clearSelect()
|
||||||
|
this.control.removePlaceholder(startIndex)
|
||||||
|
// 插入
|
||||||
|
const elementList = this.control.getElementList()
|
||||||
|
const startElement = elementList[startIndex]
|
||||||
|
const start = startIndex + 1
|
||||||
|
const data = valueSet.value.split('')
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
elementList.splice(start + i, 0, {
|
||||||
|
...startElement,
|
||||||
|
value: data[i],
|
||||||
|
controlComponent: ControlComponent.VALUE
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// render
|
||||||
|
const newIndex = start + data.length - 1
|
||||||
|
this.control.repaintControl(newIndex)
|
||||||
|
// 设置状态
|
||||||
|
this.element.control!.code = code
|
||||||
|
this.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
private _createSelectPopupDom() {
|
||||||
|
const control = this.element.control!
|
||||||
|
const valueSets = control.valueSets
|
||||||
|
if (!Array.isArray(valueSets) || !valueSets.length) return
|
||||||
|
const position = this.control.getPosition()
|
||||||
|
if (!position) return
|
||||||
|
// dom树:<div><ul><li>item</li></ul></div>
|
||||||
|
const selectPopupContainer = document.createElement('div')
|
||||||
|
selectPopupContainer.classList.add('select-control-popup')
|
||||||
|
selectPopupContainer.setAttribute(EDITOR_COMPONENT, EditorComponent.POPUP)
|
||||||
|
const ul = document.createElement('ul')
|
||||||
|
for (let v = 0; v < valueSets.length; v++) {
|
||||||
|
const valueSet = valueSets[v]
|
||||||
|
const li = document.createElement('li')
|
||||||
|
const code = this.getCode()
|
||||||
|
if (code === valueSet.code) {
|
||||||
|
li.classList.add('active')
|
||||||
|
}
|
||||||
|
li.onclick = () => {
|
||||||
|
this.setSelect(valueSet.code)
|
||||||
|
}
|
||||||
|
li.append(document.createTextNode(valueSet.value))
|
||||||
|
ul.append(li)
|
||||||
|
}
|
||||||
|
selectPopupContainer.append(ul)
|
||||||
|
// 定位
|
||||||
|
const { coordinate: { leftTop: [left, top] }, lineHeight } = position
|
||||||
|
const preY = this.control.getPreY()
|
||||||
|
selectPopupContainer.style.left = `${left}px`
|
||||||
|
selectPopupContainer.style.top = `${top + preY + lineHeight}px`
|
||||||
|
// 追加至container
|
||||||
|
const container = this.control.getContainer()
|
||||||
|
container.append(selectPopupContainer)
|
||||||
|
this.selectDom = selectPopupContainer
|
||||||
|
}
|
||||||
|
|
||||||
|
public awake() {
|
||||||
|
if (this.isPopup) return
|
||||||
|
const { startIndex } = this.control.getRange()
|
||||||
|
const elementList = this.control.getElementList()
|
||||||
|
if (elementList[startIndex + 1]?.controlId !== this.element.controlId) return
|
||||||
|
this._createSelectPopupDom()
|
||||||
|
this.isPopup = true
|
||||||
|
}
|
||||||
|
|
||||||
|
public destroy() {
|
||||||
|
if (!this.isPopup) return
|
||||||
|
this.selectDom?.remove()
|
||||||
|
this.isPopup = false
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ export class TextControl implements IControlInstance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1
|
return endIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
public cut(): number {
|
public cut(): number {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { ElementType } from '../..'
|
import { ElementType } from '../..'
|
||||||
|
import { ControlComponent } from '../../dataset/enum/Control'
|
||||||
import { IEditorOption } from '../../interface/Editor'
|
import { IEditorOption } from '../../interface/Editor'
|
||||||
import { IElement } from '../../interface/Element'
|
import { IElement } from '../../interface/Element'
|
||||||
import { IRange } from '../../interface/Range'
|
import { IRange } from '../../interface/Range'
|
||||||
@@ -137,6 +138,90 @@ export class RangeManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public shrinkBoundary() {
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const range = this.getRange()
|
||||||
|
const { startIndex, endIndex } = range
|
||||||
|
const startElement = elementList[startIndex]
|
||||||
|
const endElement = elementList[endIndex]
|
||||||
|
if (startIndex === endIndex) {
|
||||||
|
if (startElement.controlComponent === ControlComponent.PLACEHOLDER) {
|
||||||
|
// 找到第一个placeholder字符
|
||||||
|
let index = startIndex - 1
|
||||||
|
while (index > 0) {
|
||||||
|
const preElement = elementList[index]
|
||||||
|
if (
|
||||||
|
preElement.controlId !== startElement.controlId ||
|
||||||
|
preElement.controlComponent === ControlComponent.PREFIX
|
||||||
|
) {
|
||||||
|
range.startIndex = index
|
||||||
|
range.endIndex = index
|
||||||
|
break
|
||||||
|
}
|
||||||
|
index--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 首、尾为占位符时,收缩到最后一个前缀字符后
|
||||||
|
if (
|
||||||
|
startElement.controlComponent === ControlComponent.PLACEHOLDER ||
|
||||||
|
endElement.controlComponent === ControlComponent.PLACEHOLDER
|
||||||
|
) {
|
||||||
|
let index = endIndex - 1
|
||||||
|
while (index > 0) {
|
||||||
|
const preElement = elementList[index]
|
||||||
|
if (
|
||||||
|
preElement.controlId !== endElement.controlId
|
||||||
|
|| preElement.controlComponent === ControlComponent.PREFIX
|
||||||
|
) {
|
||||||
|
range.startIndex = index
|
||||||
|
range.endIndex = index
|
||||||
|
return
|
||||||
|
}
|
||||||
|
index--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 向右查找到第一个Value
|
||||||
|
if (startElement.controlComponent === ControlComponent.PREFIX) {
|
||||||
|
let index = startIndex + 1
|
||||||
|
while (index < elementList.length) {
|
||||||
|
const nextElement = elementList[index]
|
||||||
|
if (
|
||||||
|
nextElement.controlId !== startElement.controlId
|
||||||
|
|| nextElement.controlComponent === ControlComponent.VALUE
|
||||||
|
) {
|
||||||
|
range.startIndex = index - 1
|
||||||
|
break
|
||||||
|
} else if (nextElement.controlComponent === ControlComponent.PLACEHOLDER) {
|
||||||
|
range.startIndex = index - 1
|
||||||
|
range.endIndex = index - 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 向左查找到第一个Value
|
||||||
|
if (endElement.controlComponent !== ControlComponent.VALUE) {
|
||||||
|
let index = startIndex - 1
|
||||||
|
while (index > 0) {
|
||||||
|
const preElement = elementList[index]
|
||||||
|
if (
|
||||||
|
preElement.controlId !== startElement.controlId
|
||||||
|
|| preElement.controlComponent === ControlComponent.VALUE
|
||||||
|
) {
|
||||||
|
range.startIndex = index
|
||||||
|
break
|
||||||
|
} else if (preElement.controlComponent === ControlComponent.PLACEHOLDER) {
|
||||||
|
range.startIndex = index
|
||||||
|
range.endIndex = index
|
||||||
|
return
|
||||||
|
}
|
||||||
|
index--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) {
|
public render(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) {
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.globalAlpha = this.options.rangeAlpha
|
ctx.globalAlpha = this.options.rangeAlpha
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ export enum EditorComponent {
|
|||||||
MENU = 'menu',
|
MENU = 'menu',
|
||||||
MAIN = 'main',
|
MAIN = 'main',
|
||||||
FOOTER = 'footer',
|
FOOTER = 'footer',
|
||||||
CONTEXTMENU = 'contextmenu'
|
CONTEXTMENU = 'contextmenu',
|
||||||
|
POPUP = 'popup'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EditorContext {
|
export enum EditorContext {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export interface IValueSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IControlSelect {
|
export interface IControlSelect {
|
||||||
|
code: string | null;
|
||||||
valueSets: IValueSet[];
|
valueSets: IValueSet[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ElementType, IEditorOption, IElement } from '..'
|
|||||||
import { ZERO } from '../dataset/constant/Common'
|
import { ZERO } from '../dataset/constant/Common'
|
||||||
import { defaultControlOption } from '../dataset/constant/Control'
|
import { defaultControlOption } from '../dataset/constant/Control'
|
||||||
import { EDITOR_ELEMENT_ZIP_ATTR } from '../dataset/constant/Element'
|
import { EDITOR_ELEMENT_ZIP_ATTR } from '../dataset/constant/Element'
|
||||||
import { ControlComponent } from '../dataset/enum/Control'
|
import { ControlComponent, ControlType } from '../dataset/enum/Control'
|
||||||
|
|
||||||
interface IFormatElementListOption {
|
interface IFormatElementListOption {
|
||||||
isHandleFirstElement?: boolean;
|
isHandleFirstElement?: boolean;
|
||||||
@@ -71,7 +71,7 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme
|
|||||||
}
|
}
|
||||||
i--
|
i--
|
||||||
} else if (el.type === ElementType.CONTROL) {
|
} else if (el.type === ElementType.CONTROL) {
|
||||||
const { prefix, postfix, value, placeholder } = el.control!
|
const { prefix, postfix, value, placeholder, code, type, valueSets } = el.control!
|
||||||
const controlId = getUUID()
|
const controlId = getUUID()
|
||||||
// 移除父节点
|
// 移除父节点
|
||||||
elementList.splice(i, 1)
|
elementList.splice(i, 1)
|
||||||
@@ -95,9 +95,23 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
// 值
|
// 值
|
||||||
if (value && value.length) {
|
if (
|
||||||
for (let v = 0; v < value.length; v++) {
|
(value && value.length) ||
|
||||||
const element = value[v]
|
(type === ControlType.SELECT && code && (!value || !value.length))
|
||||||
|
) {
|
||||||
|
let valueList: IElement[] = value || []
|
||||||
|
if (!value || !value.length) {
|
||||||
|
if (Array.isArray(valueSets) && valueSets.length) {
|
||||||
|
const valueSet = valueSets.find(v => v.code === code)
|
||||||
|
if (valueSet) {
|
||||||
|
valueList = [{
|
||||||
|
value: valueSet.value
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let v = 0; v < valueList.length; v++) {
|
||||||
|
const element = valueList[v]
|
||||||
const valueStrList = element.value.split('')
|
const valueStrList = element.value.split('')
|
||||||
for (let e = 0; e < valueStrList.length; e++) {
|
for (let e = 0; e < valueStrList.length; e++) {
|
||||||
const value = valueStrList[e]
|
const value = valueStrList[e]
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ elementList.splice(112, 0, {
|
|||||||
control: {
|
control: {
|
||||||
type: ControlType.SELECT,
|
type: ControlType.SELECT,
|
||||||
value: null,
|
value: null,
|
||||||
|
code: null,
|
||||||
placeholder: '有无',
|
placeholder: '有无',
|
||||||
prefix: '{',
|
prefix: '{',
|
||||||
postfix: '}',
|
postfix: '}',
|
||||||
@@ -100,6 +101,9 @@ elementList.splice(112, 0, {
|
|||||||
}, {
|
}, {
|
||||||
value: '无',
|
value: '无',
|
||||||
code: '98176'
|
code: '98176'
|
||||||
|
}, {
|
||||||
|
value: '不详',
|
||||||
|
code: '98177'
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user