Der Codemirror-Editor lädt erst Inhalte, wenn Sie darauf klicken

78

Ich verwende Codemirror 2 und es funktioniert einwandfrei, außer dass der eingestellte Wert des Editors erst in den Editor geladen wird, wenn ich auf den Editor klicke und er fokussiert wird.

Ich möchte, dass der Editor den Inhalt von sich selbst anzeigt, ohne dass darauf geklickt werden muss. Irgendwelche Ideen?

Alle Codemirror-Demos funktionieren wie erwartet, also habe ich mir gedacht, dass der Textbereich möglicherweise nicht fokussiert ist, also habe ich das auch versucht.

$("#editor").focus();
var editor =    CodeMirror.fromTextArea(document.getElementById("editor"), {
                    mode: "text/html",
                    height: "197px",
                    lineNumbers: true
                });
Karl
quelle
3
Ich habe dieses Problem auch, wenn ich einen CodeMirror-Editor in ein modales Popup lade. Haben Sie eine Lösung gefunden, wie Sie den Editor fokussieren können? Vielen Dank.
Ray

Antworten:

54

Sie müssen refresh () nach setValue () aufrufen. Sie müssen jedoch setTimeout verwenden, um die Aktualisierung () auf zu verschieben, nachdem CodeMirror / Browser das Layout entsprechend dem neuen Inhalt aktualisiert hat:

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

Es funktioniert gut für mich. Ich habe die Antwort hier gefunden .

nvd_ai
quelle
1
Ich hatte das gleiche Problem mit den Registerkarten der jQuery-Benutzeroberfläche, und es hilft mir.
Greenif
Wenn ich könnte, würde ich diese Antwort 10 Mal abstimmen. hat meinen Tag gerettet.
Jonathana
28

Ich gehe davon aus, dass Sie (oder ein von Ihnen geladenes Skript) sich so in das DOM einmischen, dass der Editor beim Erstellen versteckt ist oder sich auf andere Weise an einer seltsamen Position befindet. Die refresh()Methode muss aufgerufen werden, nachdem sie sichtbar gemacht wurde.

Marijn
quelle
Vielen Dank für die Antwort, ich werde das auch versuchen.
Karl
2
In meiner Implementierung wurde das übergeordnete Objekt gestartet, display: none;das dieses Problem verursachte. Diese Antwort löste das Problem problemlos! Vielen Dank, @Marijn!
Soleil
Dies löste auch meinen Fall mit dem übergeordneten Element GWT TabLayoutPanel oder DisclosurePanel, das die Anzeige ihrer untergeordneten Elemente umschaltet. Ich habe es mithilfe des Listeners in diesen übergeordneten Bedienfeldern behoben und eine Aktualisierung des Code-Spiegels verschoben, wenn es angezeigt wird.
Jolivier
28

Nur für den Fall und für alle, die die Dokumentation nicht sorgfältig genug lesen (wie ich), aber darauf stoßen. Dafür gibt es ein Autorefresh-Addon .

Sie müssen autorefresh.jsIhre Datei hinzufügen . Jetzt können Sie es so verwenden.

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

});

klappt wunderbar.

Vikash Saini
quelle
Das hat bei mir funktioniert. Die Verwendung setTimeoutmit einer tatsächlichen Zeit im Inneren ist unvorhersehbar und das war das einzige, was bisher für mich funktioniert hat. Diese Lösung ist viel robuster.
Intcreator
Dies funktioniert nur bei mir, wenn ich einen einzelnen setValue () habe. Wenn ich den Wert jedoch mehrmals festlegen möchte, muss ich den CodeMirror-Editor dennoch manuell fokussieren.
Chris
@phpheini Ich habe auch das gleiche Problem. Haben Sie einen Weg gefunden, damit umzugehen?
Prismaticorb
Ich habe keine wirkliche Lösung, aber in meinem Fall verwende ich verschiedene Registerkarten, um den Inhalt meiner Website zu organisieren. Also habe ich den Editor in eine andere Registerkarte eingefügt und wenn der Benutzer die Registerkarte ändert, rufe ich die codeMirror.refresh()Funktion auf, um den Editor zu aktualisieren.
Chris
Das funktioniert bei mir nicht. Das Autorefresh-Plugin funktioniert (das Ändern von Dokumenten erfordert keinen Aufruf mehr zum Aktualisieren), aber wenn das übergeordnete Element des Editors mit beginnt display: none, muss ich immer noch auf den Editor klicken, damit der Text angezeigt wird
Lewy Blue
10

