简单html行内编辑插件
当我们要修改h5页面上的一个表格或者段落的文本时候,通常的方法弹出一个模态对话框来提示用户输入,点击确认后根据输入的内容来修改文本节点,但这样用户体验肯定不是很好。之前看到有x-editable插件可以很好的进行行内编辑,拿来使用却发现和我用的bootstrap4不太兼容,无奈自己动手实现一个吧。
首先,理清行内编辑的基本原理:选中要编辑的DOM节点,先保存文本节点值然后插入一个文本输入框,当按下回车键的时候保存文本框输入的值同时移除文本输入框。是不是很简单?不过需要注意的是和文件重命名一样,不要默认选中文件后缀名,也不允许输入空文本。editText.js如下:
1 // 行内文本编辑 2 function editText(id, callback = null) { 3 let node = document.getElementById(id); 4 let text = node.innerText; 5 // 插入文本框 6 let input = document.createElement('input'); 7 input.type = 'text'; 8 input.placeholder = '输入文本不能为空'; 9 input.spellcheck = false; 10 input.value = text; 11 node.innerText = ''; 12 node.append(input); 13 // 选中文本 14 let end = text.search(/\.\w+$/); 15 input.focus(); 16 input.selectionStart = 0; 17 input.selectionEnd = (end == -1) ? text.length : end; 18 // 按键事件 19 input.onkeydown = function(e) { 20 // 按下回车键 21 if (e.keyCode == 13) { 22 let data = this.value; 23 if (data == '') { 24 return; 25 } else { 26 input.onblur = false; 27 this.remove(); 28 node.innerText = data; 29 if (callback) { 30 callback(data); 31 } 32 } 33 // 按下ESC键 34 } else if (e.keyCode == 27) { 35 input.onblur = false; 36 this.remove(); 37 node.innerText = text; 38 } 39 } 40 // 失去焦点默认完成编辑 41 input.onblur = function() { 42 let data = this.value; 43 this.remove(); 44 if (data == '') { 45 node.innerText = text; 46 } else { 47 node.innerText = data; 48 if (callback) { 49 callback(data); 50 } 51 } 52 } 53 }
这里使用id选中元素,然后插入文本输入框编辑,可以传入一个回调函数来处理编辑后的数据。需要注意的是当编辑完成remove输入框的时候会触发blur事件,所以我添加了input.onblur = false来取消该事件,以防止重复移除,这句写成this.onblur = false也行,不过vscode编辑器会提示你“此构造函数可能会转换为类声明”,因为我们以前就是用函数来申明类型的。该函数调用过程也非常简单:
1 <body> 2 <p id="text">hello.txt</p> 3 <button onclick="edit()">编辑</button> 4 <script src="./editText.js"></script> 5 <script> 6 function edit() { 7 editText('text', function(data) { 8 console.log('新文本:' + data); 9 }); 10 } 11 </script> 12 </body>
演示一下行内编辑效果:
最后我们可以把它封装成jquery插件,方便以后调用,改名为jquery.editText.js:
1 $.fn.extend({ 2 editText: function(callback = null) { 3 let $node = $(this); 4 let text = $node.text(); 5 $node.text('').append($('<input>').attr({type:'text', placeholder:'输入文本不能为空', spellcheck:false}).val(text).on({ 6 keydown: function(e) { 7 if (e.keyCode == 13) { 8 let data = $(this).val(); 9 if (data == '') { 10 return; 11 } else { 12 $(this).remove(); 13 $node.text(data); 14 if (callback) { 15 callback(data); 16 } 17 } 18 } else if (e.keyCode == 27) { 19 $(this).remove(); 20 $node.text(text); 21 } 22 }, 23 blur: function() { 24 let data = $(this).val(); 25 $(this).remove(); 26 if (data == '') { 27 $node.text(text); 28 } else { 29 $node.text(data); 30 if (callback) { 31 callback(data); 32 } 33 } 34 }, 35 focus: function() { 36 let end = text.search(/\.\w+$/); 37 this.setSelectionRange(0, end == -1 ? text.length : end); 38 } 39 })).children('input:first').focus(); 40 } 41 });
引入jquery后即可使用:
1 <body> 2 <p id="text">hello.txt</p> 3 <button onclick="edit()">编辑</button> 4 <script src="./jquery-3.4.1.min.js"></script> 5 <script src="./jquery.editText.js"></script> 6 <script> 7 function edit() { 8 $('#text').editText();//可以不带回调函数 9 } 10 </script> 11 </body>