diff --git a/django/contrib/admin/media/css/changelists.css b/django/contrib/admin/media/css/changelists.css
index 43033780ac..a9d7543829 100644
--- a/django/contrib/admin/media/css/changelists.css
+++ b/django/contrib/admin/media/css/changelists.css
@@ -228,6 +228,12 @@
     border-right: 1px solid #ddd;
 }
 
+.action_counter{
+    font-size: 11px;
+    margin: 0 0.5em;
+    display: none;
+}
+
 #changelist table input {
     margin: 0;
 }
diff --git a/django/contrib/admin/media/js/actions.js b/django/contrib/admin/media/js/actions.js
index d34488ab9d..87b2e1b84e 100644
--- a/django/contrib/admin/media/js/actions.js
+++ b/django/contrib/admin/media/js/actions.js
@@ -1,10 +1,22 @@
 var Actions = {
     init: function() {
-        var selectAll = document.getElementById('action-toggle');
+        counterSpans = document.getElementsBySelector('span._acnt');
+        counterContainer = document.getElementsBySelector('span.action_counter');
+        actionCheckboxes = document.getElementsBySelector('tr input.action-select');
+        selectAll = document.getElementById('action-toggle');
+        for(var i = 0; i < counterContainer.length; i++) {
+            counterContainer[i].style.display = 'inline';
+        }
         if (selectAll) {
             selectAll.style.display = 'inline';
             addEvent(selectAll, 'click', function() {
                 Actions.checker(selectAll.checked);
+                Actions.counter();
+            });
+        }
+        for(var i = 0; i < actionCheckboxes.length; i++) {
+            addEvent(actionCheckboxes[i], 'click', function() {
+                Actions.counter();
             });
         }
         var changelistTable = document.getElementsBySelector('#changelist table')[0];
@@ -16,6 +28,7 @@ var Actions = {
                 if (target.className == 'action-select') {
                     var tr = target.parentNode.parentNode;
                     Actions.toggleRow(tr, target.checked);
+                    Actions.checked();
                 }
             });
         }
@@ -27,13 +40,26 @@ var Actions = {
             tr.className = tr.className.replace(' selected', '');
         }  
     },
+    checked: function() {
+        selectAll.checked = false;
+    },
     checker: function(checked) {
-        var actionCheckboxes = document.getElementsBySelector('tr input.action-select');
         for(var i = 0; i < actionCheckboxes.length; i++) {
             actionCheckboxes[i].checked = checked;
             Actions.toggleRow(actionCheckboxes[i].parentNode.parentNode, checked);
         }
+    },
+    counter: function() {
+        counter = 0;
+        for(var i = 0; i < actionCheckboxes.length; i++) {
+            if(actionCheckboxes[i].checked){
+                counter++;
+            }
+        }
+        for(var i = 0; i < counterSpans.length; i++) {
+            counterSpans[i].innerHTML = counter;
+        }
     }
 };
 
-addEvent(window, 'load', Actions.init);
+addEvent(window, 'load', Actions.init);
\ No newline at end of file
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index c18af6260a..6dc707eefb 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -210,6 +210,7 @@ class ModelAdmin(BaseModelAdmin):
     action_form = helpers.ActionForm
     actions_on_top = True
     actions_on_bottom = False
+    actions_selection_counter = True
 
     def __init__(self, model, admin_site):
         self.model = model
@@ -1024,7 +1025,13 @@ class ModelAdmin(BaseModelAdmin):
         else:
             action_form = None
 
+        if cl.result_count == 1:
+            module_name = force_unicode(opts.verbose_name)
+        else:
+            module_name = force_unicode(opts.verbose_name_plural)
+
         context = {
+            'module_name': module_name,
             'title': cl.title,
             'is_popup': cl.is_popup,
             'cl': cl,
@@ -1035,6 +1042,7 @@ class ModelAdmin(BaseModelAdmin):
             'action_form': action_form,
             'actions_on_top': self.actions_on_top,
             'actions_on_bottom': self.actions_on_bottom,
+            'actions_selection_counter': self.actions_selection_counter,
         }
         context.update(extra_context or {})
         context_instance = template.RequestContext(request, current_app=self.admin_site.name)
diff --git a/django/contrib/admin/templates/admin/actions.html b/django/contrib/admin/templates/admin/actions.html
index bf4b975dfb..6d96616678 100644
--- a/django/contrib/admin/templates/admin/actions.html
+++ b/django/contrib/admin/templates/admin/actions.html
@@ -2,4 +2,9 @@
 <div class="actions">
     {% for field in action_form %}<label>{{ field.label }} {{ field }}</label>{% endfor %}
     <button type="submit" class="button" title="{% trans "Run the selected action" %}" name="index" value="{{ action_index|default:0 }}">{% trans "Go" %}</button>
+    {% if actions_selection_counter %}
+    <span class="action_counter">
+      {% blocktrans with cl.result_count as total_count %}<span class="_acnt">0</span> of {{ total_count }} {{ module_name }} selected{% endblocktrans %}
+    </span>
+    {% endif %}
 </div>
diff --git a/docs/ref/contrib/admin/_images/article_actions.png b/docs/ref/contrib/admin/_images/article_actions.png
index df4ab8f1ec..78a78ae494 100644
Binary files a/docs/ref/contrib/admin/_images/article_actions.png and b/docs/ref/contrib/admin/_images/article_actions.png differ
diff --git a/docs/ref/contrib/admin/_images/article_actions_message.png b/docs/ref/contrib/admin/_images/article_actions_message.png
index 31c5637469..6ea9439b8e 100644
Binary files a/docs/ref/contrib/admin/_images/article_actions_message.png and b/docs/ref/contrib/admin/_images/article_actions_message.png differ
diff --git a/docs/ref/contrib/admin/_images/user_actions.png b/docs/ref/contrib/admin/_images/user_actions.png
index 9a62f70685..fdbe2ad897 100644
Binary files a/docs/ref/contrib/admin/_images/user_actions.png and b/docs/ref/contrib/admin/_images/user_actions.png differ
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
index 97e9c8bcc9..d4851330c1 100644
--- a/docs/ref/contrib/admin/index.txt
+++ b/docs/ref/contrib/admin/index.txt
@@ -697,6 +697,12 @@ Controls where on the page the actions bar appears. By default, the admin
 changelist displays actions at the top of the page (``actions_on_top = True;
 actions_on_bottom = False``).
 
+.. attribute:: ModelAdmin.actions_selection_counter
+
+Controls whether a selection counter is display next to the action dropdown.
+By default, the admin changelist will display it
+(``actions_selection_counter = True``).
+
 .. attribute:: ModelAdmin.change_list_template
 
 Path to a custom template that will be used by the model objects "change list"
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
index df43701586..899fff80bc 100644
--- a/tests/regressiontests/admin_views/tests.py
+++ b/tests/regressiontests/admin_views/tests.py
@@ -1209,6 +1209,13 @@ class AdminActionsTest(TestCase):
         self.assertContains(response, msg)
         self.failUnlessEqual(Subscriber.objects.count(), 2)
 
+    def test_selection_counter(self):
+        """
+        Check if the selection counter is there.
+        """
+        response = self.client.get('/test_admin/admin/admin_views/subscriber/')
+        self.assertContains(response, '<span class="_acnt">0</span> of 2 subscribers selected')
+
 
 class TestCustomChangeList(TestCase):
     fixtures = ['admin-views-users.xml']