2014-02-24 24 views
0

我很新的客戶端開發。雖然可能有一些解決方案已經可用。讓我試着描述我的問題場景。我有一個JSF page(表格),其中存在不同的下降點(選擇框)。他們可以是國籍,語言或宗教。當我們輸入代碼時,它會選擇國籍或語言。在這基本上是一個server hit goes(partial ajax request)。我的高級建議我完全開發這個auto-complete功能完全客戶端。他們不希望任何服務器遭受攻擊。JSF - 自動完成功能選擇框不打服務器

他們基本上想要的是,當我輸入一些值時,它從客戶端加載建議列表,它不應該去服務器。它應該比update the jsf component相應嗎?我怎樣才能解決這個問題?任何建議都有幫助。

當前項目基地有此代碼 - 自定義組件

public class VisionSelectOneMenuRenderer extends InputRenderer { 
    @Override 
    public void decode(FacesContext context, UIComponent component) { 
    VisionSelectOneMenu menu = (VisionSelectOneMenu) component; 

    if (menu.isDisabled() || menu.isReadonly()) { 
     return; 
    } 

    decodeBehaviors(context, menu); 

    String clientId = menu.getClientId(context); 
    String value = context.getExternalContext().getRequestParameterMap().get(clientId + "_selectBox"); 

    if (value != null) { 
     menu.setSubmittedValue(value); 
    } 
    } 

    @Override 
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException { 
    VisionSelectOneMenu menu = (VisionSelectOneMenu) component; 

    encodeMarkup(context, menu); 
    encodeScript(context, menu); 
    } 

    protected void encodeMarkup(FacesContext context, VisionSelectOneMenu menu) throws IOException { 
    List<SelectItem> selectItems = getSelectItems(context, menu); 
    String clientId = menu.getClientId(context); 
    boolean disabled = menu.isDisabled(); 
    Class type = getValueType(context, menu); 

    String styleclass = menu.getStyleClass(); 
    styleclass = styleclass == null ? VisionSelectOneMenu.STYLE_CLASS : VisionSelectOneMenu.STYLE_CLASS + " " + styleclass; 
    styleclass = disabled ? styleclass + " ui-state-disabled" : styleclass; 
    styleclass = "sfield"; 

    /* writer.startElement("div", menu); 
writer.writeAttribute("id", clientId, "id"); 
writer.writeAttribute("class", styleclass, "styleclass"); 
if(style != null) 
writer.writeAttribute("style", style, "style"); */ 

    encodeInput(context, menu, clientId, selectItems, type); 
    //encodeLabel(context, menu, selectItems, type); 
    //encodeMenuIcon(context, menu); 
    // encodePanel(context, menu, selectItems, type); 

    // writer.endElement("div"); 
    } 

    protected void encodeInput(FacesContext context, VisionSelectOneMenu menu, String clientId, List<SelectItem> selectItems, Class type) 
     throws IOException { 
    ResponseWriter writer = context.getResponseWriter(); 
    String inputId = clientId + "_selectBox"; 

    writer.startElement("div", menu); 
    writer.writeAttribute("class", "sfield", null); 

    writer.startElement("select", menu); 
    writer.writeAttribute("id", inputId, "id"); 
    writer.writeAttribute("tabindex", "-1", null); 
    writer.writeAttribute("name", inputId, null); 
    //writer.writeAttribute("class", "searchableSelectLookupSelect", null); 
    if (menu.getOnchange() != null) { 
     writer.writeAttribute("onchange", menu.getOnchange(), null); 
    } 
    if (menu.isDisabled()) { 
     writer.writeAttribute("disabled", "disabled", null); 
    } 

    encodeSelectItems(context, menu, selectItems, type); 

    writer.endElement("select"); 

    writer.startElement("input", null); 
    writer.writeAttribute("id", clientId, null); 
    //writer.writeAttribute("tabindex", "-1", null); 
    writer.writeAttribute("name", clientId, null); 
    writer.writeAttribute("type", "text", null); 
    writer.writeAttribute("class", "searchableSelectLookupText excludeClear", null); 
    if (menu.isDisabled()) { 
     writer.writeAttribute("disabled", "disabled", null); 
    } 
    writer.endElement("input"); 

    writer.endElement("div"); 
    } 

