| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| <html xmlns="http://www.w3.org/1999/xhtml"> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> |
| <title>关键字快速搜索</title> |
| <style> |
| body |
| { |
| font-size: 14px; |
| } |
|
|
| h3 |
| { |
| display: inline; |
| margin: 0; |
| } |
|
|
| #spnKeyNum, #spnWordNum |
| { |
| color: #F00; |
| } |
|
|
| #spnList a |
| { |
| font-size: 12px; |
| color: #0000FF; |
| } |
|
|
| #spnTime |
| { |
| color: #600; |
| } |
|
|
| textarea, #divDisplay |
| { |
| margin: 0; |
| padding: 0; |
| font-size: 14px; |
| display: block; |
| background: #EEE; |
| border: #999 solid 1px; |
| } |
|
|
| #txtKeys |
| { |
| width: 95%; |
| height: 100px; |
| } |
|
|
| #txtContent, #divDisplay |
| { |
| height: 400px; |
| width: 95%; |
| } |
|
|
| #divDisplay |
| { |
| display: none; |
| overflow: auto; |
| } |
|
|
| #divDisplay em |
| { |
| color: #F00; |
| font-style: normal; |
| } |
|
|
| #divFoot |
| { |
| padding: 5px; |
| width: 95%; |
| } |
|
|
| #spnLable2 |
| { |
| margin: 5px; |
| float: left; |
| color: #690; |
| } |
|
|
| button |
| { |
| float: left; |
| } |
|
|
| #desc |
| { |
| color: #333; |
| float: right; |
| } |
| </style> |
| </head> |
|
|
| <body onload="handleLoad();"> |
| <div id="divTop"> |
| <h3>关键字</h3> |
| <span id="spnLable1">(<span id="spnKeyNum">0</span>个)</span> |
| <span id="spnList"> |
| <a href="javascript:load('city.txt');">世界城市</a> |
| <a href="javascript:load('words.txt');">部分英文单词</a> |
| <a href="javascript:load('idiom.txt');">成语全集</a> |
| </span> |
| </div> |
| <div id="divMain"> |
| <textarea id="txtKeys" onchange="handleKeyChange();"></textarea> |
| <h3>内容</h3> |
| <span id="spnLable1">(<span id="spnWordNum">0</span>字)</span> |
| <textarea id="txtContent" onchange="handleContentChange();"></textarea> |
| <div id="divDisplay"></div> |
| </div> |
| <div id="divFoot"> |
| <span id="spnLable2">搜索用时: <span id="spnTime">0</span>ms</span> |
| <button id="btnStart" onclick="handleClick();"> 测试</button> |
| <button id="btnReset" onclick="reset()" disabled="disabled"> 重置</button> |
| <span id="desc">EtherDream 2009</span> |
| </div> |
|
|
| <script> |
| var tblRoot; |
|
|
| /* |
| * 函数: makeTree |
| * 注释: 将关键字生成一颗树 |
| */ |
| function makeTree() |
| { |
| var strKeys = objKeys.value; |
| var arrKeys = strKeys.split(""); |
| var tblCur = tblRoot = {}; |
| var key; |
|
|
| for(var i=0,n=arrKeys.length; i<n; i++) |
| { |
| key = arrKeys[i]; |
|
|
| if(key == ';') //完成当前关键字 |
| { |
| tblCur.end = true; |
| tblCur = tblRoot; |
| continue; |
| } |
|
|
| if(key in tblCur) //生成子节点 |
| tblCur = tblCur[key]; |
| else |
| tblCur = tblCur[key] = {}; |
| } |
|
|
| tblCur.end = true; //最后一个关键字没有分割符 |
| } |
|
|
| /* |
| * 函数: search |
| * 注释: 标记出内容中关键字的位置 |
| */ |
| function search(content) |
| { |
| var tblCur; |
| var i = 0; |
| var n = content.length; |
| var p, v; |
| var arrMatch = []; |
|
|
| while(i < n) |
| { |
| tblCur = tblRoot; |
| p = i; |
| v = 0; |
|
|
| for(;;) |
| { |
| if(!(tblCur = tblCur[content.charAt(p++)])) |
| { |
| i++; |
| break; |
| } |
|
|
| if(tblCur.end) //找到匹配关键字 |
| v = p; |
| } |
|
|
| if(v) //最大匹配 |
| { |
| arrMatch.push(i-1, v); |
| i = v; |
| } |
| } |
|
|
| return arrMatch; |
| } |
| </script> |
|
|
| <script> |
| var $ = function(id){return document.getElementById(id)}; |
|
|
| var objKeys = $("txtKeys"); |
| var objContent = $("txtContent"); |
| var objDisplay = $("divDisplay"); |
| var bKeyChanged = false; |
|
|
|
|
| function handleKeyChange() |
| { |
| var str = objKeys.value; |
| var n; |
|
|
| if(str.length==0) |
| n = 0; |
| else |
| n = str.split(";").length; |
|
|
| /* |
| * 显示关键字数量 |
| */ |
| $("spnKeyNum").innerHTML = n; |
|
|
| bKeyChanged = true; |
| } |
|
|
| function handleContentChange() |
| { |
| /* |
| * 显示内容长度 |
| */ |
| $("spnWordNum").innerHTML = objContent.value.length; |
| } |
|
|
| function handleLoad() |
| { |
| handleKeyChange(); |
| handleContentChange(); |
| } |
|
|
| function handleClick() |
| { |
| var strContent = objContent.value; |
| var arrMatch; |
| var arrHTML = []; |
| var strHTML; |
| var mid; |
| var p = 0; |
|
|
|
|
| $("btnStart").disabled = true; |
| $("btnReset").disabled = false; |
|
|
| if(bKeyChanged) |
| { |
| makeTree(); |
| bKeyChanged = false; |
| } |
|
|
| /* |
| * 开始搜索! |
| */ |
| var t = +new Date(); |
|
|
| arrMatch = search(strContent); |
|
|
| /* |
| * 搜索用时 |
| */ |
| $("spnTime").innerHTML = +new Date() - t; |
|
|
| /* |
| * 标记关键字 |
| */ |
| for(var i=0,n=arrMatch.length; i<n; i+=2) |
| { |
| mid = arrMatch[i]; |
| arrHTML.push(strContent.substring(p, mid), |
| "<em>", |
| strContent.substring(mid, p = arrMatch[i+1]), |
| "</em>"); |
| } |
| arrHTML.push(strContent.substring(p)); |
|
|
| strHTML = arrHTML.join("").replace(/\n/g, "<br>"); |
|
|
| /* |
| * 显示结果 |
| */ |
| objDisplay.innerHTML = strHTML; |
|
|
| objContent.style.display = "none"; |
| objDisplay.style.display = "block"; |
| } |
|
|
| function reset() |
| { |
| $("btnStart").disabled = false; |
| $("btnReset").disabled = true; |
|
|
| objContent.style.display = "block"; |
| objDisplay.style.display = "none"; |
| } |
|
|
| function load(file) |
| { |
| /* |
| * 创建HTTP组件 |
| */ |
| if(window.ActiveXObject) |
| { |
| objHttp = new ActiveXObject("Microsoft.XMLHTTP"); |
| } |
| else |
| { |
| objHttp = new XMLHttpRequest(); |
| objHttp.overrideMimeType("text/xml"); |
| } |
|
|
| objHttp.onreadystatechange = function() |
| { |
| if(objHttp.readyState != 4) |
| return; |
|
|
| objKeys.value = objHttp.responseText; |
| handleKeyChange(); |
| }; |
|
|
| /* |
| * 发送请求 |
| */ |
| objHttp.open("GET", file, true); |
| objHttp.send(null); |
| } |
|
|
| </script> |
| </body> |
| </html> |
|
|