Posted on

A WYSIWYG html editor

Background

We often prefer to edit our HTML pages and templates using text editors, such as gedit, Vim, or Bluefish.

However when it comes to creating more complex HTML tables, handcrafting becomes rather error-prone and it is preferable to be able to design/modify tables in final form (like a WYSIWYG word-processor does).

A decent current choice for a WYSIWYG HTML editor is BlueGriffon, but unfortunately its ability to edit tables is rather buggy. 

So we looked around for something that would do better.

What we came up with

There are a few browser based editors, such as TinyMCE and CKEditor, often used as editor widgets within larger applications (such as WordPress).

But we want to be able to easily edit a local file from a browser, without having to upload it to a webserver.

Also the editor should not “mess-up” the HTML, such as by inserting &nbsp;s into empty cells or too radically changing the indenting and layout with excessive <br>s.

So with ideas and code snippets gleaned from:

we cobbled together ckeditor.html:

<!DOCTYPE html>
<!-- ckeditor.html -->
<!-- Wrapper to invoke ckeditor against local file -->
<html>
<head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        <title>ckeditor</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
        <script src="https://cdn.ckeditor.com/4.8.0/full/ckeditor.js"></script>
</head>

<body>
<form>
<input name="file" type="file" id="files" class="form-control" value="">
</form>

<br /><br />
<textarea name="editarea" id="editarea" rows="10" cols="80">
CKEditor area
</textarea>

<script>
        CKEDITOR.replace( 'editarea' );
        CKEDITOR.config.enterMode = CKEDITOR.ENTER_BR;
        CKEDITOR.config.autoParagraph = false;
        CKEDITOR.config.fillEmptyBlocks = false;   // Don't fill empty table cells with nbsp's 
        CKEDITOR.config.allowedContent = true;
        CKEDITOR.config.forcePasteAsPlainText = true;
</script>

<br /><br />
<form>
Save as: <input id="inputFileNameToSaveAs" value="filename">
<button onclick="saveTextAsFile()">Save Text to File</button>
</form>

<script type="text/javascript">
function readTextFile(file, callback, encoding) {
        var reader = new FileReader();
        reader.addEventListener('load', function (e) {
                callback(this.result);
        });
        if (encoding) reader.readAsText(file, encoding);
        else reader.readAsText(file);
}

function fileChosen(input, output) {
        if (input.files && input.files[0]) {
                readTextFile(
                        input.files[0],
                        function (str) {
                                output.setData(str); // Use the setData() method
                                output.updateElement(); // Tell the CKEditor instance to update itself
                });
                $("#inputFileNameToSaveAs").val(input.files[0].name);   // Set SaveAs filename to be the same as loaded filename
        }
}

$('#files').on('change', function () {
        var result = $("#files").text();
        fileChosen(this, CKEDITOR.instances.editarea);
});

function saveTextAsFile() {
        var textToSave = CKEDITOR.instances['editarea'].getData();
        var textToSaveAsBlob = new Blob([textToSave], {type:"text/plain"});
        var textToSaveAsURL = window.URL.createObjectURL(textToSaveAsBlob);
        var fileNameToSaveAs = document.getElementById("inputFileNameToSaveAs").value;
        var downloadLink = document.createElement("a");
        downloadLink.download = fileNameToSaveAs;
        downloadLink.innerHTML = "Download File";
        downloadLink.href = textToSaveAsURL;
        downloadLink.onclick = destroyClickedElement;
        downloadLink.style.display = "none";
        document.body.appendChild(downloadLink);
        downloadLink.click();
}

function destroyClickedElement(event) {
        document.body.removeChild(event.target);
}
</script>
</body>
</html>

 

When you load ckeditor.html into your browser, you should see:

ckedit session

 

Then simply choose a file, edit it and save the result.

 

Supplemental

The above example loads the CKEditor v4.8 Javascript library from a CDN (Content Delivery Network), but it can also be downloaded locally, and indeed the CKEditor website allows you to create a custom version which just includes the editing features you want (such as a shorter toolbar with fewer icons). 

You will find details of CKEditor’s Open Source Licensing at https://ckeditor.com/ckeditor-4/pricing/,  https://ckeditor.com/legal/ckeditor-oss-license/ and https://c.cksource.com/c/4/docs/ckeditor-licencing-infographic.pdf.