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
(since onResize
only fires for window
, 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...)