1 if (window.Node && Node.prototype && !Node.prototype.contains) {
\r
2 Node.prototype.contains = function (arg) {
\r
3 return !!(this.compareDocumentPosition(arg) & 16)
\r
9 //Make nodes selectable by expression
\r
10 $.extend($.expr[':'], { sortable: "(' '+a.className+' ').indexOf(' ui-sortable ')" });
\r
12 $.fn.sortable = function(o) {
\r
13 return this.each(function() {
\r
14 new $.ui.sortable(this,o);
\r
18 //Macros for external methods that support chaining
\r
19 var methods = "destroy,enable,disable,refresh".split(",");
\r
20 for(var i=0;i<methods.length;i++) {
\r
21 var cur = methods[i], f;
\r
22 eval('f = function() { var a = arguments; return this.each(function() { if(jQuery(this).is(".ui-sortable")) jQuery.data(this, "ui-sortable")["'+cur+'"](a); }); }');
\r
23 $.fn["sortable"+cur.substr(0,1).toUpperCase()+cur.substr(1)] = f;
\r
26 //get instance method
\r
27 $.fn.sortableInstance = function() {
\r
28 if($(this[0]).is(".ui-sortable")) return $.data(this[0], "ui-sortable");
\r
32 $.ui.sortable = function(el,o) {
\r
38 $.data(this.element, "ui-sortable", this);
\r
39 $(el).addClass("ui-sortable");
\r
41 $.extend(options, o);
\r
43 items: options.items || '> li',
\r
44 smooth: options.smooth != undefined ? options.smooth : true,
\r
46 containment: options.containment ? (options.containment == 'sortable' ? el : options.containment) : null,
\r
47 zIndex: options.zIndex || 1000,
\r
48 _start: function(h,p,c,t,e) {
\r
49 self.start.apply(t, [self, e]); // Trigger the onStart callback
\r
51 _beforeStop: function(h,p,c,t,e) {
\r
52 self.stop.apply(t, [self, e]); // Trigger the onStart callback
\r
54 _drag: function(h,p,c,t,e) {
\r
55 self.drag.apply(t, [self, e]); // Trigger the onStart callback
\r
57 startCondition: function() {
\r
58 return !self.disabled;
\r
63 var items = $(options.items, el);
\r
65 //Let's determine the floating mode
\r
66 options.floating = /left|right/.test(items.css('float'));
\r
68 //Let's determine the parent's offset
\r
69 if($(el).css('position') == 'static') $(el).css('position', 'relative');
\r
70 options.offset = $(el).offset({ border: false });
\r
72 items.each(function() {
\r
73 new $.ui.mouseInteraction(this,options);
\r
76 //Add current items to the set
\r
77 items.each(function() {
\r
78 self.set.push([this,null]);
\r
81 this.options = options;
\r
84 $.extend($.ui.sortable.prototype, {
\r
86 currentTarget: null,
\r
88 prepareCallbackObj: function(self, that) {
\r
90 helper: self.helper,
\r
91 position: { left: self.pos[0], top: self.pos[1] },
\r
92 offset: self.options.cursorAt,
\r
95 options: self.options
\r
98 refresh: function() {
\r
102 var items = $(this.options.items, this.element);
\r
105 items.each(function() {
\r
107 for(var i=0;i<self.set.length;i++) { if(self.set[i][0] == this) old = true; }
\r
108 if(!old) unique.push(this);
\r
111 for(var i=0;i<unique.length;i++) {
\r
112 new $.ui.mouseInteraction(unique[i],self.options);
\r
115 //Add current items to the set
\r
117 items.each(function() {
\r
118 self.set.push([this,null]);
\r
122 destroy: function() {
\r
123 $(this.element).removeClass("ui-sortable").removeClass("ui-sortable-disabled");
\r
124 $(this.options.items, this.element).mouseInteractionDestroy();
\r
127 enable: function() {
\r
128 $(this.element).removeClass("ui-sortable-disabled");
\r
129 this.disabled = false;
\r
131 disable: function() {
\r
132 $(this.element).addClass("ui-sortable-disabled");
\r
133 this.disabled = true;
\r
135 start: function(that, e) {
\r
137 var o = this.options;
\r
140 that.helper = $('<div class="'+o.hoverClass+'"></div>').appendTo('body').css({
\r
141 height: this.element.offsetHeight+'px',
\r
142 width: this.element.offsetWidth+'px',
\r
143 position: 'absolute'
\r
148 if($(this.helper).css("zIndex")) o.ozIndex = $(this.helper).css("zIndex");
\r
149 $(this.helper).css('zIndex', o.zIndex);
\r
152 that.firstSibling = $(this.element).prev()[0];
\r
154 $(this.element).triggerHandler("sortstart", [e, that.prepareCallbackObj(this)], o.start);
\r
155 $(this.element).css('visibility', 'hidden');
\r
160 stop: function(that, e) {
\r
162 var o = this.options;
\r
164 var pos = this.pos; // patch
\r
167 var os = $(this.element).offset();
\r
168 o.beQuietAtEnd = true;
\r
169 $(this.helper).animate({ left: os.left - o.po.left, top: os.top - o.po.top }, 500, stopIt);
\r
174 function stopIt() {
\r
175 self.pos = pos; // patch
\r
177 $(self.element).css('visibility', 'visible');
\r
178 if(that.helper) that.helper.remove();
\r
179 if(self.helper != self.element) $(self.helper).remove();
\r
182 $(self.helper).css('zIndex', o.ozIndex);
\r
185 //Let's see if the position in DOM has changed
\r
186 if($(self.element).prev()[0] != that.firstSibling) {
\r
187 $(self.element).triggerHandler("sortupdate", [e, that.prepareCallbackObj(self, that)], o.update);
\r
189 $(self.element).triggerHandler("sortstop", [e, that.prepareCallbackObj(self, that)], o.stop); // patch
\r
196 drag: function(that, e) {
\r
198 var o = this.options;
\r
200 this.pos = [this.pos[0]-(o.cursorAt.left ? o.cursorAt.left : 0), this.pos[1]-(o.cursorAt.top ? o.cursorAt.top : 0)];
\r
201 var nv = $(this.element).triggerHandler("sort", [e, that.prepareCallbackObj(this)], o.sort);
\r
202 var nl = (nv && nv.left) ? nv.left : this.pos[0];
\r
203 var nt = (nv && nv.top) ? nv.top : this.pos[1];
\r
207 var p = this.pos[1];
\r
209 for(var i=0;i<m.length;i++) {
\r
211 var ci = $(m[i][0]); var cio = m[i][0];
\r
212 if(this.element.contains(cio)) continue;
\r
213 var cO = ci.offset(); //TODO: Caching
\r
214 cO = { top: cO.top, left: cO.left };
\r
216 var mb = function(e) { if(true || o.lba != cio) { ci.before(e); o.lba = cio; } }
\r
217 var ma = function(e) { if(true || o.laa != cio) { ci.after(e); o.laa = cio; } }
\r
221 var overlap = ((cO.left - (this.pos[0]+(this.options.po ? this.options.po.left : 0)))/this.helper.offsetWidth);
\r
223 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;
\r
227 var overlap = ((cO.top - (this.pos[1]+(this.options.po ? this.options.po.top : 0)))/this.helper.offsetHeight);
\r
229 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;
\r
233 if(overlap >= 0 && overlap <= 0.5) { //Overlapping at top
\r
234 ci.prev().length ? ma(this.element) : mb(this.element);
\r
237 if(overlap < 0 && overlap > -0.5) { //Overlapping at bottom
\r
238 ci.next()[0] == this.element ? mb(this.element) : ma(this.element);
\r
243 //Let's see if the position in DOM has changed
\r
244 if($(this.element).prev()[0] != that.lastSibling) {
\r
245 $(this.element).triggerHandler("sortchange", [e, that.prepareCallbackObj(this, that)], this.options.change);
\r
246 that.lastSibling = $(this.element).prev()[0];
\r
249 if(that.helper) { //reposition helper if available
\r
250 var to = $(this.element).offset();
\r
253 left: to.left+'px'
\r
257 $(this.helper).css('left', nl+'px').css('top', nt+'px'); // Stick the helper to the cursor
\r