实现类似新浪轻博客的标签列表输入框
之前基于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结构的设计,这里就不便多讲了。