Fix IE6 剪贴板撤销机制Ctrl-Z,Ctrl-Y功能会在由于Js动态改变页面元素的value后失效的Problem...

这个问题是在我们的后台的CMS系统中发现的,由于编辑人员要大量使用Js对于Textarea和Input Text中的内容作处理,当有Js改变了Input Text的value后,textarea中undo功能就失效了,这个问题是致命的。

经过我们检查,此问题只发现在IE6,而FF中是没有这个问题的,问题的原因,我们猜测是因为IE6的Undo是绑定在Page对象上的,当Js改变DOM结构或者改变了El的value,该对象不知道为什么也被重置了,而FF是将Undo功能绑定在具体每个元素上的,所以要Fix这个问题,只能采用Js模拟FF将Undo的ClipBoard绑定在每个元素上了。

方法如下,我们覆盖了IE默认的Ctrl-Z和Ctrl-Y功能,用一个长度固定的Queue存放文本区每次改变的值,因为输入文本存在连续输入的可能,所以我们作了一个延时器,当1秒后再无任何动作后,才将value值保存,同时IE在每次Undo的时候都会将光标位置保留,所以我们又用了一个同样的Queue纪录光标的位置,具体代码如下

 

< html >

< head >
< meta http - equiv = " Content-Type "  content = " text/html; charset=gb2312 " >
< title > test < / title>
< / head>

< body >

< input id = " txt1 "  type = " text "  value = ""  size = " 44 " >
< input type = " button "  value = " click me 1 "  onclick = " clickMe1() " >
< script >
function  clickMe1(){
    document.getElementById(
' txt1 ' ).value = ' 4545 ' ;
}
< / script>
< br / >
< textarea id = " txt2 "  rows = " 24 "  cols = " 57 " >< / textarea>
< input type = " button "  value = " click me 2 "  onclick = " clickMe2() " >
< script >
function  clickMe2(){
    document.getElementById(
' txt2 ' ).value = ' 4545 ' ;
}
< / script>
< br / >
< input type = " button "  value = " Apply Js Undo Function Fix IE6 Bug "  onclick = " fixUndo() " >
< script >
function  fixUndo(){
    fixIE6Undo(document.getElementById(
' txt1 ' ),document.getElementById( ' txt2 ' ));
}

