代码之家  ›  专栏  ›  技术社区  ›  Luka Milani

谷歌Chrome和javascript的问题。需要大师!

  •  0
  • Luka Milani  · 技术社区  · 14 年前

    我有个奇怪的问题 只有铬 使用一个 iframe 但在所有其他常用浏览器中工作。

    问题是:如果我输入iframe,然后按下发送按钮,它工作正常,焦点回到iframe,光标闪烁。

    但是,如果我键入然后按Enter键来调用事件处理程序函数,焦点会向后移动,但光标会消失。然后,如果您进入另一个窗口,然后返回光标。 这只发生在铬合金中 . 我做了一个示例页面来显示实际中的问题。单击下面的链接查看。

    更新:我在下面添加了代码

        var editorFrame = 'myEditor'
    
    function addFrame() {
    
        var newFrame = new Element('iframe', {
            width: '520', 
            height: '100',
            id: editorFrame,
            name: editorFrame,
            src: 'blank.asp',
            class: 'myClass'
        });
    
        $('myArea').appendChild(newFrame);
    
        window.iframeLoaded = function() {
            // this is call-back from the iframe to be sure that is loaded, so can safety attach the event handler
    
            var iframeDoc, UNDEF = "undefined";
            if (typeof newFrame.contentDocument != UNDEF) {
                iframeDoc = newFrame.contentDocument;
            } else if (typeof newFrame.contentWindow != UNDEF) {
                iframeDoc = newFrame.contentWindow.document;
            }
            if (typeof iframeDoc.addEventListener != UNDEF) {
                iframeDoc.addEventListener('keydown', keyHandler, false);
            } else if (typeof iframeDoc.attachEvent != UNDEF) {
                iframeDoc.attachEvent('onkeydown', keyHandler);  
            }
        };
    }
    
    function resetContent() 
    {   
        var myIFrame = $(editorFrame);
    
        if (myIFrame) myIFrame.contentWindow.document.body.innerHTML='';
    }
    
    function setEditFocus() 
    {
    
        var iFrame = document.frames ? document.frames[editorFrame] : $(editorFrame);
        var ifWin = iFrame .contentWindow || iFrame;
    
        ifWin.focus();
    
    }
    
    function send()
    {
        resetContent();
        setEditFocus(); 
    }
    
    function keyHandler (evt) {
    
        var myKey=(evt.which || evt.charCode || evt.keyCode)
    
        if (myKey==13)  {
    
            if (!evt) var evt = window.event;
    
            evt.returnValue = false;
    
            if (Prototype.Browser.IE) evt.keyCode = 0;
    
            evt.cancelBubble = true;
    
            if (evt.stopPropagation) evt.stopPropagation();
    
            if (evt.preventDefault) evt.preventDefault();
    
            send();
    
        }
    }
    

    在HTML页中

    <body onload="addFrame()">
    
    <div id="myArea"></div>
    <input id="myButton" type="button" value="click me to send [case 1]" onclick="send()">
    

    为了更容易理解问题,我创建了一个 复制问题的特定页面 包括完整的示例和源代码。

    您可以使用Google Chrome在这里查看: example of the problem

    我真的需要你的帮助,因为我试着解决这个问题好几天都没有运气。所有的建议、建议和解决方法都被广泛接受。

    事先谢谢。

    3 回复  |  直到 14 年前
        1
  •  3
  •   Community Reversed Engineer    7 年前

    我真的不知道问题的原因是什么,因为有时铬 将焦点正确地放在元素上,尽管大多数时候它没有。你根本不需要请求焦点,因为当你按键时焦点不会丢失。如果你省略了 setEditFocus() 打电话给你,你应该注意到,除了Chrome,它在任何东西上都能正常工作,很明显,Chrome会因为你删除了身体中的所有内容而生气。

    当你设置 contenteditable ,每个浏览器设置 innerHTML iframe文档的 body 元素不同:

    Browser           | innerHTML
    -----------------------------
    Internet Explorer | ''
    Opera             | '<br>\n'
    Firefox           | '<br>'
    Chrome/Safari     | '\n'
    

    如果您不希望在以后解析内容时看到额外的内容,那么您可能希望在前面将其删除。 addFrame() .

    我可以通过执行以下操作来“修复”问题:

    首先,更新事件处理程序以便返回 false 并防止Opera在调用时生成HTML getSelection() 后来…

    function addFrame() {
        ...
        window.iframeloaded = function() {
           ...
           if (typeof iframeDoc.addEventListener != UNDEF) {
               iframeDoc.addEventListener('keypress', keyHandler, false);
           } else if (typeof iframeDoc.attachEvent != UNDEF) {
               iframeDoc.attachEvent('onkeypress', keyHandler);
           }
        }
    }
    

    编辑:删除了原来的功能,支持下面包含的新功能

    最后,返回 从按键处理程序修复上述Opera问题。

    function keyHandler (evt) {
        var myKey=(evt.which || evt.charCode || evt.keyCode)
    
        if (myKey==13) {
            ...
            return false;
        }
    }
    

    我最初做过什么 syockit 建议,但我发现它在Chrome中使用插入符号大小做了一些奇怪的事情,这种方法似乎可以避免(尽管火狐仍然有点过时…)。如果你不在乎,设置 内层HTML 非空白可能更容易解决。

    还要注意,您应该使用 className 而不是 class 在你传递给的对象中 new Element() 因为ie似乎认为它是一个保留字,并且说它是一个语法错误。

    编辑 :在使用它之后,以下功能在IE8/firefox/chrome/safari/opera中似乎可以可靠地工作,用于更高级的测试用例。不幸的是,为了解释Opera,我确实需要包含原型的浏览器检测,因为尽管就javascript而言,所有东西看起来都是一样的,但实际的行为需要不同的代码,这些代码与其他浏览器冲突,我无法找到更好的方法来区分它们。

    下面是新函数,它关注iframe的可编辑内容,并确保如果其中已有内容,插入符号将移动到该内容的末尾:

    function focusEditableFrame(frame) {
        if (!frame)
            return;
    
        if (frame.contentWindow)
            frame = frame.contentWindow;
    
        if (!Prototype.Browser.Opera) {
            frame.focus();
    
            if (frame.getSelection) {
                if (frame.document.body.innerHTML == '')
                    frame.getSelection().extend(frame.document.body, 0);
                else
                    frame.getSelection().collapseToEnd();
            } else if (frame.document.body.createTextRange) {
                var range = frame.document.body.createTextRange();
    
                range.moveEnd('character', frame.document.body.innerHTML.length);
                range.collapse(false);
                range.select();
            }
        } else {
            frame.document.body.blur();
            frame.document.body.focus();
        }
    }
    

    更新的 设置编辑焦点() (现在不需要,但既然你已经有了它):

    function setEditFocus()
    {
        focusEditableFrame($(editorFrame));
    }
    
        2
  •  1
  •   syockit    14 年前

    你知道我是怎么解决这个问题的吗?在 resetContent() 替换 '' 具有 ' ' :

    if (myIFrame) myIFrame.contentWindow.document.body.innerHTML=' ';
    

    如果有效,很好。不过,不要问为什么,这可能是Range对象的WebKit故障之一,如果愿意,请提交一个bug。

        3
  •  0
  •   Albert whatf    14 年前

    很快,你能试着在send()函数的行尾添加分号吗?看看是否有效。

    function send() {
      resetContent();
      setEditFocus();
    }