Merged after-sort-callback branch and fixed conflicts.

master
Brandon Taylor 2018-06-18 11:41:20 -04:00
commit 5ad2c0e4ec
10 changed files with 258 additions and 194 deletions

View File

@ -32,6 +32,8 @@ class SortableAdminBase(object):
change_form_template_extends = 'admin/change_form.html' change_form_template_extends = 'admin/change_form.html'
change_list_template_extends = 'admin/change_list.html' change_list_template_extends = 'admin/change_list.html'
after_sorting_js_callback_name = None
def changelist_view(self, request, extra_context=None): def changelist_view(self, request, extra_context=None):
""" """
If the model that inherits Sortable has more than one object, If the model that inherits Sortable has more than one object,
@ -206,7 +208,11 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
except AttributeError: except AttributeError:
verbose_name_plural = opts.verbose_name_plural verbose_name_plural = opts.verbose_name_plural
context = self.admin_site.each_context(request) if VERSION <= (1, 7):
context = {}
else:
context = self.admin_site.each_context(request)
context.update({ context.update({
'title': u'Drag and drop {0} to change display order'.format( 'title': u'Drag and drop {0} to change display order'.format(
capfirst(verbose_name_plural)), capfirst(verbose_name_plural)),
@ -218,7 +224,8 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
'sortable_by_class_is_sortable': sortable_by_class_is_sortable, 'sortable_by_class_is_sortable': sortable_by_class_is_sortable,
'sortable_by_class_display_name': sortable_by_class_display_name, 'sortable_by_class_display_name': sortable_by_class_display_name,
'jquery_lib_path': jquery_lib_path, 'jquery_lib_path': jquery_lib_path,
'csrf_cookie_name': getattr(settings, 'CSRF_COOKIE_NAME', 'csrftoken') 'csrf_cookie_name': getattr(settings, 'CSRF_COOKIE_NAME', 'csrftoken'),
'after_sorting_js_callback_name': self.after_sorting_js_callback_name
}) })
return render(request, self.sortable_change_list_template, context) return render(request, self.sortable_change_list_template, context)
@ -241,7 +248,8 @@ class SortableAdmin(SortableAdminBase, ModelAdmin):
'change_form_template_extends': self.change_form_template_extends, 'change_form_template_extends': self.change_form_template_extends,
'has_sortable_tabular_inlines': self.has_sortable_tabular_inlines, 'has_sortable_tabular_inlines': self.has_sortable_tabular_inlines,
'has_sortable_stacked_inlines': self.has_sortable_stacked_inlines, 'has_sortable_stacked_inlines': self.has_sortable_stacked_inlines,
'csrf_cookie_name': getattr(settings, 'CSRF_COOKIE_NAME', 'csrftoken') 'csrf_cookie_name': getattr(settings, 'CSRF_COOKIE_NAME', 'csrftoken'),
'after_sorting_js_callback_name': self.after_sorting_js_callback_name
}) })
return super(SortableAdmin, self).change_view(request, object_id, return super(SortableAdmin, self).change_view(request, object_id,

View File

@ -1,47 +1,54 @@
(function($){ <script>
(function($){
$(function() {
jQuery('.sortable').sortable({ $(function() {
axis : 'y', jQuery('.sortable').sortable({
containment : 'parent', axis : 'y',
tolerance : 'pointer', containment : 'parent',
items : 'li', tolerance : 'pointer',
stop : function(event, ui) { items : 'li',
var indexes = [], stop : function(event, ui) {
lineItems = ui.item.parent().find('> li'); var indexes = [],
lineItems = ui.item.parent().find('> li');
lineItems.each(function(i) {
indexes.push($(this).find(':hidden[name="pk"]').val()); lineItems.each(function(i) {
}); indexes.push($(this).find(':hidden[name="pk"]').val());
});
$.ajax({
url: ui.item.find('a.admin_sorting_url').attr('href'), $.ajax({
type: 'POST', url: ui.item.find('a.admin_sorting_url').attr('href'),
data: { indexes: indexes.join(',') }, type: 'POST',
success: function() { data: { indexes: indexes.join(',') },
// set icons based on position success: function() {
lineItems.each(function(index, element) { // set icons based on position
var icon = $(element).find('a.admin_sorting_url .fa'); lineItems.each(function(index, element) {
icon.removeClass('fa-sort-desc fa-sort-asc fa-sort'); var icon = $(element).find('a.admin_sorting_url .fa');
icon.removeClass('fa-sort-desc fa-sort-asc fa-sort');
if (index === 0) {
icon.addClass('fa fa-sort-desc'); if (index === 0) {
} icon.addClass('fa fa-sort-desc');
else if (index == lineItems.length - 1) { }
icon.addClass('fa fa-sort-asc'); else if (index == lineItems.length - 1) {
} icon.addClass('fa fa-sort-asc');
else { }
icon.addClass('fa fa-sort'); else {
} icon.addClass('fa fa-sort');
}); }
});
ui.item.effect('highlight', {}, 1000);
} ui.item.effect('highlight', {}, 1000);
});
} {% if after_sorting_js_callback_name %}
}).click(function(e){ {# if a callback is defined in a custom template, execute it #}
e.preventDefault(); window['{{ after_sorting_js_callback_name }}']();
}); {% endif %}
}); }
});
})(django.jQuery); }
}).click(function(e){
e.preventDefault();
});
});
})(django.jQuery);
</script>

View File

@ -7,17 +7,17 @@
{% url 'admin:jsi18n' as jsi18nurl %} {% url 'admin:jsi18n' as jsi18nurl %}
{% if has_sortable_tabular_inlines or has_sortable_stacked_inlines %} {% if has_sortable_tabular_inlines or has_sortable_stacked_inlines %}
<script type="text/javascript" src="{% static 'adminsortable/js/jquery-ui-django-admin.min.js' %}"></script> <script src="{% static 'adminsortable/js/jquery-ui-django-admin.min.js' %}"></script>
<script src="{% static 'adminsortable/js/jquery.ui.touch-punch.min.js' %}"></script> <script src="{% static 'adminsortable/js/jquery.ui.touch-punch.min.js' %}"></script>
{% include 'adminsortable/csrf/jquery.django-csrf.html' with csrf_cookie_name=csrf_cookie_name %} {% include 'adminsortable/csrf/jquery.django-csrf.html' with csrf_cookie_name=csrf_cookie_name %}
{% endif %} {% endif %}
{% if has_sortable_tabular_inlines %} {% if has_sortable_tabular_inlines %}
<script type="text/javascript" src="{% static 'adminsortable/js/admin.sortable.tabular.inlines.js' %}"></script> {% include 'adminsortable/edit_inline/admin.sortable.stacked.inlines.html' with after_sorting_js_callback_name=after_sorting_js_callback_name %}
{% endif %} {% endif %}
{% if has_sortable_stacked_inlines %} {% if has_sortable_stacked_inlines %}
<script type="text/javascript" src="{% static 'adminsortable/js/admin.sortable.stacked.inlines.js' %}"></script> {% include 'adminsortable/edit_inline/admin.sortable.tabular.inlines.html' with after_sorting_js_callback_name=after_sorting_js_callback_name %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -21,14 +21,14 @@
{% endblock %} {% endblock %}
{% block extrahead %} {% block extrahead %}
{{ block.super }}
{{ media.js }}
<script src="{% static jquery_lib_path %}"></script> <script src="{% static jquery_lib_path %}"></script>
<script src="{% static 'admin/js/jquery.init.js' %}"></script> <script src="{% static 'admin/js/jquery.init.js' %}"></script>
{{ block.super }}
{{ media.js }}
<script src="{% static 'adminsortable/js/jquery-ui-django-admin.min.js' %}"></script> <script src="{% static 'adminsortable/js/jquery-ui-django-admin.min.js' %}"></script>
<script src="{% static 'adminsortable/js/jquery.ui.touch-punch.min.js' %}"></script> <script src="{% static 'adminsortable/js/jquery.ui.touch-punch.min.js' %}"></script>
{% include 'adminsortable/csrf/jquery.django-csrf.html' with csrf_cookie_name=csrf_cookie_name %} {% include 'adminsortable/csrf/jquery.django-csrf.html' with csrf_cookie_name=csrf_cookie_name %}
<script src="{% static 'adminsortable/js/admin.sortable.js' %}"></script> {% include 'adminsortable/admin.sortable.html' with after_sorting_js_callback_name=after_sorting_js_callback_name %}
<script type="text/javascript"> <script type="text/javascript">
(function($) { (function($) {

View File

@ -1,70 +1,78 @@
(function($){ <script>
(function($){
$(function() {
var sorting_urls = $(':hidden[name="admin_sorting_url"]'); $(function() {
if (sorting_urls.length > 0) var sorting_urls = $(':hidden[name="admin_sorting_url"]');
{ if (sorting_urls.length > 0)
var sortable_inline_groups = sorting_urls.closest('.inline-group') {
var sortable_inline_rows = sortable_inline_groups.find('.inline-related'); var sortable_inline_groups = sorting_urls.closest('.inline-group')
var sortable_inline_rows = sortable_inline_groups.find('.inline-related');
sortable_inline_groups.addClass('sortable')
sortable_inline_rows.addClass('sortable'); sortable_inline_groups.addClass('sortable')
sortable_inline_rows.addClass('sortable');
sortable_inline_groups.sortable({
axis : 'y', sortable_inline_groups.sortable({
containment : 'parent', axis : 'y',
create: function(event, ui) { containment : 'parent',
$('.inline-related :checkbox').unbind(); create: function(event, ui) {
}, $('.inline-related :checkbox').unbind();
tolerance : 'pointer', },
items : '.inline-related', tolerance : 'pointer',
stop : function(event, ui) items : '.inline-related',
{ stop : function(event, ui)
if ($('.inline-deletelink').length > 0) { {
$(ui.sender).sortable('cancel'); if ($('.inline-deletelink').length > 0) {
alert($('#localized_save_before_reorder_message').val()); $(ui.sender).sortable('cancel');
return false; alert($('#localized_save_before_reorder_message').val());
} return false;
}
var indexes = [];
ui.item.parent().children('.inline-related').each(function(i) var indexes = [];
{ ui.item.parent().children('.inline-related').each(function(i)
var index_value = $(this).find(':hidden[name$="-id"]').val(); {
if (index_value !== "" && index_value !== undefined) { var index_value = $(this).find(':hidden[name$="-id"]').val();
indexes.push(index_value); if (index_value !== "" && index_value !== undefined) {
} indexes.push(index_value);
}); }
});
$.ajax({
url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(), $.ajax({
type: 'POST', url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(),
data: { indexes : indexes.join(',') }, type: 'POST',
success: function() { data: { indexes : indexes.join(',') },
var fieldsets = ui.item.find('fieldset'), success: function() {
highlightedSelector = fieldsets.filter('.collapsed').length === fieldsets.length ? 'h3' : '.form-row', var fieldsets = ui.item.find('fieldset'),
icons = ui.item.parent().find('h3 > .fa'); highlightedSelector = fieldsets.filter('.collapsed').length === fieldsets.length ? 'h3' : '.form-row',
icons = ui.item.parent().find('h3 > .fa');
// set icons based on position
icons.removeClass('fa-sort-desc fa-sort-asc fa-sort'); // set icons based on position
icons.each(function(index, element) { icons.removeClass('fa-sort-desc fa-sort-asc fa-sort');
var icon = $(element); icons.each(function(index, element) {
if (index === 0) { var icon = $(element);
icon.addClass('fa fa-sort-desc'); if (index === 0) {
} icon.addClass('fa fa-sort-desc');
else if (index == icons.length - 1) { }
icon.addClass('fa fa-sort-asc'); else if (index == icons.length - 1) {
} icon.addClass('fa fa-sort-asc');
else { }
icon.addClass('fa fa-sort'); else {
} icon.addClass('fa fa-sort');
}); }
});
ui.item.find(highlightedSelector).effect('highlight', {}, 1000);
} ui.item.find(highlightedSelector).effect('highlight', {}, 1000);
});
} {% if after_sorting_js_callback_name %}
}); {# if a callback is defined in a custom template, execute it #}
} window['{{ after_sorting_js_callback_name }}']();
}); {% endif %}
}
})(django.jQuery); });
}
});
}
});
})(django.jQuery);
</script>

View File

@ -1,69 +1,77 @@
(function($){ <script>
(function($){
$(function() {
var sorting_urls = $(':hidden[name="admin_sorting_url"]'); $(function() {
if (sorting_urls.length) var sorting_urls = $(':hidden[name="admin_sorting_url"]');
{ if (sorting_urls.length)
var sortable_inline_group = sorting_urls.closest('.inline-group'); {
var tabular_inline_rows = sortable_inline_group.find('.tabular table tbody tr'); var sortable_inline_group = sorting_urls.closest('.inline-group');
var tabular_inline_rows = sortable_inline_group.find('.tabular table tbody tr');
tabular_inline_rows.addClass('sortable');
tabular_inline_rows.addClass('sortable');
sortable_inline_group.find('.tabular.inline-related').sortable({
axis : 'y', sortable_inline_group.find('.tabular.inline-related').sortable({
containment : 'parent', axis : 'y',
create: function(event, ui) { containment : 'parent',
$('td.delete :checkbox').unbind(); create: function(event, ui) {
}, $('td.delete :checkbox').unbind();
tolerance : 'pointer', },
items : 'tr:not(.add-row)', tolerance : 'pointer',
stop : function(event, ui) { items : 'tr:not(.add-row)',
if ($('.inline-deletelink').length > 0) { stop : function(event, ui) {
$(ui.sender).sortable('cancel'); if ($('.inline-deletelink').length > 0) {
alert($('#localized_save_before_reorder_message').val()); $(ui.sender).sortable('cancel');
return false; alert($('#localized_save_before_reorder_message').val());
} return false;
}
var indexes = [];
ui.item.parent().children('tr').each(function(i) var indexes = [];
{ ui.item.parent().children('tr').each(function(i)
var index_value = $(this).find('.original :input:first').val(); {
var index_value = $(this).find('.original :input:first').val();
if (index_value !== '' && index_value !== undefined) { if (index_value !== '' && index_value !== undefined) {
indexes.push(index_value); indexes.push(index_value);
} }
}); });
$.ajax({ $.ajax({
url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(), url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(),
type: 'POST', type: 'POST',
data: { indexes : indexes.join(',') }, data: { indexes : indexes.join(',') },
success: function() { success: function() {
// set icons based on position // set icons based on position
var icons = ui.item.parent().find('.fa'); var icons = ui.item.parent().find('.fa');
icons.removeClass('fa-sort-desc fa-sort-asc fa-sort'); icons.removeClass('fa-sort-desc fa-sort-asc fa-sort');
icons.each(function(index, element) { icons.each(function(index, element) {
var icon = $(element); var icon = $(element);
if (index === 0) { if (index === 0) {
icon.addClass('fa fa-sort-desc'); icon.addClass('fa fa-sort-desc');
} }
else if (index == icons.length - 1) { else if (index == icons.length - 1) {
icon.addClass('fa fa-sort-asc'); icon.addClass('fa fa-sort-asc');
} }
else { else {
icon.addClass('fa fa-sort'); icon.addClass('fa fa-sort');
} }
}); });
// highlight sorted row, then re-stripe table // highlight sorted row, then re-stripe table
ui.item.effect('highlight', {}, 1000); ui.item.effect('highlight', {}, 1000);
tabular_inline_rows.removeClass('row1 row2'); tabular_inline_rows.removeClass('row1 row2');
$('.tabular table tbody tr:odd').addClass('row2'); $('.tabular table tbody tr:odd').addClass('row2');
$('.tabular table tbody tr:even').addClass('row1'); $('.tabular table tbody tr:even').addClass('row1');
}
}); {% if after_sorting_js_callback_name %}
} {# if a callback is defined in a custom template, execute it #}
}); window['{{ after_sorting_js_callback_name }}']();
} {% endif %}
}); }
});
})(django.jQuery); }
});
}
});
})(django.jQuery);
</script>

View File

@ -83,6 +83,9 @@ class ProjectAdmin(SortableAdmin):
NonSortableCreditInline, NonSortableNoteInline NonSortableCreditInline, NonSortableNoteInline
] ]
list_display = ['__str__', 'category'] list_display = ['__str__', 'category']
after_sorting_js_callback_name = 'afterSortCallback'
sortable_change_list_template = 'adminsortable/custom_change_list.html'
sortable_change_form_template = "adminsortable/custom_change_form.html"
admin.site.register(Project, ProjectAdmin) admin.site.register(Project, ProjectAdmin)

View File

@ -0,0 +1,15 @@
{% extends "adminsortable/change_form.html" %}
{% block extrahead %}
{{ block.super }}
<script>
django.jQuery(document).on('order:changed', function(event) {
console.log(event.message);
});
window['{{ after_sorting_js_callback_name }}'] = function() {
django.jQuery(document).trigger({ type: 'order:changed', message: 'Order changed', time: new Date() });
};
</script>
{% endblock %}

View File

@ -0,0 +1,15 @@
{% extends 'adminsortable/change_list.html' %}
{% block extrahead %}
{{ block.super }}
<script>
django.jQuery(document).on('order:changed', function(event) {
console.log(event.message);
});
window['{{ after_sorting_js_callback_name }}'] = function() {
django.jQuery(document).trigger({ type: 'order:changed', message: 'Order changed', time: new Date() });
};
</script>
{% endblock %}