Search code examples
formsjsfeditortinymcefacelets

Why <h:outputScript> does not work inside <h:form>


I am using JSF 2.1. I'm trying to use TinyEditor on a <h:inputTextarea>. Here is my code,

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<h:head>

    <h:outputStylesheet library="css" name="editor_style.css" />
    <h:outputStylesheet library="css" name="css/main.css" />
    <h:outputStylesheet library="css" name="css/dropdown.css" />    
    <h:outputScript name="js/tinyeditor.js"></h:outputScript>
</h:head>

<h:body>
    <div class="content">
        <ui:include src="/template/layout/commonLayout.xhtml" />
        <ui:include src="/template/layout/menu.xhtml" />
        <h:form>
            <div class="quick_links">
                <div class="q_title">                   
                </div>
                <div class="q_window">
                    <div class="q_top"></div>
                    <div class="q_main">

                        <h:inputTextarea value="#{EditorBean.value}" id="input"
                            style="width:100%; height:300px;">Sample FAQ</h:inputTextarea>

                        <h:outputScript>                        
                new TINY.editor.edit('editor',{
                    id:'input',
                    width:945,
                    height:175,
                    cssclass:'te',
                    controlclass:'tecontrol',
                    rowclass:'teheader',
                    dividerclass:'tedivider',
                    controls:['bold','italic','underline','strikethrough','|','subscript','superscript','|',
                              'orderedlist','unorderedlist','|','outdent','indent','|','leftalign',
                              'centeralign','rightalign','blockjustify','|','unformat','|','undo','redo','n',
                              'font','size','style','|','hr','link','unlink'],
                    footer:true,
                    fonts:['Verdana','Arial','Georgia','Trebuchet MS'],
                    xhtml:true,
                    cssfile:'style.css',
                    bodyid:'editor',
                    footerclass:'tefooter',
                    toggle:{text:'Source',activetext:'HTML',cssclass:'toggle'},
                    resize:{cssclass:'resize'}
                });
               </h:outputScript>

                    </div>
                    <div class="q_bottom"></div>
                </div>
                <h:commandButton value="Savebutton" action="#{EditorBean.test}"></h:commandButton>
            </div>
            <div class="push"></div>
        </h:form>
    </div>


</h:body>
</html>

If I remove the <h:form> tag, then only editor gets displayed, but the <h:commandButton> doesn't work. If I keep the <h:form> tag, then the <h:commandButton> works, but the TinyEditor editor does not get initialized.

How is this caused and how can I solve it?


Solution

  • The <h:outputScript> works perfectly fine. The concrete problem is just in your own JavaScript code. You specified an ID of "input" in the TinyEditor configuration script:

    id:'input',
    

    However there is no such HTML element with that ID in the JSF-generated HTML output. Yes, you should be looking at the JSF-generated HTML output, because that's basically all what the browser is retrieving. JavaScript does not run in webserver, but in the webbrowser and sees the JSF-generated HTML output only. Rightclick page in browser and do View Source to see it yourself as well.

    The generated ID of the <h:inputTextarea> has in this particular construct the ID of the <h:form> prepended. In your particular case, you didn't specify any ID for the <h:form>, so JSF will autogenerate one like so j_id123 so that the HTML element ID of the <textarea> as generated by <h:inputTextarea> will become j_id123:input. You need to specify exactly that ID in the TinyEditor configuration script.

    However, better is to specify a fixed ID on the <h:form>, as the autogenerated ID may change whenever you add/remove components to the view.

    <h:form id="form">
        <h:inputTextarea id="input" />
        ...
    

    This way the generated <textarea> will get an ID of form:input. Then you can just use it in the TinyEditor configuration script:

    id:'form:input',