Codemirror content not visible in bootstrap modal until it is clicked

╄→尐↘猪︶ㄣ 提交于 2019-12-05 01:00:58

A cleaner solution perhaps?

Bootstrap modals have an event that fires after the modal is shown. In Bootstrap 3, this is shown.bs.modal.

modal.on('shown.bs.modal', function() {
    // initialize codemirror here
});

I figured it has something to do with viewport size change while tabs are hidden and shown again. So the following worked for me:

1) Listen for clicks over the tabs 2) On click, call refresh() on all CM editors or just the one inside a tab, as you prefer

It's important to note that refresh() must be called with a small time-out, otherwise in some browsers (i got this in Chrome), the editor is displayed, but with some invalid offsets.

Try something like this:

$(document).ready(function() {
    $("#your_nav_tabs a").click(function(e) {
        if(window.codeMirrorInstances != null) { // window.codeMirrorInstances must be initialized and tracked manually
            $.each(window.codeMirrorInstances, function(index, cm) {
                setTimeout(function() {
                    cm.refresh();
                }, 100);
            });
        }

        return false;
    });
});
Brett

With help from this question, I was able to get a CodeMirror editor, which was sitting in an inactive bootstrap 3 tab and therefore not completely initialized, and refresh it when the tab is clicked. Maybe someone finds it useful.

Coffeescript version:

$('a[data-toggle="tab"]').on 'shown.bs.tab', (e) ->
  target = $(e.target).attr("href") # activated tab
  $(target + ' .CodeMirror').each (i, el) ->
    el.CodeMirror.refresh()

If you initialize editor on modal shown event, problem will be solved. Just put this script on parent page.

$('#myModal').on('shown', function () {
    CodeMirror.fromTextArea(document.getElementById('MyTextArea'), { mode: 'xml', lineNumbers: true });
});

You can now use the Code Mirror addon Auto Refresh: https://codemirror.net/doc/manual.html#addon_autorefresh

Just include the script dependency

<script src="../display/autorefresh.js" %}"></script>
Which now gives you the option "autoRefresh" to auto refresh just once right after displaying the content.
var myCodeMirror = CodeMirror.fromTextArea(myTextArea,{
  autoRefresh: true,
});

The docs also state its a 250ms time delay after showing the hidden content. You can increase that delay if you are loading a lot of content.

I'm having a similar issue with regards to bootstrap in general (not specifically with modals). However, my solution was to make sure I created the codemirror editor as early as possible (rather than on the document's ready event). I'm guessing this has something to do with the way bootstrap calculates the widths and heights in the grid.

<body>
    <!-- my page content -->

    <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>

    <script type="text/javascript">
        // Create the code editor here rather than on document.ready
        editor = CodeMirror(...);
    </script>
</body>

I was having a very similar problem with CodeMirror: if it was initialized while it wasn't the active bootstrap tab, it wouldn't show any content. My workaround was the opposite from @pbergqvist - to initialize the CodeMirror control as late as possible, i.e., after the tab in question was selected. Using TypeScript, it looks kind of like this:

var tabClicked = $.Deferred();
$('#scriptTab').click(() => tabClicked.resolve());
$.ajax('/api/script')
    .done(script => {
        this.tabClicked.done(() => {
            setTimeout(()=> {
                var codeMirror = CodeMirror.fromTextArea($('#script')[0]);
                codeMirror.getDoc().setValue(script);
            }, 10);
        });
    })
    .fail(err=> console.error('Error retrieving script: ' + JSON.stringify(err)));

Hope this helps someone.

(angular,bootstrap) I just solved it with a simple timeout, like this:

<button class="btn btn-default pull-right margin" data-toggle="modal" data-target="#codesnippetmodal" ng-click="getcodesnippet(module)">
 open modal
</button>

and then in my controller:

$scope.getcodesnippet = function(module) {
    var clientmodule = {
        clientid: $rootScope.activeclient.id,
        moduleid: module.id
    }
    Data.post('getCodesnippet', {
        clientmodule: clientmodule
    }).then(function(results) {

        codesnippet_editor.setValue(results.codesnippet);
        setTimeout(function() {
            codesnippet_editor.refresh();
        }, 500);
    });
}

to avoid getting refreshed every time (meaning position and changes lost) i strongly advise for using like this:

$('#meinetabs a[data-toggle="tab"]').on('shown.bs.tab', function (e) 
{
    if (var5 !=="5")
         {
            editor_htaccess.refresh();
         }
    var5 = "5";
})  

Its under MIT license because i am such a nice person

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!