2015-07-21 48 views
1

我刚刚将CodeMirror(带有一些插件)作为JSF 2.0复合组件(请参阅下面的代码)实现。只要组件没有放置在某个标签或对话框中(只是在页面加载后不可见),该组件才能正常工作。在制表符或对话框中,看起来像组件被渲染,但内容和行号在组件被点击之前不可见。作为JSF 2.0复合组件的CodeMirror无法在选项卡或对话框中正确呈现

点击之前: 点击enter image description here

后: enter image description here

这里是我的JSF复合组件模板代码:

<!-- INTERFACE --> 
<cc:interface> 
    <cc:attribute name="styleClass" type="java.lang.String" required="true" /> 
    <cc:attribute name="value" type="java.lang.Object" /> 
    <cc:attribute name="converter" type="java.lang.String" /> 
    <cc:attribute name="mode" type="java.lang.String" /> 
    <cc:attribute name="theme" type="java.lang.String" default="eclipse" /> 
    <cc:attribute name="lineNumbers" type="java.lang.String" default="false" /> 
    <cc:attribute name="matchBrackets" type="java.lang.String" default="false" /> 
    <cc:attribute name="matchTags" type="java.lang.String" default="false" /> 
    <cc:attribute name="closeBrackets" type="java.lang.String" default="false" /> 
    <cc:attribute name="closeTag" type="java.lang.String" default="false" /> 
    <cc:attribute name="activeLine" type="java.lang.String" default="false" /> 
    <cc:attribute name="indentUnit" type="java.lang.Integer" default="2" /> 
    <cc:attribute name="smartIndent" type="java.lang.Boolean" default="true" /> 
    <cc:attribute name="readOnly" type="java.lang.Boolean" default="false" /> 
    <cc:attribute name="electricChars" type="java.lang.Boolean" default="true" /> 
    <cc:attribute name="lineWrapping" type="java.lang.Boolean" default="false" /> 
    <cc:attribute name="firstLineNumber" type="java.lang.Integer" default="1" /> 
    <cc:attribute name="tabIndex" type="java.lang.Integer" default="0" /> 
    <cc:attribute name="undoDepth" type="java.lang.Integer" default="40" /> 
    <cc:attribute name="pollInterval" type="java.lang.Integer" default="100" /> 
    <cc:attribute name="extraKeys" type="java.lang.String" default="{}" /> 
</cc:interface> 

<!-- IMPLEMENTATION --> 
<cc:implementation> 

<!-- required imports --> 

<h:inputTextarea id="cmTextArea" value="#{cc.attrs.value}" 
    styleClass="#{cc.attrs.styleClass}"> 
    <c:if test="#{not empty cc.attrs.converter}"> 
     <f:converter converterId="#{cc.attrs.converter}" /> 
    </c:if> 
</h:inputTextarea> 

<script type="text/javascript"> 
    $(function() { 
     var cmTextArea = $('.#{cc.attrs.styleClass}'), 
     myCodeMirror = CodeMirror.fromTextArea(cmTextArea[0], { 
      value: cmTextArea.val(), 
      mode: '#{cc.attrs.mode}', 
      theme: '#{cc.attrs.theme}', 
      lineNumbers: #{cc.attrs.lineNumbers}, 
      matchBrackets: '#{cc.attrs.matchBrackets}', 
      matchTags: {bothTags: #{cc.attrs.matchTags}}, 
      autoCloseBrackets: #{cc.attrs.closeBrackets}, 
      autoCloseTags: #{cc.attrs.closeTag}, 
      styleActiveLine: #{cc.attrs.activeLine}, 
      indentUnit: #{cc.attrs.indentUnit}, 
      smartIndent: #{cc.attrs.smartIndent}, 
      readOnly: #{cc.attrs.readOnly}, 
      electricChars: #{cc.attrs.electricChars}, 
      lineWrapping: #{cc.attrs.lineWrapping}, 
      firstLineNumber: #{cc.attrs.firstLineNumber}, 
      tabindex: #{cc.attrs.tabIndex}, 
      undoDepth: #{cc.attrs.undoDepth}, 
      pollInterval: #{cc.attrs.pollInterval}, 
      extraKeys: #{cc.attrs.extraKeys} 
     }); 
    }); 

</script> 

使用复合材料部件的例子:

<t:codeMirror mode="text/xml" theme="cobalt" 
       value="#{bean.content}" tabIndex="1" lineNumbers="true" 
       converter="escapeConverter" electricChars="true" lineWrapping="true" 
       extraKeys="{ 'F11': function(cm) {cm.setOption('fullScreen', !cm.getOption('fullScreen'));}, 'Ctrl-J': 'toMatchingTag','Ctrl-Space': 'autocomplete' }" 
       matchBrackets="true" closeBrackets="true" matchTags="true" 
       closeTag="true" styleClass="sampleClass" /> 

正如我所说,我不明白,为什么没有内容显示(立即)在我的组件(没有点击它),放在一个(第二 - 在页面加载不可见)选项卡,而组件,放置在Primefaces之外'tabView被正确渲染(带有内容和行号)。

任何帮助将不胜感激。谢谢!

编辑: 我想我需要调用refresh时codemirror对象变得可见(上标签显示)。太好了,它可以这样工作,但是有什么办法可以将这个调用包含在复合组件中吗?

回答

3

请参阅CodeMirror的refresh方法。编辑器需要可见才能绘制自己,并且如果将其初始化为隐藏元素,则必须在第一次变为可见时呼叫refresh

+0

好吧,我添加了一个'refresh'调用时,第二个标签(p:tabView)变为活动(在标签显示),它的工作原理。问题是我必须在每次使用我的复合组件时再创建一个JS函数。有没有办法在组件实现中包含该调用? – peterremec

+0

不幸的是,不,我们一直无法找到一种理智的方式来在给定的DOM元素变得可见时得到通知。 – Marijn

+0

我猜我认为...无论如何,感谢您的帮助。现在,我将打开这个问题并将您的答案标记为有用。 – peterremec