我有一个奇怪的问题仅在Chrome 中使用iframe
,但在所有其他常用浏览器中工作。
问题:如果我输入IFRAME然后按下按钮发送,它工作正常,焦点回到IFRAME和光标BLINK。
但是如果我输入然后按ENTER键调用事件处理函数,焦点会回来,但光标会消失。然后,如果你进入另一个窗口,然后返回光标出现。 仅在Chrome中发生。我做了示例页面以显示操作中的问题。点击下面的链接查看。
更新:我在下面添加了代码
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
我真的需要你的帮助,因为我试图解决这个问题很多天没有运气。并且所有建议,提示和解决方法都被广泛接受。
提前致谢。
答案 0 :(得分:3)
我不确定问题的原因是什么,因为Chrome 有时会正确地关注元素,尽管大部分时间它没有。您根本不需要请求焦点,因为按键时焦点不会丢失。如果您省略setEditFocus()
来电,您应该会注意到除了Chrome之外,它仍能正常运行,因为Chrome显然已经删除了您已删除正文中的所有内容。
当您设置contenteditable
时,每个浏览器都会将iframe文档的innerHTML
元素的body
设置为不同的内容:
Browser | innerHTML
-----------------------------
Internet Explorer | ''
Opera | '<br>\n'
Firefox | '<br>'
Chrome/Safari | '\n'
如果您以后在解析内容时不希望看到额外的内容,则可能需要在addFrame()
中预先删除它。
通过执行以下操作,我能够“解决”问题:
首先,更新事件处理程序,以便我们可以在其中返回false
并阻止Opera在我们稍后调用getSelection()
时生成HTML以获得乐趣...
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);
}
}
}
编辑:删除原始功能,转而使用下面的新功能
最后,从按键处理程序返回false
以修复上面提到的Opera问题。
function keyHandler (evt) {
var myKey=(evt.which || evt.charCode || evt.keyCode)
if (myKey==13) {
...
return false;
}
}
我最初做过syockit建议的内容,但我发现它在Chrome中使用插入符大小做了奇怪的事情,这种方法似乎避免了(尽管Firefox还有点偏离......)。如果您不关心这一点,将innerHTML
设置为非空白可能是一种更简单的解决方案。
另请注意,您应该在传递给className
的对象中使用class
而不是new Element()
,因为IE似乎认为它是一个保留字,并说它是语法错误
编辑:在使用它之后,以下功能似乎可以在IE8 / Firefox / Chrome / Safari / Opera中可靠地运行,以获得更高级的测试用例。不幸的是,我确实必须包含Prototype的浏览器检测以解释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();
}
}
更新setEditFocus()
(现在不是必需的,但因为你已经拥有它):
function setEditFocus()
{
focusEditableFrame($(editorFrame));
}
答案 1 :(得分:1)
你知道我是怎么解决这个的吗?在resetContent()
中,将''
替换为' '
:
if (myIFrame) myIFrame.contentWindow.document.body.innerHTML=' ';
如果有效,那就好。不要问为什么,它可能是带有Range对象的Webkit故障之一,如果你愿意,可以提交一个bug。
答案 2 :(得分:0)
很快,您可以尝试在send()函数内的行末尾添加分号吗?看看是否有效。
function send() {
resetContent();
setEditFocus();
}