我正在学习构建 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;
}
}