function  fixIE6Undo(){
    
//  Valid when UA is IE and version is less than 7
     if  ( ! ( / MSIE (\d+\.\d) / .exec(navigator.userAgent)[ 1 <=   6.0 )) {
        
return   false ;
    }
    
var  debugMode  =   false ;
    
var  debugPrint  =   function (s){
        
var  d  =  document.createElement( ' div ' );
        d.innerHTML 
=  s;
        document.body.appendChild(d);
    };
    
//  Set global Timer
     var  _undoTimer  =   null ;
    
//  Set Undo max step
     var  _maxUndoStep  =   20 ;
    
var  setBookmark  =   function (e, bookmarks){
        e.scrollTop 
=  bookmarks[ 2 ];
        
var  end  =  bookmarks[ 1 ];
        
var  start  =  bookmarks[ 0 ];
        
//  Fix IE offset bug with char return&newline
         var  ose  =  e.value.substring( 0 , end).split( / \n / g).length  -   1 ;
        
var  ost  =  e.value.substring( 0 , start).split( / \n / g).length  -   1 ;
        
//  Resume Range
         var  range  =  e.createTextRange();
        range.collapse(
true );
        range.moveEnd(
' character ' , end  -  ose);
        range.moveStart(
' character ' , start  -  ost);
        range.select();
        e.focus();
    };
    
var  applyUndoStep  =   function (e){
        e.value 
=  e._undoQueue[e._undoQueueIndex];
        
var  bookmarks  =  e._bookmarkQueue[e._undoQueueIndex];
        
if  ( ' TEXTAREA '   ==  e.tagName) {
            setBookmark(e, bookmarks);
        }
        
if  (debugMode) {
            debugPrint(e._undoQueueIndex 
+   '  -  '   +  e._undoQueue[e._undoQueueIndex]  +   ' <hr /> ' );
        }
    };
    
for  ( var  i  =   0 ; i  <  arguments.length; i ++ ) {
        
//  Deal with each argument
        ( function (el){
            
if  (( ' INPUT '   ==  el.tagName  &&   ' text '   ==  el.type)  ||   ' TEXTAREA '   ==  el.tagName) {
                el._undoQueue 
=   new  Array();
                el._bookmarkQueue 
=   new  Array();
                el._undoQueueIndex 
=   0 ;
                el._undoQueue.push(el.value 
||   '' );
                el._bookmarkQueue.push([
0 0 , el.scrollTop]);
                el.attachEvent(
' onpropertychange ' function (){
                    
if  (window.event  &&  window.event.propertyName  ==   ' value ' ) {
                        clearTimeout(_undoTimer);
                        _undoTimer 
=  setTimeout( function (){
                            
var  uQue  =  el._undoQueue;
                            
var  bQue  =  el._bookmarkQueue;
                            
if  (el.value  !=  uQue[el._undoQueueIndex]) {
                                
//  Value changed
                                el._undoQueueIndex ++ ;
                                
var  len  =  uQue.length  -  el._undoQueueIndex;
                                
if  (len  >   0 ) {
                                    
//  Slice undo queue
                                    uQue.splice(el._undoQueueIndex, len);
                                    bQue.splice(el._undoQueueIndex, len);
                                }
                                
if  (uQue.length  >=  _maxUndoStep) {
                                    
//  Reached max step
                                    uQue.shift();
                                    bQue.shift();
                                    el._undoQueueIndex
-- ;
                                }
                                
var  bookmarks  =  ( function (e){
                                    e.focus();
                                    
var  r  =  document.selection.createRange();
                                    
if  ( ! r) {
                                        
return  [ 0 0 , e.scrollTop];
                                    }
                                    
var  re  =  e.createTextRange();
                                    
var  rc  =  re.duplicate();
                                    re.moveToBookmark(r.getBookmark());
                                    rc.setEndPoint(
' EndToStart ' , re);
                                    
return  [rc.text.length, rc.text.length  +  r.text.length, e.scrollTop];
                                })(el);
                                
//  Add new value to undo queue
                                uQue.push(el.value);
                                bQue.push(bookmarks);
                            }
                        }, 
300 );
                    }
                });
                el.attachEvent(
' onkeydown ' function (){
                    
if  ( !! event.ctrlKey) {
                        
if  (event.keyCode  ==   90 ) {
                            
//  Undo with ctrl + z
                             if  (el._undoQueueIndex  >   0 ) {
                                el._undoQueueIndex
-- ;
                                applyUndoStep(el);
                            }
                            
return   false ;
                        }
                        
else  {
                            
if  (event.keyCode  ==   89 ) {
                                
//  Redo with ctrl + y
                                 if  (el._undoQueueIndex  +   1   <  el._undoQueue.length) {
                                    el._undoQueueIndex
++ ;
                                    applyUndoStep(el);
                                }
                                
return   false ;
                            }
                        }
                    }
                });
            }
        })(arguments[i]);
    }
}
< / script>

< / body>

< / html>

 

测试JS内存性能结果:
1.打开测试网页,内存占用为11,740
2.让页面任意元素获得焦点,内存占用开始小幅波动,峰值约为12,300
3.点击Apply..Js按钮,应用FixIE6Undo功能,内存降为12,624
4.在文本区反复输入长度为6521字符的文本,次数10次,重复执行Ctrl-C,Ctrl-V操作,内存占用为20,388
5.在文本区反复使用Ctrl-Y,Ctrl-Z功能,内存占用逐步增长,到42,700左右,开始微幅下滑,始终在42,650左右浮动,内存并未出现溢出现象,且经过反复测试Ctrl-Z,Ctrl-Y功能正常

 

转载于:https://www.cnblogs.com/xueduanyang/archive/2009/02/06/1385128.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值