2014-10-21 5 views
6

У меня довольно сложная страница, где у меня есть несколько экземпляров CodeMirror в скрытых вкладках внутри вкладок. Чтобы сделать его еще более сложным, я помню последние активные вкладки.Закладки Bootstrap с CodeMirror

Я смог получить его половина работает (http://codepen.io/anon/pen/LheaF) эти проблемы с закладками Второй Редактор:

  1. погрузкой Вторые вкладки перед основными вкладками Code Mirror была нажата. Когда вы нажмете вкладку «Зеркало кода», она не загрузит редактор правильно, пока вы не нажмете дважды.
  2. Я хочу, чтобы второй вкладки вызывали метод refresh(), если он уже был инициирован, как и для главного редактора.
  3. Bug, где его дублируют вторичные редакторы

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

ответ

5

Проблемы:

  1. это может случиться так, что вы создаете CodeMirror на элемент, который не виден (один из его родителей имеет дисплей: нет). Это нарушает различные расчеты, проведенные CodeMirror
  2. , получив экземпляр CodeMirror прямо из контейнера элемента CodeMirror позволяет вызвать обновления каждый раз, когда вы хотите (находя .CodeMirror рядом с textarea)
  3. фиксируется как побочный эффект 2.

увидеть обновленную версию здесь: http://codepen.io/lloiser/pen/arBkv

вы можете увидеть мои изменения в codepen ищет // --> комментарии

3

Рабочий раствор:http://codepen.io/anon/pen/hupwy

я обратился вопросы 2 и 3, как я не мог воспроизвести 1.

I использовала хэш-таблицу для хранения второго редактора объектов CodeMirror. Затем я изменил существующий код mainEditor, чтобы обновить объекты, если они уже существуют. не

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

Я не очень хорошо разбираюсь в CodeMirror так что это может быть не самым элегантным решением, но похоже, что приведенные выше код предотвращает дубликаты вы видели. Надеюсь это поможет.

0

Почему не просто установить тайм-аут .. только EXEC этот код при закладке щелкнул:

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

Это помогло мне много в то время как у меня был бой с этой проблемой. Благодаря Sekaryo Shin он спас мне время.

1

если проблема возникает, когда codemirror отображает содержимое в скрытом div, почему бы просто не развернуть все вкладки div, а затем вызвать codemirror, а затем скрыть ненужную вкладку?

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> 

хорошо работает для меня !!

0

HTML

Вот самозагрузки вкладка кадр, если вы используете JQuery-UI, это будет немного по-другому.

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