-
Notifications
You must be signed in to change notification settings - Fork 37
Home
Katavorio is a lightweight drag/drop handler, supporting containment, multiple element drag, custom css classes, drop filters, drag filters, drag clones, drag handles, constraining movement to a grid, and zooming.
Currently, Katavorio does not work "out of the box" - it was developed as part of jsPlumb 1.6.0, to support a "no dependency" version (all previous versions of jsPlumb required either jQuery, MooTools or YUI, to provide a bunch of functionality such as CSS manipulation, getting/setting element positions, supporting drag/drop etc). So, rather than re-write simple methods such as addClass
, removeClass
, getPosition
etc, Katavorio expects those methods to be provided in the constructor's options object.
All is not lost, though, as this project also contains DefaultKatavorioHelper
- the set of missing methods.
- Usage
- CSS
- Drag and Drop Scope
- Parent Constrain
- Grid Movement
- AdHoc Grid Snap
- Drag with a clone
- Filtering by element
- Filter Exclude vs Include
- Drag Handles
- Right mouse button
- Consuming filtered events
- Zoom
- Drop Precedence
First you need to instantiate an instance of Katavorio:
var k = new Katavorio({ options });
Katavorio attaches various CSS classes to elements, both at initialisation time, and on a few events during the drag/drop lifecycle:
class | default> | description |
---|---|---|
draggable | katavorio-draggable | Draggable elements |
droppable | katavorio-droppable | droppable elements |
drag | katavorio-drag | elements currently being dragged |
selected | katavorio-drag-selected | elements in current drag selection |
active | katavorio-drag-active | droppables that are targets of a currently dragged element |
hover | katavorio-drag-hover | droppables over which a matching drag element is hovering |
noSelect | katavorio-drag-no-select | added to the body to provide a hook to suppress text selection |
You can override any or all of these events by providing a JS object with the key css
to the Katavorio constructor:
var k = new Katavorio({
...,
css:{
drag:"CurrentlyBeingDraggedClass",
hover:"SomeoneIsHoveringOnMeClass"
},
...
});
You can also override the class that is set on an element currently being dragged when you make the call to draggable
:
var k = new Katavorio( ...options... );
k.draggable(someElement, {
dragClass:"CustomDragClass"
});
Similiarly, you can override the hover/active classes that are set on a droppable element:
var k = new Katavorio( ...options... );
k.droppable(someElement, {
activeClass:"CustomActiveClass",
hoverClass:"CustomHoverClass AndAnotherClass Etc"
});
Note that in all cases, Katavorio supports multiple CSS classes, via a whitespace-separated string.
Katavorio supports multiple scopes for each Drag and Drop. By default, a Katavorio instance will set a single scope on each Drag and Drop. The default value for this is katavorio-drag-scope. You can override it on a per-instance level by providing a scope in the constructor params:
var k = new Katavorio({
...
scope:"MyScope",
...
});
To constrain the movement of some draggable element to its parent, set constrain:true
in the draggable
call:
var k = new Katavorio({...options...});
k.draggable(someElement, {
constrain:true
});
To constrain the allowed placements of a draggable to a grid, provide a grid
in the draggable
call:
var k = new Katavorio({...options...});
k.draggable(someElement, {
grid:[30, 30]
});
You can snap all draggables to a grid at any point in time by calling the snapToGrid
method. If you provided a grid
for each draggable then by default the values from that grid will be used; alternatively you can override the values and provide your own. Failing both of these cases, defaults of 50px in each axis will be used:
Using the Katavorio instance configured above, this command will cause the elements to snap to a 30x30 grid:
k.snapToGrid();
This will override the default grid and specify 10x10:
k.snapToGrid(10, 10);
If you want to drag a clone of your element, set clone:true
on the draggable
call:
var k = new Katavorio({...options...});
k.draggable(someElement, {
clone:true
});
You can provide a filter
parameter to the draggable
method - a string selector defining an
element or set of elements from which dragging is not enabled:
var k = new Katavorio({ ...options... });
k.draggable(someElement, {
filter:"button"
});
Here we have told Katavorio to make someElement
draggable, but not to start a drag if the
mouse is on any child elements that are buttons.
Valid values for the filter
argument are any valid CSS selectors.
By default, Katavorio uses a supplied filter to exclude elements from initiating a drag. However, there are limitations with CSS3 filters, for instance the :not
selector only supports what are called "simple selectors",
meaning they contain a single term, such as :not(.someClass)
or :not(button)
. :not(.someClass > div)
, though,
contains more than one term and isn't supported.
To cater for limitations such as this, you can set filterExclude:false
on your draggable
call, and then the supplied
filter
is assumed to refer to elements that should initiate a drag. An example:
k.draggable(someElement, {
filter:":not(.someClass > div)"
};
The above will not work, per the explanation given in the preceding paragraph. The intention is to tell Katavorio that if
the mouse is not down on an immediate child of an element having class someClass, then drag should not begin.
Using filterExclude:false
we can rewrite this as follows:
k.draggable(someElement, {
filter:".someClass > div",
filterExclude:false
};
Katavorio also lets you provide a handle
parameter, which is treated as a filter
with filterExclude:false
. So, this
example from above:
k.draggable(someElement, {
filter:".someClass > div",
filterExclude:false
};
can be achieved like this:
k.draggable(someElement, {
handle:".someClass > div"
};
Note: You cannot combine filter
and handle
. If handle
is provided then it will be used and filter
will be
ignored. Also, remember that providing handle
means filterExclude
is implicitly set to false.
By default, Katavorio does not respond to the right mouse button. You can override this behaviour by providing a rightButtonCanDrag
parameter to the Katavorio constructor:
var k = new Katavorio({
rightButtonCanDrag:true
});
Note that due to the right mouse button generally being assigned to the context menu in browsers, you will need to attach some event handler that independently prevents the default behaviour of the right click event.
If you set a filter, you can also tell Katavorio to consume any events that were filtered (otherwise they bubble up through the DOM).
var k = new Katavorio({ ...options... });
k.draggable(someElement, {
filter:"button",
consumeFilteredEvents:true
});
This causes Katavorio to call preventDefault()
and stopPropagation()
on events that were filtered (or to set the event's
returnValue
to false in IE < 9).
Katavorio takes zoom into account when dragging elements. This is not handled by attempting to infer what, if any, CSS3
transform is affecting some dragged object. Rather, you handle this manually by calling the setZoom
method to tell Katavorio
that there is a scale transform in effect.
setZoom
takes decimal values where 1.0 means 100%.
It may be the case that you wish to configure some element to be draggable and have it not be subject to the current zoom
transformation. To do this, you can set ignoreZoom:true
on the draggable
call:
var k = new Katavorio({ ...options... });
...
...
k.draggable(someElement, {
filter:"button",
ignoreZoom:true
});
Katavorio publishes events at three times during the drag lifecycle. You bind to them in the draggable
call:
var k = new Katavorio({ options });
k.draggable(someElement, {
start:function(params) {
},
drag:function(params) {
},
stop:function(params) {
}
})
The contents of params
are as follows:
- drag The associated Drag instance
- e The associated MouseEvent
- el The element that is being dragged.
-
pos [x,y] location of the element. Only supplied by the
drag
event.
Katavorio allows for drops to occur on multiple elements: any element whose bounding box contains the location of the mouseup event is a candidate. A given Drop
can claim the event for itself by returning true
from the drop
callback:
katavorioInstance.droppable(someElement, {
drop:function() {
// do some codes
return true;
}
});
This is only guaranteed to work, though, if some other Drop
does not first claim the event. The order of the list of candidate droppables corresponds with the order in which the related elements were made droppable, so you can control it that way, if you're up for a bit of admin. Another thing you can do is to give Katavorio a hint on how to order the candidate droppables when a drop event occurs. Consider this HTML:
<div id="parent">
<h1>Foo</h1>
<div id="child"> ... </div>
</div>
We're going to make both of these elements into droppables. If a drop event occurs over the #child
element, we always want the #child
droppable to get the event, never the parent. But of course an event that occurs over the child also occurs over the parent. As mentioned above, we could control this by configuring the child as a droppable before the parent. But in the real world it isn't always possible to control things like that. So in this case (and showing parent
being configured first), we could use rank
:
katavorioInstance.droppable(parent, {
drop:function() {
...
return true;
},
rank:1
});
katavorioInstance.droppable(child, {
drop:function() {
...
return true;
},
rank:10
});
With this arrangement you will ensure the #child
element always overrides the #parent
element when responding to a drop event over the child. The default value for rank
is zero, and negative numbers are supported, so in this example we could have left rank
off of the #child
droppable and just set it to some negative value for the #parent
droppable.