javascript – How do I make a textarea an ACE editor?-ThrowExceptions

Exception or error:

I’d like to be able to convert specific textareas on a page to be ACE editors.

Does anyone have any pointers please?

EDIT:

I have the the editor.html file working with one textarea, but as soon as I add a second, the second isn’t converted to an editor.

EDIT 2:

I decided to scrap the idea of having several, and instead open one up in a new window. My new predicament is that when I hide() and show() the textarea, the display goes awry. Any ideas?

How to solve:

As far as I understood the idea of Ace, you shouldn’t make a textarea an Ace editor itself. You should create an additional div and update textarea using .getSession() function instead.

html

<textarea name="description"/>
<div id="description"/>

js

var editor = ace.edit("description");
var textarea = $('textarea[name="description"]').hide();
editor.getSession().setValue(textarea.val());
editor.getSession().on('change', function(){
  textarea.val(editor.getSession().getValue());
});

or just call

textarea.val(editor.getSession().getValue());

only when you submit the form with the given textarea. I’m not sure whether this is the right way to use Ace, but it’s the way it is used on GitHub.

###

Duncansmart has a pretty awesome solution on his github page, progressive-ace which demonstrates one simple way to hook up an ACE editor to your page.

Basically we get all <textarea> elements with the data-editor attribute and convert each to an ACE editor. The example also sets some properties which you should customize to your liking, and demonstrates how you can use data attributes to set properties per element like showing and hiding the gutter with data-gutter.

// Hook up ACE editor to all textareas with data-editor attribute
$(function() {
  $('textarea[data-editor]').each(function() {
    var textarea = $(this);
    var mode = textarea.data('editor');
    var editDiv = $('<div>', {
      position: 'absolute',
      width: textarea.width(),
      height: textarea.height(),
      'class': textarea.attr('class')
    }).insertBefore(textarea);
    textarea.css('display', 'none');
    var editor = ace.edit(editDiv[0]);
    editor.renderer.setShowGutter(textarea.data('gutter'));
    editor.getSession().setValue(textarea.val());
    editor.getSession().setMode("ace/mode/" + mode);
    editor.setTheme("ace/theme/idle_fingers");

    // copy back to textarea on form submit...
    textarea.closest('form').submit(function() {
      textarea.val(editor.getSession().getValue());
    })
  });
});
textarea {
  width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.9/ace.js"></script>
<textarea name="my-xml-editor" data-editor="xml" data-gutter="1" rows="15"></textarea>
<br>
<textarea name="my-markdown-editor" data-editor="markdown" data-gutter="0" rows="15"></textarea>

###

You can have multiple Ace Editors. Just give each textarea an ID and create an Ace Editor for both IDS like so:

<style>
#editor, #editor2 {
    position: absolute;
    width: 600px;
    height: 400px;
}
</style>
<div style="position:relative; height: 450px; " >
&nbsp;
<div id="editor">some text</div>
</div>
<div style="position:relative; height: 450px; " >
&nbsp;
<div id="editor2">some text</div>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-twilight.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-xml.js" type="text/javascript" charset="utf-8"></script>
<script>
window.onload = function() {
    var editor = ace.edit("editor");
    editor.setTheme("ace/theme/twilight");
    var XmlMode = require("ace/mode/xml").Mode;
    editor.getSession().setMode(new XmlMode());

    var editor2 = ace.edit("editor2");
    editor2.setTheme("ace/theme/twilight");
    editor2.getSession().setMode(new XmlMode());

};
</script>

###

To create an editor just do:

HTML:

<textarea id="code1"></textarea>
<textarea id="code2"></textarea>

JS:

var editor1 = ace.edit('code1');
var editor2 = ace.edit('code2');
editor1.getSession().setValue("this text will be in the first editor");
editor2.getSession().setValue("and this in the second");

CSS:

#code1, code2 { 
  position: absolute;
  width: 400px;
  height: 50px;
}

They must be explicitly positioned and sized. By show() and hide() I believe you are referring to the jQuery functions. I’m not sure exactly how they do it, but it cannot modify the space it takes up in the DOM. I hide and show using:

$('#code1').css('visibility', 'visible');
$('#code2').css('visibility', 'hidden');

If you use the css property ‘display’ it will not work.

Check out the wiki here for how to add themes, modes, etc… https://github.com/ajaxorg/ace/wiki/Embedding—API

Note: they do not have to be textareas, they can be whatever element you want.

###

For anyone like me that was routed to this page and just wants a minimal, copy-pasteable working example of using Ace using the library from CDN:

<!DOCTYPE html>
<html lang="en">
  <body>
    <div id="editor">function(){}</div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.01/ace.js" type="text/javascript" charset="utf-8"></script>
    <script>
      var editor = ace.edit("editor");
      editor.setTheme("ace/theme/monokai");
      editor.getSession().setMode("ace/mode/javascript");
      document.getElementById("editor").style.height = "300px";
    </script>
  </body>
</html>

Yields:
enter image description here

Leave a Reply

Your email address will not be published. Required fields are marked *