2014-10-21 18 views
6

Mam dość złożoną stronę, na której mam wiele instancji CodeMirror w ukrytych zakładkach w kartach. Aby to uczynić jeszcze bardziej złożonym, pamiętam ostatnie aktywne zakładki.Zakładka Bootstrap z CodeMirror

jakie udało się uzyskać to połowa pracy (http://codepen.io/anon/pen/LheaF) są problemy z kartami drugie Redaktor:

  1. Jego załadunek drugim wypustki przed głównymi kartami codemirror został wciśnięty. Po kliknięciu zakładki Kopiuj kod nie ładuje się poprawnie edytora, dopóki nie klikniesz dwa razy.
  2. Chcę, aby drugie zakładki wywoływały metodę refresh(), jeśli już została zainicjowana, tak jak robię to dla głównego edytora.
  3. Bug, gdzie jego powielania wtórnego redaktorów

(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); 

Odpowiedz

5

Problemy:

  1. może się zdarzyć, że należy utworzyć CodeMirror na element, który nie jest widoczny (jeden z rodziców jest to ma display: none). To łamie różnych obliczeń wykonanych przez CodeMirror
  2. dostając instancję CodeMirror prawo od elementu pojemnika CodeMirror pozwala nam zadzwonić odświeżania za każdym razem chcesz (poprzez znalezienie .CodeMirror obok textarea)
  3. ustalona jako efekt uboczny 2.

zobaczyć zaktualizowaną wersję tutaj: http://codepen.io/lloiser/pen/arBkv

można zobaczyć moje zmiany w codepen szuka // --> komentarzach

3

roztwór roboczy:http://codepen.io/anon/pen/hupwy

skierowałem kwestie 2 i 3, nie mogłem replikowane 1.

I używana tablica asocjacyjna do przechowywania drugiego edytora obiektów CodeMirror. Następnie zmodyfikowałem twój istniejący kod mainEditor, aby odświeżyć obiekty, jeśli już istnieją.

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}); 
    } 
} 

Nie jestem dobrze zorientowany w CodeMirror więc może to nie być najbardziej eleganckie rozwiązanie, ale wygląda na to powyższy kod zapobiega duplikaty pan widzi. Mam nadzieję że to pomoże.

0

Dlaczego nie wystarczy, aby ustawić limit czasu .. po prostu exec ten kod kiedy kliknął zakładka:

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

To bardzo mi pomogło, a ja miałem walkę z tym problemem. Dzięki Sekaryo Shin uratował mi czas.

1

jeśli problem występuje, gdy codemirror renderuje zawartość w ukrytym div, dlaczego nie po prostu diplay wszystkich div panelu kartę, a następnie wywołać codemirror, a następnie ukryć niepotrzebną kartę?

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> 

SCENARIUSZ:

<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> 

działa dobrze dla mnie !!

0

HTML

Oto bootstrap rama zakładka, jeśli używasz jQuery UI, to będzie trochę inaczej.

<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's refresh(). 
    //Also, if you use jquery-UI, it's 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 
    }); 
});