69

I'm trying to add the Ace editor to a page, but I don't know how to get the height to be set automatically based on the length of its contents.

Ideally it would work so when the content changes the height is recalculated, but I would be happy with the height just being set on page load.

For a JavaScript novice can someone help me figure out how I work out the length of the code, how many lines it spans, what the new height is and how I update the DOM to reflect this?

I found this suggestion in a Google group, but I don't really understand what it's doing and how I get it to adjust the height.

editor.getSession().getDocument().getLength() *
editor.renderer.lineHeight + editor.renderer.scrollBar.getWidth()
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
limitlessloop
  • 1,454
  • 3
  • 14
  • 21

9 Answers9

104

(UPDATE: I'm not working with this at the moment, but my answer may be out of date. To try and incorporate what others have provided, I'll echo their mention of the minLines and maxLines properties, e.g.

editor.setOptions({
    maxLines: Infinity
});

Apparently infinity is "not a very good idea, since it will disable virtual viewport even for very large documents." So picking a limit may be better.

For history's sake, the old answer was:


The post you cite is just operating on the assumption that it's a fixed width font whose character height you know, and that you know the number of lines in the document. Multiply that together you get a pixel count for how tall the content is. The suggestion is that every time a character is pressed or a cut/paste happens (which may add or remove lines), you use JavaScript to apply this concrete new size to the items in your DOM with CSS styles.

(They throw in the "width" of a scrollbar into a height calculation, and I honestly can't tell you if there's a rationale behind that or not. I'll let someone else figure that part out.)

Anyway...if you have soft wrap on, the number of rendered screen lines spanned may be more than the number of "actual" lines in the document. So it is better to use editor.getSession().getScreenLength() than editor.getSession().getDocument().getLength().

I put the editor (position: absolute) inside of a section (position: relative), and it's the only item living in that section. This code is seemingly working for me for now, I'll update it if I learn more...!

$(document).ready(function(){

    var heightUpdateFunction = function() {

        // http://stackoverflow.com/questions/11584061/
        var newHeight =
                  editor.getSession().getScreenLength()
                  * editor.renderer.lineHeight
                  + editor.renderer.scrollBar.getWidth();

        $('#editor').height(newHeight.toString() + "px");
        $('#editor-section').height(newHeight.toString() + "px");

        // This call is required for the editor to fix all of
        // its inner structure for adapting to a change in size
        editor.resize();
    };

    // Set initial size to match initial content
    heightUpdateFunction();

    // Whenever a change happens inside the ACE editor, update
    // the size again
    editor.getSession().on('change', heightUpdateFunction);
}
  • 1
    Added a test for the presence of the horizontal scroller: `var newHeight = editor.getSession().getScreenLength() * editor.renderer.lineHeight + (editor.renderer.$horizScroll ? editor.renderer.scrollBar.getWidth() : 0);` – Amit Portnoy Jul 11 '13 at 15:09
  • Ace now provides maxLines option, as described in another answer here, which works much better. Also modifying dom from change listener is a bad idea, it will slow down editor a lot. – a user Oct 31 '13 at 21:42
  • 1
    @auser Thanks for the feedback, I'm not working with Ace right now but if these options work then I'll take your word for it... until someone says they don't work. :-) – HostileFork says dont trust SE Nov 01 '13 at 15:04
  • After I set this option, the initial height will not be the value in CSS, instead, it's adapted to the height of the content. But I still want to set a fixed initial height, how can I do that? – soulmachine Dec 04 '15 at 02:53
  • 1
    I figured it out, just use `editor.setOptions({minLines: 25});` to set a minimum lines of 25 – soulmachine Dec 04 '15 at 03:04
35

Ace provides an option: maxLines so that you can simply try:

editor.setOptions({
    maxLines: 15
});

http://jsfiddle.net/cirosantilli/9xdkszbz/

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Dickeylth
  • 828
  • 9
  • 15
  • This does not answer the question. The question asks how to set the height based on how many lines are displayed. You're suggesting a hard-coded value. – Chris Peters Oct 22 '13 at 11:38
  • 9
    The answer is right and your comment is wrong. Ace provides options for `maxLines` and `minLines` and will automatically set height between these values, based on how many lines there are in the editor. You can also set `maxLines: Infinity`, but that's not a very good idea, since it will disable virtual viewport even for very large documents. – a user Oct 31 '13 at 21:41
  • You were the first to mention `maxLines` so you get my upvote. – Ciro Santilli OurBigBook.com Aug 29 '14 at 10:21
  • 1
    Is there a way to make that height include the horizontal scrollbar if it is present? In your js fiddle, change line 12 to: "d djlkf kdfjlsk fdjkl dfjkls fkdjlksdf jkdf" and both the horizontal and vertical scrollbars appear. It would be nice if height adjusted so the vertical scroll was not needed. – Jereme Dec 07 '14 at 15:26
  • In fact, you can call `var lines = editor.getSession().getDocument().getLength()` and then set the `maxLines` to that value. – cayhorstmann Feb 10 '18 at 16:41
13

Update: See Dickeylth's answer. This all still works (and people still seem to find it useful), but the basic functionality is built into ACE now.


To "automatically adjust height to contents in Ace Cloud9 editor", you just need to resize the editor to fit the div that contains it, whenever the content is edited. Assuming you started with <div id=editor>...

var editor = ace.edit("editor");                   // the editor object
var editorDiv = document.getElementById("editor");     // its container
var doc = editor.getSession().getDocument();  // a reference to the doc

editor.on("change", function() {
    var lineHeight = editor.renderer.lineHeight;
    editorDiv.style.height = lineHeight * doc.getLength() + "px";
    editor.resize();
});

You resize the div the editor lives in, then call editor.resize to get the editor to refill the div.

If you paste content with long lines, with ACE set to wrap lines, the number of new lines and actual rendered lines will differ, so the editor will scroll. This code will fix that, but you will get horizontal scrolling instead.

editor.getSession().setUseWrapMode(false)
Community
  • 1
  • 1
Carl Smith
  • 3,025
  • 24
  • 36
  • 1
    You cannot actually assume the line height to be 16px. Instead it can be retrieved from the API. Editing the answer to reflect it. – Xavi Montero Apr 14 '17 at 20:24
  • 1
    You usually *know* the height in practice, so I was only assuming you know it's 16px, but your improvement is still an improvement on hardcoding it. Nice one. +1 – Carl Smith Apr 14 '17 at 20:51
9

I think that a solution might be counting the number of lines in the editor and then resize it to fit these lines:

editor.setOptions({
     maxLines: editor.session.getLength()
});

Hope this helps.

René Fernández
  • 612
  • 8
  • 11
  • It seems to me that `maxLines: Infinity` does the same thing functionally. In my case, I have the editor in a container div with height and width set to 100%. – bildungsroman Dec 05 '18 at 23:45
2

You can use jQuery:

 var length_editor = editor.session.getLength();
 var rows_editor = length_editor * 17;

 $('#editor').css('height',rows_editor);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
1

I agree with the accepted answer, except that I would prefer editor.getSession().getScreenLength().

The issue is that if you enable wrap mode, a long line may break into multiple lines. Thus you will not be able to get correct line count with editor.getSession().getDocument().getLength().

AKFish
  • 155
  • 1
  • 7
0

My method in pure JavaScript (replace editor-container with the right id).

function adaptEditor() {
    document.getElementById('editor-container').style.height = window.innerHeight + 'px';
    editor.resize();
}
window.onresize = function(event) {
    adaptEditor();
};
adaptEditor();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Fabien Sa
  • 9,135
  • 4
  • 37
  • 44
0

This variant works better for me as sometimes the editor.renderer.lineHeight returns 1

    var resize = function() {
     var minHt = 16;
     var sl = editor.getSession().getScreenLength();
     var sw = editor.renderer.scrollBar.getWidth();
     var lh = Math.max(editor.renderer.lineHeight, minHt);
     var ht = Math.max(((sl * lh) + sw), minHt);
     $('#myEditorDiv').height(ht);
     editor.resize();
   };
Paul
  • 595
  • 6
  • 6
0

I had the same problem but found out that it was so simple to automatically adjust the height by getting the height of its parent element and give it to the #editor and trigger a resize by editor.resize(). It just worked like a charm! bellow is the code i used:

let editor = ace.edit('editor'), $editorWrapper = $('.editor-wrapper');

$('#editor').height($editorWrapper.height());
 editor.resize();

Well, I did this when I was trying to toggle maximize feature on the editor.

Codeparl
  • 300
  • 1
  • 8