001 package org.apache.myfaces.tobago.renderkit.html; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020 import org.apache.commons.lang.StringUtils; 021 import org.apache.commons.logging.Log; 022 import org.apache.commons.logging.LogFactory; 023 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_FOCUS; 024 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_INLINE; 025 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_INNER_HEIGHT; 026 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_INNER_WIDTH; 027 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_LAYOUT_HEIGHT; 028 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_LAYOUT_WIDTH; 029 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE; 030 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE_BODY; 031 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE_HEADER; 032 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_TIP; 033 import static org.apache.myfaces.tobago.TobagoConstants.FACET_LAYOUT; 034 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_OUT; 035 import org.apache.myfaces.tobago.component.ComponentUtil; 036 import org.apache.myfaces.tobago.component.SupportsMarkup; 037 import org.apache.myfaces.tobago.component.UICommand; 038 import org.apache.myfaces.tobago.component.UIData; 039 import org.apache.myfaces.tobago.component.UIPage; 040 import org.apache.myfaces.tobago.context.ResourceManagerUtil; 041 import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey; 042 import org.apache.myfaces.tobago.renderkit.LayoutInformationProvider; 043 import org.apache.myfaces.tobago.renderkit.LayoutableRendererBase; 044 import org.apache.myfaces.tobago.renderkit.RenderUtil; 045 import org.apache.myfaces.tobago.renderkit.RendererBaseWrapper; 046 import org.apache.myfaces.tobago.util.LayoutUtil; 047 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter; 048 import org.apache.myfaces.tobago.webapp.TobagoResponseWriterWrapper; 049 050 import javax.faces.component.NamingContainer; 051 import javax.faces.component.UIComponent; 052 import javax.faces.component.UIInput; 053 import javax.faces.context.FacesContext; 054 import javax.faces.context.ResponseWriter; 055 import javax.faces.model.SelectItem; 056 import javax.faces.model.SelectItemGroup; 057 import java.io.IOException; 058 import java.util.Arrays; 059 import java.util.List; 060 import java.util.Locale; 061 import java.util.Map; 062 import java.util.StringTokenizer; 063 064 /* 065 * User: weber 066 * Date: Jan 11, 2005 067 * Time: 4:59:36 PM 068 */ 069 public final class HtmlRendererUtil { 070 071 private static final Log LOG = LogFactory.getLog(HtmlRendererUtil.class); 072 073 private HtmlRendererUtil() { 074 // to prevent instantiation 075 } 076 077 public static void renderFocusId(FacesContext facesContext, UIComponent component) 078 throws IOException { 079 080 if (ComponentUtil.getBooleanAttribute(component, ATTR_FOCUS)) { 081 UIPage page = ComponentUtil.findPage(facesContext, component); 082 String id = component.getClientId(facesContext); 083 if (!StringUtils.isBlank(page.getFocusId()) && !page.getFocusId().equals(id)) { 084 LOG.warn("page focusId = \"" + page.getFocusId() + "\" ignoring new value \"" 085 + id + "\""); 086 } else { 087 TobagoResponseWriter writer = HtmlRendererUtil.getTobagoResponseWriter(facesContext); 088 writer.writeJavascript("Tobago.focusId = '" + id + "';"); 089 } 090 } 091 } 092 093 public static void prepareRender(FacesContext facesContext, UIComponent component) { 094 // xxx find a better way for this question: isTobago or isLayoutable something like that. 095 LayoutableRendererBase layoutRendererBase = ComponentUtil.getRenderer(facesContext, component); 096 if (layoutRendererBase != null && !(layoutRendererBase instanceof RendererBaseWrapper)) { 097 createCssClass(facesContext, component); 098 layoutWidth(facesContext, component); 099 layoutHeight(facesContext, component); 100 } 101 } 102 103 public static HtmlStyleMap prepareInnerStyle(UIComponent component) { 104 HtmlStyleMap htmlStyleMap = new HtmlStyleMap(); 105 Integer innerSpaceInteger = (Integer) 106 component.getAttributes().get(ATTR_INNER_WIDTH); 107 if (innerSpaceInteger != null && innerSpaceInteger != -1) { 108 htmlStyleMap.put("width", innerSpaceInteger); 109 } 110 innerSpaceInteger = (Integer) 111 component.getAttributes().get(ATTR_INNER_HEIGHT); 112 if (innerSpaceInteger != null && innerSpaceInteger != -1) { 113 htmlStyleMap.put("height", innerSpaceInteger); 114 } 115 return htmlStyleMap; 116 } 117 118 119 public static void createCssClass(FacesContext facesContext, UIComponent component) { 120 String rendererName = getRendererName(facesContext, component); 121 if (rendererName != null) { 122 StyleClasses classes = StyleClasses.ensureStyleClasses(component); 123 classes.updateClassAttributeAndMarkup(component, rendererName); 124 } 125 } 126 127 public static String getRendererName(FacesContext facesContext, UIComponent component) { 128 final String rendererType = component.getRendererType(); 129 //final String family = component.getFamily(); 130 if (rendererType != null//&& !"facelets".equals(family) 131 ) { 132 LayoutableRendererBase layoutableRendererBase = ComponentUtil.getRenderer(facesContext, component); 133 if (layoutableRendererBase != null) { 134 return layoutableRendererBase.getRendererName(rendererType); 135 } 136 } 137 return null; 138 } 139 140 public static void writeLabelWithAccessKey(TobagoResponseWriter writer, LabelWithAccessKey label) 141 throws IOException { 142 int pos = label.getPos(); 143 String text = label.getText(); 144 if (pos == -1) { 145 writer.writeText(text); 146 } else { 147 writer.writeText(text.substring(0, pos)); 148 writer.startElement(HtmlConstants.U, null); 149 writer.writeText(Character.toString(text.charAt(pos))); 150 writer.endElement(HtmlConstants.U); 151 writer.writeText(text.substring(pos + 1)); 152 } 153 } 154 155 public static void setDefaultTransition(FacesContext facesContext, boolean transition) 156 throws IOException { 157 writeScriptLoader(facesContext, null, new String[]{"Tobago.transition = " + transition + ";"}); 158 } 159 160 public static void addClickAcceleratorKey( 161 FacesContext facesContext, String clientId, char key) 162 throws IOException { 163 addClickAcceleratorKey(facesContext, clientId, key, null); 164 } 165 166 public static void addClickAcceleratorKey( 167 FacesContext facesContext, String clientId, char key, String modifier) 168 throws IOException { 169 String str 170 = createOnclickAcceleratorKeyJsStatement(clientId, key, modifier); 171 writeScriptLoader(facesContext, null, new String[]{str}); 172 } 173 174 public static void addAcceleratorKey( 175 FacesContext facesContext, String func, char key) throws IOException { 176 addAcceleratorKey(facesContext, func, key, null); 177 } 178 179 public static void addAcceleratorKey( 180 FacesContext facesContext, String func, char key, String modifier) 181 throws IOException { 182 String str = createAcceleratorKeyJsStatement(func, key, modifier); 183 writeScriptLoader(facesContext, null, new String[]{str}); 184 } 185 186 public static String createOnclickAcceleratorKeyJsStatement( 187 String clientId, char key, String modifier) { 188 String func = "Tobago.clickOnElement('" + clientId + "');"; 189 return createAcceleratorKeyJsStatement(func, key, modifier); 190 } 191 192 public static String createAcceleratorKeyJsStatement( 193 String func, char key, String modifier) { 194 StringBuilder buffer = new StringBuilder(); 195 buffer.append("new Tobago.AcceleratorKey(function() {"); 196 buffer.append(func); 197 if (!func.endsWith(";")) { 198 buffer.append(';'); 199 } 200 buffer.append("}, \""); 201 buffer.append(key); 202 if (modifier != null) { 203 buffer.append("\", \""); 204 buffer.append(modifier); 205 } 206 buffer.append("\");"); 207 return buffer.toString(); 208 } 209 210 public static String getLayoutSpaceStyle(UIComponent component) { 211 StringBuilder sb = new StringBuilder(); 212 Integer space = LayoutUtil.getLayoutSpace(component, ATTR_LAYOUT_WIDTH, ATTR_LAYOUT_WIDTH); 213 if (space != null) { 214 sb.append(" width: "); 215 sb.append(space); 216 sb.append("px;"); 217 } 218 space = LayoutUtil.getLayoutSpace(component, ATTR_LAYOUT_HEIGHT, ATTR_LAYOUT_HEIGHT); 219 if (space != null) { 220 sb.append(" height: "); 221 sb.append(space); 222 sb.append("px;"); 223 } 224 return sb.toString(); 225 } 226 227 public static Integer getStyleAttributeIntValue(HtmlStyleMap style, String name) { 228 if (style == null) { 229 return null; 230 } 231 return style.getInt(name); 232 } 233 234 public static String getStyleAttributeValue(String style, String name) { 235 if (style == null) { 236 return null; 237 } 238 String value = null; 239 StringTokenizer st = new StringTokenizer(style, ";"); 240 while (st.hasMoreTokens()) { 241 String attribute = st.nextToken().trim(); 242 if (attribute.startsWith(name)) { 243 value = attribute.substring(attribute.indexOf(':') + 1).trim(); 244 } 245 } 246 return value; 247 } 248 249 250 public static void replaceStyleAttribute(UIComponent component, String styleAttribute, String value) { 251 HtmlStyleMap style = ensureStyleAttributeMap(component); 252 style.put(styleAttribute, value); 253 } 254 255 public static void replaceStyleAttribute(UIComponent component, String attribute, 256 String styleAttribute, String value) { 257 HtmlStyleMap style = ensureStyleAttributeMap(component, attribute); 258 style.put(styleAttribute, value); 259 } 260 261 public static void replaceStyleAttribute(UIComponent component, String styleAttribute, int value) { 262 HtmlStyleMap style = ensureStyleAttributeMap(component); 263 style.put(styleAttribute, value); 264 } 265 266 public static void replaceStyleAttribute(UIComponent component, String attribute, 267 String styleAttribute, int value) { 268 HtmlStyleMap style = ensureStyleAttributeMap(component, attribute); 269 style.put(styleAttribute, value); 270 271 } 272 273 private static HtmlStyleMap ensureStyleAttributeMap(UIComponent component) { 274 return ensureStyleAttributeMap(component, ATTR_STYLE); 275 } 276 277 private static HtmlStyleMap ensureStyleAttributeMap(UIComponent component, String attribute) { 278 final Map attributes = component.getAttributes(); 279 HtmlStyleMap style = (HtmlStyleMap) attributes.get(attribute); 280 if (style == null) { 281 style = new HtmlStyleMap(); 282 attributes.put(attribute, style); 283 } 284 return style; 285 } 286 287 public static String replaceStyleAttribute(String style, String name, 288 String value) { 289 style = removeStyleAttribute(style != null ? style : "", name); 290 return style + " " + name + ": " + value + ";"; 291 } 292 293 public static String removeStyleAttribute(String style, String name) { 294 if (style == null) { 295 return null; 296 } 297 String pattern = name + "\\s*?:[^;]*?;"; 298 return style.replaceAll(pattern, "").trim(); 299 } 300 301 public static void removeStyleAttribute(UIComponent component, String name) { 302 ensureStyleAttributeMap(component).remove(name); 303 } 304 305 /** 306 * @deprecated Please use StyleClasses.ensureStyleClasses(component).add(clazz); 307 */ 308 @Deprecated 309 public static void addCssClass(UIComponent component, String clazz) { 310 StyleClasses.ensureStyleClasses(component).addFullQualifiedClass(clazz); 311 } 312 313 public static void layoutWidth(FacesContext facesContext, UIComponent component) { 314 layoutSpace(facesContext, component, true); 315 } 316 317 public static void layoutHeight(FacesContext facesContext, UIComponent component) { 318 layoutSpace(facesContext, component, false); 319 } 320 321 public static void layoutSpace(FacesContext facesContext, UIComponent component, 322 boolean width) { 323 324 // prepare html 'style' attribute 325 Integer layoutSpace; 326 String layoutAttribute; 327 String styleAttribute; 328 if (width) { 329 layoutSpace = LayoutUtil.getLayoutWidth(component); 330 layoutAttribute = ATTR_LAYOUT_WIDTH; 331 styleAttribute = HtmlAttributes.WIDTH; 332 } else { 333 layoutSpace = LayoutUtil.getLayoutHeight(component); 334 layoutAttribute = ATTR_LAYOUT_HEIGHT; 335 styleAttribute = HtmlAttributes.HEIGHT; 336 } 337 int space = -1; 338 if (layoutSpace != null) { 339 space = layoutSpace.intValue(); 340 } 341 if (space == -1 && (!RENDERER_TYPE_OUT.equals(component.getRendererType()))) { 342 UIComponent parent = component.getParent(); 343 space = LayoutUtil.getInnerSpace(facesContext, parent, width); 344 if (space > 0 && !ComponentUtil.isFacetOf(component, parent)) { 345 component.getAttributes().put(layoutAttribute, Integer.valueOf(space)); 346 if (width) { 347 component.getAttributes().remove(ATTR_INNER_WIDTH); 348 } else { 349 component.getAttributes().remove(ATTR_INNER_HEIGHT); 350 } 351 } 352 } 353 if (space > 0) { 354 LayoutInformationProvider renderer = ComponentUtil.getRenderer(facesContext, component); 355 if (layoutSpace != null 356 || !ComponentUtil.getBooleanAttribute(component, ATTR_INLINE)) { 357 int styleSpace = space; 358 if (renderer != null) { 359 if (width) { 360 styleSpace -= renderer.getComponentExtraWidth(facesContext, component); 361 } else { 362 styleSpace -= renderer.getComponentExtraHeight(facesContext, component); 363 } 364 } 365 366 replaceStyleAttribute(component, styleAttribute, styleSpace); 367 368 } 369 UIComponent layout = component.getFacet(FACET_LAYOUT); 370 if (layout != null) { 371 int layoutSpace2 = LayoutUtil.getInnerSpace(facesContext, component, 372 width); 373 if (layoutSpace2 > 0) { 374 layout.getAttributes().put(layoutAttribute, Integer.valueOf(layoutSpace2)); 375 } 376 } 377 } 378 } 379 380 public static void createHeaderAndBodyStyles(FacesContext facesContext, UIComponent component) { 381 createHeaderAndBodyStyles(facesContext, component, true); 382 createHeaderAndBodyStyles(facesContext, component, false); 383 } 384 385 public static void createHeaderAndBodyStyles(FacesContext facesContext, UIComponent component, boolean width) { 386 LayoutInformationProvider renderer = ComponentUtil.getRenderer(facesContext, component); 387 HtmlStyleMap style = (HtmlStyleMap) component.getAttributes().get(ATTR_STYLE); 388 Integer styleSpace = null; 389 try { 390 styleSpace = style.getInt(width ? "width" : "height"); 391 } catch (Exception e) { 392 /* ignore */ 393 } 394 if (styleSpace != null) { 395 int bodySpace = 0; 396 int headerSpace = 0; 397 if (!width) { 398 if (renderer != null) { 399 headerSpace = renderer.getHeaderHeight(facesContext, component); 400 } 401 bodySpace = styleSpace - headerSpace; 402 } 403 HtmlStyleMap headerStyle = ensureStyleAttributeMap(component, ATTR_STYLE_HEADER); 404 HtmlStyleMap bodyStyle = ensureStyleAttributeMap(component, ATTR_STYLE_BODY); 405 if (width) { 406 headerStyle.put("width", styleSpace); 407 bodyStyle.put("width", styleSpace); 408 } else { 409 headerStyle.put("height", headerSpace); 410 bodyStyle.put("height", bodySpace); 411 } 412 } 413 } 414 415 /** 416 * @deprecated Please use StyleClasses.ensureStyleClasses(component).updateClassAttribute(renderer, component); 417 */ 418 @Deprecated 419 public static void updateClassAttribute(String cssClass, String rendererName, UIComponent component) { 420 throw new UnsupportedOperationException( 421 "Please use StyleClasses.ensureStyleClasses(component).updateClassAttribute(renderer, component)"); 422 } 423 424 /** 425 * @deprecated Please use StyleClasses.addMarkupClass() 426 */ 427 @Deprecated 428 public static void addMarkupClass(UIComponent component, String rendererName, 429 String subComponent, StringBuilder tobagoClass) { 430 throw new UnsupportedOperationException("Please use StyleClasses.addMarkupClass()"); 431 } 432 433 /** 434 * @deprecated Please use StyleClasses.addMarkupClass() 435 */ 436 @Deprecated 437 public static void addMarkupClass(UIComponent component, String rendererName, StyleClasses classes) { 438 classes.addMarkupClass(component, rendererName); 439 } 440 441 public static void addImageSources(FacesContext facesContext, TobagoResponseWriter writer, String src, String id) 442 throws IOException { 443 StringBuilder buffer = new StringBuilder(); 444 buffer.append("new Tobago.Image('"); 445 buffer.append(id); 446 buffer.append("','"); 447 buffer.append(ResourceManagerUtil.getImageWithPath(facesContext, src, false)); 448 buffer.append("','"); 449 buffer.append(ResourceManagerUtil.getImageWithPath(facesContext, createSrc(src, "Disabled"), true)); 450 buffer.append("','"); 451 buffer.append(ResourceManagerUtil.getImageWithPath(facesContext, createSrc(src, "Hover"), true)); 452 buffer.append("');"); 453 writer.writeJavascript(buffer.toString()); 454 } 455 456 public static String createSrc(String src, String ext) { 457 int dot = src.lastIndexOf('.'); 458 if (dot == -1) { 459 LOG.warn("Image src without extension: '" + src + "'"); 460 return src; 461 } else { 462 return src.substring(0, dot) + ext + src.substring(dot); 463 } 464 } 465 466 public static TobagoResponseWriter getTobagoResponseWriter(FacesContext facesContext) { 467 468 ResponseWriter writer = facesContext.getResponseWriter(); 469 if (writer instanceof TobagoResponseWriter) { 470 return (TobagoResponseWriter) writer; 471 } else { 472 return new TobagoResponseWriterWrapper(writer); 473 } 474 } 475 476 /** 477 * @deprecated use TobagoResponseWriter.writeJavascript() 478 */ 479 @Deprecated 480 public static void writeJavascript(ResponseWriter writer, String script) throws IOException { 481 startJavascript(writer); 482 writer.write(script); 483 endJavascript(writer); 484 } 485 486 /** 487 * @deprecated use TobagoResponseWriter.writeJavascript() 488 */ 489 @Deprecated 490 public static void startJavascript(ResponseWriter writer) throws IOException { 491 writer.startElement(HtmlConstants.SCRIPT, null); 492 writer.writeAttribute(HtmlAttributes.TYPE, "text/javascript", null); 493 writer.write("\n<!--\n"); 494 } 495 496 /** 497 * @deprecated use TobagoResponseWriter.writeJavascript() 498 */ 499 @Deprecated 500 public static void endJavascript(ResponseWriter writer) throws IOException { 501 writer.write("\n// -->\n"); 502 writer.endElement(HtmlConstants.SCRIPT); 503 } 504 505 public static void writeScriptLoader(FacesContext facesContext, String script) 506 throws IOException { 507 writeScriptLoader(facesContext, new String[]{script}, null); 508 } 509 510 public static void writeScriptLoader(FacesContext facesContext, String[] scripts, String[] afterLoadCmds) 511 throws IOException { 512 TobagoResponseWriter writer = HtmlRendererUtil.getTobagoResponseWriter(facesContext); 513 514 String allScripts = "[]"; 515 if (scripts != null) { 516 allScripts = ResourceManagerUtil.getScriptsAsJSArray(facesContext, scripts); 517 } 518 519 StringBuilder script = new StringBuilder(); 520 script.append("new Tobago.ScriptLoader(\n "); 521 script.append(allScripts); 522 523 if (afterLoadCmds != null && afterLoadCmds.length > 0) { 524 script.append(", \n"); 525 boolean first = true; 526 for (String afterLoadCmd : afterLoadCmds) { 527 String[] splittedStrings = StringUtils.split(afterLoadCmd, '\n'); // split on <CR> to have nicer JS 528 for (String splitted : splittedStrings) { 529 String cmd = StringUtils.replace(splitted, "\\", "\\\\"); 530 cmd = StringUtils.replace(cmd, "\"", "\\\""); 531 script.append(first ? " " : " + "); 532 script.append("\""); 533 script.append(cmd); 534 script.append("\"\n"); 535 first = false; 536 } 537 } 538 } 539 script.append(");"); 540 541 writer.writeJavascript(script.toString()); 542 } 543 544 public static void writeStyleLoader( 545 FacesContext facesContext, String[] styles) throws IOException { 546 TobagoResponseWriter writer = HtmlRendererUtil.getTobagoResponseWriter(facesContext); 547 548 StringBuilder builder = new StringBuilder(); 549 builder.append("Tobago.ensureStyleFiles(\n "); 550 builder.append(ResourceManagerUtil.getStylesAsJSArray(facesContext, styles)); 551 builder.append(");"); 552 writer.writeJavascript(builder.toString()); 553 } 554 555 public static String getTitleFromTipAndMessages(FacesContext facesContext, UIComponent component) { 556 String messages = ComponentUtil.getFacesMessageAsString(facesContext, component); 557 return HtmlRendererUtil.addTip(messages, component.getAttributes().get(ATTR_TIP)); 558 } 559 560 public static String addTip(String title, Object tip) { 561 if (tip != null) { 562 if (title != null && title.length() > 0) { 563 title += " :: "; 564 } else { 565 title = ""; 566 } 567 title += tip; 568 } 569 return title; 570 } 571 572 public static void renderSelectItems(UIInput component, List<SelectItem> items, Object[] values, 573 TobagoResponseWriter writer, FacesContext facesContext) throws IOException { 574 575 if (LOG.isDebugEnabled()) { 576 LOG.debug("value = '" + Arrays.toString(values) + "'"); 577 } 578 for (SelectItem item : items) { 579 if (item instanceof SelectItemGroup) { 580 writer.startElement(HtmlConstants.OPTGROUP, null); 581 writer.writeAttribute(HtmlAttributes.LABEL, item.getLabel(), true); 582 if (item.isDisabled()) { 583 writer.writeAttribute(HtmlAttributes.DISABLED, true); 584 } 585 SelectItem[] selectItems = ((SelectItemGroup) item).getSelectItems(); 586 renderSelectItems(component, Arrays.asList(selectItems), values, writer, facesContext); 587 writer.endElement(HtmlConstants.OPTGROUP); 588 } else { 589 writer.startElement(HtmlConstants.OPTION, null); 590 final Object itemValue = item.getValue(); 591 String formattedValue = RenderUtil.getFormattedValue(facesContext, component, itemValue); 592 writer.writeAttribute(HtmlAttributes.VALUE, formattedValue, true); 593 if (item instanceof org.apache.myfaces.tobago.model.SelectItem) { 594 String image = ((org.apache.myfaces.tobago.model.SelectItem) item).getImage(); 595 if (image != null) { 596 String imagePath = ResourceManagerUtil.getImageWithPath(facesContext, image); 597 writer.writeStyleAttribute("background-image: url('" + imagePath + "')"); 598 } 599 } 600 if (item instanceof SupportsMarkup) { 601 StyleClasses optionStyle = new StyleClasses(); 602 optionStyle.addMarkupClass((SupportsMarkup) item, getRendererName(facesContext, component), "option"); 603 writer.writeClassAttribute(optionStyle); 604 } 605 if (RenderUtil.contains(values, item.getValue())) { 606 writer.writeAttribute(HtmlAttributes.SELECTED, true); 607 } 608 if (item.isDisabled()) { 609 writer.writeAttribute(HtmlAttributes.DISABLED, true); 610 } 611 writer.writeText(item.getLabel()); 612 writer.endElement(HtmlConstants.OPTION); 613 } 614 } 615 } 616 617 public static String getComponentId(FacesContext context, UIComponent component, String componentId) { 618 UIComponent partiallyComponent = ComponentUtil.findComponent(component, componentId); 619 if (partiallyComponent != null) { 620 String clientId = partiallyComponent.getClientId(context); 621 if (partiallyComponent instanceof UIData) { 622 int rowIndex = ((UIData) partiallyComponent).getRowIndex(); 623 if (rowIndex >= 0 && clientId.endsWith(Integer.toString(rowIndex))) { 624 return clientId.substring(0, clientId.lastIndexOf(NamingContainer.SEPARATOR_CHAR)); 625 } 626 } 627 return clientId; 628 } 629 LOG.error("No Component found for id " + componentId); 630 return null; 631 } 632 633 public static String toStyleString(String key, Integer value) { 634 StringBuilder buf = new StringBuilder(); 635 buf.append(key); 636 buf.append(":"); 637 buf.append(value); 638 buf.append("px; "); 639 return buf.toString(); 640 } 641 642 public static String toStyleString(String key, String value) { 643 StringBuilder buf = new StringBuilder(); 644 buf.append(key); 645 buf.append(":"); 646 buf.append(value); 647 buf.append("; "); 648 return buf.toString(); 649 } 650 651 public static void renderTip(UIComponent component, TobagoResponseWriter writer) throws IOException { 652 Object objTip = component.getAttributes().get(ATTR_TIP); 653 if (objTip != null) { 654 writer.writeAttribute(HtmlAttributes.TITLE, String.valueOf(objTip), true); 655 } 656 } 657 658 public static void renderImageTip(UIComponent component, TobagoResponseWriter writer) throws IOException { 659 Object objTip = component.getAttributes().get(ATTR_TIP); 660 if (objTip != null) { 661 writer.writeAttribute(HtmlAttributes.ALT, String.valueOf(objTip), true); 662 } else { 663 writer.writeAttribute(HtmlAttributes.ALT, "", false); 664 } 665 } 666 667 public static String getJavascriptString(String str) { 668 if (str != null) { 669 return "\"" + str + "\""; 670 } 671 return null; 672 } 673 674 public static String getRenderedPartiallyJavascriptArray(FacesContext facesContext, UICommand command) { 675 if (command == null) { 676 return null; 677 } 678 String[] list = command.getRenderedPartially(); 679 StringBuilder strBuilder = new StringBuilder(); 680 strBuilder.append("["); 681 for (int i = 0; i < list.length; i++) { 682 if (i != 0) { 683 strBuilder.append(","); 684 } 685 strBuilder.append("\""); 686 strBuilder.append(HtmlRendererUtil.getComponentId(facesContext, command, list[i])); 687 strBuilder.append("\""); 688 } 689 strBuilder.append("]"); 690 return strBuilder.toString(); 691 } 692 693 public static String getJavascriptArray(String[] list) { 694 StringBuilder strBuilder = new StringBuilder(); 695 strBuilder.append("["); 696 for (int i = 0; i < list.length; i++) { 697 if (i != 0) { 698 strBuilder.append(","); 699 } 700 strBuilder.append("\""); 701 strBuilder.append(list[i]); 702 strBuilder.append("\""); 703 } 704 strBuilder.append("]"); 705 return strBuilder.toString(); 706 } 707 708 public static void removeStyleClasses(UIComponent cell) { 709 Object obj = cell.getAttributes().get(org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE_CLASS); 710 if (obj != null && obj instanceof StyleClasses && cell.getRendererType() != null) { 711 StyleClasses styleClasses = (StyleClasses) obj; 712 if (!styleClasses.isEmpty()) { 713 String rendererName = cell.getRendererType().substring(0, 1).toLowerCase(Locale.ENGLISH) 714 + cell.getRendererType().substring(1); 715 styleClasses.removeTobagoClasses(rendererName); 716 } 717 if (styleClasses.isEmpty()) { 718 cell.getAttributes().remove(org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE_CLASS); 719 } 720 } 721 } 722 }