Vml:美洲豹系列教程之十二(公文留痕)

在办公自动化,公文审核的时候,就需要用到 留痕操作了,就是把修改的东西直接在文本上显示,而不直接改动它。在以前,我没有用VML去做,很勉强的用 TextRange 改变文本的颜色,然后增加一个层显示更改信息。第一次修改还可以实现,但不能做到再次修改,因为,第二次修改的时候,那些原来创建的对象都消失了,而这些对象都是通过 Select 操作得到的,用户不选择,脚本就没有办法创建那些对象。
    不久前,我想到了 VML ,开始还觉得是不可能的事情,但我发现了 TextRange 对象一个很强大的方法 getClientRects(),这个方法可以返回 TextRange 对象包含的每一行的矩形信息。意思是说,如果你用鼠表选择一段文本,文本会自动高亮显示,这样看上去就是一块块矩形组成的不规则图形。getClientRects 方法就可以得到这些矩形的坐标和高宽,这样一来,就可以在选择的文本外套一层 VML 画的矩形,Oh my god...真是酷呆了。当我第一次看到它的时候,兴奋的抱着小白(猫)满屋子乱跳。     接下来,讲讲 TextRange 对象以及 getClientRects 和 VML 结合画痕迹:
    TextRange 对象,顾名思义,文本区域,就是网页上的一部分区域,可以是文本也可以是图像和别的段落格式。所有能用鼠标选择的都可以变成 TextRange 对象。IE4 的时候就出现了。TextRange 有个强大的方法就是 execCommand(),它可以执行很多命令,动态更改网页中内容、样式。创建 TextRange 对象一般有两种途径,一种是用户选择了一段文本,可以使用 var oTextRange=document.selection.createRange(); 还有种就是直接把document 创建成 TextRange :var oTextRange=document.createTextRane() 。不知道有没有注意,两个方式使用的函数不一样,第一个因为本省就是文字了,所有使用 createRange(), 第二个不能确定是否都是文字,所有,必须用 createTextRange()。
    使用 getClientRects 返回的是一个 TextRectangle 对象,它是一个集合,没个子集拥有四个属性 bottom,top,left,right ,就是两个角的坐标,这个坐标值是相对于页面的,所以可以直接应用到 VML 中来。
