ExtJs4 + IE9 = 对象不支持属性或方法'createContextualFragment'

11
我正在IE9上使用ExtJs,几乎总是会遇到以下错误:
Microsoft JScript运行时错误: 对象不支持“createContextualFragment”属性或方法
这是什么意思?需要“createContextualFragment”做什么?怎样才能修复这个问题呢?
6个回答

25

createContextualFragment()Range对象的一个方法,它可以从HTML字符串创建一个文档片段。它在Firefox、WebKit和Opera中都存在,但目前不属于标准(它不在DOM Level 2 Range spec中,但在正在进行中的DOM Parsing and Serialization spec中),而IE 9没有实现它,这与微软实现标准功能在IE 9中之前缺失的一般方法是一致的。虽然非标准,但ExtJs必须使用此方法,尽管这是相当愚蠢的,因为可以在任何地方使用支持的innerHTML轻松实现相同的结果。

更新

您可以将以下内容打补丁到IE 9中,因为它允许扩展主机对象原型,而以前的版本则不允许。以下是从我的Rangy library改编的createContextualFragment()的一个天真实现,但适用于大多数用途。有关详细信息和更全面的实现,请参见this Rangy issue

请注意,这在IE < 9中不起作用,因为这些浏览器没有DOM Range实现。

if (typeof Range.prototype.createContextualFragment == "undefined") {
    Range.prototype.createContextualFragment = function(html) {
        var startNode = this.startContainer;
        var doc = startNode.nodeType == 9 ? startNode : startNode.ownerDocument;
        var container = doc.createElement("div");
        container.innerHTML = html;
        var frag = doc.createDocumentFragment(), n;
        while ( (n = container.firstChild) ) {
            frag.appendChild(n);
        }
        return frag;
    };
}

@tim-down Downvoter是http://stackoverflow.com/users/135952/nissan-fan..他对我有些“怨恨”,并且给我的一些问题/答案点了踩..很抱歉牵扯你进来了.. - obenjiro
@Ai_boy:没问题。我只是觉得自己没有说错什么甚至有挑衅性的话(有时候我会这样),所以有点惊讶 :) - Tim Down
2
对我来说,这个补丁在IE8中引起了问题,显然它完全缺少Range对象。因此,我将条件更改为 如果(typeof Range!=“undefined”&& typeof Range.prototype.createContextualFragment ==“undefined”) - Jim Davis
@Jim:是的,这个答案没有尝试处理IE 9之前的版本。如果你需要在IE < 9中支持范围,请使用Rangy(http://code.google.com/p/rangy/)。 - Tim Down
这对我解决了问题 - 奇怪的是,这个问题只在我安装新版IE9时出现 - 从IE10降级到IE9以尝试重现此问题,仍然像在IE10中一样工作 - 然而,新安装确实出现了相同的问题。 - Danlance
显示剩余9条评论

3
更快、更紧凑、无需循环,在IE9+以及所有好用的浏览器中均可使用:
var createContextualFragment = (function(){
  var doc = document.implementation.createHTMLDocument(''),
      range = doc.createRange(),
      body = doc.body;
  return function(html){
    body.innerHTML = html;
    range.selectNodeContents(body);
    return range.extractContents();
  }
})();

@TimDown 看看这个新的热门东西:它比其他答案更小、更简单,性能也更好。 - csuwldcat
在IE 10中工作,只需进行一个更改:将空字符串传递到createHTMLDocument()。我手头没有IE 9。 - Tim Down

2

好的,通过一些小修改,Tim Down发布的代码对我有用:

if (typeof Range.prototype.createContextualFragment == "undefined") {
    Range.prototype.createContextualFragment = function (html) {
        var doc = window.document;
        var container = doc.createElement("div");
        container.innerHTML = html;
        var frag = doc.createDocumentFragment(), n;
        while ((n = container.firstChild)) {
            frag.appendChild(n);
        }
        return frag;
    };
}

啊,我明白你做了什么修改以及我代码中的错误(我需要的是“this”,而不是“range”)。我已经修复了我的示例,它比你的示例优点在于它可以与来自当前文档以外的其他文档的范围一起使用(例如在处理iframes时非常有用)。 - Tim Down

2

ExtJS 3.4.0修复了这个问题。无需更改代码库。虽然库做得很好。


1

据我所知,这个问题在 Ext JS 3.3 中已经得到解决,我想在 4.0 正式发布之前它也会被修复(截至目前,它甚至还没有进入测试版)。


1

我刚刚将Tim Down的修复应用到我们的ext 3.3.1安装中,因为如果没有它,IE9仍然无法正确显示我们的页面。换句话说,我认为这个修复程序没有被包含在EXTJS 3.3中,至少不是公共版本。


5
只需将此代码放置在HTML头部区域:<meta http-equiv="X-UA-Compatible" content="IE=8" />,这样就没有IE9的问题了 :) 实际上,只需要一行 'html' 代码,您的应用程序就可以完美地在IE9中运行。 - obenjiro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接