    protected void encodeLabel(FacesContext context, VisionSelectOneMenu menu, List<SelectItem> selectItems, Class type) 
     throws IOException { 
    ResponseWriter writer = context.getResponseWriter(); 
    String label = getSelectedLabel(context, menu, selectItems, type); 

    writer.startElement("a", null); 
    writer.writeAttribute("href", "#", null); 
    writer.writeAttribute("class", VisionSelectOneMenu.LABEL_CONTAINER_CLASS, null); 

    if (menu.getTabindex() != null) { 
     writer.writeAttribute("tabindex", menu.getTabindex(), null); 
    } 

    writer.startElement("label", null); 
    writer.writeAttribute("class", VisionSelectOneMenu.LABEL_CLASS, null); 

    if (label.equals("&nbsp;")) { 
     writer.write(label); 
    } 
    else { 
     writer.writeText(label, null); 
    } 

    writer.endElement("label"); 
    writer.endElement("a"); 
    } 

    protected void encodeMenuIcon(FacesContext context, VisionSelectOneMenu menu) throws IOException { 
    ResponseWriter writer = context.getResponseWriter(); 

    writer.startElement("div", menu); 
    //writer.writeAttribute("class", VisionSelectOneMenu.TRIGGER_CLASS, null); 

    writer.startElement("span", menu); 
    //writer.writeAttribute("class", "ui-icon ui-icon-triangle-1-s", null); 
    writer.endElement("span"); 

    writer.endElement("div"); 
    } 

    protected void encodePanel(FacesContext context, VisionSelectOneMenu menu, List<SelectItem> selectItems, Class type) 
     throws IOException { 
    ResponseWriter writer = context.getResponseWriter(); 
    boolean customContent = menu.getVar() != null; 
    int height = calculatePanelHeight(menu, selectItems.size()); 

    writer.startElement("div", null); 
    writer.writeAttribute("id", menu.getClientId(context) + "_panel", null); 
    writer.writeAttribute("class", VisionSelectOneMenu.PANEL_CLASS, null); 

    if (height != -1) { 
     writer.writeAttribute("style", "height:" + height + "px", null); 
    } 

    if (customContent) { 
     writer.startElement("table", menu); 
     writer.writeAttribute("class", VisionSelectOneMenu.TABLE_CLASS, null); 
     writer.startElement("tbody", menu); 
     encodeOptionsAsTable(context, menu, selectItems, type); 
     writer.endElement("tbody"); 
     writer.endElement("table"); 
    } 
    else { 
     writer.startElement("ul", menu); 
     writer.writeAttribute("class", VisionSelectOneMenu.LIST_CLASS, null); 
     encodeOptionsAsList(context, menu, selectItems, type); 
     writer.endElement("ul"); 
    } 

    writer.endElement("div"); 
    } 

    protected void encodeOptionsAsTable(FacesContext context, VisionSelectOneMenu menu, List<SelectItem> selectItems, Class type) 
     throws IOException { 
    ResponseWriter writer = context.getResponseWriter(); 
    String var = menu.getVar(); 
    List<Column> columns = menu.getColums(); 
    Object value = menu.getValue(); 

    for (SelectItem selectItem : selectItems) { 
     Object itemValue = selectItem.getValue(); 
     Object coercedItemValue = null; 

     if (itemValue != null && !itemValue.equals("")) { 
     coercedItemValue = context.getApplication().getExpressionFactory().coerceToType(itemValue, type); 
     } 

     boolean selected = (value != null && value.equals(coercedItemValue)); 

     context.getExternalContext().getRequestMap().put(var, selectItem.getValue()); 

     String rowStyleClass = selected ? VisionSelectOneMenu.ROW_CLASS + " ui-state-active" : VisionSelectOneMenu.ROW_CLASS; 

     writer.startElement("tr", null); 
     writer.writeAttribute("class", rowStyleClass, null); 

     if (itemValue instanceof String) { 
     writer.startElement("td", null); 
     writer.writeAttribute("colspan", columns.size(), null); 
     writer.write(selectItem.getLabel()); 
     writer.endElement("td"); 
     } 
     else { 
     for (Column column : columns) { 
      writer.startElement("td", null); 
      column.encodeAll(context); 
      writer.endElement("td"); 
     } 
     } 

     writer.endElement("tr"); 
    } 

    context.getExternalContext().getRequestMap().put(var, null); 
    } 

