实现类似新浪轻博客的标签列表输入框

之前基于jQuery山寨了一个新浪轻博客的标签列表,demo请看这里
后来又加入了编辑功能,类似美味书签。
大致的效果就是点击一个已输入的标签,选中该标签,然后可以对该标签进行编辑。

因为存储标签的名称使用的是div元素,所以这里涉及到的难点主要有:
1)如何使div元素能够被选中;
2)如何使div元素支持编辑功能;
3)因为标签不能重复,所以修改以后使用onblur事件进行验证;

可以编辑的div

这个一般人都知道,就是给div元素加入attribute:contenteditable,这样div元素就支持编辑功能了。主流浏览器包括IE6也都能很好的支持。

点我,然后编辑我吧!

使用脚本设置attribute如下:

//js
div.setAttribute('contenteditable','');
//jQuery
$(div).attr('contenteditable','');  
$(div).attr('contenteditable',true); 
实际使用过程中发现$(div).attr('contenteditable',true);方法的行为不总是一致的.
有时候contenteditable等于"true"而有时候则等于"contenteditable"
但是我在单独的页面测试却不会出现contenteditable="contenteditable"的情况,很是奇怪!
要知道,contenteditable="contenteditable"时,div的内容是没办法编辑的!
推荐使用$(div).attr('contenteditable','');

可以失去焦点的div

一旦div可以编辑,那么往往需要在div失去焦点的时候进行一些验证或其他脚本行为。
解决办法是给div加入tabindex属性,那么就可以对div设置onblur事件。
如果不希望div的tabindex干扰到页面的tab切换,可以把tabindex设置为负数。

示例

在元素失去焦点的时候显示innerHTML:

我没加入tabindex,我有onblur事件
我加入了tabindex,我有onblur事件

可以被选中的div

function selectDIV(objId)
{
if (document.selection) 
{
document.selection.empty();
var range = document.body.createTextRange();
range.moveToElementText(document.getElementById(objId));
range.select();
}
else if (window.getSelection) 
{
window.getSelection().removeAllRanges();
var range = document.createRange();
range.selectNode(document.getElementById(objId));
window.getSelection().addRange(range);
}
}

让div可以像普通的输入框,可编辑,也可以选中?

上面的三个问题已经一一解决,那么只要给div加入tabindex、contenteditable然后在适当的时候选中div。
这样看起来问题已经全部解决了,但是实验之后发现div从始至终都不能被选中。
一番测试之后发现设置了contenteditable以后div元素就不能被选中了!

解决方案

点击div以后选中div,然后设置其contenteditable属性,失去焦点时移除contenteditable属性。
此方案貌似合情合理,但是实际测试后发现在chrome中选中功能形同虚设,bug重重。
而IE 9中div根本无法编辑!

结论

其实如果用div实现标签的编辑本身就是一件吃力不讨好的事情,需要额外处理比如按下enter键等。
正确的思路应该是利用初始的标签输入框,这样至少在某些事件上可以重复利用。
另外还可以减少一些意外情况,比如按下enter键。
不过这最终的难易程度也受到到HTML结构的设计,这里就不便多讲了。

原文地址:https://www.cnblogs.com/1000/p/2165749.html