Skip to content

Commit da943bf

Browse files
committed
[soc2009/admin-ui] Reordering selector inlines.
happy 4th! git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/admin-ui@11179 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent e0e60ef commit da943bf

File tree

7 files changed

+354
-22
lines changed

7 files changed

+354
-22
lines changed

django/contrib/admin/media/css/base.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,16 @@ table.orderable-initalized .order-cell, body>tr>td.order-cell {
350350
background-color: #F6F6F6;
351351
}
352352

353+
.dragHandle {
354+
height: 20px;
355+
width: 20px;
356+
float: right;
357+
cursor: move;
358+
background-color: #fff;
359+
border: 1px solid #f00;
360+
display: block;
361+
}
362+
353363
.empty_form {
354364
display: none;
355365
}

django/contrib/admin/media/css/forms.css

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,6 @@ fieldset.monospace textarea {
233233
width: 8em;
234234
}
235235

236-
.inline-related {
237-
position: relative;
238-
}
239-
240236
.inline-related h3 {
241237
margin: 0;
242238
color: #666;
@@ -247,10 +243,7 @@ fieldset.monospace textarea {
247243
}
248244

249245
.inline-related h3 span.delete {
250-
padding-left: 20px;
251-
position: absolute;
252-
top: 2px;
253-
right: 10px;
246+
float: right;
254247
}
255248

256249
.inline-related h3 span.delete label {
@@ -329,24 +322,26 @@ fieldset.monospace textarea {
329322
display: none;
330323
}
331324

332-
.inline-selector {
325+
ul.inline-selector {
333326
float: left;
334327
width: 19%;
328+
padding: 0;
335329
}
336330

337331
.inline-selector a, .inline-selector a:visited {
338332
color: #000;
339333
}
340334

341-
.inline-selector-item {
335+
li.inline-selector-item {
342336
background-color: #F6F6F6;
343337
border: 1px solid #E7E7E7;
344338
padding: 5px;
345339
margin: 7px 0px 7px 5px;
346340
font-size: 0.9em;
341+
list-style-type: none;
347342
}
348343

349-
.inline-selector-item:hover {
344+
li.inline-selector-item:hover {
350345
background-color: #C1DBFD;
351346
}
352347

@@ -360,7 +355,7 @@ fieldset.monospace textarea {
360355
float: right;
361356
}
362357

363-
.inline-selected {
358+
li.inline-selected {
364359
background-color: #9EB7D5;
365360
}
366361

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* .disableTextSelect - Disable Text Select Plugin
3+
*
4+
* Version: 1.1
5+
* Updated: 2007-11-28
6+
*
7+
* Used to stop users from selecting text
8+
*
9+
* Copyright (c) 2007 James Dempster (letssurf@gmail.com, http://www.jdempster.com/category/jquery/disabletextselect/)
10+
*
11+
* Dual licensed under the MIT (MIT-LICENSE.txt)
12+
* and GPL (GPL-LICENSE.txt) licenses.
13+
**/
14+
15+
/**
16+
* Requirements:
17+
* - jQuery (John Resig, http://www.jquery.com/)
18+
**/
19+
(function($){if($.browser.mozilla){$.fn.disableTextSelect=function(){return this.each(function(){$(this).css({"MozUserSelect":"none"})})};$.fn.enableTextSelect=function(){return this.each(function(){$(this).css({"MozUserSelect":""})})}}else{if($.browser.msie){$.fn.disableTextSelect=function(){return this.each(function(){$(this).bind("selectstart.disableTextSelect",function(){return false})})};$.fn.enableTextSelect=function(){return this.each(function(){$(this).unbind("selectstart.disableTextSelect")})}}else{$.fn.disableTextSelect=function(){return this.each(function(){$(this).bind("mousedown.disableTextSelect",function(){return false})})};$.fn.enableTextSelect=function(){return this.each(function(){$(this).unbind("mousedown.disableTextSelect")})}}}})(jQuery)
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
/*
2+
Copyright (c) 2009 Jordan Bach, http://www.utdallas.edu/~jrb048000/
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in
12+
all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
THE SOFTWARE.
21+
*/
22+
23+
/*
24+
List Reorder <http://www.utdallas.edu/~jrb048000/ListReorder/>
25+
26+
Enables drag-and-drop reordering of list items for any simple ordered <ol> or unordered <li> list.
27+
28+
Author: Jordan Bach
29+
Version: 0.1
30+
Created: January 1, 2009
31+
License: MIT License
32+
33+
Constructor
34+
$(expr).ListOrder(options)
35+
36+
Methods:
37+
makeDefaultOrder - sets the current list order to [0, 1, 2, ...]
38+
restoreOrder - returns the list to its original order
39+
40+
Events:
41+
listorderchanged - Fired after a list item is dropped. The 2nd argument
42+
is a jQuery object representing the list that fired the event.
43+
The 3rd argument is an array where the values represent
44+
the original index of each list item.
45+
46+
Options:
47+
itemHoverClass : 'itemHover',
48+
dragTargetClass : 'dragTarget',
49+
dropTargetClass : 'dropTarget',
50+
dragHandleClass : 'dragHandle'
51+
52+
*/
53+
54+
(function($){
55+
56+
$.fn.ListReorder = function (options) {
57+
58+
$.fn.ListReorder.defaults = {
59+
itemHoverClass : 'itemHover',
60+
dragTargetClass : 'dragTarget',
61+
dropTargetClass : 'dropTarget',
62+
dragHandleClass : 'dragHandle',
63+
useDefaultDragHandle : false
64+
};
65+
66+
var opts = $.extend({}, $.fn.ListReorder.defaults, options);
67+
68+
return this.each(function() {
69+
var theList = $(this), // The list (<ul>|<ol>)
70+
theItems = $('li', theList), // All <li> elements in the list
71+
dragActive = false, // Are we currently dragging an item?
72+
dropTarget = null, // The list placeholder
73+
dragTarget = null, // The element currently being dragged
74+
dropIndex = -1, // The list index of the dropTarget
75+
offset = {}, // Positions the mouse in the dragTarget
76+
listOrder = [], // Keeps track of order relative to original order
77+
ref = this;
78+
79+
theList.mouseout(ul_mouseout);
80+
81+
// Create the drag target
82+
dragTarget = $('<div></div>');
83+
dragTarget.insertAfter(theList);
84+
dragTarget.hide();
85+
dragTarget.css('position', 'absolute');
86+
dragTarget.addClass(opts.dragTargetClass);
87+
88+
for (var i = 0; i < theItems.length; i++)
89+
listOrder.push(i);
90+
91+
resetList();
92+
93+
function resetList() {
94+
theItems = $('li', theList),
95+
96+
// For each <li> in the list
97+
theItems.each(function() {
98+
var li = $(this);
99+
100+
var dragHandle = $('<span></span>');
101+
dragHandle.addClass(opts.dragHandleClass)
102+
.mouseover(li_mouseover)
103+
.mousedown(dragHandle_mousedown);
104+
105+
if (opts.useDefaultDragHandle)
106+
dragHandle.css({
107+
'display' : 'block',
108+
'float' : 'right',
109+
'width' : '10px',
110+
'height' : '10px',
111+
'border' : '2px solid #333',
112+
'background' : '#ccc',
113+
'cursor' : 'move'
114+
});
115+
116+
$('.' + opts.dragHandleClass, li).remove();
117+
li.prepend(dragHandle);
118+
});
119+
120+
clearListItemStyles();
121+
}
122+
123+
// Return all list items to their default state
124+
function clearListItemStyles() {
125+
theItems.each(function() {
126+
var li = $(this);
127+
li.removeClass(opts.itemHoverClass);
128+
li.removeClass(opts.dropTargetClass);
129+
});
130+
}
131+
132+
// Handle any cleanup when the mouse leaves the list
133+
function ul_mouseout() {
134+
if (!dragActive)
135+
clearListItemStyles();
136+
}
137+
138+
// Add a hover class to a list item on mouseover
139+
function li_mouseover() {
140+
if (!dragActive) {
141+
clearListItemStyles();
142+
$(this).parent().addClass(opts.itemHoverClass);
143+
}
144+
}
145+
146+
// Prepare the list for dragging an item
147+
function dragHandle_mousedown(e) {
148+
var li = $(this).parent();
149+
150+
dragActive = true;
151+
dropIndex = theItems.index(li);
152+
153+
// Show the drag target
154+
dragTarget.html(li.html());
155+
dragTarget.css('display', 'block');
156+
offset.top = e.pageY - li.offset().top;
157+
offset.left = e.pageX - li.offset().left;
158+
updateDragTargetPos(e);
159+
160+
// Insert the placeholder
161+
dropTarget = li;
162+
dropTarget.html('');
163+
dropTarget.css('height', dragTarget.css('height'));
164+
dragTarget.css('width', dropTarget.width() + 'px');
165+
dropTarget.addClass(opts.dropTargetClass);
166+
167+
// Disable Text and DOM selection
168+
$(document).disableTextSelect();
169+
170+
$(document).mouseup(dragHandle_mouseup);
171+
$(document).mousemove(document_mousemove);
172+
}
173+
174+
// If this were on the element, we could lose the drag on the element
175+
// if we move the mouse too fast
176+
function document_mousemove(e) {
177+
if (dragActive) {
178+
// drag target follows mouse cursor
179+
updateDragTargetPos(e);
180+
181+
// Don't do mess with drop index if we are above or below the list
182+
if (y_mid(dragTarget) > y_bot(theList)
183+
|| y_mid(dragTarget) < y_top(theList)) {
184+
return;
185+
}
186+
187+
// detect position of drag target relative to list items
188+
// and swap drop target and neighboring item if necessary
189+
if (y_mid(dragTarget) + 5 < y_top(dropTarget)) {
190+
swapListItems(dropIndex, --dropIndex);
191+
} else if (y_mid(dragTarget) - 5 > y_bot(dropTarget)) {
192+
swapListItems(dropIndex, ++dropIndex);
193+
}
194+
}
195+
}
196+
197+
function dragHandle_mouseup() {
198+
// Restore the drop target
199+
dropTarget.html(dragTarget.html());
200+
dropTarget.removeClass(opts.dragTargetClass);
201+
dropTarget = null;
202+
203+
// Hide the drag target
204+
dragTarget.css('display', 'none');
205+
206+
dragActive = false;
207+
dragTarget.unbind('mouseup', dragHandle_mouseup);
208+
$(document).unbind('mousemove', document_mousemove);
209+
resetList();
210+
211+
theList.trigger('listorderchanged', [theList, listOrder]);
212+
213+
// Re-enable text selection
214+
$(document).enableTextSelect();
215+
$(document).unbind('mouseup', dragHandle_mouseup);
216+
}
217+
218+
function updateDragTargetPos(e) {
219+
dragTarget.css({
220+
'top' : e.pageY - offset.top + 'px',
221+
'left' : e.pageX - offset.left + 'px'
222+
});
223+
}
224+
225+
// Change the order of two list items
226+
function swapListItems(oldDropIndex, newDropIndex) {
227+
// keep indices in bounds
228+
if (dropIndex < 0) {
229+
dropIndex = 0;
230+
return;
231+
} else if (dropIndex >= theItems.length) {
232+
dropIndex = theItems.length - 1;
233+
return;
234+
}
235+
236+
var t = listOrder[oldDropIndex];
237+
listOrder[oldDropIndex] = listOrder[newDropIndex];
238+
listOrder[newDropIndex] = t;
239+
240+
// swap list items
241+
var oldDropTarget = theItems.get(oldDropIndex),
242+
newDropTarget = theItems.get(newDropIndex),
243+
temp1 = $(oldDropTarget).clone(true);
244+
temp2 = $(newDropTarget).clone(true);
245+
246+
$(oldDropTarget).replaceWith(temp2)
247+
.mouseover(li_mouseover)
248+
.mousedown(dragHandle_mousedown);
249+
$(newDropTarget).replaceWith(temp1)
250+
.mouseover(li_mouseover)
251+
.mousedown(dragHandle_mousedown);
252+
253+
// reset so it is valid on next use
254+
theItems = $('li', theList);
255+
dropTarget = $(theItems.get(newDropIndex));
256+
}
257+
258+
function y_top(jq) {
259+
return jq.offset().top;
260+
}
261+
262+
function y_mid(jq) {
263+
return (y_top(jq) + y_bot(jq)) / 2
264+
}
265+
266+
function y_bot(jq) {
267+
return jq.offset().top + jq.outerHeight();
268+
}
269+
270+
this.makeDefaultOrder = function() {
271+
for (var i = 0; i < listOrder.length; i++)
272+
listOrder[i] = i;
273+
}
274+
275+
this.restoreOrder = function() {
276+
for (var i = 0; i < theItems.length; i++) {
277+
if (i != listOrder[i]) {
278+
var k = 0;
279+
for (; k < listOrder.length; k++)
280+
if (listOrder[k] == i)
281+
break;
282+
swapListItems(i, k);
283+
}
284+
}
285+
theList.trigger('listorderchanged', [theList, listOrder]);
286+
}
287+
});
288+
}
289+
})(jQuery);

django/contrib/admin/options.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,8 @@ def _media(self):
11291129
if self.filter_vertical or self.filter_horizontal:
11301130
js.extend(['js/SelectBox.js' , 'js/SelectFilter2.js'])
11311131
if self.order_field:
1132-
js.append('js/jquery-tablednd.js')
1132+
js.extend(['js/jquery-tablednd.js', 'js/jquery-disable.text.select.pack.js',
1133+
'js/jquery-listreorder.js'])
11331134
return forms.Media(js=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in js])
11341135
media = property(_media)
11351136

0 commit comments

Comments
 (0)