'codemirror-textarea resizable like a standard textarea
Does anybody know how to make a codemirror textarea resizable like text-area ?
So that the codemirror textarea can be resized by dragging their bottom down grabber corner.
I know it's possible for html divs (see div resizable like text-area) but I have not managed to achieve the same thing on code mirror.
Solution 1:[1]
WITHOUT JQUERY , CSS only
.CodeMirror {
resize: vertical;
overflow: auto !important;
}
After some struggle, this simple code actually worked for me. I got a resizable Codemirror Instance vertically with scroll working properly.
Solution 2:[2]
I made this little example.
Note that this resizes vertically only, which is probably what you really want? The horizontal resize ability of a normal textarea tends to break layouts - it's usually much easier to come up with a layout where the editor has a fixed width and the content below it gets pushed down if you resize.
I haven't seen the design in which you intend for this to fit, so I'm guessing.
It shouldn't be too hard to modify this and get a working resize widget that works in both directions though, if that's what you wanted.
Alternatively, consider trying this plugin by @Sphinxxx which was derived from this example.
Solution 3:[3]
If jQuery is not an option, and you can live without resizing in IE (and Edge, until it catches up with CSS resize:...), here's a proof-of-concept example of a pleasantly simple & light technique that doesn't require the drag-and-drop hack pioneered by @mindplay.dk.
Instead, here:
- a container DIV is used, with
- a plain CSS resize handle, and
- the resize events are proxied over to CM via
ResizeObserver/MutationObserver(sinceonResizeonly fires forwindow, just to make web programming that much more miserable ;) ).
One issue to iron out (in CM? in WebKit? or as a workaround I haven't had the patience + time to distill...) is the extra bottom padding added for the "CM on WebKit" scenario, where the CSS resize handle would get overlapped by CM's own pots and pans. OTOH, Firefox draws it on top of all else, so despite CM is unaware of the handle and draws its various (several!) rectangles there, Firefox still manages to win rescuing it, and resizing would work, albeit the handle would get pasted over the scrollbar arrows. (Playing with z-index or styling the crap out of CM didn't help for me.)
BTW, note: this means that plain CSS overflow: hidden; resize: both;, directly applied on the main .CodeMirror DIV, almost works in Firefox without any magic (no extra frame, no geometry tweaks etc.). Hooking the resize events (the same way as noted above) for a cm.setSize(cm_div.clientWidth, cm_div.clientHeight) would still be needed, though.
But detecting Firefox vs. Chrome to optimize it out would probably make the code much more complicated than just leaving it the same for both...
document.addEventListener("DOMContentLoaded", function(event) {
fr = document.querySelector("#cm-resize-frame")
// This 5-6 lines below is only for the WRAP/NOWRAP demo switch:
cm = null
reset = document.getElementById("wrap").onclick = function() {
cm && cm.toTextArea() // clean up previous CM instance
cm = CodeMirror.fromTextArea(document.getElementById("cm"),
{lineWrapping: document.getElementById("wrap").checked,
lineNumbers: true } // just to see if CM is actually alive & resizing
)
function cm_resize() {
cm.setSize(fr.clientWidth + 2, // chrome needs +2, others don't mind...
fr.clientHeight - 10) // and CM needs room for the resize handle :-/
}
// Needed (on FF, Edge & IE11, but not Chrome) for the scrollbars to properly initialize:
cm_resize()
// This is the actual "business logic" of the whole thing! ;)
if (window.ResizeObserver) // Chrome 64+
new ResizeObserver(cm_resize).observe(fr)
else if (window.MutationObserver) // others
new MutationObserver(cm_resize).observe(fr, {attributes: true})
}
reset()
})
#cm-resize-frame {
overflow: hidden; /* CM will manage its own scrollbars. */
resize: both;
height: 10em; /* A fixed initial height is required in Chrome both for the resize handle to appear and to not fall into a shrinking loop due to the neg. offset in cm_resize()! */
/* Optional... */
border: 1px solid lightgrey;
width: 20em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.29.0/codemirror.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.29.0/codemirror.min.js"></script>
<div id="cm-resize-frame">
<textarea id="cm">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nunc rhoncus ornare diam eget consequat. Suspendisse potenti.
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
Sed scelerisque, ex nec pharetra ultrices, ipsum mi aliquam arcu, sit amet pulvinar erat mauris sit amet mi.
Fusce pulvinar vel ex semper imperdiet. Quisque dapibus purus eu commodo volutpat.
Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
Sed scelerisque, ex nec pharetra ultrices, ipsum mi aliquam arcu, sit amet pulvinar erat mauris sit amet mi.
Fusce pulvinar vel ex semper imperdiet. Quisque dapibus purus eu commodo volutpat.</textarea>
</div>
WRAP: <input id="wrap" type="checkbox" checked>
(Again: this is just an example, demonstrating that the technique works. The JS snippet is meant to be read as pseudocode. ;) A real, polished implementation, provided that the simplicity of the approach is preserved, is very welcome, though!)
(See also on CodePen...)
Solution 4:[4]
.CodeMirror__wrapper {
resize: both;
overflow: auto !important;
}
Tried adding resize to .CodeMirror but that didn't work. Adding the resize to the wrapper worked for me though.
Solution 5:[5]
let CodeMirrorCustomResize = (params) => {
var start_x, start_y, start_h,
minHeight = params && params.minHeight ? params.minHeight : 150,
resizableObj = params && params.resizableObj ? params.resizableObj : '.handle'
let onDrag = (e) => {
sqlEditor.setSize(null, `${Math.max(minHeight, (start_h + e.pageY - start_y))}px`);
}
let onRelease = (e) => {
$('body').off("mousemove", onDrag);
$(window).off("mouseup", onRelease);
}
$('body').on("mousedown", resizableObj, (e) => {
start_x = e.pageX;
start_y = e.pageY;
start_h = $('.CodeMirror').height();
$('body').on("mousemove", onDrag);
$(window).on("mouseup", onRelease);
});
}
If someone is interested in shorter and more jQuery version of @mindplay.dk answer ( btw. thanks for this ).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Tadeu Marques |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | J. Scott Elblein |
| Solution 5 | TH3C120W |
