Bootstrap Bookmarks with CodeMirror

I have a pretty complicated page where I have multiple instances of CodeMirror in hidden tabs in tabs. To make it even more complex, I remember the last active tabs.

I managed to get it half the work ( http://codepen.io/anon/pen/LheaF ), problems with the tabs of the second editor:

  • Download two tabs before clicking the main tabs of the Code Mirror. When you click the Code Mirror tab, it will not load the editor correctly until you double-click.
  • I want the second tab to call the refresh() method if it has already been started, as for the main editor.
  • Error when duplicating secondary editors

 (function($) { var mainEditor; function initMainCodeEditor() { if (mainEditor instanceof CodeMirror) { mainEditor.refresh(); } else { // Load main editor var el = document.getElementById("codifyme"); mainEditor = CodeMirror.fromTextArea(el, { lineNumbers: true }); mainEditor.setSize('100%', 50); } } function initSecondaryCodeEditor() { var $active = $('#code_mirror_editors > .active > a'); var $sec_tab = $($active.data('target')); CodeMirror.fromTextArea($sec_tab.find('textarea')[0], { lineNumbers: true }); } $(document).ready(function() { // Only load editors if tab has been clicked $('#maintabs > li > a[data-target="#codemirror"]').on('shown.bs.tab', function(e) { initMainCodeEditor(); }); $('#code_mirror_editors > li > a[data-toggle="tab"]').on('shown.bs.tab', function(e) { initSecondaryCodeEditor(); }); // Remember tabs var json, tabsState; $('a[data-toggle="tab"]').on('shown.bs.tab', function(e) { tabsState = localStorage.getItem("tabs-state"); json = JSON.parse(tabsState || "{}"); json[$(e.target).parents("ul.nav.nav-pills, ul.nav.nav-tabs").attr("id")] = $(e.target).data('target'); localStorage.setItem("tabs-state", JSON.stringify(json)); }); tabsState = localStorage.getItem("tabs-state"); json = JSON.parse(tabsState || "{}"); $.each(json, function(containerId, target) { return $("#" + containerId + " a[data-target=" + target + "]").tab('show'); }); $("ul.nav.nav-pills, ul.nav.nav-tabs").each(function() { var $this = $(this); if (!json[$this.attr("id")]) { return $this.find("a[data-toggle=tab]:first, a[data-toggle=pill]:first").tab("show"); } }); }); // doc.ready })(jQuery); 
+6
source share
5 answers

Problems:

  • it may happen that you create a CodeMirror for an element that is not displayed (one of the parents has a display: none). This breaks the various calculations done with CodeMirror.
  • having received a CodeMirror instance directly from the CodeMirror container element, we can trigger an update every time you want (by finding a .CodeMirror next to your textarea )
  • fixed as a side effect 2.

see the updated version here: http://codepen.io/lloiser/pen/arBkv

you can see my changes in the codec looking for // --> comments

+5
source

Working solution: http://codepen.io/anon/pen/hupwy

I turned to problems 2 and 3, as I could not reproduce 1.

I used a hash table to store the second CodeMirror object editor. Then I modified the existing mainEditor code to update the objects if they already exist.

 var seccondEditor = new Object(); function initSecondaryCodeEditor(){ var $active = $('#code_mirror_editors > .active > a'); var $sec_tab = $($active.data('target')); var sec_edi = ($sec_tab.find('textarea')[0]); if(seccondEditor[sec_edi.id] instanceof CodeMirror){ seccondEditor[sec_edi.id].refresh(); } else { seccondEditor[sec_edi.id] = CodeMirror.fromTextArea(sec_edi, {lineNumbers: true}); } } 

I'm not good at CodeMirror, so this may not be the most elegant solution, but it looks like the code above prevents duplicates that you saw. Hope this helps.

+3
source

if the problem occurs when codemirror displays the content in a hidden div, why not just expand all the tab divs and then call codemirror and then hide the unwanted tab?

HTML:

  <div role="tabpanel" class="tab-pane active" id="tp1"> <textarea class="code" data-lang="text/html"> <!--- content #1 here --> </textarea> </div> <div role="tabpanel" class="tab-pane active hideAfterRendering" id="tp2"> <textarea class="code" data-lang="text/html"> <!--- content #2 here --> </textarea> </div> <div role="tabpanel" class="tab-pane active hideAfterRendering" id="tp3"> <textarea class="code" data-lang="text/html"> <!--- content #3 here --> </textarea> </div> 

SCRIPT:

  <script> $( document ).ready(function() { //render codeMirror $('.code').each(function() { CodeMirror.fromTextArea(this, { mode: "properties", lineNumbers: true, indentUnit: 4, readOnly: true, matchBrackets: true }); }); //hide tab-panel after codeMirror rendering (by removing the extra 'active' class $('.hideAfterRendering').each( function () { $(this).removeClass('active') }); }); </script> 

Works well for me.

+1
source

HTML

Here's the boot tab frame, if you use jquery-UI, it will be a little different.

 <ul class="nav nav-tabs"> <li class="active"><a href="#tab1" data-toggle="tab">tab1</a></li> <li><a href="#tab2" data-toggle="tab">tab2</a></li> </ul> <div class="tab-content"> <div class="tab-pane fade in active" id="tab1"><textarea type="text" id="tab1Content" name="xxx"></textarea></div> <div class="tab-pane fade" id="tab2"><textarea type="text" id="tab2Content" name="yyy"></textarea></div> </div> 

Js

 var cm1, cm2; $(document).ready(function () { //when the bootstrap tab is fully shown, call codemirror refresh(). //Also, if you use jquery-UI, it gonna be different here. $('.nav-tabs a').on('shown.bs.tab', function() { cm1.refresh(); cm2.refresh(); }); cm1 = CodeMirror.fromTextArea(document.getElementById("tab1Content"), { lineNumbers: true }); cm2 = CodeMirror.fromTextArea(document.getElementById("tab2Content"), { lineNumbers: true }); }); 
+1
source

Why not just set a timeout? .. just execute this code when the button is clicked:

 update_mirror = function() { var codeMirrorContainer = $sec_tab.find(".CodeMirror")[0]; if (codeMirrorContainer && codeMirrorContainer.CodeMirror) { codeMirrorContainer.CodeMirror.refresh(); } } // Attention! magic! setTimeout(update_mirror, 100); 

It helped me a lot when I fought this issue. Thanks to Sekario Shin , he saved me time.

0
source

Source: https://habr.com/ru/post/977025/


All Articles