summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Wittens <steven@10.no-reply.drupal.org>2006-11-21 08:16:39 +0000
committerSteven Wittens <steven@10.no-reply.drupal.org>2006-11-21 08:16:39 +0000
commit001d54f663136894ce0dce0a09693cc107cfb788 (patch)
tree745c0a9479855e27b331cf5b7a03ddebd2f8dd29
parent50641eafc0bfd321e09f71ab361dcf5c26469878 (diff)
downloadbrdo-001d54f663136894ce0dce0a09693cc107cfb788.tar.gz
brdo-001d54f663136894ce0dce0a09693cc107cfb788.tar.bz2
#84961: Add 'select all' and range select feature to admin tables.
-rw-r--r--CHANGELOG.txt1
-rw-r--r--includes/theme.inc10
-rw-r--r--misc/tableselect.js75
-rw-r--r--modules/comment/comment.module2
-rw-r--r--modules/node/node.module2
-rw-r--r--modules/system/system.css7
-rw-r--r--modules/user/user.module2
-rw-r--r--themes/garland/style.css9
8 files changed, 105 insertions, 3 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index ba54a8119..f16782bb2 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -30,6 +30,7 @@ Drupal 5.0, xxxx-xx-xx (development version)
* improved configurability of the contact forms.
* reorganized the settings pages.
* made it easy to investigate popular search terms
+ * added a 'select all' checkbox and a range select feature to administration tables.
- integrated urlfilter.module in filter.module
- block system:
* extended the block visibility settings with a role specific settings.
diff --git a/includes/theme.inc b/includes/theme.inc
index e90fb36f1..2dcbc021f 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -779,6 +779,16 @@ function theme_table($header, $rows, $attributes = array(), $caption = NULL) {
}
/**
+ * Returns a header cell for tables that have a select all functionality.
+ */
+function theme_table_select_header_cell() {
+ drupal_add_js(array('tableSelect' => array('selectAll' => t('Select all rows in this table'), 'selectNone' => t('Deselect all rows in this table'))), 'setting');
+ drupal_add_js('misc/tableselect.js');
+
+ return array('class' => 'select-all');
+}
+
+/**
* Return a themed sort icon.
*
* @param $style
diff --git a/misc/tableselect.js b/misc/tableselect.js
new file mode 100644
index 000000000..052af02dd
--- /dev/null
+++ b/misc/tableselect.js
@@ -0,0 +1,75 @@
+// $Id$
+
+Drupal.tableSelect = function() {
+ // Keep track of the table, which checkbox is checked and alias the settings.
+ var table = this, selectAll, checkboxes, lastChecked, settings = Drupal.settings.tableSelect;
+
+ // Store the select all checkbox in a variable as we need it quite often.
+ selectAll = $('<input type="checkbox" class="form-checkbox" />').attr('title', settings.selectAll).click(function() {
+ // Loop through all checkboxes and set their state to the select all checkbox' state.
+ checkboxes.each(function() {
+ this.checked = selectAll[0].checked;
+ // Either add or remove the selected class based on the state of the check all checkbox.
+ $(this).parents('tr:first')[ this.checked ? 'addClass' : 'removeClass' ]('selected');
+ });
+ // Update the title and the state of the check all box.
+ selectAll.attr('title', selectAll[0].checked ? settings.selectNone : settings.selectAll);
+ });
+
+ // Find all <th> with class select-all, and insert the check all checkbox.
+ $('th.select-all', table).prepend(selectAll);
+
+ // For each of the checkboxes within the table.
+ checkboxes = $('td input:checkbox', table).click(function(e) {
+ // Either add or remove the selected class based on the state of the check all checkbox.
+ $(this).parents('tr:first')[ this.checked ? 'addClass' : 'removeClass' ]('selected');
+
+ // If this is a shift click, we need to highlight everything in the range.
+ // Also make sure that we are actually checking checkboxes over a range and
+ // that a checkbox has been checked or unchecked before.
+ if (e.shiftKey && lastChecked && lastChecked != e.target) {
+ // We use the checkbox's parent TR to do our range searching.
+ Drupal.tableSelectRange($(e.target).parents('tr')[0], $(lastChecked).parents('tr')[0], e.target.checked);
+ }
+
+ // If all checkboxes are checked, make sure the select-all one is checked too, otherwise keep unchecked.
+ selectAll[0].checked = (checkboxes.length == $(checkboxes).filter(':checked').length);
+ // Set the title to the current action.
+ selectAll.attr('title', selectAll[0].checked ? settings.selectNone : settings.selectAll);
+
+ // Keep track of the last checked checkbox.
+ lastChecked = e.target;
+ });
+}
+
+Drupal.tableSelectRange = function(from, to, state) {
+ // We determine the looping mode based on the the order of from and to.
+ var mode = from.rowIndex > to.rowIndex ? 'previousSibling' : 'nextSibling';
+
+ // Traverse through the sibling nodes.
+ for (var i = from[mode]; i; i = i[mode]) {
+ // Make sure that we're only dealing with elements.
+ if (i.nodeType != 1) continue;
+
+ // Either add or remove the selected class based on the state of the target checkbox.
+ $(i)[ state ? 'addClass' : 'removeClass' ]('selected');
+ $('input:checkbox', i).each(function() {
+ this.checked = state;
+ });
+
+ if (to.nodeType) {
+ // If we are at the end of the range, stop.
+ if (i == to) break;
+ }
+ // A faster alternative to doing $(i).filter(to).length.
+ else if (jQuery.filter(to, [i]).r.length) break;
+
+ }
+}
+
+// Global Killswitch
+if (Drupal.jsEnabled) {
+ $(document).ready(function() {
+ $('form table[th.select-all]').each(Drupal.tableSelect);
+ });
+}
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index 1873c1b84..8ba74e689 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -1044,7 +1044,7 @@ function comment_admin_overview($type = 'new', $arg) {
// load the comments that we want to display
$status = ($type == 'approval') ? COMMENT_NOT_PUBLISHED : COMMENT_PUBLISHED;
$form['header'] = array('#type' => 'value', '#value' => array(
- NULL,
+ theme('table_select_header_cell'),
array('data' => t('Subject'), 'field' => 'subject'),
array('data' => t('Author'), 'field' => 'name'),
array('data' => t('Time'), 'field' => 'timestamp', 'sort' => 'desc'),
diff --git a/modules/node/node.module b/modules/node/node.module
index ef0b949d2..2ce5863db 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -1533,7 +1533,7 @@ function node_admin_nodes() {
*/
function theme_node_admin_nodes($form) {
// Overview table:
- $header = array(NULL, t('Title'), t('Type'), t('Author'), t('Status'), t('Operations'));
+ $header = array(theme('table_select_header_cell'), t('Title'), t('Type'), t('Author'), t('Status'), t('Operations'));
$output .= drupal_render($form['options']);
if (isset($form['title']) && is_array($form['title'])) {
diff --git a/modules/system/system.css b/modules/system/system.css
index c801759d6..5a92c5a89 100644
--- a/modules/system/system.css
+++ b/modules/system/system.css
@@ -325,3 +325,10 @@ html.js .resizable-textarea textarea {
display: block;
padding: 1.5em 0 .5em;
}
+
+/*
+** To be used with tableselect.js
+*/
+tr.selected td {
+ background: #ffc;
+}
diff --git a/modules/user/user.module b/modules/user/user.module
index d9e7fcb66..d35f36ecd 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -2043,7 +2043,7 @@ function user_admin_account() {
function theme_user_admin_account($form) {
// Overview table:
$header = array(
- array(),
+ theme('table_select_header_cell'),
array('data' => t('Username'), 'field' => 'u.name'),
array('data' => t('Status'), 'field' => 'u.status'),
t('Roles'),
diff --git a/themes/garland/style.css b/themes/garland/style.css
index b870d7484..195d2f646 100644
--- a/themes/garland/style.css
+++ b/themes/garland/style.css
@@ -840,6 +840,15 @@ table.system-status-report th {
border-color: #d3e7f4;
}
+#autocomplete li.selected, tr.selected td, tr.selected td.active {
+ background: #027ac6;
+ color: #fff;
+}
+
+tr.selected td a:link, tr.selected td a:visited, tr.selected td a:active {
+ color: #d3e7f4;
+}
+
/**
* CSS support
*/