1

我正在学习构建 JSF 自定义组件,我想我可以尝试构建 jQuery 拖放的实现。所以我阅读了大部分内容,实际上可以构建一个足够简单的 Draggable 和 Droppable 组件,基本上可以生成正确的jQuery js 支持拖放的数量,直到我可以关联“可拖动”对象和“可放置”容器,并且几乎可以拖放东西。

这很简单,我的问题是如何获取被删除的“数据”,或者如何绑定到 jQuery 生成的 drop 事件......我知道这应该很容易,所以如果有人能指出我正确的方向(文档/代码示例)我将非常感激...

我将粘贴尽可能少的代码。

(如您所见,我可以绑定一个 ajax 事件。我只是不知道如何调用它。)。

蒂亚..

成分...

@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;
    }


}
4

2 回答 2

0

事实证明,我缺少的是在 jQuery drop 事件上添加一个 Ajax 调用,该事件引发 Droppable.java 中定义的“drop”事件......

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

我仍然对生成的事件有疑问(它不会生成 javax.faces.behavior.event 的实例),但我想我应该为此打开一个新问题......

于 2012-07-17T16:41:17.433 回答
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);
}
于 2012-07-16T15:04:20.447 回答