2017-03-16 61 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);    
     } 
    }); 
} 

請人發帖回答,如果他們認爲他們已經更好,更容易的方法來實現這個任務。