88

I am using codemirror 2 and its working fine except that the editor's set value doesn't load into the editor until I click the editor and it becomes focused.

I want the editor to show the content of itself without it having to be clicked. Any ideas?

All of the codemirror demos work as expected so I figured maybe the textarea isn't focused so I tried that too.

$("#editor").focus();
var editor =    CodeMirror.fromTextArea(document.getElementById("editor"), {
                    mode: "text/html",
                    height: "197px",
                    lineNumbers: true
                });
Karl
  • 1,743
  • 1
  • 15
  • 20
  • 3
    I have this problem also, where I load a CodeMirror editor on a modal popup. Have you found a solution on how to make the editor focused? Thanks. – Ray Jan 12 '13 at 23:43

15 Answers15

66

You must call refresh() after setValue(). However, you must use setTimeout to postpone the refresh() to after CodeMirror/Browser has updated the layout according to the new content:

codeMirrorRef.setValue(content);
setTimeout(function() {
    codeMirrorRef.refresh();
},1);

It works well for me. I found the answer in here.

Sridhar Ratnakumar
  • 81,433
  • 63
  • 146
  • 187
nvd_ai
  • 1,060
  • 11
  • 20
45

Just in case, and for everyone who doesn't read the documentation carefully enough (like me), but stumbles upon this. There's an autorefresh addon just for that.

You need to add autorefresh.js in your file. Now you can use it like this.

var editor = CodeMirror.fromTextArea(document.getElementById("id_commentsHint"), {
  mode: "javascript",
  autoRefresh:true,
  lineNumbers: false,
  lineWrapping: true,

});

works like a charm.

Vikash Saini
  • 669
  • 9
  • 15
  • This worked for me. Using `setTimeout` with an actual time inside is unpredictable and that was the only thing working for me so far. This solution is much more robust. – intcreator May 05 '17 at 17:08
  • This only works for me when I have a single setValue(). However if I want to set the value multiple times I still have to manually focus the CodeMirror editor. – Chris May 31 '17 at 15:11
  • @phpheini I also have the same issue. Have you discovered a way to deal with this? – prismaticorb Jun 01 '17 at 20:47
  • I don't really have a solution however in my case I am using different tabs to organize my website content. So I put the editor into a different tab and then when the user changes the tab I call the `codeMirror.refresh()` function to refresh the editor. – Chris Jun 02 '17 at 15:05
  • This doesn't work for me. The autorefresh plugin works (changing documents no longer requires a call to refresh), but when the editor parent starts with `display: none`, I still have to click the editor to make the text appear – Lewy Blue Sep 26 '19 at 07:53
  • Can you share the link of an example? So I can check. – Vikash Saini Sep 26 '19 at 09:02
  • Wonderful, this worked for me and is much better than relying on `setTimeout`. If you're using NPM just add this `import 'codemirror/addon/display/autorefresh';` and then `autoRefresh: true` to the config and you're good to go. – texelate Aug 17 '20 at 10:58
  • Thank you so much. ``and then add in to your project properties as shown above. `autoRefresh:true,` – CodingEE Feb 28 '22 at 05:57
28

I expect you (or some script you loaded) is meddling with the DOM in such a way that the editor is hidden or otherwise in a strange position when created. It'll require a call to its refresh() method after it is made visible.

Marijn
  • 8,691
  • 2
  • 34
  • 37
  • Thanks for the response, Im going to try that too. – Karl Dec 20 '11 at 22:16
  • 2
    In my implementation, the parent object started out `display: none;` which caused this issue- this answer resolved the problem handily! Thank you, @Marijn! – Soleil Jun 13 '12 at 17:49
  • This solved also my case with parent element being GWT TabLayoutPanel or DisclosurePanel that toggle display of their children. I fixed it using listener on these parent panels and defering a refresh of code mirror when showing it. – jolivier Feb 19 '13 at 14:32
11

I happen to be using CodeMirror within a bootstrap tab. I suspected the bootstrap tabs were what was preventing it from showing up until clicked. I fixed this by simply calling the refresh() method on show.

var cmInstance = CodeMirror.fromTextArea(document.getElementById('cm'), {
    lineNumbers: true,
    lineWrapping: true,
    indentUnit: 4,
    mode: 'css'
});

// to fix code mirror not showing up until clicked
$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function() {
    this.refresh();
}.bind(cmInstance));
Yes Barry
  • 9,514
  • 5
  • 50
  • 69
  • 2
    I'd been looking for this forever. Thank you. CodeMirror and bootstrap tabs need this – FilT Sep 28 '20 at 17:00
  • 1
    Had exact same Bootstrap nav tabs problem. Banged my head against the wall. Then did: `$(contactTab).on('shown.bs.tab', function (e) {if (isHidden(document.querySelector('#id_content')) && typeof testEditor === "undefined") { initializeEditor(); }})` where isHidden takes `(el)` and returns `return (el.offsetParent === null)`. Sorry this is so ugly. Hope it helps someone else. – Jarad Jan 27 '22 at 18:07
5

Something worked for me.

$(document).ready(function(){
                var editor = CodeMirror.fromTextArea(document.getElementById("code2"), {
                     //lineNumbers: true,
                      readOnly: true,
                      autofocus: true,
                     matchBrackets: true,
                     styleActiveLine: true
                 });
                 setTimeout(function() {
                     editor.refresh();
                    }, 100);

        });
