2012-07-16 156 views
1

我正在學習構建JSF自定義組件,我想我可以嘗試和構建一個實現的jQuery的拖動&拖..所以我讀了大部分的東西,可以真正建立一個基本上產生jQuery的JS適量足夠簡單的可拖動和投擲的組件,支持將&下降,直到我可以在「拖動」對象和「投擲的」容器和幾乎拖關聯/左右下降東西..JSF自定義組件jQueryUI拖放

這很簡單,我的問題是如何獲得丟棄內容的「數據」,或者如何綁定到jQuery生成的drop事件......我知道它應該很容易,所以如果任何人都可以指向我正確的方向(文件/代碼樣本)我將非常感激它...

我會粘貼儘可能少的代碼,因爲我認爲我必須..只是這樣你才能看到我做了什麼..我可以分享很多東西(沒有什麼更多的東西粘貼真的..)如果有人需要它...

(正如你可以看到我可以綁定一個Ajax事件..我只是不知道如何調用它..)。

TIA ..

組件...

@FacesComponent(Draggable.COMPONENT_TYPE) 
public class Draggable extends UIComponentBase { 
    public static final String COMPONENT_TYPE = "ar.com.easytech.Draggable"; 
    public static final String DEFAULT_RENDERER_TYPE = "ar.com.easytech.DraggableRenderer"; 
    public static final String COMPONENT_FAMILY = "javax.faces.Output"; 

    public String getFamily() { 
     return COMPONENT_FAMILY; 
    } 

    public String getFor() { 
     return (String) getStateHelper().eval(PropertyKeys.forVal); 
    } 

    ... 

    protected enum PropertyKeys { 
     forVal("for"), draggableSelector, revert, containTo; 
     String c; 

     PropertyKeys() { 
     } 

     PropertyKeys(String c) { 
      this.c = c; 
     } 

     public String toString() { 
      return ((this.c != null) ? this.c : super.toString()); 
     } 
    } 

    @Override 
    public void encodeEnd(FacesContext facesContext) throws IOException { 
     ResponseWriter writer = facesContext.getResponseWriter(); 

     String clientId = getClientId(facesContext); 
     UIComponent targetComponent = findComponent(getFor()); 
     if(targetComponent == null) 
      throw new FacesException("Cannot find component \"" + getFor()); 

     String target = targetComponent.getClientId(); 

     writer.startElement("script", null); 
     writer.writeAttribute("id", clientId + "_s", null); 
     writer.writeAttribute("type", "text/javascript", null); 
     writer.write("$(function() {"); 
     writer.write("$('#" + target.replace(":", "\\\\:") + "').draggable({"); 
     if (getRevert() != null) writer.write(" revert: '" + getRevert() + "', "); 
     if (getContainTo() != null) writer.write(" containment: '" + getContainTo() + "',"); 
     writer.write("});"); 

     writer.write("});"); 
     writer.endElement("script"); 
    } 

} 

Droppable.java

@FacesComponent(Droppable.COMPONENT_TYPE) 
public class Droppable extends UIComponentBase implements ClientBehaviorHolder { 
    public static final String COMPONENT_TYPE = "ar.com.easytech.Droppable"; 
    public static final String DEFAULT_RENDERER_TYPE = "ar.com.easytech.DroppableRenderer"; 
    public static final String COMPONENT_FAMILY = "javax.faces.Output"; 

    private final static String DEFAULT_EVENT = "drop"; 
    private static final Collection<String> EVENT_NAMES = Collections.unmodifiableCollection(Arrays.asList(DEFAULT_EVENT)); 

    public String getFamily() { 
     return COMPONENT_FAMILY; 
    } 

    // Property: for 
    public String getFor() { 
     return (String) getStateHelper().eval(PropertyKeys.forVal); 
    } 

    ... 

    protected enum PropertyKeys { 
     forVal("for"), droppableSelector, activeClass, hoverClass, accept, tolerance, source; 
     String c; 

     PropertyKeys() { 
     } 

     // Constructor needed by "for" property 
     PropertyKeys(String c) { 
      this.c = c; 
     } 

     public String toString() { 
      return ((this.c != null) ? this.c : super.toString()); 
     } 
    } 