    protected void encodeOptionsAsList(FacesContext context, VisionSelectOneMenu menu, List<SelectItem> selectItems, Class type) 
     throws IOException { 
    ResponseWriter writer = context.getResponseWriter(); 
    Object value = menu.getValue(); 

    for (int i = 0; i < selectItems.size(); i++) { 
     SelectItem selectItem = selectItems.get(i); 
     Object itemValue = selectItem.getValue(); 
     String itemLabel = selectItem.getLabel(); 
     Object coercedItemValue = null; 
     itemLabel = isValueBlank(itemLabel) ? "&nbsp;" : itemLabel; 

     if (itemValue != null && !itemValue.equals("")) { 
     coercedItemValue = context.getApplication().getExpressionFactory().coerceToType(itemValue, type); 
     } 

     boolean selected = (i == 0 && value == null) || (value != null && value.equals(coercedItemValue)); 
     String itemStyleClass = selected ? VisionSelectOneMenu.ITEM_CLASS + " ui-state-active" : VisionSelectOneMenu.ITEM_CLASS; 

     writer.startElement("li", null); 
     writer.writeAttribute("class", itemStyleClass, null); 

     if (itemLabel.equals("&nbsp;")) { 
     writer.write(itemLabel); 
     } 
     else { 
     writer.writeText(itemLabel, null); 
     } 

     writer.endElement("li"); 
    } 
    } 

    protected void encodeScript(FacesContext context, VisionSelectOneMenu menu) throws IOException { 
    ResponseWriter writer = context.getResponseWriter(); 
    String clientId = menu.getClientId(context); 

    writer.startElement("script", null); 
    writer.writeAttribute("type", "text/javascript", null); 
    //writer.write("var selectedText = '';"); 

    // TEXT box script 
    //writer.write("jQuery(document).ready(function(){$('#"+clientId+"').val($('#"+clientId+"_selectBox option:selected').text());});" + 
    writer.write(
     "jQuery(document).ready(function(){" + 
      //" if($('#"+clientId+"_selectBox').is(':disabled')){ $('#"+clientId+"').attr('disabled','disabled') }" + 
      "$('#" + clientId + "_selectBox').focus(function(){" + 
      //"if(!$('#"+clientId+"_selectBox').is(':hover')){"+ 
      // " $('#"+clientId+"').val(''); $('#"+clientId+"').focus();} "+ 
      "});" + 
      "$('#" + clientId + "').val($('#" + clientId + "_selectBox option:selected').text());" + 
      /*"$('#"+clientId+"_selectBox option').each(function(){" + 
     //"var idvalue = $(this).text().split('$')[0];" + 
     "var level = $(this).text().split(' [')[0];" + 
     "var levelCode = $(this).text().split(' [')[1];" + 
     "var desc = level.concat('^');" + 

     "if(null != levelCode && typeof(levelCode)!='undefined' && levelCode.length > 0) {" + 
      "var subStr = levelCode.substring(0,3);" + 
      "desc = desc.concat(levelCode.substring(0,levelCode.length-1));" + 

      "$(this).attr('description',desc);" + 
     "}"+ 

     //"$(this).attr('description',$(this).text());" + 
     //"$(this).text(idvalue);" + 
     "$('#"+clientId+"').val($('#"+clientId+"_selectBox option:selected').text());" + 
     "}" + 
     ")});" +*/ 

      "jQuery('#" + clientId + "').keyup(" + 
      "function(event){ " + 
      "if (event.keyCode == 13 || event.keyCode == 9) { " + 
      "var enteredText = $('#" + clientId + "').val();" + 
      "$('#" + clientId + "_selectBox > option').each(function(){" + 
      " var optionValue = $(this).val();" + 
      " var optionText = $(this).text();" + 
      " var optionDesc = $(this).attr('description');" + 
      " if(optionValue == enteredText) {" + 
      "  $('#" + clientId + "').val(optionText);" + 
      "  $('#" + clientId + "_selectBox').val(optionValue);" + 
      " }" + 
      " if(optionValue != 0) {" + 
      "  var splitted = optionDesc.split('^');" + 
      "  if(splitted[1] == enteredText.toUpperCase()) {" + 
      "   $('#" + clientId + "').val(optionText);" + 
      "   $('#" + clientId + "_selectBox').val(optionValue);" + 
      "  }" + 
      " }" + 
      " " + 
      "});" + 
      "}" +// if for keycode ends 
      "});" 
    ); 

    writer.write(
     "jQuery('#" + clientId + "').click(" + 
      "function(){" + 
      "$('#" + clientId + "').val('');" + 
      "});" 
    ); 


    /*writer.write("jQuery('#"+clientId+"').focus(" + 
     "function(){" + 
     "$('#"+clientId+"_selectBox').trigger('click');" + 
     "});" 
    );*/ 

    writer.write(
     "jQuery('#" + clientId + "').blur(" + 
      "function(){" + 
      "var enteredText = $('#" + clientId + "').val();" + 
      "$('#" + clientId + "_selectBox > option').each(function(){" + 
      " var optionValue = $(this).val();" + 
      " var optionText = $(this).text();" + 
      " var optionDesc = $(this).attr('description');" + 
      " if(optionValue == enteredText) {" + 
      "  $('#" + clientId + "').val(optionText);" + 
      "  $('#" + clientId + "_selectBox').val(optionValue);" + 
      "  jQuery('#" + clientId + "_selectBox').trigger('change'); " + 
      " }" + 
      " if(optionValue != 0) {" + 
      "  var splitted = optionDesc.split('^');" + 
      "  if(splitted[1] == enteredText.toUpperCase()) {" + 
      "   $('#" + clientId + "').val(optionText);" + 
      "   $('#" + clientId + "_selectBox').val(optionValue); jQuery('#" + clientId + "_selectBox').trigger('change');" + 
      "  }" + 
      " }" + 
      " " + 
      "});" + 
      "  $('#" + clientId + "').val($('#" + clientId + "_selectBox option:selected').text());" + 
      "});" 
    ); 


    //writer.write("jQuery('#"+clientId+"_selectBox').onmouseover(this.size=this.length)"); 

    encodeClientBehaviors(context, menu); 

    writer.endElement("script"); 
    } 


