在iframe中扩展DOM元素的原型

时间:2017-03-16 05:31:21

标签: javascript html iframe prototype

考虑这个JS代码。它基本上初始化一个CKEditor实例,等待1秒,然后运行codeToDebug

function codeToDebug(){
    setNodeListProp("attr", function customAttr(name, val){
        if(typeof val != "undefined"){
            this.setAttribute(name, val);
            return this;
        }
        else return this.getAttribute(name);
    });

    // secondary check: all elements on the current document HAVE `attr` method
    var all = document.querySelectorAll("*");
    for(var i = 0, len = all.length;i < len; i++) 
        if(!all[i].attr) // always false
            console.dir(all[i]); // never executes

    // logs undefined
    console.log(
            document.querySelector(".cke_wysiwyg_frame")
                .contentDocument
                .querySelector(".cke_editable").attr);
}

window.onload = function(){
    // Replace the <textarea id="editor1"> with a CKEditor
    // instance, using default configuration.
    CKEDITOR.editorConfig = function (config) {
        config.language = 'es';
        config.uiColor = '#F7B42C';
        config.height = 300;
        config.toolbarCanCollapse = true;

    };
    CKEDITOR.replace('editor1');
    // wait for async editor to load
    setTimeout(codeToDebug, 1000);
};

function setNodeListProp(prop, func){
    // in case of custom created array of Nodes, Array.prototype is necessary
    Array.prototype[prop] = NodeList.prototype[prop] = function() {
        var args = [].slice.call(arguments, 0);
        this.forEach(function(node) {
            func.apply(node, args);
        });
        return this;
    };

    Node.prototype[prop] = func;
}

codeToDebug方法使用方法Node扩展了NodeListattr的原型。如果log存在于CKEditor的iframe内的attr textarea上,那么.cke_editable。令人惊讶的是,它记录了undefined

  

我的问题:

     
      
  1. 为什么我在iframe扩展中的Node s的原型是什么?当我在主文档中扩展它时? (不是所有元素共享的共同全局Node - 无论它们在哪里?)
  2.   
  3. 扩展所有元素的DOM的最佳方法是什么 - 这些元素存在于网页文档,iframe及其进一步嵌套的iframe中?
  4.   

备注:

  1. 我已经阅读了扩展DOM的Kangax的文章(以及Prototype&#39;错误)。但我的用例完全不同。我只应支持最新版本的Chrome和Opera - 两者都是Webkit - 因此我并不担心冲突。所以,请放心,我已经考虑了扩展原型的风险,但这个问题与此无关。

  2. 这里是HTML(出于某种原因,JSBin或Code Snippets不会显示CKEditor):<script src="https://cdn.ckeditor.com/4.5.1/standard/ckeditor.js"></script><script>..ABOVE_JS_CODE..</script><textarea name="editor1" id="editor1" rows="10" cols="80"></textarea>(我在本地创建了index.html

1 个答案:

答案 0 :(得分:0)

所以,我自己写了一个函数来解决这个问题。可能对寻求类似解决方案的任何人都有好处。

(function protoExtensionWork(){
    window.updateAllValuesPerWin = function(win){       
        for(var i = 0, count = protoExtensionNames.length; i < count; i++)
            setNodeListPropPerWindow(protoExtensionNames[i], protoExtensionFunctions[i], win);
    };

    // fill this up as per your requirement
    var protoExtensionNames = [], protoExtensionFunctions = [];

    function setNodeListPropPerWindow(prop, func, win){
        // in case of custom created array of Nodes, Array.prototype is necessary
        win.Array.prototype[prop] = win.NodeList.prototype[prop] = function() {
            var args = [].slice.call(arguments, 0);
            this.forEach(function(node) {
                func.apply(node, args);
            });
            return this;
        };

        win.Node.prototype[prop] = func;    
    }
})();

这是寻找iframe s的第二段代码:

function initiateIframeCheck(parentDoc){
    var iframes = parentDoc.querySelectorAll("iframe"),
        win, doc;

    iframes.forEach(function(iframe){       
        try{                
            doc = iframe.contentDocument;
            win = iframe.contentWindow;

            // make sure handler's not already attached
            if(!doc[UNIQ_KEY]){
                doc[UNIQ_KEY] = true;
                updateAllValuesPerWin(win);     
                setInterval(initiateIframeCheck, IFRAME_CHECK_TIMER, doc);
            }
        }catch(e){ // CORS
            //console.dir(e);               
        }
    });
}

如果有人认为他们有更好,更合适的方法来完成这项任务,请任何人发表答案。