    @Override 
    public void queueEvent(FacesEvent event) { 
     FacesContext context = FacesContext.getCurrentInstance(); 

     if (isRequestSource(context)) { 
      Map<String, String> params = context.getExternalContext() 
        .getRequestParameterMap(); 
      String eventName = params.get("javax.faces.behavior.event"); 
      String clientId = getClientId(context); 

      AjaxBehaviorEvent behaviorEvent = (AjaxBehaviorEvent) event; 

      if (eventName.equals("drop")) { 
       String dragId = params.get(clientId + "_sourceId"); 
       String dropId = params.get(clientId + "_targetId"); 
       DragDropEvent dndEvent = null; 
       String datasourceId = getSource(); 

       if (datasourceId != null) { 
        UIData datasource = (UIData) findComponent(datasourceId); 
        String[] idTokens = dragId.split(String 
          .valueOf(UINamingContainer 
            .getSeparatorChar(context))); 
        int rowIndex = Integer 
          .parseInt(idTokens[idTokens.length - 2]); 
        datasource.setRowIndex(rowIndex); 
        Object data = datasource.getRowData(); 
        datasource.setRowIndex(-1); 

        dndEvent = new DragDropEvent(this, 
          behaviorEvent.getBehavior(), dragId, dropId, data); 
       } else { 
        dndEvent = new DragDropEvent(this, 
          behaviorEvent.getBehavior(), dragId, dropId); 
       } 

       super.queueEvent(dndEvent); 
      } 

     } else { 
      super.queueEvent(event); 
     } 
    } 

    @Override 
    public Collection<String> getEventNames() { 
     return EVENT_NAMES; 
    } 

    @Override 
    public String getDefaultEventName() { 
     return DEFAULT_EVENT; 
    } 

    @Override 
    public void decode(FacesContext context) { 

     if (context == null) { 
       throw new NullPointerException(); 
      } 

      String clientId = getClientId(context); 
      Map<String, String> requestParameterMap = context.getExternalContext().getRequestParameterMap(); 
      String value = (String) requestParameterMap.get(clientId); 
      if (value == null || value.equals("") || !clientId.equals(value)) 
       return; 
      ActionEvent actionEvent = new ActionEvent(this); 
      queueEvent(actionEvent); 
    } 

    @Override 
    public void encodeEnd(FacesContext context) throws IOException { 

     ClientBehaviorContext behaviorContext = 
        ClientBehaviorContext.createClientBehaviorContext(context,this, DEFAULT_EVENT, getClientId(context), null); 

     ResponseWriter writer = context.getResponseWriter(); 
     String clientId = getClientId(context); 
     UIComponent targetComponent = findComponent(getFor()); 
     if(targetComponent == null) 
      throw new FacesException("Cannot find component \"" + getFor()); 
     String target = targetComponent.getClientId(); 

     writer.startElement("script", null); 
     writer.writeAttribute("id", clientId + "_s", null); 
     writer.writeAttribute("type", "text/javascript", null); 
     writer.write("$(function() {"); 
     writer.write("$('#" + target.replace(":", "\\\\:") + "').droppable({"); 

     if (getActiveClass() != null) writer.write(" activeClass: '" + getActiveClass() + "',"); 
     if (getHoverClass() != null) writer.write(" hoverClass: '" + getHoverClass() + "',"); 
     if (getAccept() != null) writer.write(" accept: '" + getAccept() + "',"); 
     if (getTolerance() != null) writer.write(" tolerance: '" + getTolerance() + "',"); 

     Map<String,List<ClientBehavior>> behaviors = getClientBehaviors(); 
     if (behaviors.containsKey(DEFAULT_EVENT)) { 
      String drop = behaviors.get(DEFAULT_EVENT).get(0).getScript(behaviorContext); 
      writer.writeAttribute("drop:", drop, null); 
     } 

     writer.write("});"); 
     writer.write("});"); 
     writer.endElement("script"); 
    } 

    // Private 

    private boolean isRequestSource(FacesContext context) { 
     return this.getClientId(context).equals(context.getExternalContext().getRequestParameterMap() .get("javax.faces.source")); 
    } 
} 

而且它的用法會是這樣的..