    protected void encodeClientBehaviors(FacesContext context, ClientBehaviorHolder component) throws IOException { 
    String script = ""; 
    ResponseWriter writer = context.getResponseWriter(); 
    String clientId = ((UIComponent) component).getClientId(context); 


    //ClientBehaviors 
    Map<String, List<ClientBehavior>> behaviorEvents = component.getClientBehaviors(); 

    if (!behaviorEvents.isEmpty()) { 

     List<ClientBehaviorContext.Parameter> params = Collections.emptyList(); 

     for (Iterator<String> eventIterator = behaviorEvents.keySet().iterator(); eventIterator.hasNext();) { 
     String event = eventIterator.next(); 

     for (Iterator<ClientBehavior> behaviorIter = behaviorEvents.get(event).iterator(); behaviorIter.hasNext();) { 
      ClientBehavior behavior = behaviorIter.next(); 
      ClientBehaviorContext cbc = ClientBehaviorContext.createClientBehaviorContext(
       context, 
       (UIComponent) component, 
       event, 
       clientId, 
       params 
     ); 
      script += behavior.getScript(cbc); //could be null if disabled 
     } 
     } 
    } 

    // SELECT Box scripts 
    writer.write(
     "jQuery('#" + clientId + "_selectBox').change(" + 
      "function(){" + 
      "var selectedValue = $('#" + clientId + "_selectBox option:selected').text();" + 
      "  $('#" + clientId + "').val(selectedValue);" + script + 
      "}" + 
      ");});" 
    ); 
    } 

