diff --git a/django/contrib/admin/static/admin/css/base.css b/django/contrib/admin/static/admin/css/base.css index 89f2225c7c..5db94a7d25 100644 --- a/django/contrib/admin/static/admin/css/base.css +++ b/django/contrib/admin/static/admin/css/base.css @@ -309,77 +309,84 @@ tr.alt { /* SORTABLE TABLES */ +thead th { + padding: 0; + line-height: normal; +} + thead th a:link, thead th a:visited { color: #666; - display: block; } thead th.sorted { background: #c5c5c5 url(../img/nav-bg-selected.gif) top left repeat-x; } -table thead th.sorted a { - padding-right: 13px; +table thead th .text span { + padding: 2px 5px; + display:block; } -table thead th.ascending a { - background: url(../img/arrow-up.gif) right .4em no-repeat; -} - -table thead th.descending a { - background: url(../img/arrow-down.gif) right .4em no-repeat; -} - -table thead th.sorted a span.text { - display: block; - float: left; - cursor: pointer; /* IE needs this */ -} - -table thead th.sorted a span.sortpos { - display: block; - float: right; - font-size: .6em; - text-align: right; - cursor: pointer; /* IE needs this */ -} - -table thead th.sorted a img { - vertical-align: top; -} - -table thead th.sorted a span.clear { - display: block; - clear: both; -} - -#sorting-popup-div { - display: none; - position: absolute; - background-color: white; - border: 1px solid #ddd; - z-index: 2000; /* more than filters on right */ -} - -#sorting-popup-div table { - border-right: 0px; - border-left: 0px; -} - -#sorting-popup-div .reset { - text-align: center; -} - -#sorting-popup-div .cancel { - font-size: 10px; - background: #e1e1e1 url(../img/nav-bg.gif) 0 50% repeat-x; - border-top: 1px solid #ddd; - text-align: center; -} - -#sorting-popup-div .cancel a { - width: 100%; +table thead th .text a { display: block; + cursor: pointer; + padding: 2px 5px; +} + +table thead th.sortable:hover { + background: white url(../img/nav-bg-reverse.gif) 0 -5px repeat-x; +} + +thead th.sorted a.sortremove { + visibility: hidden; +} + +table thead th.sorted:hover a.sortremove { + visibility: visible; +} + +table thead th.sorted .sortoptions { + display: block; + padding: 4px 5px 0 5px; + float: right; + text-align: right; +} + +table thead th.sorted .sortpriority { + font-size: .8em; + min-width: 12px; + text-align: center; + vertical-align: top; +} + +table thead th.sorted .sortoptions a { + width: 14px; + height: 12px; + display: inline-block; +} + +table thead th.sorted .sortoptions a.sortremove { + background: url(../img/sorting-icons.gif) -4px -5px no-repeat; +} + +table thead th.sorted .sortoptions a.sortremove:hover { + background: url(../img/sorting-icons.gif) -4px -27px no-repeat; +} + +table thead th.sorted .sortoptions a.ascending { + background: url(../img/sorting-icons.gif) -5px -50px no-repeat; +} + +table thead th.sorted .sortoptions a.ascending:hover { + background: url(../img/sorting-icons.gif) -5px -72px no-repeat; +} + +table thead th.sorted .sortoptions a.descending { + background: url(../img/sorting-icons.gif) -5px -94px no-repeat; +} + +table thead th.sorted .sortoptions a.descending:hover { + background: url(../img/sorting-icons.gif) -5px -115px no-repeat; } /* ORDERABLE TABLES */ diff --git a/django/contrib/admin/static/admin/css/rtl.css b/django/contrib/admin/static/admin/css/rtl.css index fce6b1ab0e..029bf36f82 100644 --- a/django/contrib/admin/static/admin/css/rtl.css +++ b/django/contrib/admin/static/admin/css/rtl.css @@ -80,22 +80,7 @@ div.breadcrumbs { /* SORTABLE TABLES */ - -table thead th.sorted a { - padding-left: 13px; - padding-right: 0px; -} - -table thead th.ascending a, -table thead th.descending a { - background-position: left; -} - -table thead th.sorted a span.text { - float: right; -} - -table thead th.sorted a span.sortpos { +table thead th.sorted .sortoptions { float: left; } diff --git a/django/contrib/admin/static/admin/img/arrow-down.gif b/django/contrib/admin/static/admin/img/arrow-down.gif deleted file mode 100644 index a967b9fd55..0000000000 Binary files a/django/contrib/admin/static/admin/img/arrow-down.gif and /dev/null differ diff --git a/django/contrib/admin/static/admin/img/arrow-up.gif b/django/contrib/admin/static/admin/img/arrow-up.gif deleted file mode 100644 index 3fe4851399..0000000000 Binary files a/django/contrib/admin/static/admin/img/arrow-up.gif and /dev/null differ diff --git a/django/contrib/admin/static/admin/img/icon_cog.gif b/django/contrib/admin/static/admin/img/icon_cog.gif deleted file mode 100644 index e390ef2ef5..0000000000 Binary files a/django/contrib/admin/static/admin/img/icon_cog.gif and /dev/null differ diff --git a/django/contrib/admin/static/admin/img/sorting-icons.gif b/django/contrib/admin/static/admin/img/sorting-icons.gif new file mode 100644 index 0000000000..451aae5987 Binary files /dev/null and b/django/contrib/admin/static/admin/img/sorting-icons.gif differ diff --git a/django/contrib/admin/templates/admin/change_list_results.html b/django/contrib/admin/templates/admin/change_list_results.html index b1db6470c9..e3d4b2549a 100644 --- a/django/contrib/admin/templates/admin/change_list_results.html +++ b/django/contrib/admin/templates/admin/change_list_results.html @@ -11,15 +11,17 @@ {% for header in result_headers %} - {% if header.sortable %}{% endif %} - {{ header.text|capfirst }} - {% if header.sortable %} - {% if header.sort_pos > 0 %} - {% if header.sort_pos == 1 %} {% endif %} - {{ header.sort_pos }} - {% endif %} - - {% endif %} + {% if header.sortable %} + {% if header.sort_priority > 0 %} +
+ + {% if num_sorted_fields > 1 %}{{ header.sort_priority }}{% endif %} + +
+ {% endif %} + {% endif %} +
{% if header.sortable %}{{ header.text|capfirst }}{% else %}{{ header.text|capfirst }}{% endif %}
+
{% endfor %} @@ -33,90 +35,4 @@ - -{# Sorting popup: #} -
- - - - {% for header in result_headers|dictsort:"sort_pos" %} - {% if header.sort_pos > 0 %} - - - - - - - - {% endif %} - {% endfor %} - -
- {% trans "Sorting by:" %} -
{{ header.sort_pos }}{{ header.text|capfirst }}{% if header.ascending %}{% trans "ascending" %}{% else %}{% trans "descending" %}{% endif %}{% trans "toggle" %}{% trans "remove" %}
-
{% trans "Reset sorting" %}
-
{% trans "Cancel" %}
-
- - {% endif %} diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index 0f5eafc24d..ba3d1329ad 100644 --- a/django/contrib/admin/templatetags/admin_list.py +++ b/django/contrib/admin/templatetags/admin_list.py @@ -83,7 +83,6 @@ def result_headers(cl): """ ordering_field_columns = cl.get_ordering_field_columns() for i, field_name in enumerate(cl.list_display): - admin_order_field = None text, attr = label_for_field(field_name, cl.model, model_admin = cl.model_admin, return_attr = True @@ -95,25 +94,31 @@ def result_headers(cl): if field_name == 'action_checkbox': yield { "text": text, - "class_attrib": mark_safe(' class="action-checkbox-column"') + "class_attrib": mark_safe(' class="action-checkbox-column"'), + "sortable": False, } continue admin_order_field = getattr(attr, "admin_order_field", None) if not admin_order_field: # Not sortable - yield {"text": text} + yield { + "text": text, + "sortable": False, + } continue # OK, it is sortable if we got this far - th_classes = [] + th_classes = ['sortable'] order_type = '' new_order_type = 'asc' - sort_pos = 0 + sort_priority = 0 + sorted = False # Is it currently being sorted on? if i in ordering_field_columns: + sorted = True order_type = ordering_field_columns.get(i).lower() - sort_pos = ordering_field_columns.keys().index(i) + 1 + sort_priority = ordering_field_columns.keys().index(i) + 1 th_classes.append('sorted %sending' % order_type) new_order_type = {'asc': 'desc', 'desc': 'asc'}[order_type] @@ -144,8 +149,9 @@ def result_headers(cl): yield { "text": text, "sortable": True, + "sorted": sorted, "ascending": order_type == "asc", - "sort_pos": sort_pos, + "sort_priority": sort_priority, "url_primary": cl.get_query_string({ORDER_VAR: '.'.join(o_list_primary)}), "url_remove": cl.get_query_string({ORDER_VAR: '.'.join(o_list_remove)}), "url_toggle": cl.get_query_string({ORDER_VAR: '.'.join(o_list_toggle)}), @@ -260,13 +266,14 @@ def result_list(cl): Displays the headers and data list together """ headers = list(result_headers(cl)) + num_sorted_fields = 0 for h in headers: - # Sorting in templates depends on sort_pos attribute - h.setdefault('sort_pos', 0) + if h['sortable'] and h['sorted']: + num_sorted_fields += 1 return {'cl': cl, 'result_hidden_fields': list(result_hidden_fields(cl)), 'result_headers': headers, - 'reset_sorting_url': cl.get_query_string(remove=[ORDER_VAR]), + 'num_sorted_fields': num_sorted_fields, 'results': list(results(cl))} @register.inclusion_tag('admin/date_hierarchy.html') diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt index 5b92f95f59..9cf268a869 100644 --- a/docs/releases/1.4.txt +++ b/docs/releases/1.4.txt @@ -360,13 +360,16 @@ Removed admin icons ~~~~~~~~~~~~~~~~~~~ As part of an effort to improve the performance and usability of the admin's -vertical and horizontal "filter" widgets, some icon files were removed and -grouped into a single sprite file (``selector-icons.gif``): +changelist sorting interface and of the admin's :attr:`horizontal +` and :attr:`vertical +` "filter" widgets, some icon +files were removed and grouped into two sprite files, respectively: ``selector-add.gif``, ``selector-addall.gif``, ``selector-remove.gif``, ``selector-removeall.gif``, ``selector_stacked-add.gif`` and -``selector_stacked-remove.gif``. If you used those icons to customize the -admin then you will want to replace them with your own icons or retrieve them -from a previous release. +``selector_stacked-remove.gif`` into ``selector-icons.gif``; and +``arrow-up.gif`` and ``arrow-down.gif`` into ``sorting-icons.gif``. If you used +those icons to customize the admin then you will want to replace them with your +own icons or retrieve them from a previous release. Compatibility with old signed data ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~