migrate context and context_list features. Drag and drop is still WIP

This commit is contained in:
Reinier Balt 2012-01-31 12:09:00 +01:00
parent de309c8ee8
commit 4a8fdbabc2
12 changed files with 246 additions and 94 deletions

View file

@ -0,0 +1,163 @@
(function($) {
/*
* Simulate drag of a JQuery UI sortable list
* Repository: https://github.com/mattheworiordan/jquery.simulate.drag-sortable.js
* Author: http://mattheworiordan.com
*
* options are:
* - move: move item up (positive) or down (negative) by Integer amount
* - handle: selector for the draggable handle element (optional)
* - listItem: selector to limit which sibling items can be used for reordering
* - placeHolder: if a placeholder is used during dragging, we need to consider it's height
*
*/
$.fn.simulateDragSortable = function(options) {
// build main options before element iteration
var opts = $.extend({}, $.fn.simulateDragSortable.defaults, options);
// iterate and move each matched element
return this.each(function() {
// allow for a drag handle if item is not draggable
var that = this,
handle = opts.handle ? $(this).find(opts.handle)[0] : $(this)[0],
listItem = opts.listItem,
placeHolder = opts.placeHolder,
sibling = $(this),
moveCounter = Math.floor(opts.move),
direction = moveCounter > 0 ? 'down' : 'up',
moveVerticalAmount = 0,
dragPastBy = 0;
if (moveCounter === 0) { return; }
while (moveCounter !== 0) {
if (direction === 'down') {
if (sibling.next(listItem).length) {
sibling = sibling.next(listItem);
moveVerticalAmount += sibling.outerHeight();
}
moveCounter -= 1;
} else {
if (sibling.prev(listItem).length) {
sibling = sibling.prev(listItem);
moveVerticalAmount -= sibling.outerHeight();
}
moveCounter += 1;
}
}
var center = findCenter(handle);
var x = Math.floor(center.x), y = Math.floor(center.y);
dispatchEvent(handle, 'mousedown', createEvent('mousedown', handle, { clientX: x, clientY: y }));
// simulate drag start
dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x+1, clientY: y+1 }));
// Sortable is using a fixed height placeholder meaning items jump up and down as you drag variable height items into fixed height placeholder
placeHolder = placeHolder && $(this).parent().find(placeHolder);
if (placeHolder && placeHolder.length) {
// we're going to move past it, and back again
moveVerticalAmount += (direction === 'down' ? -1 : 1) * Math.min($(this).outerHeight() / 2, 5);
// Sortable UI bug when dragging down and place holder exists. You need to drag past by the total height of this
// and then drag back to the right point
dragPastBy = (direction === 'down' ? 1 : -1) * $(this).outerHeight() / 2;
} else {
// no place holder
if (direction === 'down') {
// need to move at least as far as this item and or the last sibling
if ($(this).outerHeight() > $(sibling).outerHeight()) {
moveVerticalAmount += $(this).outerHeight() - $(sibling).outerHeight();
}
moveVerticalAmount += $(sibling).outerHeight() / 2;
} else {
// move a little extra to ensure item clips into next position
moveVerticalAmount -= Math.min($(this).outerHeight() / 2, 5);
}
}
if (sibling[0] !== $(this)[0]) {
// step through so that the UI controller can determine when to show the placeHolder
var targetOffset = moveVerticalAmount + dragPastBy;
for (var offset = 0; Math.abs(offset) < Math.abs(targetOffset); offset += (direction === 'down' ? 10 : -10)) {
// drag move
dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y + offset }));
}
dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y + targetOffset }));
} else {
if (window.console) {
console.log('Could not move as at top or bottom already');
}
}
setTimeout(function() {
dispatchEvent(document, 'mousemove', createEvent('mousemove', document, { clientX: x, clientY: y + moveVerticalAmount }));
}, 5);
setTimeout(function() {
dispatchEvent(handle, 'mouseup', createEvent('mouseup', handle, { clientX: x, clientY: y + moveVerticalAmount }));
}, 10);
});
};
function createEvent(type, target, options) {
var evt;
var e = $.extend({
target: target,
preventDefault: function() { },
stopImmediatePropagation: function() { },
stopPropagation: function() { },
isPropagationStopped: function() { return true; },
isImmediatePropagationStopped: function() { return true; },
isDefaultPrevented: function() { return true; },
bubbles: true,
cancelable: (type != "mousemove"),
view: window,
detail: 0,
screenX: 0,
screenY: 0,
clientX: 0,
clientY: 0,
ctrlKey: false,
altKey: false,
shiftKey: false,
metaKey: false,
button: 0,
relatedTarget: undefined
}, options || {});
if ($.isFunction(document.createEvent)) {
evt = document.createEvent("MouseEvents");
evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,
e.screenX, e.screenY, e.clientX, e.clientY,
e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
e.button, e.relatedTarget || document.body.parentNode);
} else if (document.createEventObject) {
evt = document.createEventObject();
$.extend(evt, e);
evt.button = { 0:1, 1:4, 2:2 }[evt.button] || evt.button;
}
return evt;
}
function dispatchEvent(el, type, evt) {
if (el.dispatchEvent) {
el.dispatchEvent(evt);
} else if (el.fireEvent) {
el.fireEvent('on' + type, evt);
}
return evt;
}
function findCenter(el) {
var el = $(el), o = el.offset();
return {
x: o.left + el.outerWidth() / 2,
y: o.top + el.outerHeight() / 2
};
}
//
// plugin defaults
//
$.fn.simulateDragSortable.defaults = {
move: 0
};
})(jQuery);