How I Created My Own Codepen (Online Text Editor)
Tags: html, javascript
Published: 2019-09-29 17:04:35

{% codepen https://codepen.io/Dillion/pen/GRKLJBP default-tab=result %}

So, I created my own Online Text Editor as seen above and it was honestly fascinating even to myself.

Kindly play around with it a little before proceeding.

In this article, I would be discussing how I created it.
You could use the technique I'd be mentioning to create more fascinating online editors.
And I also want to believe that Text editors like Codepen and Glitch use this same technique combined with other techniques.

### The Inspiration
Last two weeks, I went through Brian Holt's article on Frontend Masters (Introduction to Web Development) and I noticed how he used inline text editors to enable users practice.
I was a little bit curious but the curiousity didn't go far.

Recently, I came accross a where someone shared a link to a website - [shtml.com](shtml.com).

It's a recorded video of someone using an online text editor. This brought the curiosity back. But, the curiosity wasn't too strong.
Just four days ago, I saw this article on amaizing things HTML can do. A link was presented to learn more. The link showed how to make editable contents as well as style pages in real-time. So, I kicked off.

### The How
Basically, browsers render codes resulting in web pages.
Requirements
- A section to type raw codes
- A section to render the codes
- Localstorage (optional) - so you don't have to start all over again when refreshed.

* `contenteditable`
This attribute when specified allows a child of an element to be editable when rendered already.

The first div is editable while the other isn't.
I used javascript to handle Localstorage and to also render the raw code on the second div.

```html
<!-- The HTML file -->
<div class='container'>
  <h1 class='header'>Online Text Editor</h1>
  <div class='edit-container'>
    <p class='hint' contenteditable>This div has a class of "edit-container" of which you can style. Same thing with the next div with class of "display-container"...Write your codes  and it will display in the next div</p>
    <div id='edit' contenteditable>

    </div>
  </div>
  <div id='display' class='display-container'>
  </div>
  <footer>
    <p align='center'>Created with <span class='hearts'>&hearts;</span> by <a href='https://twitter.com/iamdillion'>Dillion Megida</a></p>
  </footer>
</div>
```
In the HTML file above, I have a general `.container` div. I also have a `.header` element.
Next, I have the `edit-container`, with a `.hint` paragraph which is editable and the container for raw codes, `#div`.
Adjacent to the display container is the `.display-container` div with an id of 'display' where the raw codes will be rendered.

```css
/* The CSS file */
::-webkit-scrollbar {
  width: 5px;
}
::-webkit-scrollbar-thumb {
  background-color: yellow;
}
::-webkit-scrollbar-track {
  background-color: lightblue;
}
* {
  box-sizing: border-box;
  outline: 0;
}
body {
  margin: 0;
  font-family: helvetica;
}
.header {
  width: 100%;
  text-align: center;
  margin: 20px 0 0;
  color: teal;
}
.hint {
  color: pink;
  padding: 0 10px;
  font-size: 15px;
}
.container {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
.container div:not(#edit) {
  background-color: teal;
  margin: 5px 10px;
  width: 45%;
  height: 70%;
  overflow-y: auto;
  padding-bottom: 30px;
}
#edit {
  color: white;
  font-family: monospace;
  font-size: 16px;
  width: 100%;
  display: inline-block;
  padding: 10px;
}
.hearts {
  color: red;
  font-size: 25px;
}
footer {
  width: 100%;
}

@media only screen and (max-width: 550px) {
  .container div:not(#edit) {
    width: 90%;
  }
}
```
This is basic CSS codes with media rules too.

```javascript
// The javascript file
let display;
let edit;

// Check storage to get saved item else ''
let editContainer = localStorage.getItem('edit-container');
if(editContainer && editContainer.length > 0) {
  // Capture the target elements
  display = document.getElementById('display');
  edit = document.getElementById('edit');
  // Initialize elements with their children
display.innerHTML = editContainer;
edit.innerText = editContainer;
} else {
  let initialContents = "<style> \n.intro { \ncolor: yellow; \ntext-decoration: underline; \ntext-align: center;\n} \n</style>\n\n<h3 class='intro'>Designed by Dillion Megida</h3>";
  
  localStorage.setItem('edit-container', initialContents);
  
  display = document.getElementById('display');
  edit = document.getElementById('edit');
  edit.innerText = initialContents;
  display.innerHTML = initialContents;
}

// When a new data is typed in the edit field, add to storage and update the display panel    
window.addEventListener('keyup', () => {
  // Get the current text in edit container and display
  edit = document.getElementById('edit');
  editContainer = edit.innerText;
  display = document.getElementById('display');
  display.innerHTML = editContainer;
  
  // Update storage
  localStorage.setItem('edit-container', editContainer);
});
```
Firstly, i defined `display` and `edit` variable.
Next, I try to check if there is a saved copy of propbably a previous code.
If there is and the length is greater than 0, the display and edit variable will target the respective ids.
The display renders the code as `innerHTML` while the edit renders the code as `innerText`.

If there is no saved copy, some initial codes are displayed and also added to storage.

`window.addEventListener('keyup')...` listens for every keyup events and executes a call back function.
The function simply targets the ids, takes the `innerText` from `edit-container`, renders the text as `innerHTML` for the display-container and also stores it in local storage.

**Note:** There are many ways to achieve this. Just have fun!

I would still be trying more things on the pen.

I do hope you learned a lot from this and you already feel inspired to create your own editor.

When you do create one, kindly share the pen or the link in the comment section or reach out to me on twitter ([@iamdillion](https://twitter.com/iamdillion)) so that I could also check out your beautiful work.

Thanks for reading : )