Commit d49f6391 by jml0128

fix:优化div文字输入功能

1 parent 1dfb2198
{
"name": "xrk-bi",
"version": "0.1.2",
"version": "0.1.1",
"description": "xrk-bi",
"author": "xrk",
"main": "dist/bundler.js",
......
......@@ -202,3 +202,101 @@ export const keepLastIndex = (obj, focusOffset) => {
rangeForIE.select();
}
};
export const initDivInput = (
dom,
options = { useWrap: false, usePasteStyle: false, callback: () => {} }
) => {
const { useWrap, usePasteStyle, callback } = options;
const maxlength = dom.getAttribute('maxlength');
let baseIndex = 0;
let focusIndex = 0;
let leftText = '';
let rightText = '';
let deleteText = '';
dom.innerHTML = dom.innerText;
const setIndex = function() {
const { innerText } = this;
const { baseOffset, focusOffset } = getSelection();
[baseIndex, focusIndex] = [baseOffset, focusOffset].sort((a, b) => a - b);
leftText = innerText.slice(0, baseIndex);
rightText = innerText.slice(focusIndex);
deleteText = innerText.slice(baseIndex, focusIndex);
};
const dealText = function(text, isPaste) {
// 还可以显示多少文字,最小为0
const canInsertTextLength = Math.max(
maxlength - leftText.length - rightText.length,
0
);
if (isPaste) {
return text.slice(0, canInsertTextLength);
}
// 最终显示的文字
const resultText = `${leftText}${text.slice(
0,
canInsertTextLength
)}${rightText}`;
this.innerText = resultText;
// 重置光标位置
getSelection().collapse(
this.firstChild,
baseIndex + Math.min(Math.max(canInsertTextLength, 0), text.length)
);
};
dom.addEventListener('compositionstart', function(event) {
setIndex.call(this);
});
dom.addEventListener('compositionend', function(event) {
dealText.call(this, event.data);
});
dom.addEventListener('beforeinput', function(event) {
const { inputType } = event;
if (inputType != 'insertCompositionText') {
setIndex.call(this);
}
if (
this.innerText.length - (focusIndex - baseIndex) >= maxlength &&
['insertText', 'insertCompositionText', 'insertParagraph'].includes(
inputType
)
) {
// 超出长度并且是输入操作,则禁止输入
event.preventDefault();
}
if (inputType === 'insertParagraph' && !useWrap) {
// 禁止换行
event.preventDefault();
}
});
if (!usePasteStyle) {
dom.addEventListener('paste', function(e) {
e.stopPropagation();
e.preventDefault();
setIndex.call(this);
let text = '',
event = e.originalEvent || e;
if (event.clipboardData && event.clipboardData.getData) {
text = event.clipboardData.getData('text/plain');
} else if (window.clipboardData && window.clipboardData.getData) {
text = window.clipboardData.getData('Text');
}
// 粘贴不能超过最大长度
text = dealText.call(this, text, true);
if (document.queryCommandSupported('insertText')) {
document.execCommand('insertText', false, text);
} else {
document.execCommand('paste', false, text);
}
});
dom.addEventListener('blur', function() {
callback(this.innerText);
});
} else {
console.warn('启用usePasteStyle,在粘贴时候无法限制字符长度');
}
};
......@@ -6,9 +6,10 @@
<div class="bi-chart-choice-mixin-toggle-axis">
<BiBlank height="25" :usePrint="true"></BiBlank>
<div
ref="input"
class="bi-chart-choice-mixin-toggle-axis_sub_title"
:contenteditable="contenteditable"
@input="input"
:maxlength="999"
>
{{ customGroupTitle || dealAxis.join('与') }}
</div>
......@@ -32,7 +33,7 @@
import mixin from '../mixin/index';
import { Button } from 'element-ui';
import BiBlank from './blank.vue';
import { keepLastIndex } from '../chart-type/common';
import { initDivInput } from '../chart-type/common';
export default {
name: 'bi-chart-choice-mixin-toggle-axis',
mixins: [mixin],
......@@ -57,16 +58,18 @@ export default {
}
},
methods: {
input(event) {
const focusOffset = window.getSelection().focusOffset;
this.$emit('change-title', event.target.innerText);
this.$nextTick(() => {
keepLastIndex(event.target, focusOffset);
});
},
toggle() {
this.$emit('toggle-axis');
}
},
created() {
this.$nextTick(() => {
initDivInput(this.$refs['input'], {
callback: res => {
this.$emit('change-title', res);
}
});
});
}
};
</script>
......
......@@ -21,7 +21,7 @@
ref="input"
class="bi-chart-desc_textarea"
:contenteditable="!isPrint"
@input="input"
:maxlength="maxLength"
>
{{ localText }}
</span>
......@@ -45,7 +45,7 @@
import mixin from '../mixin/index';
import { Button } from 'element-ui';
import BiBlank from './blank.vue';
import { keepLastIndex } from '../chart-type/common';
import { initDivInput } from '../chart-type/common';
export default {
name: 'bi-chart-desc',
mixins: [mixin],
......@@ -71,70 +71,19 @@ export default {
}
},
methods: {
keepLastIndex(obj) {
if (window.getSelection) {
obj.focus(); //解决ff不获取焦点无法定位问题
var range = window.getSelection(); //创建range
range.selectAllChildren(obj); //range 选择obj下所有子内容
range.collapseToEnd(); //光标移至最后
} else if (document.selection) {
var rangeForIE = document.selection.createRange(); //创建选择对象
rangeForIE.moveToElementText(obj); //range定位到obj
rangeForIE.collapse(false); //光标移至最后
rangeForIE.select();
}
},
toggleShow() {
this.$emit('change-status');
},
blur() {
this.$refs['input'].focus();
},
input(event) {
const range = window.getSelection(); //创建range
const focusOffset = range.focusOffset;
try {
const { innerText } = event.target;
if (
`${event.target.innerText}`.length > this.maxLength &&
this.localText.length === this.maxLength
) {
event.target.innerText = this.localText;
this.$nextTick(() => {
keepLastIndex(event.target, focusOffset - 1);
});
return;
}
const text = `${innerText}`.slice(0, this.maxLength);
this.localText = text;
this.$emit('change-text', this.localText);
this.$nextTick(() => {
keepLastIndex(event.target, focusOffset);
});
} catch (error) {
console.log(error);
}
}
},
mounted() {
const inputDom = this.$refs['input'];
if (inputDom) {
inputDom.innerHTML = inputDom.innerText;
inputDom.addEventListener('paste', function(e) {
e.stopPropagation();
e.preventDefault();
var text = '',
event = e.originalEvent || e;
if (event.clipboardData && event.clipboardData.getData) {
text = event.clipboardData.getData('text/plain');
} else if (window.clipboardData && window.clipboardData.getData) {
text = window.clipboardData.getData('Text');
}
if (document.queryCommandSupported('insertText')) {
document.execCommand('insertText', false, text);
} else {
document.execCommand('paste', false, text);
initDivInput(inputDom, {
callback: res => {
this.$emit('change-text', res);
}
});
}
......
......@@ -7,9 +7,10 @@
<div class="bi-chart-title-darg"></div>
<div class="bi-chart-title_hr" v-if="!hideHr"></div>
<div
ref="input"
class="bi-chart-title_name"
:contenteditable="contenteditable"
@input="input"
:maxlength="999"
>
<!-- {{ `${name}`.slice(0, 36) }}{{ `${name}`.length > 36 ? '...' : '' }} -->
{{ name }}
......@@ -104,7 +105,7 @@ import BiTypesChart from './types-chart.vue';
import mixin from '../mixin/index';
import types from '../chart-type/types';
import eventBus from '../eventBus';
import { keepLastIndex } from '../chart-type/common';
import { initDivInput } from '../chart-type/common';
export default {
name: 'bi-chart-title',
mixins: [mixin],
......@@ -151,13 +152,6 @@ export default {
}
},
methods: {
input(event) {
const focusOffset = window.getSelection().focusOffset;
this.$emit('change-title', event.target.innerText);
this.$nextTick(() => {
keepLastIndex(event.target, focusOffset);
});
},
changeColors(colors) {
this.visibleColors = false;
this.$emit('change-colors', colors);
......@@ -180,6 +174,13 @@ export default {
this.guide.use = false;
});
}
this.$nextTick(() => {
initDivInput(this.$refs['input'], {
callback: res => {
this.$emit('change-title', res);
}
});
});
}
};
</script>
......
......@@ -76,11 +76,7 @@
ref="input"
style="outline: none;display:inline-block;"
:contenteditable="!drag && !isPrint"
@input="
e => {
input(e, index, item.maxLength);
}
"
:maxlength="item.maxLength"
>
{{ item.name }}
</div>
......@@ -94,7 +90,7 @@ import { Popover, Button } from 'element-ui';
import { Swiper, SwiperSlide } from 'vue-awesome-swiper';
import 'swiper/swiper-bundle.css';
import mixin, { printWidth } from '../mixin/index';
import { keepLastIndex } from '../chart-type/common';
import { initDivInput } from '../chart-type/common';
export default {
name: 'bi-cover',
mixins: [mixin],
......@@ -208,31 +204,6 @@ export default {
off(document, 'touchmove', this._dragHandler);
});
},
input(event, index, maxLength) {
const range = window.getSelection(); //创建range
const focusOffset = range.focusOffset;
try {
const { innerText } = event.target;
if (
`${event.target.innerText}`.length > maxLength &&
this.content[index]['name'].length === maxLength
) {
event.target.innerText = this.content[index]['name'];
this.$nextTick(() => {
keepLastIndex(event.target, focusOffset - 1);
});
return;
}
const text = `${innerText}`.slice(0, maxLength);
this.content[index]['name'] = text;
this.$nextTick(() => {
keepLastIndex(event.target, focusOffset);
});
} catch (error) {
console.log(error);
}
},
dealCoverContent(arr) {
const baseContent = [
{
......@@ -279,25 +250,10 @@ export default {
this.dealCoverContent(newV);
this.$nextTick(() => {
Array.isArray(this.$refs['input']) &&
this.$refs['input'].forEach(item => {
item.innerHTML = item.innerText;
item.addEventListener('paste', function(e) {
e.stopPropagation();
e.preventDefault();
var text = '',
event = e.originalEvent || e;
if (event.clipboardData && event.clipboardData.getData) {
text = event.clipboardData.getData('text/plain');
} else if (
window.clipboardData &&
window.clipboardData.getData
) {
text = window.clipboardData.getData('Text');
}
if (document.queryCommandSupported('insertText')) {
document.execCommand('insertText', false, text);
} else {
document.execCommand('paste', false, text);
this.$refs['input'].forEach((item, index) => {
initDivInput(item, {
callback: res => {
this.content[index]['name'] = res;
}
});
});
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!