Code

Ticket #12282: admin-selectacross.2.diff

File admin-selectacross.2.diff, 9.7 KB (added by jezdez, 4 years ago)

Featuring less brain farts

Line 
1diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py
2index d047d89..29b777f 100644
3--- a/django/contrib/admin/helpers.py
4+++ b/django/contrib/admin/helpers.py
5@@ -17,6 +17,8 @@ ACTION_CHECKBOX_NAME = '_selected_action'
6 
7 class ActionForm(forms.Form):
8     action = forms.ChoiceField(label=_('Action:'))
9+    select_across = forms.BooleanField(label='', required=False, initial=0,
10+        widget=forms.HiddenInput({'class': 'select-across'}))
11 
12 checkbox = forms.CheckboxInput({'class': 'action-select'}, lambda value: False)
13 
14diff --git a/django/contrib/admin/media/css/changelists.css b/django/contrib/admin/media/css/changelists.css
15index a9d7543..99ff8bc 100644
16--- a/django/contrib/admin/media/css/changelists.css
17+++ b/django/contrib/admin/media/css/changelists.css
18@@ -228,12 +228,6 @@
19     border-right: 1px solid #ddd;
20 }
21 
22-.action_counter{
23-    font-size: 11px;
24-    margin: 0 0.5em;
25-    display: none;
26-}
27-
28 #changelist table input {
29     margin: 0;
30 }
31@@ -250,6 +244,21 @@
32     background: white url(../img/admin/nav-bg-reverse.gif) 0 -10px repeat-x;
33 }
34 
35+#changelist .actions.selected {
36+    background: #fffccf;
37+    border-top: 1px solid #fffee8;
38+    border-bottom: 1px solid #edecd6;
39+}
40+
41+#changelist .actions span.all,
42+#changelist .actions span.action-counter,
43+#changelist .actions span.clear,
44+#changelist .actions span.question {
45+    font-size: 11px;
46+    margin: 0 0.5em;
47+    display: none;
48+}
49+
50 #changelist .actions:last-child {
51     border-bottom: none;
52 }
53diff --git a/django/contrib/admin/media/js/actions.js b/django/contrib/admin/media/js/actions.js
54index 658f015..c50bdf5 100644
55--- a/django/contrib/admin/media/js/actions.js
56+++ b/django/contrib/admin/media/js/actions.js
57@@ -1,20 +1,42 @@
58 var Actions = {
59     init: function() {
60         counterSpans = document.getElementsBySelector('span._acnt');
61-        counterContainer = document.getElementsBySelector('span.action_counter');
62+        counterContainer = document.getElementsBySelector('span.action-counter');
63+        allContainer = document.getElementsBySelector('div.actions span.all');
64+        actionContainer = document.getElementsBySelector('div.actions');
65         actionCheckboxes = document.getElementsBySelector('tr input.action-select');
66+        acrossInputs = document.getElementsBySelector('div.actions input.select-across');
67+        acrossQuestions = document.getElementsBySelector('div.actions span.question');
68+        acrossClears = document.getElementsBySelector('div.actions span.clear');
69+        acrossQuestionLinks = document.getElementsBySelector('div.actions span.question a');
70+        acrossClearsLinks = document.getElementsBySelector('div.actions span.clear a');
71+
72+        Actions.setDisplay(counterContainer, 'inline');
73         selectAll = document.getElementById('action-toggle');
74-        lastChecked = null;
75-        for(var i = 0; i < counterContainer.length; i++) {
76-            counterContainer[i].style.display = 'inline';
77-        }
78         if (selectAll) {
79-            selectAll.style.display = 'inline';
80+            Actions.setDisplay([selectAll], 'inline');
81             addEvent(selectAll, 'click', function() {
82                 Actions.checker(selectAll.checked);
83                 Actions.counter();
84             });
85+            for(var i = 0; i < acrossQuestionLinks.length; i++) {
86+                addEvent(acrossQuestionLinks[i], 'click', function() {
87+                    Actions.setAcrossInputs(1);
88+                    Actions.showClear()
89+                    return false;
90+                });
91+            }
92+            for(var i = 0; i < acrossClearsLinks.length; i++) {
93+                addEvent(acrossClearsLinks[i], 'click', function() {
94+                    selectAll.checked = false;
95+                    Actions.clearAcross();
96+                    Actions.checker(0);
97+                    Actions.counter();
98+                    return false;
99+                });
100+            }
101         }
102+        lastChecked = null;
103         for(var i = 0; i < actionCheckboxes.length; i++) {
104             addEvent(actionCheckboxes[i], 'click', function(e) {
105                 if (!e) { var e = window.event; }
106@@ -57,15 +79,54 @@ var Actions = {
107             tr.className = tr.className.replace(' selected', '');
108         } 
109     },
110-    checked: function() {
111-        selectAll.checked = false;
112+    setAcrossInputs: function(checked) {
113+        for(var i = 0; i < acrossInputs.length; i++) {
114+            acrossInputs[i].value = checked;
115+        }
116     },
117     checker: function(checked) {
118+        if (checked) {
119+            Actions.showQuestion()
120+        } else {
121+            Actions.reset();
122+        }
123         for(var i = 0; i < actionCheckboxes.length; i++) {
124             actionCheckboxes[i].checked = checked;
125             Actions.toggleRow(actionCheckboxes[i].parentNode.parentNode, checked);
126         }
127     },
128+    setDisplay: function(elements, value) {
129+        for(var i = 0; i < elements.length; i++) {
130+            elements[i].style.display = value;
131+        }
132+    },
133+    showQuestion: function() {
134+        Actions.setDisplay(acrossQuestions, 'inline');
135+        Actions.setDisplay(acrossClears, 'none');
136+        Actions.setDisplay(allContainer, 'none');
137+    },
138+    showClear: function() {
139+        Actions.setDisplay(acrossQuestions, 'none');
140+        Actions.setDisplay(acrossClears, 'inline');
141+        Actions.setDisplay(counterContainer, 'none');
142+        Actions.setDisplay(allContainer, 'inline');
143+        for(var i = 0; i < actionContainer.length; i++) {
144+            Actions.toggleRow(actionContainer[i], true)
145+        }
146+    },
147+    reset: function() {
148+        Actions.setDisplay(allContainer, 'none')
149+        Actions.setDisplay(acrossQuestions, 'none');
150+        Actions.setDisplay(acrossClears, 'none');
151+        Actions.setDisplay(counterContainer, 'inline');
152+    },
153+    clearAcross: function() {
154+        Actions.reset()
155+        Actions.setAcrossInputs(0);
156+        for(var i = 0; i < actionContainer.length; i++) {
157+            Actions.toggleRow(actionContainer[i], false)
158+        }
159+    },
160     counter: function() {
161         counter = 0;
162         for(var i = 0; i < actionCheckboxes.length; i++) {
163@@ -76,7 +137,13 @@ var Actions = {
164         for(var i = 0; i < counterSpans.length; i++) {
165             counterSpans[i].innerHTML = counter;
166         }
167-        selectAll.checked = (counter == actionCheckboxes.length);
168+        if (counter == actionCheckboxes.length) {
169+            selectAll.checked = true;
170+            Actions.showQuestion()
171+        } else {
172+            selectAll.checked = false;
173+            Actions.clearAcross()
174+        }
175     }
176 };
177 
178diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
179index 6dc707e..5297487 100644
180--- a/django/contrib/admin/options.py
181+++ b/django/contrib/admin/options.py
182@@ -724,13 +724,17 @@ class ModelAdmin(BaseModelAdmin):
183             # Get the list of selected PKs. If nothing's selected, we can't
184             # perform an action on it, so bail.
185             selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME)
186-            if not selected:
187+
188+            if not action_form.cleaned_data.get('select_across'):
189+                queryset = queryset.filter(pk__in=selected)
190+
191+            if not selected or not queryset.exists():
192                 # Reminder that something needs to be selected or nothing will happen
193                 msg = _("Items must be selected in order to perform actions on them. No items have been changed.")
194                 self.message_user(request, msg)
195                 return None
196 
197-            response = func(self, request, queryset.filter(pk__in=selected))
198+            response = func(self, request, queryset)
199 
200             # Actions may return an HttpResponse, which will be used as the
201             # response from the POST. If not, we'll be a good little HTTP
202diff --git a/django/contrib/admin/templates/admin/actions.html b/django/contrib/admin/templates/admin/actions.html
203index 6d96616..11f5e71 100644
204--- a/django/contrib/admin/templates/admin/actions.html
205+++ b/django/contrib/admin/templates/admin/actions.html
206@@ -1,10 +1,28 @@
207 {% load i18n %}
208 <div class="actions">
209-    {% for field in action_form %}<label>{{ field.label }} {{ field }}</label>{% endfor %}
210+    {% for field in action_form %}{% if field.label %}<label>{{ field.label }} {% endif %}{{ field }}{% if field.label %}</label>{% endif %}{% endfor %}
211     <button type="submit" class="button" title="{% trans "Run the selected action" %}" name="index" value="{{ action_index|default:0 }}">{% trans "Go" %}</button>
212     {% if actions_selection_counter %}
213-    <span class="action_counter">
214-      {% blocktrans with cl.result_count as total_count %}<span class="_acnt">0</span> of {{ total_count }} {{ module_name }} selected{% endblocktrans %}
215-    </span>
216+        <span class="action-counter">
217+            {% blocktrans with cl.result_count as total_count %}
218+            <span class="_acnt">0</span> of {{ total_count }} {{ module_name }} selected
219+            {% endblocktrans %}
220+        </span>
221+        {% if cl.result_count != cl.result_list|length %}
222+        <span class="all">
223+            {% blocktrans with cl.result_count as total_count %}
224+            All {{ total_count }} {{ module_name }} selected
225+            {% endblocktrans %}
226+        </span>
227+        <span class="question">
228+            <a href="javascript:;" title="{% trans "Click here to select all objects across all pages" %}">
229+                {% blocktrans with cl.result_count as total_count %}
230+                    Select all {{ total_count }} {{ module_name }}
231+                {% endblocktrans %}
232+            </a>
233+        </span>
234+        <span class="clear"><a href="javascript:;">{% trans "Clear selection" %}</a></span>
235+        {% endif %}
236     {% endif %}
237 </div>
238+