作为 JSF 2.0 复合组件的 CodeMirror 无法在选项卡或对话框中正确呈现
CodeMirror as a JSF 2.0 composite component doesn't render properly in tab or dialog
我刚刚将 CodeMirror(带有一些插件)实现为 JSF 2.0 复合组件(参见下面的代码)。只要该组件未放置在某些选项卡或对话框中(任何在页面加载后不可见的内容),该组件就可以正常工作。在选项卡或对话框中时,组件似乎已呈现,但内容和行号在单击组件之前不可见。
点击前:
点击后:
这是我的 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 正确呈现(包含内容和行号)。
如有任何帮助,我们将不胜感激。谢谢!
编辑:
我想我需要在 codemirror 对象可见时调用 refresh
(在选项卡显示上)。太好了,它是这样工作的,但是有什么方法可以将该调用包含在复合组件本身中吗?
参见 CodeMirror 的 refresh
方法。编辑器需要可见才能绘制自身,如果在隐藏元素中初始化它,则必须在它第一次可见时调用 refresh
。
我刚刚将 CodeMirror(带有一些插件)实现为 JSF 2.0 复合组件(参见下面的代码)。只要该组件未放置在某些选项卡或对话框中(任何在页面加载后不可见的内容),该组件就可以正常工作。在选项卡或对话框中时,组件似乎已呈现,但内容和行号在单击组件之前不可见。
点击前:
点击后:
这是我的 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 正确呈现(包含内容和行号)。
如有任何帮助,我们将不胜感激。谢谢!
编辑:
我想我需要在 codemirror 对象可见时调用 refresh
(在选项卡显示上)。太好了,它是这样工作的,但是有什么方法可以将该调用包含在复合组件本身中吗?
参见 CodeMirror 的 refresh
方法。编辑器需要可见才能绘制自身,如果在隐藏元素中初始化它,则必须在它第一次可见时调用 refresh
。