zoukankan      html  css  js  c++  java
  • Fix IE6 剪贴板撤销机制CtrlZ,CtrlY功能会在由于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([
    00, 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 [00, 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功能正常

  • 相关阅读:
    贪心算法(2)-Kruskal最小生成树
    qsort函数、sort函数 (精心整理篇)
    并查集(2)-按秩合并和路径压缩
    C语言二维数组作为函数的参数
    结构体定义 typedef struct 用法详解和用法小结
    并查集(1)-判断无向图是否存在环
    蚂蚁庄园攻略
    java 获取class文件所在路径
    background-color
    appendChild append insertBefore prepend
  • 原文地址:https://www.cnblogs.com/xueduanyang/p/1385128.html
Copyright © 2011-2022 走看看