How I made a live code editor with Vanilla Javascript?
Tags: javascript, codepen, webdev, programming
Published: 2021-12-19 15:17:04

I'm a huge fan of Codepen and Codesandbox websites. I tried to make a website like them some times. Ofcourse they're huge. I wasn't gonna be able to make a websites like them, but i wanted to see through how the things works. This is just a beginning. I'm going to make a website to render React JS and JSX codes live next.


![CodeXC Editor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/14eorath1jzr7go8r5my.png)

**Libraries that I used**
- [Codemirror Editor](https://codemirror.net/)

Codemirror already has CDNs to import but i wanted to import it locally. If you just want to try it out, you can use CDNs.

```html
<!-- Codemirror Library -->
<script src="./Codemirror/lib/codemirror.js"></script>
<link rel="stylesheet" href="./Codemirror/lib/codemirror.css">
<link rel="stylesheet" href="./Codemirror/theme/ayu-mirage.css">
<!-- MODES TO HIGHLIGHT CODES -->
<script src="./Codemirror/mode/javascript/javascript.js"></script>
<script src="./Codemirror/mode/css/css.js"></script>
<script src="./Codemirror/mode/xml/xml.js"></script>
<!-- ADDONS -->
<script src="./Codemirror/addon/selection/active-line.js"></script>
<!-- Style -->
<link rel="stylesheet" href="style.css">
```
Codemirror has so many addons like folding code blocks, autocomplete, custom searching input, auto closing brackets, auto closing tags etc.

**And here is how my html look like:**

```html
<div class="container">
        <div class="pane code-pane">
            <div class="html-box code-box" id="html-box">
                <div class="title">
                    <span class="title-text">
                        HTML
                    </span>
                </div>
            </div>
            <div class="css-box code-box" id="css-box">
                <div class="title">
                    <span class="title-text">
                        CSS
                    </span>
                </div>
            </div>
            <div class="js-box code-box" id="js-box">
                <div class="title">
                    <span class="title-text">
                        JS
                    </span>
                </div>
            </div>
        </div>
        <div class="pane output">
            <iframe id="preview" frameborder="0"></iframe>
        </div>
    </div>
    <script src="app.js"></script>
```

There's two section. Bottom and top. They has pane class for the common purposes and unique classes for the differences. 

Top pane has html, css and js sections init and everyone has their own titles. That's it.

**And here is my CSS codes look like:**

```css
body{box-sizing: border-box;margin: 0; padding: 0; font-family: monospace;}
.container{
    width: 100vw; height: 100vh; overflow: hidden; background-color: #ddd;
    display: flex; flex-direction: column; }
.pane{ width: 100%; height: 50%; }
.code-pane{ background-color: aqua; display: flex; }
.output{ background-color: aquamarine; }
.code-box{ width: 34%; height: 100%; display: flex;  flex-direction: column;
    box-sizing: border-box; border-right: 1px solid white; font-size: 1.3rem; }
.html-box{ background-color: azure; resize: horizontal; overflow: auto; }
.css-box{ background-color: bisque; resize: horizontal; overflow: auto; }
.js-box{ background-color: blanchedalmond; resize: horizontal; overflow: auto;}
.title{ width: 100%; height: 40px; background-color: cadetblue; }
.title-text{ color: white; font-size: 2rem; margin-left: 20px;
     padding: 0 10px 0 10px; background-color: #3d3d3d; }
.CodeMirror{ height: 100%;}
#preview { width: 100%; height: 100%; background-color: cadetblue; }
```
HTML, CSS and JS boxes have resize functionalities horizontally. But i didn't use any other library to make it better. I only used CSS "resize: horizontal;" to make the divs resizable. But i'm sure it wouldn't be that much hard to make it. You can just use vanilla javascript and some math to do it.

**And here is my javascript file:**

```js
//Code Mirror Initialization

var htmlCodeInstance = CodeMirror(document.getElementById("html-box"), {
    lineNumbers: true,
    tabSize: 4,
    mode: "xml",
    theme: "ayu-mirage",
    styleActiveLine: true,
});
var cssCodeInstance = CodeMirror(document.getElementById("css-box"), {
    lineNumbers: true,
    tabSize: 4,
    mode: "css",
    theme: "ayu-mirage",
    styleActiveLine: true,
});
var jsCodeInstance = CodeMirror(document.getElementById("js-box"), {
    lineNumbers: true,
    tabSize: 4,
    mode: "javascript",
    theme: "ayu-mirage",
    styleActiveLine: true,
});

// Run update() function, when the instances have change
htmlCodeInstance.on("change", function(){
    console.log(htmlCodeInstance.getValue())
    update();
});
cssCodeInstance.on("change", function(){
    console.log(cssCodeInstance.getValue())
    update();
});
jsCodeInstance.on("change", function(){
    console.log(jsCodeInstance.getValue())
    update();
});

//Change iFrame when you receive changes
function update() {
    let preview = document.getElementById("preview").contentWindow.document;
    codeTemplate = `
    <!DOCTYPE html>
    <html>
    <head>
    <style>`
     + cssCodeInstance.getValue() + 
    `</style>
    <body>` + 
    htmlCodeInstance.getValue() +
    `<script>` + jsCodeInstance.getValue() + `</script>` +
    `</body>
    </html>`
    console.log("CODE TEMPLATE: " + codeTemplate)
    preview.open();
    preview.write(codeTemplate);
    preview.close();
}
```

In the first part. I initialized my divs to the Codemirror and give some properties. I know there's a better way to do it. Please check this out before you use this method.

{% post https://dev.to/kudadam/using-multiples-instance-of-codemirror-in-a-file-5hcl %}

In the second part, I gave it "onchange" method all of the editors that I have in the page. If one of them has changed update() function will be called.

".on()" method is built-in in Codemirror. So, I didn't use "addEventListener" or "onChange" property in HTML document. This is a better way I think.

and finally, in the last part, I take the iframe in the html document. This function only be called when the user type something in one of the editors. 

I made a Code Template. So, when the user change something in one of the editors, they'll change the template and i'll write it to the iframe. 

That's it. Hope you like it. See you soon.

[SEE GITHUB REPOSITORY](https://github.com/mfatihgul/CodeXC---Live-Code-Editor)