Skip to content

Commit 411c500

Browse files
committed
add a Select2SortableWidget
1 parent 215dfd5 commit 411c500

File tree

10 files changed

+4661
-0
lines changed

10 files changed

+4661
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* HTML5 Sortable jQuery Plugin
3+
* https://github.com/voidberg/html5select2sortable
4+
*
5+
* Original code copyright 2012 Ali Farhadi.
6+
* This version is mantained by Alexandru Badiu <[email protected]>
7+
*
8+
* Thanks to the following contributors: andyburke, bistoco, daemianmack, drskullster, flying-sheep, OscarGodson, Parikshit N. Samant, rodolfospalenza, ssafejava
9+
*
10+
* Released under the MIT license.
11+
*/
12+
'use strict';
13+
14+
(function ($) {
15+
var dragging, draggingHeight, placeholders = $();
16+
$.fn.select2sortable = function (options) {
17+
var method = String(options);
18+
19+
options = $.extend({
20+
connectWith: false,
21+
placeholder: null,
22+
dragImage: null
23+
}, options);
24+
25+
return this.each(function () {
26+
27+
var index, items = $(this).children(options.items), handles = options.handle ? items.find(options.handle) : items;
28+
29+
if (method === 'reload') {
30+
$(this).children(options.items).off('dragstart.h5s dragend.h5s selectstart.h5s dragover.h5s dragenter.h5s drop.h5s');
31+
}
32+
if (/^enable|disable|destroy$/.test(method)) {
33+
var citems = $(this).children($(this).data('items')).attr('draggable', method === 'enable');
34+
if (method === 'destroy') {
35+
$(this).off('sortupdate');
36+
$(this).removeData('opts');
37+
citems.add(this).removeData('connectWith items')
38+
.off('dragstart.h5s dragend.h5s dragover.h5s dragenter.h5s drop.h5s').off('sortupdate');
39+
handles.off('selectstart.h5s');
40+
}
41+
return;
42+
}
43+
44+
var soptions = $(this).data('opts');
45+
46+
if (typeof soptions === 'undefined') {
47+
$(this).data('opts', options);
48+
}
49+
else {
50+
options = soptions;
51+
}
52+
53+
var startParent, newParent;
54+
var placeholder = ( options.placeholder === null ) ? $('<' + (/^ul|ol$/i.test(this.tagName) ? 'li' : 'div') + ' class="select2sortable-placeholder"/>') : $(options.placeholder).addClass('select2sortable-placeholder');
55+
56+
$(this).data('items', options.items);
57+
placeholders = placeholders.add(placeholder);
58+
if (options.connectWith) {
59+
$(options.connectWith).add(this).data('connectWith', options.connectWith);
60+
}
61+
62+
items.attr('role', 'option');
63+
items.attr('aria-grabbed', 'false');
64+
65+
// Setup drag handles
66+
handles.attr('draggable', 'true').not('a[href], img').on('selectstart.h5s', function() {
67+
if (this.dragDrop) {
68+
this.dragDrop();
69+
}
70+
return false;
71+
}).end();
72+
73+
// Handle drag events on draggable items
74+
items.on('dragstart.h5s', function(e) {
75+
var dt = e.originalEvent.dataTransfer;
76+
dt.effectAllowed = 'move';
77+
dt.setData('text', '');
78+
79+
if (options.dragImage && dt.setDragImage) {
80+
dt.setDragImage(options.dragImage, 0, 0);
81+
}
82+
83+
index = (dragging = $(this)).addClass('select2sortable-dragging').attr('aria-grabbed', 'true').index();
84+
draggingHeight = dragging.outerHeight();
85+
startParent = $(this).parent();
86+
dragging.parent().triggerHandler('sortstart', {item: dragging, startparent: startParent});
87+
}).on('dragend.h5s',function () {
88+
if (!dragging) {
89+
return;
90+
}
91+
dragging.removeClass('select2sortable-dragging').attr('aria-grabbed', 'false').show();
92+
placeholders.detach();
93+
newParent = $(this).parent();
94+
if (index !== dragging.index() || startParent.get(0) !== newParent.get(0)) {
95+
dragging.parent().triggerHandler('sortupdate', {item: dragging, oldindex: index, startparent: startParent, endparent: newParent});
96+
}
97+
dragging = null;
98+
draggingHeight = null;
99+
}).add([this, placeholder]).on('dragover.h5s dragenter.h5s drop.h5s', function(e) {
100+
if (!items.is(dragging) && options.connectWith !== $(dragging).parent().data('connectWith')) {
101+
return true;
102+
}
103+
if (e.type === 'drop') {
104+
e.stopPropagation();
105+
placeholders.filter(':visible').after(dragging);
106+
dragging.trigger('dragend.h5s');
107+
return false;
108+
}
109+
e.preventDefault();
110+
e.originalEvent.dataTransfer.dropEffect = 'move';
111+
if (items.is(this)) {
112+
var thisHeight = $(this).outerHeight();
113+
if (options.forcePlaceholderSize) {
114+
placeholder.height(draggingHeight);
115+
}
116+
117+
// Check if $(this) is bigger than the draggable. If it is, we have to define a dead zone to prevent flickering
118+
if (thisHeight > draggingHeight) {
119+
// Dead zone?
120+
var deadZone = thisHeight - draggingHeight, offsetTop = $(this).offset().top;
121+
if (placeholder.index() < $(this).index() && e.originalEvent.pageY < offsetTop + deadZone) {
122+
return false;
123+
}
124+
else if (placeholder.index() > $(this).index() && e.originalEvent.pageY > offsetTop + thisHeight - deadZone) {
125+
return false;
126+
}
127+
}
128+
129+
dragging.hide();
130+
$(this)[placeholder.index() < $(this).index() ? 'after' : 'before'](placeholder);
131+
placeholders.not(placeholder).detach();
132+
} else if (!placeholders.is(this) && !$(this).children(options.items).length) {
133+
placeholders.detach();
134+
$(this).append(placeholder);
135+
}
136+
return false;
137+
});
138+
});
139+
};
140+
})(jQuery);

0 commit comments

Comments
 (0)