按需求弄了一个 取词 以及 标红 的小应用。

先上demo :http://qianduannotes.sinaapp.com/getKeyword/

很多平时常用的东西,都用上了,所以拿出来说说。

一、代码

var GetKeywords = {
  str: "",
  limit: 11,
  keywords:[],

init : function(){
var box = this._(“article”),
_this = this;

//获取已经存在的关键词
this.getAllKeyWord();

//让rmKeyWord函数全局化
window.rmkeyWord = this.rmkeyWord;

//取词事件
box.onmouseup = function(evt){
  var evt = evt || window.event,
    target = evt.target || evt.srcElement;

  //如果鼠标是在button上弹起,则忽略
  if(target.id == "btn") return;
  GetKeywords.str = _this.getSelectionText();

  if(_this.str.length == 0) return;
  if(_this._("btn")) {
    _this.removeBtn();
    if(GetKeywords.str == "") return;
    _this.createBtn(evt);
    return;
  }
  _this.createBtn(evt);
}

},

//工具函数
_: function(obj){
return document.getElementById(obj);
},

//获取选中文本
getSelectionText: function(){
if(window.getSelection) {
return window.getSelection().toString();
} else if(document.selection && document.selection.createRange) {
return document.selection.createRange().text;
}
return ‘’;
},

//创建按钮
createBtn: function(evt){
var button = document.createElement(“div”),
evt = evt || window.event,
x = evt.pageX || evt.x,
y = evt.pageY || evt.y,
i, j, len,
cssList = “”,
_this = this,
csses = {
“height” : “30px”,
“line-height” : “30px”,
“position”: “absolute”,
“top”: y + 10 + “px”,
“left”: x + 10 + “px”,
“cursor”: “pointer”,
“border”: “1px solid #000”,
“background”: “#EEE”,
“padding”: “2px 8px”,
“border-radius”: “3px”
};
for(i in csses){
if(csses.hasOwnProperty(i)){
cssList += i + “:” + csses[i] + “;”;
}
}
button.style.cssText = cssList;
button.innerHTML = “添加到关键词列表”;
button.setAttribute(“id”, “btn”);

this._("article").appendChild(button);

button.onclick = function(){
  if(_this.str.length > _this.limit){
    alert("关键词长度最长为11,可以通过设置GetKeywords.limit来控制长度。");
    _this.removeBtn();
    return;
  }

  for(j = 0, len = GetKeywords.keywords.length; j < len; j++){
    if(GetKeywords.keywords[j] == _this.str){
      alert("已经存在该关键词了~");
      _this.removeBtn();
      return;
    }
    continue;
  }
  _this.keywords.push(_this.str);
  _this.setRed(_this.str);
  _this.addTo();
  _this.removeBtn();
};

},

//删除按钮
removeBtn: function(){
var btn = this._(“btn”);
btn.parentNode.removeChild(btn);
},

//加入到关键词里列表
addTo: function(){
var word = this._(“wordList”);
word.innerHTML += “<span><font>” + this.str + “</font><a href=’#’ onclick=’rmkeyWord(this);’></a></span>”;
},

//关键词标红
setRed: function(str){
var content = this._(“article”),
temp = ‘(‘ + str + ‘)’;
reg = new RegExp(temp,’g’);

content.innerHTML = content.innerHTML.replace(reg, "&lt;span style='color:red;'&gt;$1&lt;/span&gt;");

},

//删除标红
rmRed: function(str){
var content = this._(“article”),
temp = “(<span[^<]*” + str + “</span>)”;
reg = new RegExp(temp,’gi’);
content.innerHTML = content.innerHTML.replace(reg, str);
},

//获取已经存在的关键词(也可以用来获取所有关键词)
getAllKeyWord: function (){
var spans = this._(“wordList”).getElementsByTagName(“span”),
key = [], i = 0, len;
for(len = spans.length; i < len; i++){
var font = spans[i].getElementsByTagName(“font”)[0];
var temp = font.innerText || font.textContent;
this.setRed(temp);
key.push(temp);
}
this.keywords = key;
},

//删除关键词
rmkeyWord: function (obj){
var target = obj.parentNode,
word = obj.previousSibling.innerHTML,
i = 0, len;
GetKeywords.rmRed(word);
for(len = GetKeywords.keywords.length; i < len; i++){
if(GetKeywords.keywords[i] == word){
GetKeywords.keywords.splice(i,i);
}
continue;
}
target.parentNode.removeChild(target);
return;
}
}

