/**
   * Implements {@link ClientSideConverter#generateClientSideConverter(FacesContext, UIComponent)}
   */
  public String generateClientSideConverter(FacesContext context, UIComponent component) {
    UIInput input = (UIInput) component;
    DateTimeConverter converter = (DateTimeConverter) input.getConverter();

    String dateType = converter.getType();
    int valueType = TYPE_TIMESTAMP;
    if (StringUtil.isNotEmpty(dateType)) {
      if (dateType.equals(DateTimeConverter.TYPE_DATE)) {
        valueType = TYPE_DATE;
      } else if (dateType.equals(DateTimeConverter.TYPE_TIME)) {
        valueType = TYPE_TIME;
      }
    }

    // TODO in 9.0.2, should update this to handle message changes for SPR#MKEE7TXMLG
    String message;
    if (TYPE_DATE == valueType) {
      message = getMessageDate();
    } else if (TYPE_TIME == valueType) {
      message = getMessageTime();
    } else {
      message = getMessageBoth();
    }

    DojoModuleResource module;
    StringBuilder builder = new StringBuilder();
    switch (valueType) {
      case TYPE_DATE:
        {
          module = ISO_DATE_CONVERTER_MODULE;
          builder.append("new extlib.date.IsoDateConverter({message:"); // $NON-NLS-1$
          JavaScriptUtil.addMessage(builder, message);
          builder.append("})"); // $NON-NLS-1$
          break;
        }
      case TYPE_TIME:
        {
          module = ISO_TIME_CONVERTER_MODULE;
          builder.append("new extlib.date.IsoTimeConverter({message:"); // $NON-NLS-1$
          JavaScriptUtil.addMessage(builder, message);
          builder.append("})"); // $NON-NLS-1$
          break;
        }
      default:
        { // TYPE_TIMESTAMP
          module = ISO_DATE_TIME_CONVERTER_MODULE;
          builder.append("new extlib.date.IsoDateTimeConverter({message:"); // $NON-NLS-1$
          JavaScriptUtil.addMessage(builder, message);
          builder.append("})"); // $NON-NLS-1$
          break;
        }
    }
    if (null != module) {
      UIViewRootEx rootEx = (UIViewRootEx) context.getViewRoot();
      rootEx.addEncodeResource(context, module);
    }
    return builder.toString();
  }
 protected void writeErrorSummaryButton(
     FacesContext context, ResponseWriter w, FormLayout c, String id, String shadeId)
     throws IOException {
   w.startElement("input", c); // $NON-NLS-1$
   w.writeAttribute("type", "button", null); // $NON-NLS-1$ $NON-NLS-2$
   w.writeAttribute("value", "OK", null); // $NON-NLS-1$ $NLS-MobileFormTableRenderer_iphone.OK-2$
   StringBuilder b = new StringBuilder();
   b.append("XSP.hideMobileFormTableError("); // $NON-NLS-1$
   JavaScriptUtil.addString(b, id);
   b.append(","); // $NON-NLS-1$
   JavaScriptUtil.addString(b, shadeId);
   b.append(");"); // $NON-NLS-1$
   w.writeAttribute("onclick", b, null); // $NON-NLS-1$
   w.endElement("input"); // $NON-NLS-1$
 }
 protected void calculateFormLabelWidth(FacesContext context, UIComponent component) {
   StringBuilder script = new StringBuilder();
   script.append("XSP.addOnLoad(function(){XSP.resizeForm("); // $NON-NLS-1$
   JavaScriptUtil.addString(script, component.getClientId(context));
   script.append(")});"); // $NON-NLS-1$
   ExtLibUtil.addScript(context, script.toString());
 }
  @Override
  protected void writeErrorSummary(
      FacesContext context, ResponseWriter w, FormLayout c, ComputedFormData formData)
      throws IOException {
    if (!c.isDisableErrorSummary()) {
      // Should we apply a filter to retain only the message belonging to the controls within the
      // form?
      // Easy enough with a FilteredIterator
      Iterator<FacesMessage> msg = ((DominoFacesContext) context).getMessages();
      if (msg.hasNext()) {
        String id =
            c.getClientId(context) + NamingContainer.SEPARATOR_CHAR + "popup"; // $NON-NLS-1$
        String shadeId =
            c.getClientId(context) + NamingContainer.SEPARATOR_CHAR + "shade"; // $NON-NLS-1$
        writeErrorSummaryShade(context, w, c, shadeId);

        // TODO: make the addition of js to the component a separate function
        // center the error dialog on the screen
        StringBuilder b = new StringBuilder();
        b.append("XSP.addOnLoad(function(){"); // $NON-NLS-1$
        b.append("XSP.centerNode("); // $NON-NLS-1$
        JavaScriptUtil.addString(b, id);
        b.append(");"); // $NON-NLS-1$
        b.append("});"); // $NON-NLS-1$
        String script = b.toString();
        ExtLibUtil.addScript(context, script);

        w.startElement("div", c); // $NON-NLS-1$
        String style = (String) getProperty(PROP_STYLEERRORSUMMARY);
        if (StringUtil.isNotEmpty(style)) {
          w.writeAttribute("style", style, null); // $NON-NLS-1$
        }
        String cls = (String) getProperty(PROP_STYLECLASSERRORSUMMARY);
        if (StringUtil.isNotEmpty(cls)) {
          w.writeAttribute("class", cls, null); // $NON-NLS-1$
        }
        if (StringUtil.isNotEmpty(id)) {
          w.writeAttribute("id", id, null); // $NON-NLS-1$
        }

        writeErrorSummaryContent(context, w, c, msg);
        writeErrorSummaryButton(context, w, c, id, shadeId);
        w.endElement("div"); // $NON-NLS-1$
      }
    }
  }
  // === continue code from InputRendererUtil ===
  // ClientSide validation
  // com.ibm.xsp.renderkit.html_basic.InputRendererUtil.generateClientSideValidation(FacesContext,
  // UIInput, ResponseWriter)
  private void generateClientSideValidation(
      FacesContext context, UIInput uiInput, ResponseWriter writer) throws IOException {
    // Check if the input field is required
    boolean required = uiInput.isRequired();
    Converter c = InputRendererUtil.findConverter(context, uiInput);
    Validator[] v = uiInput.getValidators();

    // Check if it might make sense to generate a function
    boolean validate = required;
    if (!validate) {
      validate = c instanceof ClientSideConverter;
    }
    if (!validate) {
      for (int i = 0; i < v.length; i++) {
        validate = v[i] instanceof ClientSideValidator;
        if (validate) {
          break;
        }
      }
    }

    if (validate) {
      // This flag is maintained if we actually need to generate the function
      // Some converter/validator may not actually generate any client code, depending on their
      // parameters
      validate = false;

      StringBuilder b = new StringBuilder(128);
      b.append("XSP.attachValidator("); // $NON-NLS-1$
      JavaScriptUtil.addString(b, uiInput.getClientId(context));

      // Add the required flag
      if (required) {
        b.append(",new XSP.RequiredValidator("); // $NON-NLS-1$
        JavaScriptUtil.addMessage(b, InputRendererUtil.getRequiredMessage(context, uiInput));
        b.append(")");
        validate = true;
      } else {
        b.append(",null"); // $NON-NLS-1$
      }

      // Add the converter
      if (c instanceof ClientSideConverter) {
        ClientSideConverter clientSideConverter = (ClientSideConverter) c;
        // TODO this is handling of converterRenderer
        // differs from the original implementation in InputRendererUtil.
        String s;
        Renderer renderer =
            FacesUtil.getRenderer(context, uiInput.getFamily(), uiInput.getRendererType());
        ClientSideConverter converterRenderer =
            (ClientSideConverter) FacesUtil.getRendererAs(renderer, ClientSideConverter.class);
        if (null != converterRenderer) {
          // if the control renderer implements ClientSideConverter
          // delegate to the renderer instead of to the converter.
          s = converterRenderer.generateClientSideConverter(context, uiInput);
        } else {
          s = clientSideConverter.generateClientSideConverter(context, uiInput);
        }
        if (StringUtil.isNotEmpty(s)) {
          b.append(",");
          b.append(s); // not JSUtil because contains client script.
          validate = true;
        } else {
          b.append(",null"); // $NON-NLS-1$
        }
      } else {
        b.append(",null"); // $NON-NLS-1$
      }

      // And add the validator
      for (int i = 0; i < v.length; i++) {
        if (v[i] instanceof ClientSideValidator) {
          String s = ((ClientSideValidator) v[i]).generateClientSideValidation(context, uiInput);
          if (StringUtil.isNotEmpty(s)) {
            b.append(",");
            b.append(s); // not JSUtil because contains client script.
            validate = true;
          }
        }
      }

      // Finally, check for multiple values
      String multiSep = null;
      if (uiInput instanceof UIInputEx) {
        multiSep = ((UIInputEx) uiInput).getMultipleSeparator();
      }
      if (c instanceof ListConverter) {
        multiSep = ((ListConverter) c).getDelimiter();
        if (StringUtil.isEmpty(multiSep)) {
          multiSep = ","; // $NON-NLS-1$
        }
      }
      if (StringUtil.isNotEmpty(multiSep)) {
        b.append(",");
        JSUtil.addString(b, multiSep);
      }

      b.append(");");

      // get the scriptcollector component (needed to add script blocks the the rendered output).
      if (validate) {
        JavaScriptUtil.addScriptOnLoad(b.toString());
      }
    }
  }