How to make an ACE Editor instance resizable by the user dinamically with a drag & drop bar

How to make an ACE Editor instance resizable by the user dinamically with a drag & drop bar

A regular problem that some developers face when implementing ACE Editor into their project is the fact that the component doesn't allow to modify its size dinamically by the user's actions. This becomes a headache as you will need to implement this feature by yourself, taking care of window resizing events, drag and drop etc. In case you are getting started with the implementation of such feature, we would like to share with you a very basic implementation using jQuery for a vertically resizable instance of ACE Editor. Although there are other implementations out there, they mostly support only a single instance of ACE Editor, however with this snippet, you will be able to provide resizing support for multiple instances of ACE Editor.

In this article, we will explain you how to make a single or multiple instances of ACE Editor resizable in the browser window using either jQuery or Vanilla JavaScript.

A. jQuery version

Using jQuery is recommended to handle the resizing feature of Ace Editor, due to the ease of writing the code and the animation during the mouse events (it will look prettier than the Vanilla JS version). To get started create a globally accesible object that will store the dragging status of the instance of ace editor that you want to make resizable. Then, include the makeAceEditorResizable function as follows:

/**
 * Global variable to store the ids of the status of the current dragged ace editor.
 */
window.draggingAceEditor = {};

function makeAceEditorResizable(editor){
    var id_editor = editor.container.id;
    var id_dragbar = '#' + id_editor + '_dragbar';
    var id_wrapper = '#' + id_editor + '_wrapper';
    var wpoffset = 0;
    window.draggingAceEditor[id_editor] = false;

    $(id_dragbar).mousedown(function(e) {
        e.preventDefault();

        window.draggingAceEditor[id_editor] = true;
    
        var _editor = $('#' + id_editor);
        var top_offset = _editor.offset().top - wpoffset;
    
        // Set editor opacity to 0 to make transparent so our wrapper div shows
        _editor.css('opacity', 0);
    
        // handle mouse movement
        $(document).mousemove(function(e){
            var actualY = e.pageY - wpoffset;
            // editor height
            var eheight = actualY - top_offset;
            
            // Set wrapper height
            $(id_wrapper).css('height', eheight);
            
            // Set dragbar opacity while dragging (set to 0 to not show)
            $(id_dragbar).css('opacity', 0.15);
        });
    });
    
    $(document).mouseup(function(e){
        if (window.draggingAceEditor[id_editor])
        {
            var ctx_editor = $('#' + id_editor);
    
            var actualY = e.pageY - wpoffset;
            var top_offset = ctx_editor.offset().top - wpoffset;
            var eheight = actualY - top_offset;
    
            $( document ).unbind('mousemove');
            
            // Set dragbar opacity back to 1
            $(id_dragbar).css('opacity', 1);
            
            // Set height on actual editor element, and opacity back to 1
            ctx_editor.css('height', eheight).css('opacity', 1);
            
            // Trigger ace editor resize()
            editor.resize();

            window.draggingAceEditor[id_editor] = false;
        }
    });
}

Then with this function, you can turn an already initialized ace editor instance into a resizable one, having in count the following markup:

<div id="editor_wrapper" class="app_editor_wrapper">
    <div id="editor" class="app_editor">echo "Hello, this is some PHP code to edit";</div>
    <div id="editor_dragbar" class="app_editor_dragbar"></div>
</div>

Note that the editor needs to be wrapper into a div with the same id of your editor and _wrapper as suffix. The dragbar div will have as well the same id of your editor and _dragbar as suffix. Once you have the markup, you can easily initialize the ace editor and convert it into a resizable version providing the ace editor variable as argument to the given function:

makeAceEditorResizable(aceEditorInstance);

With this, your editor should be now vertically resizable.

Live example

The following codepen shows you how easy it is to play with 2 resizable Ace Editor instances.

See the Pen Resizable ACE Editor by Our Code World (@ourcodeworld) on CodePen.

B. VanillaJS version

Unlike its counterpart written with jQuery, the vanillajs version doesn't include a decent animation of resizing the element. You may modify it and add it if you want. The script works just like the jQuery script:

/**
 * VanillaJS version to make ace editor vertically resizable.
 * 
 * @param editor Ace Editor instance.
 */
function makeAceEditorResizable(editor){
    var id_editor = editor.container.id;
    var id_dragbar = id_editor + '_dragbar';
    var id_wrapper =  id_editor + '_wrapper';
    var wpoffset = 0;
    window.draggingAceEditor[id_editor] = false;

    var action_mousedown = function(e) {
        e.preventDefault();

        window.draggingAceEditor[id_editor] = true;

        // Set editor opacity to 0 to make transparent so our wrapper div shows
        document.getElementById(id_editor).style.opacity = 0;
    
        document.addEventListener("mousemove", action_document_mousemove);
    };

    var action_document_mousemove = function(e){
        var _editor = document.getElementById(id_editor);
        var rect = _editor.getBoundingClientRect();

        var rsl = {
            top: rect.top + document.body.scrollTop
        };

        var top_offset = rsl.top - wpoffset;

        var actualY = e.pageY - wpoffset;

        // editor height
        var eheight = actualY - top_offset;
        
        // Set wrapper height
        document.getElementById(id_wrapper).style.height = eheight;
        
        // Set dragbar opacity while dragging (set to 0 to not show)
        document.getElementById(id_dragbar).style.opacity =  0.15;
    };

    document.getElementById(id_dragbar).addEventListener("mousedown", action_mousedown);
 
    var action_mouseup = function(e){
        if (window.draggingAceEditor[id_editor])
        {
            var ctx_editor = document.getElementById(id_editor);
            
            var rect = ctx_editor.getBoundingClientRect();

            var rsl = {
                top: rect.top + document.body.scrollTop
            };

            var actualY = e.pageY - wpoffset;
            var top_offset = rsl.top - wpoffset;
            var eheight = actualY - top_offset;
            
            document.removeEventListener("mousemove", action_document_mousemove);
            
            // Set dragbar opacity back to 1
            document.getElementById(id_dragbar).style.opacity = 1;
            
            // Set height on actual editor element, and opacity back to 1
            ctx_editor.style.height = eheight + "px";
            ctx_editor.style.opacity = 1;
            
            // Trigger ace editor resize()
            editor.resize();

            window.draggingAceEditor[id_editor] = false;
        }
    };

    document.addEventListener("mouseup", action_mouseup);
}

Requires the same markup style:

<div id="editor_wrapper" class="app_editor_wrapper">
    <div id="editor" class="app_editor">echo "Hello, this is some PHP code to edit";</div>
    <div id="editor_dragbar" class="app_editor_dragbar"></div>
</div>

Note that the editor needs to be wrapper into a div with the same id of your editor and _wrapper as suffix. The dragbar div will have as well the same id of your editor and _dragbar as suffix. Once you have the markup, you can easily initialize the ace editor and convert it into a resizable version providing the ace editor variable as argument to the given function:

makeAceEditorResizable(aceEditorInstance);

With this, your editor should be now vertically resizable.

Live example

The following codepen shows you how easy it is to play with 2 resizable Ace Editor instances with Vanilla JS.

See the Pen Resizable ACE Editor with Vanilla JS by Our Code World (@ourcodeworld) on CodePen.

In some use cases, for example when the entire window is scrollable, you may have problems with the offset generated by the getBoundingClientRect method of JavaScript.

Happy coding !

This could interest you

Become a more social person