| 6 |
|
|
| 7 |
(function($) { |
(function($) { |
| 8 |
|
|
| 9 |
|
//Make nodes selectable by expression |
| 10 |
|
$.extend($.expr[':'], { sortable: "(' '+a.className+' ').indexOf(' ui-sortable ')" }); |
| 11 |
|
|
| 12 |
$.fn.sortable = function(o) { |
$.fn.sortable = function(o) { |
| 13 |
return this.each(function() { |
return this.each(function() { |
| 14 |
new $.ui.sortable(this,o); |
new $.ui.sortable(this,o); |
| 15 |
}); |
}); |
|
}, |
|
|
$.fn.stopAll = function() { |
|
|
return this.each(function(){ |
|
|
if (this.queue) { |
|
|
if (this.queue['fx']) { |
|
|
if (this.queue['fx'][0]) { |
|
|
this.queue['fx'] = [this.queue['fx'][0]]; |
|
|
this.queue['fx'][0].startTime = (new Date()).getTime() - 1000000000; |
|
|
} |
|
|
} |
|
|
} |
|
|
}); |
|
| 16 |
} |
} |
| 17 |
|
|
| 18 |
|
//Macros for external methods that support chaining |
| 19 |
|
var methods = "destroy,enable,disable,refresh".split(","); |
| 20 |
|
for(var i=0;i<methods.length;i++) { |
| 21 |
|
var cur = methods[i], f; |
| 22 |
|
eval('f = function() { var a = arguments; return this.each(function() { if(jQuery(this).is(".ui-sortable")) jQuery.data(this, "ui-sortable")["'+cur+'"](a); }); }'); |
| 23 |
|
$.fn["sortable"+cur.substr(0,1).toUpperCase()+cur.substr(1)] = f; |
| 24 |
|
}; |
| 25 |
|
|
| 26 |
|
//get instance method |
| 27 |
|
$.fn.sortableInstance = function() { |
| 28 |
|
if($(this[0]).is(".ui-sortable")) return $.data(this[0], "ui-sortable"); |
| 29 |
|
return false; |
| 30 |
|
}; |
| 31 |
|
|
| 32 |
$.ui.sortable = function(el,o) { |
$.ui.sortable = function(el,o) { |
| 33 |
|
|
| 34 |
this.element = el; |
this.element = el; |
| 35 |
this.set = []; |
this.set = []; |
| 36 |
var options = {}; |
var options = {}; |
| 37 |
var self = this; |
var self = this; |
| 38 |
|
$.data(this.element, "ui-sortable", this); |
| 39 |
|
$(el).addClass("ui-sortable"); |
| 40 |
|
|
| 41 |
$.extend(options, o); |
$.extend(options, o); |
| 42 |
$.extend(options, { |
$.extend(options, { |
| 43 |
items: options.items || '> li', |
items: options.items || '> li', |
| 44 |
|
smooth: options.smooth != undefined ? options.smooth : true, |
| 45 |
helper: 'clone', |
helper: 'clone', |
| 46 |
containment: options.containment ? (options.containment == 'sortable' ? el : options.containment) : null, |
containment: options.containment ? (options.containment == 'sortable' ? el : options.containment) : null, |
| 47 |
zIndex: options.zIndex || 1000, |
zIndex: options.zIndex || 1000, |
| 53 |
}, |
}, |
| 54 |
_drag: function(h,p,c,t,e) { |
_drag: function(h,p,c,t,e) { |
| 55 |
self.drag.apply(t, [self, e]); // Trigger the onStart callback |
self.drag.apply(t, [self, e]); // Trigger the onStart callback |
| 56 |
|
}, |
| 57 |
|
startCondition: function() { |
| 58 |
|
return !self.disabled; |
| 59 |
} |
} |
| 60 |
}); |
}); |
| 61 |
|
|
| 62 |
//Get the items |
//Get the items |
| 63 |
self.set = $(options.items, el).each(function() { |
var items = $(options.items, el); |
|
new $.ui.mouseInteraction(this,options); |
|
|
}); |
|
| 64 |
|
|
| 65 |
//Let's determine the floating mode |
//Let's determine the floating mode |
| 66 |
options.floating = /left|right/.test(self.set.css('float')); |
options.floating = /left|right/.test(items.css('float')); |
|
options.animated = options.animated && self.set.css('position') == 'relative'; |
|
| 67 |
|
|
| 68 |
//Let's determine the parent's offset |
//Let's determine the parent's offset |
| 69 |
if($(el).css('position') == 'static') $(el).css('position', 'relative'); |
if($(el).css('position') == 'static') $(el).css('position', 'relative'); |
| 70 |
options.offset = $(el).offset({ border: false }); |
options.offset = $(el).offset({ border: false }); |
| 71 |
|
|
| 72 |
|
items.each(function() { |
| 73 |
|
new $.ui.mouseInteraction(this,options); |
| 74 |
|
}); |
| 75 |
|
|
| 76 |
|
//Add current items to the set |
| 77 |
|
items.each(function() { |
| 78 |
|
self.set.push([this,null]); |
| 79 |
|
}); |
| 80 |
|
|
| 81 |
this.options = options; |
this.options = options; |
| 82 |
} |
} |
| 83 |
|
|
| 84 |
$.extend($.ui.sortable.prototype, { |
$.extend($.ui.sortable.prototype, { |
| 85 |
plugins: {}, |
plugins: {}, |
|
pos: null, |
|
|
opos: null, |
|
| 86 |
currentTarget: null, |
currentTarget: null, |
| 87 |
lastTarget: null, |
lastTarget: null, |
|
helper: null, |
|
|
timer: null, |
|
|
slowMode: false, |
|
|
element: null, |
|
|
init: false, |
|
| 88 |
prepareCallbackObj: function(self, that) { |
prepareCallbackObj: function(self, that) { |
| 89 |
return { |
return { |
| 90 |
helper: self.helper, |
helper: self.helper, |
| 120 |
|
|
| 121 |
}, |
}, |
| 122 |
destroy: function() { |
destroy: function() { |
| 123 |
|
$(this.element).removeClass("ui-sortable").removeClass("ui-sortable-disabled"); |
| 124 |
|
$(this.options.items, this.element).mouseInteractionDestroy(); |
| 125 |
|
|
| 126 |
}, |
}, |
| 127 |
|
enable: function() { |
| 128 |
|
$(this.element).removeClass("ui-sortable-disabled"); |
| 129 |
|
this.disabled = false; |
| 130 |
|
}, |
| 131 |
|
disable: function() { |
| 132 |
|
$(this.element).addClass("ui-sortable-disabled"); |
| 133 |
|
this.disabled = true; |
| 134 |
|
}, |
| 135 |
start: function(that, e) { |
start: function(that, e) { |
| 136 |
|
|
| 137 |
var o = this.options; |
var o = this.options; |
| 138 |
//cache each elements position. When we insert an element before or after the actual position will not coutn anymore TODO cache elements position for each active sortable |
|
|
that.cachedItemsPos = []; |
|
|
//remember container position |
|
|
that.pos = $(that.element).offset({ border: false}); |
|
|
that.set = $(that.options.items, that.element).not(':last').each(function(nr){ |
|
|
that.cachedItemsPos[nr] = { |
|
|
x: this.offsetLeft, |
|
|
y: this.offsetTop, |
|
|
w: this.offsetWidth, |
|
|
h: this.offsetHeight |
|
|
}; |
|
|
}); |
|
|
o.lastOverlap = -1; |
|
|
o.movedElement = null; |
|
|
|
|
|
|
|
|
$.ui.plugin.call('start', this); |
|
| 139 |
if(o.hoverClass) { |
if(o.hoverClass) { |
| 140 |
that.helper = $('<div class="'+o.hoverClass+'"></div>').appendTo('body').css({ |
that.helper = $('<div class="'+o.hoverClass+'"></div>').appendTo('body').css({ |
| 141 |
height: this.element.offsetHeight+'px', |
height: this.element.offsetHeight+'px', |
| 143 |
position: 'absolute' |
position: 'absolute' |
| 144 |
}); |
}); |
| 145 |
} |
} |
| 146 |
|
|
| 147 |
if(o.zIndex) { |
if(o.zIndex) { |
| 148 |
if($(this.helper).css("zIndex")) o.ozIndex = $(this.helper).css("zIndex"); |
if($(this.helper).css("zIndex")) o.ozIndex = $(this.helper).css("zIndex"); |
| 149 |
$(this.helper).css('zIndex', o.zIndex); |
$(this.helper).css('zIndex', o.zIndex); |
| 150 |
} |
} |
|
that.firstSibling = $(this.element).prev()[0]; |
|
| 151 |
|
|
| 152 |
if(o.start) o.start.apply(this.element, [this.helper, this.pos, o.cursorAt, this]); |
that.firstSibling = $(this.element).prev()[0]; |
| 153 |
|
|
| 154 |
$(this.element).triggerHandler("sortstart", [e, that.prepareCallbackObj(this)], o.start); |
$(this.element).triggerHandler("sortstart", [e, that.prepareCallbackObj(this)], o.start); |
| 155 |
$(this.element).css('visibility', 'hidden'); |
$(this.element).css('visibility', 'hidden'); |
| 156 |
|
|
| 157 |
return false; |
return false; |
| 158 |
|
|
| 159 |
}, |
}, |
| 160 |
stop: function(that, e) { |
stop: function(that, e) { |
| 161 |
|
|
| 162 |
var o = this.options; |
var o = this.options; |
| 163 |
|
var self = this; |
| 164 |
|
|
| 165 |
$.ui.plugin.call('stop', this); |
|
| 166 |
$(this.element).css('visibility', 'visible'); |
if(o.smooth) { |
| 167 |
|
var os = $(this.element).offset(); |
| 168 |
if(that.helper) |
o.beQuietAtEnd = true; |
| 169 |
that.helper.remove(); |
$(this.helper).animate({ left: os.left - o.po.left, top: os.top - o.po.top }, 500, stopIt); |
| 170 |
|
} else { |
| 171 |
if(o.ozIndex) |
stopIt(); |
| 172 |
$(this.helper).css('zIndex', o.ozIndex); |
} |
|
|
|
| 173 |
|
|
| 174 |
//Let's see if the position in DOM has changed |
function stopIt() { |
| 175 |
if($(this.element).prev()[0] != that.firstSibling) { |
|
| 176 |
$(this.element).triggerHandler("sortupdate", [e, that.prepareCallbackObj(this, that)], o.update); |
$(self.element).css('visibility', 'visible'); |
| 177 |
|
if(that.helper) that.helper.remove(); |
| 178 |
|
if(self.helper != self.element) $(self.helper).remove(); |
| 179 |
|
|
| 180 |
|
if(o.ozIndex) |
| 181 |
|
$(self.helper).css('zIndex', o.ozIndex); |
| 182 |
|
|
| 183 |
|
|
| 184 |
|
//Let's see if the position in DOM has changed |
| 185 |
|
if($(self.element).prev()[0] != that.firstSibling) { |
| 186 |
|
//$(self.element).triggerHandler("sortupdate", [e, that.prepareCallbackObj(self, that)], o.update); |
| 187 |
|
} |
| 188 |
|
|
| 189 |
} |
} |
| 190 |
//clear previous cache TODO: clear al active sortables |
|
| 191 |
that.cachedItemsPos = null; |
|
|
that.pos = null; |
|
|
o.lastOverlap = false; |
|
| 192 |
return false; |
return false; |
| 193 |
|
|
| 194 |
}, |
}, |
| 195 |
drag: function(that, e) { |
drag: function(that, e) { |
| 196 |
// remember the dragged element. We need this to exclude this one from items we check against |
|
|
draggedEl = this.element; |
|
| 197 |
var o = this.options; |
var o = this.options; |
|
this.pos = [this.pos[0]-o.cursorAt.left, this.pos[1]-o.cursorAt.top]; |
|
|
$.ui.plugin.call('drag', this); |
|
| 198 |
|
|
| 199 |
|
this.pos = [this.pos[0]-(o.cursorAt.left ? o.cursorAt.left : 0), this.pos[1]-(o.cursorAt.top ? o.cursorAt.top : 0)]; |
| 200 |
var nv = $(this.element).triggerHandler("sort", [e, that.prepareCallbackObj(this)], o.sort); |
var nv = $(this.element).triggerHandler("sort", [e, that.prepareCallbackObj(this)], o.sort); |
| 201 |
var nl = (nv && nv.left) ? nv.left : this.pos[0]; |
var nl = (nv && nv.left) ? nv.left : this.pos[0]; |
| 202 |
var nt = (nv && nv.top) ? nv.top : this.pos[1]; |
var nt = (nv && nv.top) ? nv.top : this.pos[1]; |
| 203 |
//overlaped element |
|
| 204 |
var targetIndex = null; |
|
| 205 |
//overlap index |
var m = that.set; |
| 206 |
var targetOverlap = null; |
var p = this.pos[1]; |
| 207 |
|
|
| 208 |
that.set.each(function(nr){ |
for(var i=0;i<m.length;i++) { |
| 209 |
if (o.lastOverlap == this || targetIndex != null) |
|
| 210 |
return; |
var ci = $(m[i][0]); var cio = m[i][0]; |
| 211 |
if(that.options.floating) { |
if(this.element.contains(cio)) continue; |
| 212 |
elPosition = that.pos.left + that.cachedItemsPos[nr].x; |
var cO = ci.offset(); //TODO: Caching |
| 213 |
elDimension = that.cachedItemsPos[nr].w; |
cO = { top: cO.top, left: cO.left }; |
| 214 |
curPosition = e.pageX; |
|
| 215 |
overlapY = (e.pageY - that.pos.top - that.cachedItemsPos[nr].y) / that.cachedItemsPos[nr].h; |
var mb = function(e) { if(true || o.lba != cio) { ci.before(e); o.lba = cio; } } |
| 216 |
overlapY = overlapY >= 0 && overlapY <=1; |
var ma = function(e) { if(true || o.laa != cio) { ci.after(e); o.laa = cio; } } |
| 217 |
|
|
| 218 |
|
if(o.floating) { |
| 219 |
|
|
| 220 |
|
var overlap = ((cO.left - (this.pos[0]+(this.options.po ? this.options.po.left : 0)))/this.helper.offsetWidth); |
| 221 |
|
|
| 222 |
|
if(!(cO.top < this.pos[1]+(this.options.po ? this.options.po.top : 0) + cio.offsetHeight/2 && cO.top + cio.offsetHeight > this.pos[1]+(this.options.po ? this.options.po.top : 0) + cio.offsetHeight/2)) continue; |
| 223 |
|
|
| 224 |
} else { |
} else { |
| 225 |
elPosition = that.pos.top + that.cachedItemsPos[nr].y; |
|
| 226 |
elDimension = that.cachedItemsPos[nr].h; |
var overlap = ((cO.top - (this.pos[1]+(this.options.po ? this.options.po.top : 0)))/this.helper.offsetHeight); |
| 227 |
curPosition = e.pageY; |
|
| 228 |
overlapY = true; |
if(!(cO.left < this.pos[0]+(this.options.po ? this.options.po.left : 0) + cio.offsetWidth/2 && cO.left + cio.offsetWidth > this.pos[0]+(this.options.po ? this.options.po.left : 0) + cio.offsetWidth/2)) continue; |
| 229 |
} |
|
|
overlap = (curPosition - elPosition) / elDimension; |
|
|
if (overlap >= 0 && overlap <= 1 && overlapY) { |
|
|
targetIndex = nr; |
|
|
targetOverlap = overlap; |
|
|
} |
|
|
}); |
|
|
//one element was overlaped |
|
|
if (targetIndex != null) { |
|
|
where = 'after'; |
|
|
elementIndex = that.set.index(this.element); |
|
|
o.lastOverlap = that.set[targetIndex]; |
|
|
if (elementIndex > targetIndex || that.set[targetIndex] == this.element) { |
|
|
targetIndex --; |
|
|
} |
|
|
if (targetIndex < 0) { |
|
|
targetIndex = 0; |
|
|
where = 'before'; |
|
|
} |
|
|
if (o.animated) { |
|
|
toMoveIndex = targetIndex; |
|
|
if (o.lastIndex > targetIndex) { |
|
|
toMoveIndex = o.lastIndex ; |
|
|
} |
|
|
if (o.movedElement && o.movedElement[0] == that.set[toMoveIndex]) { |
|
|
o.movedElement |
|
|
.stopAll() |
|
|
.css({ |
|
|
top: 0, |
|
|
left: 0 |
|
|
}); |
|
|
} |
|
|
o.movedElement = $(that.set[toMoveIndex]); |
|
|
oldPos = { |
|
|
top: o.movedElement[0].offsetTop, |
|
|
left: o.movedElement[0].offsetLeft |
|
|
}; |
|
| 230 |
} |
} |
|
$(that.set[targetIndex])[where](this.element); |
|
| 231 |
|
|
| 232 |
if (o.animated) { |
if(overlap >= 0 && overlap <= 0.5) { //Overlapping at top |
| 233 |
o.movedElement.css({ |
ci.prev().length ? ma(this.element) : mb(this.element); |
|
top: oldPos.top - o.movedElement[0].offsetTop + 'px', |
|
|
left: oldPos.left - o.movedElement[0].offsetLeft + 'px' |
|
|
}).animate({ |
|
|
top: 0, |
|
|
left: 0 |
|
|
}, 500); |
|
|
o.lastIndex = targetIndex; |
|
| 234 |
} |
} |
| 235 |
|
|
| 236 |
|
if(overlap < 0 && overlap > -0.5) { //Overlapping at bottom |
| 237 |
|
ci.next()[0] == this.element ? mb(this.element) : ma(this.element); |
| 238 |
|
} |
| 239 |
|
|
| 240 |
} |
} |
| 241 |
|
|
| 242 |
//Let's see if the position in DOM has changed |
//Let's see if the position in DOM has changed |
| 246 |
} |
} |
| 247 |
|
|
| 248 |
if(that.helper) { //reposition helper if available |
if(that.helper) { //reposition helper if available |
| 249 |
var to = $(this.element).offsetLite({ border: false }); |
var to = $(this.element).offset(); |
| 250 |
that.helper.css({ |
that.helper.css({ |
| 251 |
top: to.top+'px', |
top: to.top+'px', |
| 252 |
left: to.left+'px' |
left: to.left+'px' |
| 253 |
}); |
}); |
| 254 |
} |
} |
| 255 |
|
|
|
|
|
| 256 |
$(this.helper).css('left', nl+'px').css('top', nt+'px'); // Stick the helper to the cursor |
$(this.helper).css('left', nl+'px').css('top', nt+'px'); // Stick the helper to the cursor |
| 257 |
return false; |
return false; |
| 258 |
|
|