8 Replies Latest reply on May 19, 2008 8:06 PM by Dmitry Shultz

    Encoding, again

    Fab Mars Novice

      Hello
      I'm still stuggling with my custom JSF component (non ajax). I'm on JSF 1.2, Facelets, RF 3.2.0 SR1, and Glassfish v2.

      My issue is very similar to rendering a simple HtmlOutputLink. I need to render some URI attribute during my component rendering phase.

      If you look at the source code of JSF RI in OutputLinkRenderer, you see the URI to render is built using a StringBuffer and simple ?, &, = appended between its params. Then the resulting URI is passed into context.getExternalContext() .encodeResourceURL() before being output using writer.writeURIAttribute().

      If I do *exactly* the same in my custom component, I get an error page from the RF filter (the Neko one I guess). It seems the &'s in my URI are the cause of the problem. How can both behaviors be different ?

      Can you guys at RF please explain me what I have to do to properly let RF render without error a URI attribute in a custom JSF component ??

      Thanks very much in advance.

        • 1. Re: Encoding, again
          Sergey Smirnov Master

          any prove about your "*exactly*"? Code snippets, for example.

          • 2. Re: Encoding, again
            Fab Mars Novice

            Hello Sergey. Thanks for replying.
            Actually I wanna make it clear I'm not sure whether RF is the cause of my issues, or if it's myself. Probably myself despite the *exactly* :) Until now RF has proven to be extremely useful and reliable with me.

            Now the code of my renderer, interesting parts in bold. In a nutshell, this is a custom FCK Editor component, like the FCK doc says, you need to output 2 hidden components to configure the editor (begining of the code) and 1 iframe for the display of the editor (middle). Fallback case is a textarea (end of the code).

             public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException {
             super.encodeEnd(facesContext, uiComponent);
            
             ResponseWriter writer = facesContext.getResponseWriter();
            
             HtmlFckEditor fckEditorComponent = (HtmlFckEditor) uiComponent;
             String clientId = fckEditorComponent.getClientId(facesContext);
            
            
             //the editor code
             writer.startElement("div", null);
            
             String value = (String)fckEditorComponent.getValue();
            
             if(isCompatible(facesContext)) {
            
             //hidden input with original value
             writer.startElement("input", uiComponent);
             writer.writeAttribute("type", "hidden", null);
             writer.writeAttribute("id", clientId, null);
             writer.writeAttribute("name", clientId, null);
             writer.writeAttribute("value", value, null);
             writer.endElement("input");
            
             //config
             String configId = clientId + "___Config";
             writer.startElement("input", uiComponent);
             writer.writeAttribute("type", "hidden", null);
             writer.writeAttribute("id", configId, null);
             writer.writeAttribute("name", configId, null);
             writer.writeAttribute("value", getConfigUrl(fckEditorComponent), null);
             writer.endElement("input");
            
            
             //frame url
             String basePath = fckEditorComponent.getBasePath();
             if(basePath == null) {
             basePath = "/fckeditor/";
             }
             else {
             if(!basePath.startsWith("/")) {
             basePath = "/" + basePath;
             }
             if(!basePath.endsWith("/")) {
             basePath += "/";
             }
             }
             basePath = facesContext.getExternalContext().getRequestContextPath() + basePath;
            
            
            
            String frameLink = basePath + "editor/fckeditor.html?InstanceName=" + clientId;
             //toolbar
             String toolbarSet = fckEditorComponent.getToolbarSet();
             if(toolbarSet != null && toolbarSet.length() > 0) {
             frameLink += "&Toolbar=" + toolbarSet;
             }
            
             //iframe
             String frameId = clientId + "___Frame";
             writer.startElement("iframe", uiComponent);
             writer.writeAttribute("id", frameId, null);
            
             writer.writeURIAttribute("src", facesContext.getExternalContext() .encodeResourceURL(frameLink), null);
            
             String width = fckEditorComponent.getWidth();
             if(width == null) {
             width = "100%";
             }
             writer.writeAttribute("width", width, null);
            
             String height = fckEditorComponent.getHeight();
             if(height == null) {
             height = "100%";
             }
             writer.writeAttribute("height", height, null);
            
             writer.writeAttribute("frameborder", "no", null);
             writer.writeAttribute("scrolling", "no", null);
             writer.endElement("iframe");
            
             writer.write("\n");
            
             // Adding the onComplete callback
             writer.startElement("script", null);
             writer.writeAttribute("lang", "text/javascript", null);
             // Hidden iframe creation
             writer.writeText("function FCKeditor_OnComplete(editorInstance) { window.status = editorInstance.Description; }", null);
             writer.endElement("script");
             }
             else {
             //regular textarea
             writer.startElement("textarea", uiComponent);
             writer.writeAttribute("id", clientId, null);
             writer.writeAttribute("rows", "4", null);
             writer.writeAttribute("cols", "40", null);
             String style = "width: " + fckEditorComponent.getWidth() + "; height: " + fckEditorComponent.getHeight();
             writer.writeAttribute("style", style, null);
             writer.writeAttribute("wrap", "virtual", null);
             writer.writeText(value != null ? value : "", null);
             writer.endElement("textarea");
             }
             writer.endElement("div");
            
             writer.write("\n");
             }
            


            • 3. Re: Encoding, again
              Fab Mars Novice

              Excuse me for insisting, but I realized actually all URI outputs are now escaped the same way as my component: all ampersands are escaped to %26 when using the NEKO filter, producing non-useable URLs.

              Example:

              <h:outputLink value="http://www.google.com/search">
               <f:param name="hl" value="en"/>
               <f:param name="q" value="RichFaces"/>
               <f:param name="btnG" value="Google+Search"/>
               <f:param name="meta" value=""/>
              
               <h:outputText value="Search RF on Google"/>
              </h:outputLink>
              


              This code produces a wrong URL that Google will not be able to parse correctly when using the NEKO filter.
              However, when using the TIDY filter, the output produces useable links.

              Some side-effect happened between RF 3.1.x and 3.2.0 that made the NEKO filter totally useless in my opinion. Or is there a configuration thing I missed ?

              Please answer :)

              • 4. Re: Encoding, again
                Alexander Smirnov Master

                Sorry, it was a real bug. I have fixed it in the current development code. see http://jira.jboss.com/jira/browse/RF-3320

                • 5. Re: Encoding, again
                  Fab Mars Novice

                  Thanks a lot !

                  • 6. Re: Encoding, again
                    Dmitry Shultz Novice

                    Hey fabmars,

                    Can you please share your JSF enabled FCK component?
                    I will appreciate very much!

                    • 7. Re: Encoding, again
                      Fab Mars Novice

                      write to <my username here> at gmail.com and I'll give you.

                      • 8. Re: Encoding, again
                        Dmitry Shultz Novice

                        i've got the component from fabmars.

                        It is nicely packaged, has ant build script and all config files, provided with 'readme' email and it works very well!

                        Thanks a Lot Man!