Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically adjust height to contents in Ace Cloud 9 editor

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()
like image 692
limitlessloop Avatar asked Jul 20 '12 17:07

limitlessloop


3 Answers

(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);
}
like image 77
HostileFork says dont trust SE Avatar answered Nov 17 '22 21:11

HostileFork says dont trust SE


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

editor.setOptions({
    maxLines: 15
});

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

like image 43
Dickeylth Avatar answered Nov 17 '22 19:11

Dickeylth


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)
like image 13
Carl Smith Avatar answered Nov 17 '22 21:11

Carl Smith