GetKeywords.init();

以上是所有js代码,比较长,下面将列举一些比较突出的点(望高人多多指点)。

二、代码分析

1.获取文本

getSelectionText: function(){
if(window.getSelection) {
return window.getSelection().toString();
} else if(document.selection && document.selection.createRange) {
return document.selection.createRange().text;
}
return '';
}

这个在以前(JavaScript操控光标,你会么?)的文章里也说过,就不赘述了。

2.创建控制框

createBtn: function(evt){
var button = document.createElement("div"),
//...
csses = {
"height" : "30px",
"line-height" : "30px",
"position": "absolute",
"top": y + 10 + "px",
"left": x + 10 + "px",
"cursor": "pointer",
"border": "1px solid #000",
"background": "#EEE",
"padding": "2px 8px",
"border-radius": "3px"
};
for(i in csses){
if(csses.hasOwnProperty(i)){
cssList += i + ":" + csses[i] + ";";
}
}
button.style.cssText = cssList;
button.innerHTML = "添加到关键词列表";
button.setAttribute("id", "btn");
  //...
}

这里有一点我想说说,在写js的时候,会经常涉及到对DOM对象style的处理,如果不想额外加入一个plugins.css之类的文件,可以像上面一样,将样式放置在一个对象中,然后利用for in将其写入,本来开始我用的是

obj.style[i] = csses[i];

不知道为什么,在IE下报错了,后来便用cssText代替。

效果:

添加到列表

3.标红

//关键词标红
setRed: function(str){
var content = this._("article"),
temp = '(' + str + ')';
reg = new RegExp(temp,'g');

content.innerHTML = content.innerHTML.replace(reg, "<span>$1</span>");
}

这里主要就是正则表达式的事情了,正则的话,推荐两篇文章

  • 一篇是司徒正美的,讲的比较全面,比较系统。点我链接过去→
  • 一篇是30分钟搞定正则,这个讲说是对所有语言,JS的话正则这一块还不是特别完善和强大。点我链接过去→

哈哈,相信用过正则的人不需要我来解释这个$1了吧,他的意思就是匹配到的第一个。

当然,删除标红和这个原理是差不多的。

//删除标红
rmRed: function(str){
var content = this._("article"),
temp = "(<span[^<]*" +="" str="" "<="" span="">)";
reg = new RegExp(temp,'gi');

content.innerHTML = content.innerHTML.replace(reg, str);
}

</span[^<]*”>

这里是写完这篇blog才发现的一个bug, IE下如果rmRed中的正则是'g',貌似该函数会无效,在IE8控制台下查看,NND,输出innerHTML中的标签全部变成大写了,无奈,只好改成'gi'。

4.获取所有关键词和删除关键词

//获取已经存在的关键词(也可以用来获取所有关键词)
getAllKeyWord: function (){
//...
},

//删除关键词
rmkeyWord: function (obj){
//...
GetKeywords.rmRed(word);
for(len = GetKeywords.keywords.length; i < len; i++){
if(GetKeywords.keywords[i] == word){
GetKeywords.keywords.splice(i,i);
}
continue;
}
//...
}

这个地方,有一个疑问,在调用的时候,使用this.keywords没反应,但是改成GetKeywords就行了,还没研究具体原因是什么~

5.初始化

GetKeywords.init();

init()为总入口,进去之后,先获取已经存在的关键词,然后标红,接着绑定onmouseup事件。

三、然后

当然咯,这个案例的ajax部分还没写,弄完之后还得给后台送过去。。好吧,明天接着弄吧。

写这玩意儿还是花了点功夫,不过鄙人写代码的水平还在初级阶段,望大神们不要吐槽,多提宝贵意见,谢谢!

然后,还是那个demo,http://qianduannotes.sinaapp.com/getKeyword/

顺便,推广下,团队做的一个网站,主要技术是爬虫,高峰期PV稳定在120W以上,找工作的童鞋可以多去踩踩~

宣讲会查询系统——海投网 

P.S:刚让队友测试,还是发现了不少bug,果然考虑问题还是不全面啊~还要继续加油。。。