<h:form id="frm"> 
     <div id="container" class="container"> 
     <ui:repeat var="row" value="#{homeBean.data}" id="dnd" > 
      <h:panelGroup layout="block" id="draggable" styleClass="draggable"> 
      <h:outputText value="#{row}" /> 
      </h:panelGroup> 
      <et:draggable for="draggable" draggableSelector=".draggable" containTo="parent" revert="invalid" /> 
     </ui:repeat> 

     <h:panelGroup layout="block" id="droppable" styleClass="droppable"> 
      <p>Drop Here!</p> 
     </h:panelGroup> 
     </div> 

    <h:dataTable id="selectedItems" var="data" value="#{homeBean.selectedRows}"> 
    <h:column> 
     <h:outputText value="#{data.name}" /> 
    </h:column> 
    </h:dataTable> 

     <et:droppable for="droppable" droppableSelector=".droppable" hoverClass="ui-state-hover" activeClass="ui-state-active" > 
     <f:ajax listener="#{homeBean.objectDropped}" render="@form" event="drop" /> 
     </et:droppable> 
    </h:form> 

HomeBean.java

@ManagedBean 
public class HomeBean { 


    private List<String> data = new ArrayList<String>(); 
    private List<String> selectedRows = new ArrayList<String>(); 

    @PostConstruct 
    public void init() { 

     data.add("Value 1"); 
     data.add("Value 2"); 
    } 

    public void objectDropped(DragDropEvent event) { 
     selectedRows.add(event.getSourceId()); 
    } 

    public List<String> getData() { 
     return data; 
    } 

    public void setData(List<String> data) { 
     this.data = data; 
    } 

    public List<String> getSelectedRows() { 
     return selectedRows; 
    } 

    public void setSelectedRows(List<String> selectedRows) { 
     this.selectedRows = selectedRows; 
    } 


} 
+0

你的意思是排序?像這樣? http://jqueryui.com/demos/sortable/ – Daniel 2012-07-16 09:10:50

+0

@Daniel,我實際上需要一步之前,我需要綁定jQuery下降事件'$(「.selector」).bind(「drop」,function(event, ui){ ... });'所以我可以創建我的自定義(好吧..它實際上結束了就像PrimeFaces ....)DragDropEvent並調用DE BB做一些與丟棄的項目.. – FMQ 2012-07-16 14:49:53

+0

嗨@FMQ,我對JSF中的自定義拖放組件也很感興趣。您能否與我分享一些如何做的經驗,或者一些教程或文檔會非常感謝。先進的謝謝! – Sonn 2017-11-19 16:52:57

回答

0

爲了您的例子,這是通過JSF傳遞從jQuery的事件數據到服務器的一種方式(其言自明INMO)

$(".selector").bind("drop", function(event, ui) { 
    $("#myInputHiddenID").val("someJsonStringCanBePlacedHereForExample"); 
    $("#myButtonID").click(); 
}); 


<h:commandButton id="myButtonID" action="#{myBean.myAction()}" style="display:none" > 
    <f:ajax></f:ajax> 
    <h:inputHidden id="myInputHiddenID" value="#{myBean.myStringData}" /> 
</h:commandButton> 

public void myAction() { 
    System.out.println(myStringData); 
} 
+0

@丹尼爾..是的...這應該工作,但我實際上正在嘗試在我創建的自定義組件中實現此目的..例如PrimeFaces爲「drop」事件生成此代碼$(function() {PrimeFaces.cw( '可投放', 'widget_carForm_j_idt35',{ID: 'carForm:j_idt35',目標: 'carForm:selectedCars',activeClass: 'UI狀態高亮',onDrop:handleDrop,公差: '觸摸',行爲:{drop:function(event){PrimeFaces。ab({source:'carForm:j_idt35',event:'drop',process:'carForm:j_idt35',update:'carForm:dropArea carForm:availableCars'},arguments [1]);}}});}) ;'這會生成一個DragDropEvent ... – FMQ 2012-07-16 16:40:26

+0

這部分是我無法理解的,它與我的組件有什麼關係......我對問題的解釋可能不清楚..如果是這樣的話......請讓我知道所以我可以嘗試澄清我的問題......謝謝! – FMQ 2012-07-16 16:43:28

+0

dunno,看起來像一些構造函數('cw'),嘗試調試js,然後...將斷點放入'cw'中(或將'debugger;'放在函數內部)並調試代碼以瞭解更多... – Daniel 2012-07-17 05:52:26

0

因爲它turn's出來,有什麼我失蹤是jQuery的添加AJAX調用掉落事件引發中Droppable.java定義的「滴」事件....

writer.write(" jsf.ajax.request(this,event,{execute: '"); 
writer.write(getClientId() +"', sourceId: ui.draggable.attr('id') , targetId: $(this).attr('id')}); "); 

我仍然有生成的事件的問題(它不會生成的javax的實例.faces.behavior.event),但我猜我應該爲此打開一個新的問題...