H.HISTORY
H.HISTORY

Reputation: 518

CodeMirror with 2 text editors and live preview?

I'm trying to create a live editor like jsfiddle where users can put html in html box (textarea) and css in css box(textarea) and preview the changes live in an iframe.

I am using codemirror as the editor.

So far I can only get the preview of one of the textareas in my iframe and I cannot figure out how to get the values of both textareas (css/html) and display them in my iframe exactly like jsfiddle.

This is what I have so far:

http://jsfiddle.net/vwqgtznv/

and this is my javascript code:

   <script>
      var delay;
      // Initialize CodeMirror editor with a nice html5 canvas demo.
      var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
    lineNumbers: true,
    styleActiveLine: true,
    matchBrackets: true,
        mode: 'text/html'
      });
      editor.on("change", function() {
        clearTimeout(delay);
        //alert("hellooooo");



        delay = setTimeout(updatePreview, 300);
      });

      function updatePreview() {
        var previewFrame = document.getElementById('preview');
        var preview =  previewFrame.contentDocument ||  previewFrame.contentWindow.document;
        preview.open();
        preview.write(editor.getValue());
        preview.close();
      }
      setTimeout(updatePreview, 300);
    </script>

        <script>
      var delay2;
      // Initialize CodeMirror editor with a nice html5 canvas demo.
      var editor2 = CodeMirror.fromTextArea(document.getElementById('codert'), {
    lineNumbers: true,
    styleActiveLine: true,
    matchBrackets: true,
        mode: 'text/html'
      });
      editor2.on("change", function() {
        clearTimeout(delay2);
        //alert("hellooooo");



        delay2 = setTimeout(updatePreview2, 300);
      });

      function updatePreview2() {
        var previewFrame2 = document.getElementById('preview');
        var preview2 =  previewFrame2.contentDocument ||  previewFrame2.contentWindow.document;
        preview2.open();
        preview2.write(editor2.getValue());
        preview2.close();
      }
      setTimeout(updatePreview2, 300);
    </script>

could someone please help me out and advise on this issue?

Thanks in advance.

Upvotes: 3

Views: 3557

Answers (2)

Hugolpz
Hugolpz

Reputation: 18258

Building upon @North's answer and guidance, I propose this answer. If you +1 this answer, please give +1 to North's answer as well. This is an optimization and expansion up North's anwser, building up a jsfiddle-clone. It therefor demo an answer to the question of this current page.

  • Jsfiddle -- richer code to go further
  • Blogpost -- Medium post with some other helpers.

In .html :

 <!-- load the relevant dependencies via script and style/link tags. -->
 <textarea class="code" id="editor-html">
 <textarea class="code" id="editor-css">
 <textarea class="code" id="editor-js">

In .js file :

var editorsSettings = {
  lineWrapping: true,
  lint: true,
  lineNumbers: true,
  foldGutter: true,
  gutters: ["CodeMirror-lint-markers","CodeMirror-linenumbers", "CodeMirror-foldgutter"],
  tabSize: 2,
  indentUnit: 2,
  matchBrackets: true
}

// Editors HTML, CSS, JS : init, bind, define settings.
let editorHTML = CodeMirror.fromTextArea(document.querySelector('#editor-html'), {
  mode : "htmlmixed", // require modes for xml, css, js.
  htmlMode: true,
  ...editorsSettings
});
let editorCSS = CodeMirror.fromTextArea(document.querySelector('#editor-css'), {
  mode: 'text/css',
  ...editorsSettings
});
let editorJS = CodeMirror.fromTextArea(document.querySelector('#editor-js'), {
  mode: 'text/javascript',
  ...editorsSettings
});

// Fetch and organize into results
let updatePreview = function() {
  let preview = document.querySelector('#preview');
  let previewDocument = preview.contentDocument || preview.contentWindow.document;
  previewDocument.open();
  previewDocument.write(editorHTML.getValue());
  previewDocument.write("<script>"+editorJS.getValue()+"<"+"/script>");
  previewDocument.close();
  previewDocument.querySelector('head').innerHTML = '<style>' + editorCSS.getValue() + '</style>';
}

Upvotes: 0

North
North

Reputation: 1434

Your problem is append CSS to iframe head. Use the code below to update your iframe head for CSS.

function loadCSS() {
    var $head = $("#preview").contents().find("head");                
    $head.html("<style>" + editor.getValue() + "</style>");
}; 

HTML textarea should be updated with CSS. Add loadCSS() to your updatePreview2()(html textarea update function).

function updatePreview2() {
    var previewFrame2 = document.getElementById('preview');
    var preview2 =  previewFrame2.contentDocument ||  previewFrame2.contentWindow.document;
    preview2.open();
    preview2.write(editor2.getValue());
    preview2.close();

    // added this line
    loadCSS(); 
}

And when your CSS textarea changes, the preview content will be updated by updatePreview()(CSS textarea update function) with CSS content. It should update head only.

function updatePreview() {
    loadCSS();
}

Here is the Jsfiddle, please take a demo here.

By the way, try to name your variable and function precisely will make more people help you.

Update

A clean JsFiddle version.

Upvotes: 4

Related Questions