2017-03-16 46 views
1

考虑这个JS代码。它基本上初始化CKEditor的实例,等待1秒,然后运行codeToDebug在iframe中扩展DOM元素的原型

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方法延伸NodeNodeList原型与方法attr。如果attr出现在CKEditor的iframe中的.cke_editable textarea中,则它为log。令人惊讶的是,它记录undefined


我的问题:

  1. 为什么不是Node秒的iframe中的原型扩展,当我在主文档中扩展呢? (是不是所有元素共享一个共同的全球Node - 无论他们身在何处)
  2. 什么是延长所有 DOM元素的最佳方式 - 其存在于网页文件,在其内部框架,还有更多的嵌套iframe?

注:

  1. 我已经阅读Kangax的文章(和原型的错误)延伸DOM。但我的用例完全不同。我只能支持Chrome和Opera的最新版本 - 都是Webkit - 因此我不担心冲突。所以,请放心,我已考虑扩大原型的风险,但这个问题不是这个问题。

  2. 这里是HTML(出于某种原因JSBin或代码片段将不会显示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

+0

当您创建一个iFrame时,它与另一个窗口一样好,因此它将拥有自己的范围初始化。除此之外的任何范围内的任何重写都不会影响它。你也可以使用你自己的库来接受一个选择器并且可以迭代使用它。重写原型不是一个好习惯,因为有一个更改浏览器也会引发类似的行为,导致不一致。 – Rajesh

回答

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);    
     } 
    }); 
} 

请人发帖回答,如果他们认为他们已经更好,更容易的方法来实现这个任务。