    protected void encodeSelectItems(FacesContext context, VisionSelectOneMenu menu, List<SelectItem> selectItems, Class type) 
     throws IOException { 
    ResponseWriter writer = context.getResponseWriter(); 
    Converter converter = getConverter(context, menu); 
    Object value = menu.getValue(); 

    for (SelectItem selectItem : selectItems) { 
     Object itemValue = selectItem.getValue(); 
     String itemLabel = selectItem.getLabel(); 
     String tLabel = itemLabel; 

     if (itemValue != null && !itemValue.equals("")) { 
     itemValue = context.getApplication().getExpressionFactory().coerceToType(itemValue, type); 
     } 

     writer.startElement("option", null); 
     writer.writeAttribute("description", tLabel, null); 
     writer.writeAttribute("value", getOptionAsString(context, menu, converter, itemValue), null); 


     if (value != null && value.equals(itemValue)) { 
     writer.writeAttribute("selected", "selected", null); 
     } 

     //if((Long)itemValue != 0) { 
     /*if((Long)itemValue == 209) { 
     writer.write(itemLabel + " [AFG]"); 
     } else if((Long)itemValue == 203) { 
     writer.write(itemLabel + " [PAK]"); 
     } else if((Long)itemValue == 205) { 
     writer.write(itemLabel + " [IND]"); 
     } else { 
     writer.write(itemLabel + " [" + itemValue + "]"); 
     }*/ 
     /*} 
     else 
     writer.write(itemLabel);*/ 

     //writer.write(itemLabel); 
     if (itemLabel.contains("^")) { 
     String[] formattedLabel = itemLabel.split("\\^"); 

     itemLabel = formattedLabel[0] + " [" + formattedLabel[1] + "]" + " [" + itemValue + "]"; 
     writer.write(itemLabel); 
     } 
     else { 
     if (itemValue instanceof Long) { 
      if ((Long) itemValue != 0) { 
      writer.write(itemLabel + " [" + itemValue + "]"); 
      } 
      else { 
      writer.write(itemLabel); 
      } 
     } 
     else { 
      writer.write(itemLabel); 
     } 
     } 

     writer.endElement("option"); 
    } 
    } 

    protected String getSelectedLabel(FacesContext context, VisionSelectOneMenu menu, List<SelectItem> items, Class type) { 
    Object value = menu.getValue(); 
    String label = null; 

    for (SelectItem item : items) { 
     Object itemValue = item.getValue(); 
     if (itemValue != null && !itemValue.equals("")) { 
     itemValue = context.getApplication().getExpressionFactory().coerceToType(item.getValue(), type); 
     } 

     if (value != null && value.equals(itemValue)) { 
     label = item.getLabel(); 
     break; 
     } 
    } 

    if (label == null) { 
     label = !items.isEmpty() ? items.get(0).getLabel() : "&nbsp;"; 
    } 

    return label; 
    } 

    protected int calculatePanelHeight(VisionSelectOneMenu menu, int itemSize) { 
    int height = menu.getHeight(); 

    if (height != Integer.MAX_VALUE) { 
     return height; 
    } 
    else if (itemSize > 10) { 
     return 200; 
    } 

    return -1; 
    } 

    @Override 
    public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException { 
    //Rendering happens on encodeEnd 
    } 

    @Override 
    public boolean getRendersChildren() { 
    return true; 
    } 

    protected Class getValueType(FacesContext context, VisionSelectOneMenu menu) { 
    ValueExpression ve = menu.getValueExpression("value"); 
    Class type = ve == null ? String.class : ve.getType(context.getELContext()); 

    return type == null ? String.class : type; 
    } 
} 

感謝。

+1

如果你不打服務器,它不是ajax調用。所以你必須提供所有的選項,然後做客戶端JavaScript查找匹配的值。 但是,如果你想更新jsf組件,我認爲這將是一個阿賈克斯調用無論如何在圖片中。 –

回答

1

正如Oskars Pakers所建議的,如果不訪問服務器端,您將無法執行任何AJAX。在你的情況下解決方案將把所有的數據在客戶端<option>標籤。然而,這可能會非常緩慢加載取決於你有多少數據,並會讓你的服務器生成不必要的代碼,如果用戶不需要它。如果你仍然決定這麼做,那麼模擬客戶端自動完成行爲的最佳選擇是使用Select2,如果你的老闆改變了主意,它們也具有一定的優勢,可以構建AJAX功能。

+0

我們是否可以嚴格使用AJAX組件並將這些值綁定到後臺bean。 – benz

+0

是的,這是我通過'來做的事情'看看Rotten Tomatoes的例子 – Kuba