View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.custom.tabbedpane;
20  
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Map;
26  
27  import javax.faces.application.ResourceDependency;
28  import javax.faces.application.ViewHandler;
29  import javax.faces.component.UIComponent;
30  import javax.faces.component.UIForm;
31  import javax.faces.component.UINamingContainer;
32  import javax.faces.component.behavior.ClientBehavior;
33  import javax.faces.component.behavior.ClientBehaviorHolder;
34  import javax.faces.context.FacesContext;
35  import javax.faces.context.ResponseWriter;
36  import javax.faces.event.ComponentSystemEvent;
37  import javax.faces.event.ComponentSystemEventListener;
38  import javax.faces.event.ListenerFor;
39  
40  import org.apache.myfaces.component.UserRoleUtils;
41  import org.apache.myfaces.shared_tomahawk.renderkit.ClientBehaviorEvents;
42  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
43  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
44  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRenderer;
45  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
46  import org.apache.myfaces.shared_tomahawk.renderkit.html.util.FormInfo;
47  import org.apache.myfaces.shared_tomahawk.renderkit.html.util.JavascriptUtils;
48  import org.apache.myfaces.shared_tomahawk.renderkit.html.util.ResourceUtils;
49  import org.apache.myfaces.tomahawk.application.PreRenderViewAddResourceEvent;
50  import org.apache.myfaces.tomahawk.util.TomahawkResourceUtils;
51  
52  /**
53   * @JSFRenderer
54   *   renderKitId = "HTML_BASIC" 
55   *   family = "javax.faces.Panel"
56   *   type = "org.apache.myfaces.TabbedPane"
57   * 
58   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
59   * @version $Revision: 783584 $ $Date: 2009-06-10 19:00:13 -0500 (miƩ, 10 jun 2009) $
60   */
61  @ResourceDependency(library="oam.custom.tabbedpane",name="defaultStyles.css")
62  @ListenerFor(systemEventClass=PreRenderViewAddResourceEvent.class)
63  public class HtmlTabbedPaneRenderer
64          extends HtmlRenderer implements ComponentSystemEventListener
65  {
66      private static final String HEADER_ROW_CLASS = "myFaces_pannelTabbedPane_HeaderRow";
67      private static final String ACTIVE_HEADER_CELL_CLASS = "myFaces_panelTabbedPane_activeHeaderCell";
68      private static final String INACTIVE_HEADER_CELL_CLASS = "myFaces_panelTabbedPane_inactiveHeaderCell";
69      private static final String DISABLED_HEADER_CELL_CLASS = "myFaces_panelTabbedPane_disabledHeaderCell";
70      private static final String EMPTY_HEADER_CELL_CLASS = "myFaces_panelTabbedPane_emptyHeaderCell";
71      private static final String SUB_HEADER_ROW_CLASS = "myFaces_pannelTabbedPane_subHeaderRow";
72      private static final String SUB_HEADER_CELL_CLASS = "myFaces_panelTabbedPane_subHeaderCell";
73      private static final String SUB_HEADER_CELL_CLASS_ACTIVE = "myFaces_panelTabbedPane_subHeaderCell_active";
74      private static final String SUB_HEADER_CELL_CLASS_INACTIVE = "myFaces_panelTabbedPane_subHeaderCell_inactive";
75      private static final String SUB_HEADER_CELL_CLASS_FIRST = "myFaces_panelTabbedPane_subHeaderCell_first";
76      private static final String SUB_HEADER_CELL_CLASS_LAST = "myFaces_panelTabbedPane_subHeaderCell_last";
77      private static final String CONTENT_ROW_CLASS = "myFaces_panelTabbedPane_contentRow";
78      private static final String TAB_PANE_CLASS = "myFaces_panelTabbedPane_pane";
79  
80      private static final String DEFAULT_BG_COLOR = "white";
81  
82      private static final String AUTO_FORM_SUFFIX = ".autoform";
83      private static final String TAB_DIV_SUFFIX = ".content";
84  
85      public void processEvent(ComponentSystemEvent event)
86      {
87          HtmlPanelTabbedPane tabbedPane = (HtmlPanelTabbedPane)event.getComponent();
88          if( tabbedPane.isClientSide() )
89          {
90              FacesContext facesContext = FacesContext.getCurrentInstance();
91              TomahawkResourceUtils.addOutputScriptResource(facesContext,
92                      "oam.custom.tabbedpane",
93                      "dynamicTabs.js");
94  
95              TomahawkResourceUtils.addInlineOutputStylesheetResource(facesContext,
96                      '#'+getTableStylableId(tabbedPane,facesContext)+" ."+ACTIVE_HEADER_CELL_CLASS+" input,\n" +
97                      '#'+getTableStylableId(tabbedPane,facesContext)+" ."+TAB_PANE_CLASS+",\n" +
98                      '#'+getTableStylableId(tabbedPane,facesContext)+" ."+SUB_HEADER_CELL_CLASS+"{\n"+
99                      "background-color:" + tabbedPane.getBgcolor()+";\n"+
100                     "}\n");
101         }
102     }
103 
104     public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException
105     {
106         // NoOp
107     }
108 
109     public boolean getRendersChildren()
110     {
111         return true;
112     }
113 
114     public void encodeChildren(FacesContext facescontext, UIComponent uicomponent) throws IOException
115     {
116         // NoOp
117     }
118 
119     public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException
120     {
121         RendererUtils.checkParamValidity(facesContext, uiComponent, HtmlPanelTabbedPane.class);
122         HtmlPanelTabbedPane tabbedPane = (HtmlPanelTabbedPane)uiComponent;
123         if (tabbedPane.getBgcolor() == null)
124         {
125             tabbedPane.setBgcolor(DEFAULT_BG_COLOR);
126         }
127 
128         //AddResource addResource = AddResourceFactory.getInstance(facesContext);
129 
130         //addResource.addStyleSheet(facesContext,AddResource.HEADER_BEGIN,
131         //                          HtmlTabbedPaneRenderer.class, "defaultStyles.css");
132 
133         //if( tabbedPane.isClientSide() ){
134         //        addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, HtmlTabbedPaneRenderer.class, "dynamicTabs.js");
135         //        addResource.addInlineStyleAtPosition(facesContext,AddResource.HEADER_BEGIN,
136         //                                             '#'+getTableStylableId(tabbedPane,facesContext)+" ."+ACTIVE_HEADER_CELL_CLASS+" input,\n" +
137         //                                             '#'+getTableStylableId(tabbedPane,facesContext)+" ."+TAB_PANE_CLASS+",\n" +
138         //                                             '#'+getTableStylableId(tabbedPane,facesContext)+" ."+SUB_HEADER_CELL_CLASS+"{\n"+
139         //                                             "background-color:" + tabbedPane.getBgcolor()+";\n"+
140         //                                             "}\n");
141         //}
142 
143 
144         ResponseWriter writer = facesContext.getResponseWriter();
145 
146         Map<String, List<ClientBehavior>> behaviors = tabbedPane.getClientBehaviors();
147         if (!behaviors.isEmpty())
148         {
149             ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
150         }
151         
152         for (UIComponent child : tabbedPane.getChildren())
153         {
154             if (child instanceof HtmlPanelTab)
155             {
156                 Map<String, List<ClientBehavior>> bh = ((HtmlPanelTab) child).getClientBehaviors();
157                 if (!bh.isEmpty())
158                 {
159                     ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
160                 }
161             }
162         }
163 
164         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
165 
166         int selectedIndex = tabbedPane.getSelectedIndex();
167 
168         FormInfo parentFormInfo = RendererUtils.findNestingForm(tabbedPane, facesContext);
169         if (parentFormInfo == null)
170         {
171             writeFormStart(writer, facesContext, tabbedPane);
172         }
173 
174         List children = tabbedPane.getChildren();
175 
176         if( tabbedPane.isClientSide() ){
177             List headerIDs = new ArrayList();
178             List tabIDs = new ArrayList();
179             for (int i = 0, len = children.size(); i < len; i++)
180             {
181                 UIComponent child = getUIComponent((UIComponent)children.get(i));
182                 if (child instanceof HtmlPanelTab && child.isRendered()){
183                     HtmlPanelTab tab = (HtmlPanelTab) child;
184                     tabIDs.add( child.getClientId(facesContext) + TAB_DIV_SUFFIX);
185                     if( ! isDisabled(facesContext, tab) )
186                         headerIDs.add( getHeaderCellID(tab, facesContext) );
187                 }
188             }
189 
190             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
191             writer.startElement(HTML.SCRIPT_ELEM, tabbedPane);
192             writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
193             writer.write('\n');
194 
195             writer.write( getHeaderCellsIDsVar(tabbedPane,facesContext)+"= new Array(" );
196             for(Iterator ids=headerIDs.iterator(); ids.hasNext();){
197                 String id = (String)ids.next();
198                 writer.write('"'+JavascriptUtils.encodeString( id )+'"');
199                 if( ids.hasNext() )
200                     writer.write(',');
201             }
202             writer.write( ");\n" ); // end Array
203 
204             writer.write( getTabsIDsVar(tabbedPane,facesContext)+"= new Array(" );
205             for(Iterator ids=tabIDs.iterator(); ids.hasNext();){
206                 String id = (String)ids.next();
207                 writer.write('"'+JavascriptUtils.encodeString( id )+'"');
208                 if( ids.hasNext() )
209                     writer.write(',');
210             }
211             writer.write( ");\n" ); // end Array
212 
213             writer.endElement(HTML.SCRIPT_ELEM);
214             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
215 
216             String submitFieldIDAndName = getTabIndexSubmitFieldIDAndName(tabbedPane, facesContext);
217             writer.startElement(HTML.INPUT_ELEM, tabbedPane);
218             writer.writeAttribute(HTML.ID_ATTR, submitFieldIDAndName, null);
219             writer.writeAttribute(HTML.NAME_ATTR, submitFieldIDAndName, null);
220             writer.writeAttribute(HTML.STYLE_ATTR, "display:none", null);
221             writer.endElement(HTML.INPUT_ELEM);
222         }
223 
224         writeTableStart(writer, facesContext, tabbedPane);
225         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
226         writer.startElement(HTML.TR_ELEM, tabbedPane);
227         writer.writeAttribute(HTML.CLASS_ATTR, HEADER_ROW_CLASS, null);
228 
229         //Tab headers
230         int tabIdx = 0;
231         int visibleTabCount = 0;
232         int visibleTabSelectedIdx = -1;
233         for (int i = 0, len = children.size(); i < len; i++)
234         {
235             UIComponent child = getUIComponent((UIComponent)children.get(i));
236             if (child instanceof HtmlPanelTab)
237             {
238                 if (child.isRendered())
239                 {
240                     writeHeaderCell(writer,
241                                     facesContext,
242                                     tabbedPane,
243                                     (HtmlPanelTab)child,
244                                     tabIdx,
245                                     visibleTabCount,
246                                     tabIdx == selectedIndex,
247                                     isDisabled(facesContext, (HtmlPanelTab)child));
248                     if (tabIdx == selectedIndex)
249                     {
250                         visibleTabSelectedIdx = visibleTabCount;
251                     }
252                     visibleTabCount++;
253                 }
254                 tabIdx++;
255             }
256         }
257 
258         //Empty tab cell on the right for better look
259         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
260         HtmlRendererUtils.writePrettyIndent(facesContext);
261         writer.startElement(HTML.TD_ELEM, tabbedPane);
262         writer.writeAttribute(HTML.CLASS_ATTR, EMPTY_HEADER_CELL_CLASS, null);
263         writer.write("&#160;");
264         writer.endElement(HTML.TD_ELEM);
265         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
266         writer.endElement(HTML.TR_ELEM);
267 
268         //Sub header cells
269         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
270         writer.startElement(HTML.TR_ELEM, tabbedPane);
271         writer.writeAttribute(HTML.CLASS_ATTR, SUB_HEADER_ROW_CLASS, null);
272         writeSubHeaderCells(writer, facesContext, tabbedPane, visibleTabCount, visibleTabSelectedIdx);
273         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
274         writer.endElement(HTML.TR_ELEM);
275 
276         //Tabs
277         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
278         writer.startElement(HTML.TR_ELEM, tabbedPane);
279         writer.writeAttribute(HTML.CLASS_ATTR, CONTENT_ROW_CLASS, null);
280         writer.startElement(HTML.TD_ELEM, tabbedPane);
281         writer.writeAttribute(HTML.COLSPAN_ATTR, Integer.toString(visibleTabCount + 1), null);
282         String tabContentStyleClass = tabbedPane.getTabContentStyleClass();
283         writer.writeAttribute(HTML.CLASS_ATTR, TAB_PANE_CLASS+(tabContentStyleClass==null ? "" : " "+tabContentStyleClass), null);
284 
285         writeTabsContents(writer, facesContext, tabbedPane, selectedIndex);
286 
287         writer.endElement(HTML.TD_ELEM);
288         writer.endElement(HTML.TR_ELEM);
289 
290         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
291         writer.endElement(HTML.TABLE_ELEM);
292 
293         if (parentFormInfo == null)
294         {
295             writeFormEnd(writer, facesContext);
296         }
297     }
298 
299 
300     public void decode(FacesContext facesContext, UIComponent uiComponent)
301     {
302         RendererUtils.checkParamValidity(facesContext, uiComponent, HtmlPanelTabbedPane.class);
303 
304         HtmlPanelTabbedPane tabbedPane = (HtmlPanelTabbedPane)uiComponent;
305 
306         Map paramMap = facesContext.getExternalContext().getRequestParameterMap();
307 
308         int tabIdx = 0;
309         List children = tabbedPane.getChildren();
310         for (int i = 0, len = children.size(); i < len; i++)
311         {
312             UIComponent child = getUIComponent((UIComponent)children.get(i));
313             if (child instanceof HtmlPanelTab)
314             {
315                 String paramName = tabbedPane.getClientId(facesContext) + "." + tabIdx;
316                 String paramValue = (String)paramMap.get(paramName);
317                 if (paramValue != null && paramValue.length() > 0)
318                 {
319                     tabbedPane.queueEvent(new TabChangeEvent(tabbedPane,
320                                                              tabbedPane.getSelectedIndex(),
321                                                              tabIdx));
322                     return;
323                 }
324                 tabIdx++;
325             }
326         }
327 
328         // No request due to a header button pressed.
329         // Restore a client-side switch
330         if( tabbedPane.isClientSide() ){
331             String clientSideIndex = (String)paramMap.get(getTabIndexSubmitFieldIDAndName(tabbedPane, facesContext));
332             if (clientSideIndex != null && clientSideIndex.length() > 0)
333             {
334                 tabbedPane.setSelectedIndex( Integer.parseInt(clientSideIndex) );
335                 return;
336             }
337         }
338     }
339 
340     protected void writeFormStart(ResponseWriter writer,
341                                   FacesContext facesContext,
342                                   UIComponent tabbedPane)
343         throws IOException
344     {
345         ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
346         String viewId = facesContext.getViewRoot().getViewId();
347         String actionURL = viewHandler.getActionURL(facesContext, viewId);
348 
349         //write out auto form
350         writer.startElement(HTML.FORM_ELEM, tabbedPane);
351         writer.writeAttribute(HTML.NAME_ATTR, tabbedPane.getClientId(facesContext) + AUTO_FORM_SUFFIX, null);
352         writer.writeAttribute(HTML.STYLE_ATTR, "display:inline", null);
353         writer.writeAttribute(HTML.METHOD_ATTR, "post", null);
354         writer.writeURIAttribute(HTML.ACTION_ATTR,
355                                  facesContext.getExternalContext().encodeActionURL(actionURL),
356                                  null);
357         writer.flush();
358     }
359 
360     protected String getHeaderCellsIDsVar(HtmlPanelTabbedPane tabbedPane, FacesContext facesContext){
361         return JavascriptUtils.getValidJavascriptName(
362                 "panelTabbedPane_"+tabbedPane.getClientId(facesContext)+"_HeadersIDs",
363                 false);
364     }
365 
366     protected String getTabsIDsVar(HtmlPanelTabbedPane tabbedPane, FacesContext facesContext){
367         return JavascriptUtils.getValidJavascriptName(
368                 "panelTabbedPane_"+tabbedPane.getClientId(facesContext)+"_IDs",
369                 false);
370     }
371 
372     protected String getDefaultActiveHeaderStyleClass(HtmlPanelTabbedPane tabbedPane, FacesContext facesContext){
373         return JavascriptUtils.getValidJavascriptName(
374                 "panelTabbedPane_"+tabbedPane.getClientId(facesContext)+"_ActiveStyle",
375                 false);
376     }
377 
378     protected String getHeaderClasses(HtmlPanelTabbedPane tabbedPane, HtmlPanelTab tab, String defaultClass, String userClass){
379         String headerCellClass = defaultClass;
380         String userTabStyleClass = tab.getStyleClass();
381 
382         if( userClass != null )
383             headerCellClass = headerCellClass + " " + userClass;
384 
385         if( userTabStyleClass != null )
386             headerCellClass = headerCellClass + " " + userTabStyleClass;
387 
388         return headerCellClass;
389     }
390 
391     protected void writeTableStart(ResponseWriter writer,
392                                    FacesContext facesContext,
393                                    HtmlPanelTabbedPane tabbedPane)
394         throws IOException
395     {
396         String oldBgColor = tabbedPane.getBgcolor();
397         tabbedPane.setBgcolor(null);
398 
399         writer.startElement(HTML.TABLE_ELEM, tabbedPane);
400         writer.writeAttribute(HTML.ID_ATTR, getTableStylableId(tabbedPane,facesContext), null);
401         String oldTabbedStyleClass = tabbedPane.getStyleClass();
402         tabbedPane.setStyleClass ((oldTabbedStyleClass == null) ? "myFaces_panelTabbedPane" : "myFaces_panelTabbedPane " + oldTabbedStyleClass);
403         writer.writeAttribute(HTML.CELLSPACING_ATTR, "0", null);
404         Map<String, List<ClientBehavior>> behaviors = tabbedPane.getClientBehaviors();
405         
406         if (behaviors != null && !behaviors.isEmpty())
407         {
408             HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, tabbedPane, behaviors);
409             HtmlRendererUtils.renderHTMLAttributes(writer, tabbedPane, HTML.TABLE_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS); 
410         }
411         else
412         {
413             HtmlRendererUtils.renderHTMLAttributes(writer, tabbedPane, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);            
414         }
415         writer.flush();
416 
417         tabbedPane.setBgcolor(oldBgColor);
418         tabbedPane.setStyleClass(oldTabbedStyleClass);
419     }
420 
421     /**
422      * As the colon (:) can't be used in CSS, transforms the id to make it safe to use for CSS. 
423      */
424     protected String getTableStylableId(HtmlPanelTabbedPane tabbedPane, FacesContext facesContext){
425         String originalID = tabbedPane.getClientId( facesContext );
426         return originalID.replace(':','_');
427     }
428 
429     protected String getTabIndexSubmitFieldIDAndName(HtmlPanelTabbedPane tabbedPane, FacesContext facesContext){
430         return tabbedPane.getClientId(facesContext)+"_indexSubmit";
431     }
432 
433     protected String getHeaderCellID(HtmlPanelTab tab, FacesContext facesContext){
434         return tab.getClientId(facesContext)+"_headerCell";
435     }
436 
437     // Do not change without modifying the .js
438     private String getSubHeaderCellID(HtmlPanelTab tab, FacesContext facesContext){
439         return tab.getClientId(facesContext)+"_headerCell_sub";
440     }
441 
442     protected void writeHeaderCell(ResponseWriter writer,
443                                    FacesContext facesContext,
444                                    HtmlPanelTabbedPane tabbedPane,
445                                    HtmlPanelTab tab,
446                                    int tabIndex,
447                                    int visibleTabIndex,
448                                    boolean active,
449                                    boolean disabled)
450         throws IOException
451     {
452         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
453         HtmlRendererUtils.writePrettyIndent(facesContext);
454         writer.startElement(HTML.TD_ELEM, tabbedPane);
455         writer.writeAttribute(HTML.ID_ATTR, getHeaderCellID(tab, facesContext), null);
456 
457         if (disabled)
458         {
459             String disabledClass = tabbedPane.getDisabledTabStyleClass();
460             writer.writeAttribute(HTML.CLASS_ATTR,
461                                   DISABLED_HEADER_CELL_CLASS + (disabledClass==null ? "" : ' '+disabledClass),
462                                   null);
463         }
464         else{
465             if (active)
466             {
467                 writer.writeAttribute(HTML.CLASS_ATTR,
468                                       getHeaderClasses(tabbedPane, tab, ACTIVE_HEADER_CELL_CLASS, tabbedPane.getActiveTabStyleClass()),
469                                       null);
470             }
471             else
472             {
473                 writer.writeAttribute(HTML.CLASS_ATTR,
474                                       getHeaderClasses(tabbedPane, tab, INACTIVE_HEADER_CELL_CLASS, tabbedPane.getInactiveTabStyleClass()),
475                                       null);
476             }
477         }
478       
479         if (tab.getStyle() != null) {
480             writer.writeAttribute(HTML.STYLE_ATTR, tab.getStyle(), null);
481         }
482 
483         String label = tab.getLabel();
484         if (label == null || label.length() == 0)
485         {
486             label = "Tab " + tabIndex;
487         }
488 
489         if (disabled) {
490             writer.startElement(HTML.LABEL_ELEM, tabbedPane);
491             // writer.writeAttribute(HTML.NAME_ATTR, tabbedPane.getClientId(facesContext) + "." + tabIndex, null); // Usefull ?
492             writer.writeText(label, null);
493             writer.endElement(HTML.LABEL_ELEM);
494         } else {
495             // Button
496             writer.startElement(HTML.INPUT_ELEM, tabbedPane);
497             writer.writeAttribute(HTML.TYPE_ATTR, "submit", null);
498             writer.writeAttribute(HTML.NAME_ATTR, tabbedPane.getClientId(facesContext) + "." + tabIndex, null);
499             writer.writeAttribute(HTML.VALUE_ATTR, label, null);
500             if( tabbedPane.isClientSide() ){
501                 String activeUserClass = tabbedPane.getActiveTabStyleClass();
502                 String inactiveUserClass = tabbedPane.getInactiveTabStyleClass();
503                 String activeSubStyleUserClass = tabbedPane.getActiveSubStyleClass();
504                 String inactiveSubStyleUserClass = tabbedPane.getInactiveSubStyleClass();
505                 
506                 String serverSideScript = "return myFaces_showPanelTab("
507                     +tabIndex+",'"+getTabIndexSubmitFieldIDAndName(tabbedPane, facesContext)+"',"
508                     +'\''+getHeaderCellID(tab, facesContext)+"','"+tab.getClientId(facesContext) + TAB_DIV_SUFFIX +"',"
509                     +getHeaderCellsIDsVar(tabbedPane,facesContext)+','+getTabsIDsVar(tabbedPane,facesContext)+','
510                     + (activeUserClass==null ? "null" : '\''+activeUserClass+'\'')+','+ (inactiveUserClass==null ? "null" : '\''+inactiveUserClass+'\'')+','
511                     + (activeSubStyleUserClass==null ? "null" : '\''+activeSubStyleUserClass+'\'')+','+ (inactiveSubStyleUserClass==null ? "null" : '\''+inactiveSubStyleUserClass+'\'')+");";
512                 
513                 Map<String, List<ClientBehavior>> behaviors = tab.getClientBehaviors();
514                 HtmlRendererUtils.renderBehaviorizedAttribute(facesContext, writer, HTML.ONCLICK_ATTR, 
515                         tab, ClientBehaviorEvents.CLICK, null, behaviors, HTML.ONCLICK_ATTR, 
516                         (String) tab.getAttributes().get(HTML.ONCLICK_ATTR), serverSideScript);
517                 
518                 //String onclickEvent = tab.getAttributes().get(HTML.ONCLICK_ATTR) != null ? (String) tab.getAttributes().get(HTML.ONCLICK_ATTR) : "";
519 
520                 //if(!("").equals(onclickEvent) && onclickEvent.charAt(onclickEvent.length()-1) !=  ';') {
521                 //    onclickEvent += ";";
522                 //}
523                 
524                 //writer.writeAttribute(HTML.ONCLICK_ATTR,
525                 //                      onclickEvent +
526                 //                      serverSideScript,
527                 //                      null);
528             }
529 
530             writer.endElement(HTML.INPUT_ELEM);
531         }
532         writer.endElement(HTML.TD_ELEM);
533     }
534 
535 
536     protected void writeSubHeaderCells(ResponseWriter writer,
537                                        FacesContext facesContext,
538                                        HtmlPanelTabbedPane tabbedPane,
539                                        int visibleTabCount,
540                                        int visibleTabSelectedIndex)
541             throws IOException
542     {
543         String activeSubStyleUserClass = tabbedPane.getActiveSubStyleClass();
544         String inactiveSubStyleUserClass = tabbedPane.getInactiveSubStyleClass();
545 
546         List children = tabbedPane.getChildren();
547         StringBuffer classes = new StringBuffer();
548         for (int i = 0, len = children.size(), renderedIndex = 0; i < len; i++)
549         {
550             UIComponent child = getUIComponent((UIComponent)children.get(i));
551             if (child instanceof HtmlPanelTab && child.isRendered())
552             {
553                 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
554                 HtmlRendererUtils.writePrettyIndent(facesContext);
555                 writer.startElement(HTML.TD_ELEM, tabbedPane);
556                 writer.writeAttribute(HTML.ID_ATTR, getSubHeaderCellID((HtmlPanelTab)child, facesContext), null);
557                 classes.setLength(0);
558                 classes.append(SUB_HEADER_CELL_CLASS);
559                 if( renderedIndex == 0 ){
560                     classes.append(' ');
561                     classes.append(SUB_HEADER_CELL_CLASS_FIRST);
562                 }
563                 if( renderedIndex == visibleTabCount ){
564                     classes.append(' ');
565                     classes.append(SUB_HEADER_CELL_CLASS_LAST);
566                 }
567                 if( renderedIndex == visibleTabSelectedIndex ){
568                     if( activeSubStyleUserClass != null ){
569                         classes.append(' ');
570                         classes.append(activeSubStyleUserClass);
571                     }
572                 }else if( inactiveSubStyleUserClass != null ){
573                     classes.append(' ');
574                     classes.append(inactiveSubStyleUserClass);
575                 }
576 
577                 classes.append(' ');
578                 classes.append(renderedIndex == visibleTabSelectedIndex ? SUB_HEADER_CELL_CLASS_ACTIVE : SUB_HEADER_CELL_CLASS_INACTIVE);
579 
580                 writer.writeAttribute(HTML.CLASS_ATTR, classes.toString(), null);
581 
582                 writer.write("&#160;");
583                 writer.endElement(HTML.TD_ELEM);
584 
585                 renderedIndex++;
586             }
587         }
588 
589         // Empty Cell Sub
590         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
591         HtmlRendererUtils.writePrettyIndent(facesContext);
592         writer.startElement(HTML.TD_ELEM, tabbedPane);
593         writer.writeAttribute(
594                 HTML.CLASS_ATTR,
595                 SUB_HEADER_CELL_CLASS+' '+SUB_HEADER_CELL_CLASS_LAST
596                 +(inactiveSubStyleUserClass != null ? ' '+inactiveSubStyleUserClass : ""),
597                 null);
598         writer.write("&#160;");
599         writer.endElement(HTML.TD_ELEM);
600     }
601 
602     protected void writeTabsContents(ResponseWriter writer, FacesContext facesContext, HtmlPanelTabbedPane tabbedPane,
603                                      int selectedIndex) throws IOException {
604         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
605 
606         int tabIdx = 0;
607         List children = tabbedPane.getChildren();
608         for (int i = 0, len = children.size(); i < len; i++) {
609             UIComponent child = getUIComponent((UIComponent) children.get(i));
610             if (child instanceof HtmlPanelTab) {
611                 String activeTabVar = tabbedPane.getActiveTabVar();
612                 if (activeTabVar != null) {
613                     Map requestMap = facesContext.getExternalContext().getRequestMap();
614                     requestMap.put(activeTabVar, Boolean.valueOf(tabIdx == selectedIndex));
615                 }
616 
617                 HtmlPanelTab tab = (HtmlPanelTab)child;
618                 writer.startElement(HTML.DIV_ELEM, tabbedPane);
619                writer.writeAttribute(HTML.ID_ATTR, tab.getClientId(facesContext) + TAB_DIV_SUFFIX, null);
620                 // the inactive tabs are hidden with a div-tag
621                 if (tabIdx != selectedIndex) {
622                     writer.writeAttribute(HTML.STYLE_ATTR, "display:none", null);
623                 }
624                 if (tabbedPane.isClientSide() || selectedIndex == tabIdx) {
625                   // render all content in client side mode or only the selected in server side mode
626                   RendererUtils.renderChild(facesContext, child);
627                 }
628                 writer.endElement(HTML.DIV_ELEM);
629 
630                 tabIdx++;
631                 if (activeTabVar != null) {
632                     Map requestMap = facesContext.getExternalContext().getRequestMap();
633                     requestMap.remove(tabbedPane.getActiveTabVar());
634                 }
635             } else {
636                 RendererUtils.renderChild(facesContext, child);
637             }
638         }
639    }
640 
641     private UIComponent getUIComponent(UIComponent uiComponent)
642     {
643         /* todo: handle forms other than UIForm */
644         if (uiComponent instanceof UIForm || uiComponent instanceof UINamingContainer)
645         {
646             List children = uiComponent.getChildren();
647             for (int i = 0, len = children.size(); i < len; i++)
648             {
649                 uiComponent = getUIComponent((UIComponent)children.get(i));
650             }
651         }
652         return uiComponent;
653     }
654 
655     protected void writeFormEnd(ResponseWriter writer,
656                                 FacesContext facesContext)
657         throws IOException
658     {
659         //write state marker
660         ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
661         viewHandler.writeState(facesContext);
662 
663         writer.endElement(HTML.FORM_ELEM);
664     }
665 
666     protected boolean isDisabled(FacesContext facesContext, HtmlPanelTab tab)
667     {
668         return !UserRoleUtils.isEnabledOnUserRole(tab) || tab.isDisabled();
669     }
670 }