Commit d49f6391 by jml0128

fix:优化div文字输入功能

1 parent 1dfb2198
{ {
"name": "xrk-bi", "name": "xrk-bi",
"version": "0.1.2", "version": "0.1.1",
"description": "xrk-bi", "description": "xrk-bi",
"author": "xrk", "author": "xrk",
"main": "dist/bundler.js", "main": "dist/bundler.js",
......
...@@ -202,3 +202,101 @@ export const keepLastIndex = (obj, focusOffset) => { ...@@ -202,3 +202,101 @@ export const keepLastIndex = (obj, focusOffset) => {
rangeForIE.select(); 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 @@ ...@@ -6,9 +6,10 @@
<div class="bi-chart-choice-mixin-toggle-axis"> <div class="bi-chart-choice-mixin-toggle-axis">
<BiBlank height="25" :usePrint="true"></BiBlank> <BiBlank height="25" :usePrint="true"></BiBlank>
<div <div
ref="input"
class="bi-chart-choice-mixin-toggle-axis_sub_title" class="bi-chart-choice-mixin-toggle-axis_sub_title"
:contenteditable="contenteditable" :contenteditable="contenteditable"
@input="input" :maxlength="999"
> >
{{ customGroupTitle || dealAxis.join('与') }} {{ customGroupTitle || dealAxis.join('与') }}
</div> </div>
...@@ -32,7 +33,7 @@ ...@@ -32,7 +33,7 @@
import mixin from '../mixin/index'; import mixin from '../mixin/index';
import { Button } from 'element-ui'; import { Button } from 'element-ui';
import BiBlank from './blank.vue'; import BiBlank from './blank.vue';
import { keepLastIndex } from '../chart-type/common'; import { initDivInput } from '../chart-type/common';
export default { export default {
name: 'bi-chart-choice-mixin-toggle-axis', name: 'bi-chart-choice-mixin-toggle-axis',
mixins: [mixin], mixins: [mixin],
...@@ -57,16 +58,18 @@ export default { ...@@ -57,16 +58,18 @@ export default {
} }
}, },
methods: { methods: {
input(event) {
const focusOffset = window.getSelection().focusOffset;
this.$emit('change-title', event.target.innerText);
this.$nextTick(() => {
keepLastIndex(event.target, focusOffset);
});
},
toggle() { toggle() {
this.$emit('toggle-axis'); this.$emit('toggle-axis');
} }
},
created() {
this.$nextTick(() => {
initDivInput(this.$refs['input'], {
callback: res => {
this.$emit('change-title', res);
}
});
});
} }
}; };
</script> </script>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
ref="input" ref="input"
class="bi-chart-desc_textarea" class="bi-chart-desc_textarea"
:contenteditable="!isPrint" :contenteditable="!isPrint"
@input="input" :maxlength="maxLength"
> >
{{ localText }} {{ localText }}
</span> </span>
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
import mixin from '../mixin/index'; import mixin from '../mixin/index';
import { Button } from 'element-ui'; import { Button } from 'element-ui';
import BiBlank from './blank.vue'; import BiBlank from './blank.vue';
import { keepLastIndex } from '../chart-type/common'; import { initDivInput } from '../chart-type/common';
export default { export default {
name: 'bi-chart-desc', name: 'bi-chart-desc',
mixins: [mixin], mixins: [mixin],
...@@ -71,70 +71,19 @@ export default { ...@@ -71,70 +71,19 @@ export default {
} }
}, },
methods: { 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() { toggleShow() {
this.$emit('change-status'); this.$emit('change-status');
}, },
blur() { blur() {
this.$refs['input'].focus(); 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() { mounted() {
const inputDom = this.$refs['input']; const inputDom = this.$refs['input'];
if (inputDom) { if (inputDom) {
inputDom.innerHTML = inputDom.innerText; initDivInput(inputDom, {
inputDom.addEventListener('paste', function(e) { callback: res => {
e.stopPropagation(); this.$emit('change-text', res);
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);
} }
}); });
} }
......
...@@ -7,9 +7,10 @@ ...@@ -7,9 +7,10 @@
<div class="bi-chart-title-darg"></div> <div class="bi-chart-title-darg"></div>
<div class="bi-chart-title_hr" v-if="!hideHr"></div> <div class="bi-chart-title_hr" v-if="!hideHr"></div>
<div <div
ref="input"
class="bi-chart-title_name" class="bi-chart-title_name"
:contenteditable="contenteditable" :contenteditable="contenteditable"
@input="input" :maxlength="999"
> >
<!-- {{ `${name}`.slice(0, 36) }}{{ `${name}`.length > 36 ? '...' : '' }} --> <!-- {{ `${name}`.slice(0, 36) }}{{ `${name}`.length > 36 ? '...' : '' }} -->
{{ name }} {{ name }}
...@@ -104,7 +105,7 @@ import BiTypesChart from './types-chart.vue'; ...@@ -104,7 +105,7 @@ import BiTypesChart from './types-chart.vue';
import mixin from '../mixin/index'; import mixin from '../mixin/index';
import types from '../chart-type/types'; import types from '../chart-type/types';
import eventBus from '../eventBus'; import eventBus from '../eventBus';
import { keepLastIndex } from '../chart-type/common'; import { initDivInput } from '../chart-type/common';
export default { export default {
name: 'bi-chart-title', name: 'bi-chart-title',
mixins: [mixin], mixins: [mixin],
...@@ -151,13 +152,6 @@ export default { ...@@ -151,13 +152,6 @@ export default {
} }
}, },
methods: { methods: {
input(event) {
const focusOffset = window.getSelection().focusOffset;
this.$emit('change-title', event.target.innerText);
this.$nextTick(() => {
keepLastIndex(event.target, focusOffset);
});
},
changeColors(colors) { changeColors(colors) {
this.visibleColors = false; this.visibleColors = false;
this.$emit('change-colors', colors); this.$emit('change-colors', colors);
...@@ -180,6 +174,13 @@ export default { ...@@ -180,6 +174,13 @@ export default {
this.guide.use = false; this.guide.use = false;
}); });
} }
this.$nextTick(() => {
initDivInput(this.$refs['input'], {
callback: res => {
this.$emit('change-title', res);
}
});
});
} }
}; };
</script> </script>
......
...@@ -76,11 +76,7 @@ ...@@ -76,11 +76,7 @@
ref="input" ref="input"
style="outline: none;display:inline-block;" style="outline: none;display:inline-block;"
:contenteditable="!drag && !isPrint" :contenteditable="!drag && !isPrint"
@input=" :maxlength="item.maxLength"
e => {
input(e, index, item.maxLength);
}
"
> >
{{ item.name }} {{ item.name }}
</div> </div>
...@@ -94,7 +90,7 @@ import { Popover, Button } from 'element-ui'; ...@@ -94,7 +90,7 @@ import { Popover, Button } from 'element-ui';
import { Swiper, SwiperSlide } from 'vue-awesome-swiper'; import { Swiper, SwiperSlide } from 'vue-awesome-swiper';
import 'swiper/swiper-bundle.css'; import 'swiper/swiper-bundle.css';
import mixin, { printWidth } from '../mixin/index'; import mixin, { printWidth } from '../mixin/index';
import { keepLastIndex } from '../chart-type/common'; import { initDivInput } from '../chart-type/common';
export default { export default {
name: 'bi-cover', name: 'bi-cover',
mixins: [mixin], mixins: [mixin],
...@@ -208,31 +204,6 @@ export default { ...@@ -208,31 +204,6 @@ export default {
off(document, 'touchmove', this._dragHandler); 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) { dealCoverContent(arr) {
const baseContent = [ const baseContent = [
{ {
...@@ -279,25 +250,10 @@ export default { ...@@ -279,25 +250,10 @@ export default {
this.dealCoverContent(newV); this.dealCoverContent(newV);
this.$nextTick(() => { this.$nextTick(() => {
Array.isArray(this.$refs['input']) && Array.isArray(this.$refs['input']) &&
this.$refs['input'].forEach(item => { this.$refs['input'].forEach((item, index) => {
item.innerHTML = item.innerText; initDivInput(item, {
item.addEventListener('paste', function(e) { callback: res => {
e.stopPropagation(); this.content[index]['name'] = res;
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);
} }
}); });
}); });
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!