org.wicketstuff.jwicket.ui.dragdrop.DroppableBehavior Maven / Gradle / Ivy
package org.wicketstuff.jwicket.ui.dragdrop;
import org.apache.wicket.Component;
import org.apache.wicket.Request;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.wicketstuff.jwicket.ComponentFinder;
import org.wicketstuff.jwicket.JQueryJavascriptResourceReference;
import org.wicketstuff.jwicket.JsMap;
import org.wicketstuff.jwicket.SpecialKeys;
import org.wicketstuff.jwicket.ui.AbstractJqueryUiEmbeddedBehavior;
/**
* You can add an instance of this class to a Wicket {@link Component} to make it
* a droppable {@link Component} i.e. the target of a drag operation.
* An instance of this class can be added to one and only one
* {@link Component}. Another {@link Component} that should have exactly the
* same behavior needs it's own instance.
*/
public class DroppableBehavior extends AbstractDragDropBehavior {
private static final long serialVersionUID = 1L;
private static final String DROPPED_COMPONENTID_IDENTIFIER = "wsjqDroppedComponent";
public static final JQueryJavascriptResourceReference uiDroppableJs = new JQueryJavascriptResourceReference(DraggableBehavior.class, "jquery.ui.droppable.min.js");
private JsMap options = new JsMap();
private DraggablesAcceptedByDroppable draggablesAcceptedByDroppable = null;
public DroppableBehavior() {
super( AbstractJqueryUiEmbeddedBehavior.jQueryUiWidgetJs,
AbstractJqueryUiEmbeddedBehavior.jQueryUiMouseJs,
DraggableBehavior.jQueryUiDraggableJs,
uiDroppableJs,
SpecialKeys.specialKeysJs);
}
private boolean onActivatedNotificationWanted = false;
/**
* If set to {@code true}, the callback-Method {@link #onActivate(AjaxRequestTarget, Component, SpecialKeys)}
* is called when the drag operation ends.
* @param value {@code true} or {@code false}.
* @return this object
*/
public DroppableBehavior setWantOnActivatedNotification(final boolean value) {
onActivatedNotificationWanted = value;
return this;
}
private boolean onDeactivateNotificationWanted = false;
/**
* If set to {@code true}, the callback-Method {@link #onDeactivate(AjaxRequestTarget, Component, SpecialKeys)}
* is called when the drag operation ends.
* @param value {@code true} or {@code false}.
* @return this object
*/
public DroppableBehavior setWantOnDeactivateNotification(final boolean value) {
onDeactivateNotificationWanted = value;
return this;
}
/** You can restrict the {@link Component}s that can be dragged and dropped to
* a {@link Component} marked with this behavior. See {@link DraggablesAcceptedByDroppable}
* for more information. If the {@link DraggablesAcceptedByDroppable} is empty (i.e. it
* contains no names) then the droppable does not accept any draggables.
*
* @param accepted the accepted
* @return this object
*/
public DroppableBehavior setDraggablesAcceptedByDroppable(final DraggablesAcceptedByDroppable accepted) {
draggablesAcceptedByDroppable = accepted;
if (accepted != null)
options.put("accept", new JsFunction(accepted.getJsAcceptCheckerFunctionName()));
else
options.remove("accept");
return this;
}
/**
* Sets the 'activeClass' property for this draggable. Please consult the
* jQuery documentation for a detailled description of this property.
* @param activeClass the CSS class' name
* @return this object
*/
public DroppableBehavior setActiveClass(final String activeClass) {
if (activeClass == null)
options.remove("activeClass");
else
options.put("activeClass", activeClass);
return this;
}
public DroppableBehavior setActiveClass(final AjaxRequestTarget target, final String activeClass) {
setActiveClass(activeClass);
if (activeClass != null)
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('option','activeClass','" + activeClass + "');");
else
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('option','activeClass',false);");
return this;
}
/**
* Sets the 'addClasses' property for this draggable. Please consult the
* jQuery documentation for a detailled description of this property.
* @param value {@code true} or {@code false}.
* @return this object
*/
public DroppableBehavior setAddClasses(final boolean value) {
if (value)
options.remove("addClasses");
else
options.put("addClasses", value);
return this;
}
public DroppableBehavior setAddClasses(final AjaxRequestTarget target, final boolean value) {
setAddClasses(value);
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('option','addClasses'," + value + ");");
return this;
}
/**
* Sets the 'greedy' property for this draggable. Please consult the
* jQuery documentation for a detailled description of this property.
* @param value {@code true} or {@code false}.
* @return this object
*/
public DroppableBehavior setGreedy(final boolean value) {
if (value)
options.remove("greedy");
else
options.put("greedy", value);
return this;
}
public DroppableBehavior setGreedy(final AjaxRequestTarget target, final boolean value) {
setGreedy(value);
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('option','greedy'," + value + ");");
return this;
}
/**
* Sets the 'hoverClass' property for this draggable. Please consult the
* jQuery documentation for a detailled description of this property.
* @param hoverClass the CSS class' name
* @return this object
*/
public DroppableBehavior setHoverClass(final String hoverClass) {
if (hoverClass == null)
options.remove("hoverClass");
else
options.put("hoverClass", hoverClass);
return this;
}
public DroppableBehavior setHoverClass(final AjaxRequestTarget target, final String hoverClass) {
setHoverClass(hoverClass);
if (hoverClass != null)
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('option','hoverClass','" + hoverClass + "');");
else
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('option','hoverClass',false);");
return this;
}
/**
* Sets the 'scope' property for this draggable. Please consult the
* jQuery documentation for a detailled description of this property.
* @param scope the scode
* @return this object
*/
public DroppableBehavior setScope(final String scope) {
if (scope == null)
options.remove("scope");
else
options.put("scope", scope);
return this;
}
public DroppableBehavior setScope(final AjaxRequestTarget target, final String scope) {
setScope(scope);
if (scope != null)
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('option','scope','" + scope + "');");
else
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('option','scope','default');");
return this;
}
public static enum DropTolerance {
FTI("fit"),
INTERSECT("intersect"),
POINTER("pointer"),
TOUCH("touch")
;
private final String value;
private DropTolerance(final String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
public String toString() {
return this.value;
}
}
/**
* Sets the 'tolerance' property for this droppable. Please consult the
* jquery documentation for a detailled description of this property.
* @param tolerance the tolerance
* @return this object
*/
public DroppableBehavior setTolerance(final DropTolerance tolerance) {
if (tolerance == null)
options.remove("tolerance");
else
options.put("tolerance", tolerance.getValue());
return this;
}
public DroppableBehavior setScope(final AjaxRequestTarget target, final DropTolerance tolerance) {
setTolerance(tolerance);
if (tolerance != null)
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('option','tolerance','" + tolerance.getValue() + "');");
else
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('option','tolerance','" + DropTolerance.INTERSECT + "');");
return this;
}
/**
* handles the event processing during dragging.
*/
@Override
protected void respond(final AjaxRequestTarget target) {
Component component = getComponent();
Request request;
if (component != null && (request = component.getRequest()) != null) {
EventType dragEventType = EventType.stringToType(request.getParameter(EventType.IDENTIFIER));
ComponentFinder visitor = new ComponentFinder(request.getParameter(DROPPED_COMPONENTID_IDENTIFIER));
component.getPage().visitChildren(visitor);
if (component instanceof IDroppable) {
IDroppable draggableComponent = (IDroppable)component;
if (dragEventType == EventType.DROP)
draggableComponent.onDrop(target, visitor.getFoundComponent(), new SpecialKeys(request));
else if (dragEventType == EventType.DROP_ACTIVATE)
draggableComponent.onActivate(target, visitor.getFoundComponent(), new SpecialKeys(request));
else if (dragEventType == EventType.DROP_DEACTIVATE)
draggableComponent.onDeactivate(target, visitor.getFoundComponent(), new SpecialKeys(request));
}
if (dragEventType == EventType.DROP)
onDrop(target, visitor.getFoundComponent(), new SpecialKeys(request));
else if (dragEventType == EventType.DROP_ACTIVATE)
onActivate(target, visitor.getFoundComponent(), new SpecialKeys(request));
else if (dragEventType == EventType.DROP_DEACTIVATE)
onDeactivate(target, visitor.getFoundComponent(), new SpecialKeys(request));
}
}
/**
* This method is called when a draggable {@link Component} is dropped onto
* a {@link Component} marked with this behavior.
*
* @param target the AjaxRequestTarget of the drop operation.
* @param draggedComponent The dragged component
* @param specialKeys the special keys that were pressed when the event occurs
*/
protected void onDrop(AjaxRequestTarget target, final Component draggedComponent, final SpecialKeys specialKeys) {}
/**
* This method is called when a draggable {@link Component} is starting to
* drag and the dragging {@link Component}'s name is accepted to be
* dropped onto this.
*
* @param target The {@link AjaxRequestTarget} associated with this
* drop operation.
* @param draggedComponent The dragged component
* @param specialKeys the special keys that were pressed when the event occurs
*/
protected void onActivate(final AjaxRequestTarget target, final Component draggedComponent, final SpecialKeys specialKeys) {}
/**
* This method is called when a draggable {@link Component} has stopped
* dragging and the dragging {@link Component}'s name was accepted to be
* dropped onto this.
*
* @param target The {@link AjaxRequestTarget} associated with this
* drop operation.
* @param draggedComponent The dragged component
* @param specialKeys the special keys that were pressed when the event occurs
*/
protected void onDeactivate(final AjaxRequestTarget target, final Component draggedComponent, final SpecialKeys specialKeys) {}
/**
* Disable the dropping
*
* @param target An AjaxRequestTarget
*/
public void disable(final AjaxRequestTarget target) {
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('disable');");
}
/**
* Enable the dropping
*
* @param target An AjaxRequestTarget
*/
public void enable(final AjaxRequestTarget target) {
target.appendJavascript("jQuery('#" + getComponent().getMarkupId() + "').droppable('enable');");
}
// We need to render the drop accept checker function only once
private boolean dropAcceptedCheckerRendered = false;
/**
* @see org.apache.wicket.behavior.AbstractAjaxBehavior#renderHead(org.apache.wicket.markup.html.IHeaderResponse)
*/
@Override
public void renderHead(final IHeaderResponse response) {
super.renderHead(response);
if (draggablesAcceptedByDroppable != null && ! dropAcceptedCheckerRendered) {
draggablesAcceptedByDroppable.renderJsDropAcceptFunction(response);
dropAcceptedCheckerRendered = true;
}
}
@Override
/**
* For internal use only.
*/
protected JsBuilder getJsBuilder() {
if (onDeactivateNotificationWanted)
options.put("deactivate",
new JsFunction("function(ev,ui) { \n"+
"wicketAjaxGet('" +
this.getCallbackUrl() +
"&" + EventType.IDENTIFIER + "=" + EventType.DROP_DEACTIVATE +
"&" + DROPPED_COMPONENTID_IDENTIFIER + "='+jQuery(ui.draggable).attr('id')" +
"+'&keys='+jQuery.jWicketSpecialKeysGetPressed()" +
"); }"));
options.put("drop",
new JsFunction("function(ev,ui) { \n"+
"wicketAjaxGet('" +
this.getCallbackUrl() +
"&" + EventType.IDENTIFIER + "=" + EventType.DROP +
"&" + DROPPED_COMPONENTID_IDENTIFIER + "='+jQuery(ui.draggable).attr('id')" +
"+'&keys='+jQuery.jWicketSpecialKeysGetPressed()" +
"); " +
"}"));
if (onActivatedNotificationWanted)
options.put("activate",
new JsFunction("function(ev,ui) { \n"+
"wicketAjaxGet('" +
this.getCallbackUrl() +
"&" + EventType.IDENTIFIER + "=" + EventType.DROP_ACTIVATE +
"&" + DROPPED_COMPONENTID_IDENTIFIER + "='+jQuery(ui.draggable).attr('id')" +
"+'&keys='+jQuery.jWicketSpecialKeysGetPressed()" +
"); }"));
JsBuilder builder = new JsBuilder();
builder.append("jQuery('#" + getComponent().getMarkupId() + "').droppable(");
builder.append("{");
builder.append(options.toString(rawOptions));
builder.append("}");
builder.append(");");
return builder;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy