2017-03-16 2 views
1

Betrachten Sie diesen JS-Code. Es initialisiert grundsätzlich eine CKEditors Beispiel wartet 1 Sekunde läuft dann codeToDebugErweiterter Prototyp von DOM-Elementen in iframes

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 Die Methode des Prototyps von NodeNodeList und mit einem Verfahren attr erstreckt. Es dann log s, wenn attr auf der .cke_editable Textarea in CKEditors iframe vorhanden ist. Überraschenderweise loggt es undefined.


Meine Fragen:

  1. Warum ist nicht der Prototyp Node s innerhalb eines Iframes erweitert, wenn ich es im Hauptdokument am erstreckt? (Ist nicht ein gemeinsames globales Node geteilt durch alle Elemente - unabhängig davon, wo sie sind)
  2. Was ist der beste Weg ist, DOM von alle Elementen zu erweitern - die auf der Webseite Dokument vorhanden sind, in seiner iframes und seine weiteren verschachtelten iframes?

Hinweise:

  1. ich schon Kangax des Artikels (und Prototype Bugs) mit der Erweiterung DOM lesen. Aber mein Anwendungsfall ist völlig anders. Ich soll nur die neuesten Versionen von Chrome und Opera unterstützen - sowohl Webkit als auch ich bin nicht besorgt über Konflikte. Also seien Sie versichert, dass ich die Risiken der Erweiterung des Prototyps in Betracht gezogen habe, aber diese Frage ist nicht so.

  2. Hier ist die HTML (aus irgendeinem Grunde JSBin oder Code-Schnipsel zeigt CKEditor nicht): <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> (I erstellt lokal ein index.html)

+0

Wenn Sie ein iFrame erstellen, ist es so gut wie ein anderes Fenster und daher wird es eine eigene Bereichsinitialisierung haben. Jegliche Überschreibung in einem anderen Bereich, als sie ist, hat keinen Einfluss darauf. Sie können auch eine eigene Bibliothek verwenden, die einen Selektor akzeptiert und mit ihr iterieren kann. Es ist keine gute Übung, den Prototyp zu überschreiben, da es einen Änderungsbrowser gibt, der ebenfalls ein ähnliches Verhalten auslöst, das Inkonsistenzen verursacht. – Rajesh

Antwort

0

Also, ich selbst eine Funktion geschrieben, dieses Problem zu lösen. Könnte für jeden nützlich sein, der nach einer ähnlichen Lösung sucht.

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

und dies ist das zweite Stück Code für die Suche nach 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);    
     } 
    }); 
} 

Bitte jemand eine Antwort hinterlassen, wenn sie denken, sie haben eine bessere und apt Methode, um diese Aufgabe zu erreichen.