Ich verwende CodeMirror zufällig auf einer Bootstrap-Registerkarte. Ich vermutete, dass die Bootstrap-Registerkarten verhinderten, dass sie angezeigt wurden, bis sie angeklickt wurden. Ich habe dies behoben, indem ich einfach die gezeigte refresh()Methode aufgerufen habe.

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));
Ja, Barry
quelle
1
Ich hatte schon immer danach gesucht. Vielen Dank. CodeMirror- und Bootstrap-Registerkarten benötigen dies
FilT
5

Etwas hat bei mir funktioniert.

$(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
quelle
2

Die Version 5.14.2 von Codemirror behebt dies vollständig mit einem Add-On. Siehe diese Antwort für Details.

Paul Whipp
quelle
Das Autorefresh-Addon behebt dieses Problem nicht für mich.
Lewy Blue
1

Eine weitere Lösung (die mir auch klar wurde, weil der Editor sichtbar sein musste, um ordnungsgemäß zu erstellen) besteht darin, das übergeordnete Element während der Erstellung vorübergehend an das body-Element anzuhängen und es nach Abschluss wieder anzubringen.

Auf diese Weise müssen Sie sich nicht in Elemente einmischen oder sich Gedanken über die Sichtbarkeit in vorhandenen Hierarchien machen, in denen Ihr Editor möglicherweise vergraben ist.

In meinem Fall habe ich für processr.com mehrere Elemente zur Bearbeitung verschachtelten Codes, die alle im laufenden Betrieb erstellt werden müssen, wenn der Benutzer Aktualisierungen vornimmt. Daher gehe ich wie folgt vor:

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

Es funktioniert großartig und es gab bisher kein sichtbares Flackern oder ähnliches.

davestewart
quelle
1

Ich arbeite mit reagieren, und all diese Antworten haben bei mir nicht funktioniert ... Nach dem Lesen der Dokumentation hat es so funktioniert:

Im Konstruktor habe ich eine Instanz von Code Mirror initialisiert:

this.mirrorInstance = null;

und beim Öffnen der Registerkarte, die den CodeEditor enthält, habe ich die Instanz nach 1 Millisekunde aktualisiert:

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

und hier ist der JSX-Code:

<CodeMirror
           value={this.state.codeEditor}
           options={{
           mode: "htmlmixed",
           theme: "default",
           lineNumbers: true,
           lineWrapping: true,
           autoRefresh: true
           }}
           editorDidMount={editor => {
           this.mirrorInstance = editor;
           }}
        />
Ammar Ismaeel
quelle
0

Versuchen Sie, den Fokus auf das DOM-Element anstelle des jQuery-Objekts aufzurufen.

var editor=$( '#editor' );
editor[0].focus();
// or
document.getElementById( 'editor' ).focus();
czarchaisch
quelle
Danke für die Antwort, ich werde das versuchen.
Karl
0

Ich bin heute Abend selbst auf eine Version dieses Problems gestoßen.

Eine Reihe anderer Beiträge betrachten die Sichtbarkeit des übergeordneten Textbereichs als wichtig. Wenn dieser ausgeblendet ist, können Sie auf dieses Problem stoßen.

In meiner Situation waren das Formular selbst und die unmittelbare Umgebung in Ordnung, aber mein Backbone-Ansichtsmanager weiter oben in der Renderkette war das Problem.

Mein Ansichtselement wird erst im DOM platziert, wenn sich die Ansicht vollständig gerendert hat. Ich denke, ein Element, das sich nicht im DOM befindet, wird als ausgeblendet betrachtet oder einfach nicht behandelt.

Um dies zu umgehen, habe ich eine Post-Render-Phase (Pseudocode) hinzugefügt:

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

In postRender kann die Ansicht das tun, was sie benötigt, da sie weiß, dass der gesamte Inhalt jetzt auf dem Bildschirm sichtbar ist. Hier habe ich den CodeMirror verschoben und es hat einwandfrei funktioniert.

Dies kann auch dazu beitragen, zu erklären, warum Probleme mit Popups auftreten können, da in einigen Fällen versucht wird, den gesamten Inhalt vor dem Anzeigen zu erstellen.

Hoffe das hilft jemandem.

Toby

Toby Skinner
quelle
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>
Koray Bayram
quelle
0

Etwas hat bei mir funktioniert! :) :)

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

      setTimeout(function(){
        clearInterval(sh);  
      },2000)
cnwangzd
quelle
0

Mithilfe der Aktualisierung können Sie dieses Problem beheben. Aber es scheint nicht freundlich

MuYunyun
quelle