function createRect(num)
{
 var newMark=document.createElement("<div id='mark"+num+"'></div>");
 edit.insertBefore(newMark);
 var oRcts = oTempRange.getClientRects();//oTempRange是一个 TextRange 对象
 for(var i=0;i< oRcts.length;i++)
 {
  var t=oRcts[i].top;
  var l=oRcts[i].left;
  var r=oRcts[i].right;
  var b=oRcts[i].bottom;
  var newRect=document.createElement("<v:roundRect οncοntextmenu='popID="+num+";popUp();' id='Rect"+num+"no"+i+"' style='position:absolute;visibility:hidden' filled=f strokeColor=red strokeWeight=1.5pt></v:roundRect>");
  newMark.insertBefore(newRect);
  newRect.style.posTop=t+document.body.scrollTop-3;
  newRect.style.posLeft=l-2;
  newRect.style.width=r-l;
  newRect.style.height=b-t;
  newRect.style.visibility="";
 }
}

    其他的代码就不再说了,我想说说整个脚本执行的过程。首先用户用鼠标选择一段文字,然后脚本马上把选择的文字创建成临时 TextRange 对象,并且通过 execCommand 把这段文字的背景颜色改掉,以做对比。当用户点右键的时候,脚本检查到用户的事件源,如果临时 TextRange 对象存在,菜单上将显示 “标记选择中的”这项,如果事件源是已经标记过的文本,菜单上将显示“取消标记”这项。当用户意见选择“标记选中的”的时候,脚本弹出 对话框,提示用户意见输入对选择的这段文字的处理。
    脚本得到用户的选择,就执行上面的代码,用 VML 把选择的文字框起来,然后生成一个层,上面记录的是修改的内容。当用户选择的“取消标记”,本身已经标记过的文字在点右键的事件上就有个 popID=XX 的表达式,popID是个全局变量,通过这个popID 到 Document 中去寻找相应的 VML 标记和层,然后使他们的 outerHTML 为空,就起到了取消标记的目的!
    可以访问下面的页面,可以实现过程的。
     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html xmlns:v="urn:schemas-microsoft-com:vml"> <head> <title>公文留痕</title> </head> <STYLE> v\:* { BEHAVIOR: url(#default#VML) } </STYLE> <style type="text/css"> .memo{ border-top: solid black; border-right:solid black; border-bottom:solid black; border-left:solid black; padding-top:10px; padding-left:10px; padding-bottom:10px; padding-right:10px; border-width:1px; background-color:#EFEFEF; font-size:11.2pt; font-family:宋体; } .ddd{ padding-left : 3; padding-top : 3; padding-bottom : 3; padding-right : 3; border-top: solid black; border-right:solid black; border-bottom:solid black; border-left:solid black; border-width:1px; color:black; font-size:12px; } .delText{ /* 删除线的样式 */ text-decoration : line-through; color=red; } .editText{ /* 修改的样式 */ text-decoration :none; color:white; background-color:#ff6699; } .item{ /*右键菜单样式*/ width:100%; height:23px; border-width:0px; background:white; } .bbb { BORDER-BOTTOM: black 2px inset; BORDER-LEFT: white 2px outset; BORDER-RIGHT: black 2px inset; BORDER-TOP: white 2px outset } .mask { BACKGROUND: yellow; COLOR: red; CURSOR: hand } .temp { BACKGROUND: #ffffcc; COLOR: #0000ff; CURSOR: hand } .edit { BORDER-BOTTOM: red 2px solid; BORDER-LEFT: red 2px solid; BORDER-RIGHT: red 2px solid; BORDER-TOP: red 2px solid } .wen{ padding-top:3px; padding-left:3px; padding-bottom:3px; padding-right:3px; FONT-SIZE: 9.2pt; LINE-HEIGHT: 20px; BACKGROUND-COLOR: #99ccff; BORDER-BOTTOM: #330099 1px solid; BORDER-LEFT: #330099 1px solid; BORDER-RIGHT: #330099 1px solid; BORDER-TOP: #330099 1px solid; cursor:move; /*filter:Alpha(Opacity="80",FinishOpacity="90",Style="0");*/ } .inside { LEFT: 1px; POSITION: relative; TOP: 1px } </style> <script language="JavaScript"> <!-- function SymError() { return true; } window.onerror = SymError; //--> </script> <script language="JScript"> var nowID=0; var popID=0; var padHeight=0; function init() { newID=parseInt(document.all("n").value); } function createDelLine(num) { var newMark=document.createElement("<div id='mark"+num+"'></div>"); memo.insertBefore(newMark); var oRcts = oTempRange.getClientRects(); for(var i=0;i<oRcts.length;i++) { var t=oRcts[i].top; var l=oRcts[i].left; var r=oRcts[i].right; var b=oRcts[i].bottom; var newRect=document.createElement("<v:roundRect οncοntextmenu='popID="+num+";popUp();' id='Rect"+num+"no"+i+"' style='position:absolute;visibility:hidden' filled=t fillcolor=red strokeColor=red strokeWeight=1pt></v:roundRect>"); newMark.insertBefore(newRect); newRect.style.posTop=t+document.body.scrollTop-2+(b-t)/2; newRect.style.posLeft=l-2; newRect.style.width=r-l; newRect.style.height=2; newRect.style.visibility=""; } } function createRect(num) { var newMark=document.createElement("<div id='mark"+num+"'></div>"); edit.insertBefore(newMark); var oRcts = oTempRange.getClientRects(); for(var i=0;i<oRcts.length;i++) { var t=oRcts[i].top; var l=oRcts[i].left; var r=oRcts[i].right; var b=oRcts[i].bottom; var newRect=document.createElement("<v:roundRect οncοntextmenu='popID="+num+";popUp();' id='Rect"+num+"no"+i+"' style='position:absolute;visibility:hidden' filled=f strokeColor=red strokeWeight=1.5pt></v:roundRect>"); newMark.insertBefore(newRect); newRect.style.posTop=t+document.body.scrollTop-3; newRect.style.posLeft=l-2; newRect.style.width=r-l; newRect.style.height=b-t; newRect.style.visibility=""; } } var PopSrcElement=null; var SelectOk=false; var oTempRange=null; function createTempRange() { hideMenu(); doc_click(); if(document.selection.type=="Text") { oTempRange=document.selection.createRange(); //把选择的文本创建成 TextRange 对象 if(oTempRange.htmlText!=""){ //检查选择的是否为空字符 RangePosLeft=oTempRange.boundingLeft; RangePosTop =oTempRange.offsetTop+document.body.scrollTop+oTempRange.boundingHeight; oTempRange.execCommand("BackColor",true,"#99ccff");; oTempRange.execCommand("UnSelect"); SelectOk=true; } else SelectOK=false; } } function doc_click() { dragapproved=false; if((self.event.button==1)&&(oTempRange!=null)) //取消临时标记 { oTempRange.execCommand("BackColor",true,"#EFEFEF"); oTempRange=null; SelectOk=false; } } function popUp() { PopSrcElement=event.srcElement; //获得 Popup 事件源 self.event.returnValue=false; setButton(); var newxx=event.x+document.body.scrollLeft-3; var newyy=event.y+document.body.scrollTop-3; if((event.clientY+135)>document.body.clientHeight) newyy=newyy-135; if((event.clientX+120)>document.body.clientWidth) newxx=newxx-120; popmenu.style.posLeft=newxx; popmenu.style.posTop=newyy; popmenu.style.visibility=""; } function setButton() { document.all.item1.disabled=true; document.all.item2.disabled=true; document.all.item3.disabled=true; if(SelectOk==true) { document.all.item1.disabled=false; //显示标记 按钮 document.all.item3.disabled=false; //显示拷贝 按钮 } if(PopSrcElement.className=="wen") { document.all.item2.disabled=false; //显示取消标记 按钮 document.all.item3.disabled=false; //显示拷贝 按钮 } if(popID!=0) document.all.item2.disabled=false; //显示取消标记 按钮 } function hideMenu() //隐藏弹出菜单 { popmenu.style.visibility="hidden"; } function setColor(n) //改变菜单条颜色 { document.all("item"+n).style.color="white"; document.all("item"+n).style.background="#316AC5"; } function clearColor(n) { document.all("item"+n).style.color="black"; document.all("item"+n).style.background="white"; } function maskText() { hideMenu(); var mask=showModalDialog("Mask.html",null,"status:no;center:yes;help:no;minimize:no;maximize:no;dialogWidth:400px;scroll:no;dialogHeight:250px"); if(mask!=""){ var del=mask.charAt(1); //获得是 删除 还是 修改 mask=mask.substring(3,mask.length); //替换掉参数 ,剩下的就是 文本了 nowID++; TempRange = false; if(del=="1") { createDelLine(nowID); oTempRange.execCommand("BackColor",true,"#EFEFEF"); oTempRange=null; SelectOk=false; } else { createRect(nowID); oTempRange.execCommand("BackColor",true,"#EFEFEF"); oTempRange=null; SelectOk=false; mask=re(mask); var newMemo=document.createElement("<input id='more"+nowID+"' type=hidden>") //标记的内容 newMemo.value=rere(mask); memo.insertBefore(newMemo); var newDIV=document.createElement("<DIV id='memo"+nowID+"' οncοntextmenu='popID="+nowID+";popUp()' class='wen' style='position:absolute;left:"+RangePosLeft+";top:"+RangePosTop+";width:150px;z-index:9'></DIV>"); newDIV.innerHTML="<img alt='展开' id='expand"+nowID+"' src='expand.gif' style='cursor:hand' οnclick='expandMemo("+nowID+",1)'>"+document.all("more"+nowID).value.substring(0,10); memo.insertBefore(newDIV); } } else return } var popID=0; function expandMemo(n,b) { if(b==1) document.all("memo"+n).innerHTML="<img alt='收缩' id='expand"+n+"' src='collapse.gif' style='cursor:hand' οnclick='expandMemo("+n+",0)'>"+document.all("more"+n).value; else document.all("memo"+n).innerHTML="<img alt='展开' id='expand"+n+"' src='expand.gif' style='cursor:hand' οnclick='expandMemo("+n+",1)'>"+document.all("more"+n).value.substring(0,10); } function copyTo() { hideMenu(); if(SelectOk==true) //拷贝选择的文字 { oTempRange.execCommand("Copy"); alert("已经将\n\n"+oTempRange.text+"\n\n复制了!"); return } if(PopSrcElement.className=="wen") //拷贝 标记的文字 { var textR=document.body.createTextRange(); textR.moveToElementText(PopSrcElement); textR.execCommand("Copy"); alert("已经将\n\n"+textR.text+"\n\n复制了!"); } if(PopSrcElement.className=="editText") //拷贝 标记的文字 { var textR=document.body.createTextRange(); textR.moveToElementText(PopSrcElement); textR.execCommand("Copy"); alert("已经将\n\n"+textR.text+"\n\n复制了!"); } } function save() { if (dialog("确定要保存所做的修改吗?\n你也可以在下次继续修改本公文。","保存修改",36+256)=="6"){ saveForm.TextContentMemo.value=document.all("memo").innerHTML; saveForm.TextContent.value=document.all("edit").innerHTML; saveForm.TotalMarked.value=nowID; } } function unMask() { hideMenu(); if (dialog("确实要取消对这个标记吗?","取消标记",36+256)=="6") { document.all("mark"+popID).outerHTML=""; if(document.all("memo"+popID)) document.all("memo"+popID).outerHTML=""; } popID=0; } function showhelp() //显示帮助信息 { var msg="\n" +"\n 第一步:选择一段文字" +"\n 第二步:在选择的文字上面点右键" +"\n 第三步:选择“标记选中”的,然后输入标记的内容\n\n" +"\n ■注意事项:■■■■■■■\n" +"\n 1.要取消标记,在标记上点右键,选择“取消标记”\n" +"\n 2.要复制选中的文本,请选择“复制选中的”\n" +"\n 美洲豹" +"\n\n 2002年4月18日"; dialog(msg,"在线帮助",64); } function DragStart() { if ("IMG"==event.srcElement.tagName) event.returnValue=false; } //有关移动的过程和函数 var dragapproved=false var eventsource,x,y var popeventsource="" function move() { if(event.button==1 && dragapproved) { hideMenu(); var newleft=temp1+event.clientX-x var newtop=temp2+event.clientY-y eventsource.style.pixelLeft=newleft eventsource.style.pixelTop=newtop return false } } function drags() { if((!document.all)&&(event.srcElement.tagName=="INPUT")) return if (event.srcElement.className=="wen") { dragapproved=true eventsource=event.srcElement temp1=eventsource.style.pixelLeft temp2=eventsource.style.pixelTop x=event.clientX y=event.clientY document.οnmοusemοve=move } } //document.οndragstart=DragStart; document.οnmοuseup=createTempRange; //document.onselectstart=selectStart; document.οnmοusedοwn=drags; self.οnlοad=init; </script> <script language="VBScript"> Function dialog(msg,title,head) dialog=MsgBox(msg,head,title) End Function Function re(t) tt=t tt= Replace(tt,"'","''") tt= Trim(Replace(tt,Chr(10),"<br>",1)) tt= Replace(tt," ","&nbsp;",1) re=tt End Function Function reit(str,d,s) reit=Replace(str,d,s) End Function Function rere(t) t=Replace(t,"<","&lt;",1) t=Replace(t,">","&gt;",1) t=Replace(t,"&lt;br&gt;","<br>",1) rere=t End Function </script> <body> <table align="center"> <tr> <td align="center"> <table align="center"> <tr> <td>公文头部</td> </tr> </table> <div align="left" class="memo" style="position:absolute;top:0;left:0px;width:700;line-height:23px" id="edit" οncοntextmenu="popID=0;popUp()"> <h3>VML 和 TextRange 对象的结合,可以在知道文字位置的情况下给文字画筐,画圈...</h3> <ul> <li>第一步:选择一段文字 <li>在选择的文字上面点右键 <li>第三步:选择“标记选中”的,然后输入标记的内容 </ul> <b>注意:使用的时候,因为标记都是绝对定位,所以文章也必须使用绝对定位!!</b> &nbsp;&nbsp;&nbsp;&nbsp;各工程公司、项目部: <br> <br> &nbsp;&nbsp;&nbsp;&nbsp;根据在建工程施工进度的进展情况与业主对工期的要求,经过对工程量的认真盘点,结合集团公司今年的总体施工部署,现下达2002年二季度施工计划,请认真予以执行。今年赣龙线十九标段要完成产值2亿元,宁启线二标段和W10、W11标段的主体工程均要完成,施工任务艰巨,请你们要结合施工现场的实际情况,优化施工资源的配置,抓紧前期征迁工作的办理,见缝插针,把制约工期的桥涵基础、软基施工争取在本季度内超计划完成,为铺开工作面,在施工的黄金季节到来时加快施工进度创造条件。<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;<font style="font-size:12pt">2002年一季度施工计划安排9043万元</font>,由于宁启线启动难,施工受征迁影响太大,赣龙线计划实际上是为适应年度投资计划而安排,又加春节放假和雨季提前的影响,集团公司一季度实际完成建安产值为6495.1万元,完成计划的71.8%。<br> <br> &nbsp;&nbsp;&nbsp;&nbsp;2002年二季度施工计划安排17270万元,其中,基建项目安排14441万元,外委工程安排1519万元,更新改造工程安排1256万元,自身建设及其他小型工程安排54.4万元。各公司2002年二季度施工计划安排如下:一公司3010万元,二公司4570万元,三公司5940万元,四公司1388万元,五公司168万元电务公司1400万元,厦门公司794万元。<br> <ul> <li>图形可以任意放</li> <li>图形可以任意放</li> <li>图形可以任意放</li> <li>图形可以任意放</li> </ul> <p style="text-indent:20px;"> sadfasfa <br>sdf</p> <table border="1"> <tr> <td>fddfg</td> <td>fgdsfg</td> </tr> <tr> <td>sdfgsdfg</td> <td>sgdfgsfgf</td> </tr> </table> </div> </td> </tr> </table> <div id="memo"></div> <div class="bbb" id="popmenu" style="background-color:white;HEIGHT: 135px; LEFT: 0px; POSITION: absolute; TOP: 0px; visibility:hidden; WIDTH: 120px; Z-INDEX: 9"> <button class="item" name="item1" οnmοuseοver="setColor(1)" οnmοuseοut="clearColor(1)" οnmοusedοwn="maskText();">&nbsp;标记选中的</button><br> <button class="item" name="item2" οnmοuseοver="setColor(2)" οnmοuseοut="clearColor(2)" οnmοusedοwn="unMask();">&nbsp;取消标记&nbsp;&nbsp;</button><br> <hr align=center SIZE=2 width="95%"> <button class="item" name="item3" οnmοuseοver="setColor(3)" οnmοuseοut="clearColor(3)" οnmοusedοwn="copyTo();" >&nbsp;复制&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</button><br> <button class="item" name="item4" οnmοuseοver="setColor(4)" οnmοuseοut="clearColor(4)" οnmοusedοwn="save();">&nbsp;保存修改&nbsp;&nbsp;</button><br> <button class="item" name="item5" οnmοuseοver="setColor(5)" οnmοuseοut="clearColor(5)" οnmοusedοwn="hideMenu();showhelp();">&nbsp;在线帮助&nbsp;&nbsp;</button> </div> <form name="saveForm"> <input type="hidden" name="n" value="0"> <!-- 总共有多少留痕操作 --> <input type="hidden" name="con"> <!-- 文本内容(包含修改过的内容) --> <input type="hidden" name="memory"> <!-- 留痕的内容 由多个<DIV>组成 --> </form> </body> </html> 文本修改留痕


    到目前为止,关于VML的介绍已经全部写完了。当然我想这里面错误还是有的,理解上也有很不足,表达上还有欠缺的地方。由于 VML 应用的还不太普遍,但功能强大,我觉得有必要让大家都了解一下VML技术,至少让大家知道,很多东西其实都可以用VML完成的。大家一起研究吧!

转载于:https://www.cnblogs.com/savageworld/archive/2006/07/18/453749.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值