Jinu
  • 93
  • 1
  • 6
2

The 5.14.2 version of codemirror addresses this fully with an add on. See this answer for details.

Community
  • 1
  • 1
Paul Whipp
  • 16,028
  • 4
  • 42
  • 54
2

I am working with react, and all these answers did not work with me...After reading the documentation it worked like this:

in the constructor, I initialized an instance of code Mirror:

this.mirrorInstance = null;

and on opening the tab that contains the codeEditor, I refreshed the instance after 1 millisecocnd:

toggleSubTab() {
    setTimeout(() => {
      this.mirrorInstance.refresh();
    }, 1);
  }

and here is the JSX code:

<CodeMirror
           value={this.state.codeEditor}
           options={{
           mode: "htmlmixed",
           theme: "default",
           lineNumbers: true,
           lineWrapping: true,
           autoRefresh: true
           }}
           editorDidMount={editor => {
           this.mirrorInstance = editor;
           }}
        />
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Ammar Ismaeel
  • 651
  • 1
  • 11
  • 21
1

I just ran into a version of this problem myself this evening.

A number of other posts regard the visibility of the textarea parent as being important, if it's hidden then you can run into this problem.

In my situation the form itself and immediate surroundings were fine but my Backbone view manager higher up the rendering chain was the problem.

My view element isn't placed on the DOM until the view has rendered itself fully, so I guess an element not on the DOM is considered hidden or just not handled.

To get around it I added a post-render phase (pseudocode):

view.render();
$('body').html(view.el);
view.postRender();

In postRender the view can do what it needs knowing that all the content is now visible on the screen, this is where I moved the CodeMirror and it worked fine.

This might also go some of the way to explain also why one may run into problems with things like popups as in some cases they may try to build all content before displaying.

Hope that helps someone.

Toby

1

Yet another solution (which I also realised was because the editor needed to be visible to create properly) is to temporarily attach the parent element to the body element during construction, then reattach once complete.

This way, you don't need to meddle with elements, or worry about visibility in any existing hierarchies that your editor might be buried.

In my case, for processr.com, I have multiple, nested code editing elements, all of which need to be created on the fly as the user makes updates, so I do the following:

this.$elements.appendTo('body');
for (var i = 0; i < data.length; i++)
{
    this.addElement(data[i]);
}
this.$elements.appendTo(this.$view);

It works great, and there's been no visible flicker or anything like that so far.

davestewart
  • 705
  • 1
  • 8
  • 11
0
<div class="tabbable-line">
    <ul class="nav nav-tabs">
        <li class="active">
            <a href="#tabXml1" data-toggle="tab" aria-expanded="true">Xml 1</a>
        </li>
        <li class="">
            <a href="#tabXml2" id="xmlTab2Header" data-toggle="tab" aria-expanded="true">Xml 2</a>
        </li>
    </ul>
    <div class="tab-content">
        <div class="tab-pane active" id="tabXml1">
            <textarea id="txtXml1" />
        </div>
        <div class="tab-pane" id="tabXml2">
            <textarea id="txtXml2" />
        </div>
    </div>
</div>

<link rel="stylesheet" href="~/Content/codemirror.min.css">
<style type="text/css">
    .CodeMirror {
        border: 1px solid #eee;
        max-width: 100%;
        height: 400px;
    }
</style>

<script src="~/Scripts/codemirror.min.js"></script>
<script src="~/Scripts/codemirror.xml.min.js"></script>
<script>
        $(document).ready(function () {
            var cmXml1;
            var cmXml2;
            cmXml1 = CodeMirror.fromTextArea(document.getElementById("txtXml1"), {
                mode: "xml",
                lineNumbers: true
            });
            cmXml2 = CodeMirror.fromTextArea(document.getElementById("txtXml2"), {
                mode: "xml",
                lineNumbers: true
            });
            // Refresh code mirror element when tab header is clicked.
            $("#xmlTab2Header").click(function () {
                setTimeout(function () {
                    cmXml2.refresh();
                }, 10);
            });
        });
</script>
0

Something worked for me! :)

      var sh = setInterval(function() {
       agentConfigEditor.refresh();
      }, 500); 

      setTimeout(function(){
        clearInterval(sh);  
      },2000)
cnwangzd
  • 9
  • 1
0

using refresh help solve this problem. But it seems not friendly

MuYunyun
  • 64
  • 7
0

The reason:

CodeMirror won't update DOM content when it's DOM Node is unvisible.

For example:

when the CodeMirror's Dom is setted style to 'display: none'.

The way to fix:

when CodeMirror's Dom is visible, manual excute the cm.refresh() method.

For example in my application, the CodeMirror Dom will visible when the tab element clicked.

So the simple method is:

window.onclick = () => {
    setTimeout(() => {
        codeMirrorRef.refresh();
    }, 10);
};

You can add event listener on more specific element to improve the performance.

Keifer Gu
  • 1
  • 1
0

chain this to the master codemirror object, make sure that nothing else is chained

.on('change', editor => {
   globalContent = editor.getValue();
});;
dizad87
  • 448
  • 4
  • 15
0

Try calling focus on the DOM element instead of the jQuery object.

var editor=$( '#editor' );
editor[0].focus();
// or
document.getElementById( 'editor' ).focus();
czarchaic
  • 6,268
  • 29
  • 23