### Eclipse Workspace Patch 1.0
#P nodequeue
Index: nodequeue_block/nodequeue_block.info
===================================================================
--- nodequeue_block/nodequeue_block.info	(revision 0)
+++ nodequeue_block/nodequeue_block.info	(revision 0)
@@ -0,0 +1,5 @@
+; $Id $
+name = Nodequeue Block
+description = Add a configuration block for each nodequeue
+package = Nodequeue
+core = 6.x
Index: nodequeue_block/nodequeue_block_dragdrop.js
===================================================================
--- nodequeue_block/nodequeue_block_dragdrop.js	(revision 0)
+++ nodequeue_block/nodequeue_block_dragdrop.js	(revision 0)
@@ -0,0 +1,154 @@
+// $Id: nodequeue_dragdrop.js,v 1.2 2009/08/17 21:37:06 ezrag Exp $
+
+Drupal.behaviors.nodequeueDrag = function(context) {  
+  $('.nodequeue-dragdrop').each(function(){
+    tableDrag = Drupal.tableDrag[$(this).attr('id')];
+    
+    tableDrag.onDrop = function() {
+      $('#'+$(this).attr('table').id+' td.position').each(function(i){
+        $(this).html(i + 1);
+      });
+    }    
+  });
+}
+
+Drupal.behaviors.nodequeueReverse = function(context) {
+  $('input[value="Reverse"]').click(function(){
+    var table = $(this).parent().find('.nodequeue-dragdrop:first');
+    // reverse table rows...
+    table.find('tr.draggable').each(function(i){
+      table.find('tbody').prepend(this);
+    });
+
+    // ...and update node positions
+    var size = table.find('.node-position').size();
+    table.find('.node-position').each(function(i){
+      var val = $(this).val();
+      $(this).val(size - val + 1);
+    });
+
+    nodequeueInsertChangedWarning(table.attr('id'));
+    nodequeueRestripeTable(table.attr('id'));
+
+    return false;
+  });
+};
+
+Drupal.behaviors.nodequeueShuffle = function(context) {
+  $('input[value="Shuffle"]').click(function(){
+    // randomize table rows...
+    var table = $(this).parent().find('.nodequeue-dragdrop:first');
+    var rows = $('#'+table.attr('id')+' tbody tr:not(:hidden)').get();
+    rows.sort(function(){return (Math.round(Math.random())-0.5);});
+    $.each(rows, function(i, row) {
+      $('#'+table.attr('id')+' tbody').prepend(this);
+    });
+    
+    var reverse = Drupal.settings.nodequeue.reverse[$('.nodequeue-dragdrop').index(table)];
+    console.log(reverse);
+    // ...and update node positions
+    var size = reverse ? table.find('.node-position').size() : 1;
+    table.find('.node-position').each(function(i){
+      var val = $(this).val();
+      $(this).val(size);
+      reverse ? size-- : size++;
+    });
+
+    nodequeueInsertChangedWarning(table.attr('id'));
+    nodequeueRestripeTable(table.attr('id'));
+
+    return false;
+  });
+};
+
+Drupal.behaviors.nodequeueClear = function(context) {
+  $('input[value="Clear"]').click(function(){
+    // mark nodes for removal
+    var table = $(this).parent().find('.nodequeue-dragdrop:first');
+    table.find('.node-position').each(function(i){
+      $(this).val('r');
+    });
+
+    // remove table rows...
+    rows = $('#'+table.attr('id')+' tbody tr:not(:hidden)').hide();
+
+    nodequeuePrependEmptyMessage(table.attr('id'));
+    nodequeueInsertChangedWarning(table.attr('id'));
+
+    return false;
+  });
+};
+
+Drupal.behaviors.nodequeueRemoveNode = function(context) {
+  $('a.nodequeue-remove').css('display', 'block');
+  $('a.nodequeue-remove').click(function() {
+    a = $(this).attr('id');
+    a = '#' + a.replace('nodequeue-remove-', 'edit-') + '-position';
+    $(a).val('r');
+
+    // hide the current row
+    $(this).parent().parent().fadeOut('fast', function(){
+      var table = $(this).parent().parent();
+      if ($('#'+table.attr('id')+' tbody tr:not(:hidden)').size() == 0) {
+        nodequeuePrependEmptyMessage(table.attr('id'));
+      }
+      else {
+        nodequeueRestripeTable(table.attr('id'))
+        nodequeueInsertChangedWarning(table.attr('id'));
+      }
+    });
+
+    return false;
+  });
+}
+
+Drupal.behaviors.nodequeueClearTitle = function(context) {
+  var widget = $('input[value="Enter the title of a node to add it to the queue"]');
+  widget.css('color', '#999');
+  widget.focus(function(){
+    if (this.value == this.defaultValue) {
+      this.value = '';
+      $(this).css('color', '#000');
+    }
+  }).blur(function(){
+    if (!this.value.length) {
+      $(this).css('color', '#999');
+      this.value = this.defaultValue;
+    }
+  });
+}
+
+/**
+ * Restripe the nodequeue table after removing an element or changing the
+ * order of the elements.
+ */
+function nodequeueRestripeTable(tableID) {
+  $('#'+tableID+' tbody tr:not(:hidden)')
+  .filter(':odd')
+    .removeClass('odd').addClass('even')
+      .end()
+  .filter(':even')
+    .removeClass('even').addClass('odd')
+      .end();
+
+  $('#'+tableID).find('tr:visible td.position').each(function(i){
+    $(this).html(i + 1);
+  });
+}
+
+/**
+ * Add a row to the nodequeue table explaining that the queue is empty.
+ */
+function nodequeuePrependEmptyMessage(tableID) {
+  $('#'+tableID+' tbody').prepend('<tr class="odd"><td colspan="6">No nodes in this queue.</td></tr>');
+}
+
+/**
+ * Display a warning reminding the user to save the nodequeue.
+ */
+function nodequeueInsertChangedWarning(tableID) {
+  if (Drupal.tableDrag[tableID].changed == false) {
+    $(Drupal.theme('tableDragChangedWarning')).insertAfter('#'+tableID).hide().fadeIn('slow');
+    Drupal.tableDrag[tableID].changed = true;
+  }
+}
Index: nodequeue.module
===================================================================
--- nodequeue.module	(revision 28766)
+++ nodequeue.module	(working copy)
@@ -1108,7 +1108,8 @@
   // add submit, reverse, shuffle, and clear buttons
   $form['submit'] = array(
     '#type' => 'submit',
-    '#value' => t('Save')
+    '#value' => t('Save'),
+    '#submit' => array('nodequeue_arrange_subqueue_form_submit'),
   );
   $form['reverse'] = array(
     '#type' => 'submit',
Index: nodequeue_block/nodequeue_block.module
===================================================================
--- nodequeue_block/nodequeue_block.module	(revision 0)
+++ nodequeue_block/nodequeue_block.module	(revision 0)
@@ -0,0 +1,163 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Makes individual nodequeue administration available as blocks
+ */
+
+/**
+ * Implementation of hook_block().
+ *
+ * @param string $op
+ * @param integer $delta
+ * @param array $edit
+ * @return array
+ */
+function nodequeue_block_block($op = 'list', $delta = 0, $edit = array()) {
+  $nodequeue_array = nodequeue_block_get_nodequeues();
+  $blocks = array();
+  if ($op == 'list') {
+    $block_delta = 0;
+    foreach ($nodequeue_array as $queue_item) {
+      $blocks[$block_delta]['info'] = t('Nodequeue Block: ') . $queue_item['name'];
+      $blocks[$block_delta]['cache'] = BLOCK_CACHE_GLOBAL;
+      $block_delta ++;    
+    }
+  drupal_rebuild_theme_registry();  
+  return $blocks;
+  }
+  elseif ($op == 'view') {
+    while ($delta >= 0) {
+      $qid = $nodequeue_array[$delta]['qid'];
+      $queue =  nodequeue_load($qid);
+      $subqueues = nodequeue_load_subqueues_by_queue($qid);
+      $subqueue = array_shift($subqueues);
+      $nodes = _nodequeue_dragdrop_get_nodes($queue, $subqueue);
+      $block['title'] =  'Nodequeue: ' . $nodequeue_array[$delta]['name'];
+      $block['content'] = drupal_get_form('nodequeue_arrange_subqueue_form_' . $qid, $queue, $nodes, $subqueue);
+      drupal_rebuild_theme_registry();
+      return $block;
+    }
+  }
+}
+
+/**
+ * Implementation of hook_forms().
+ */
+
+function nodequeue_block_forms($form_id) {
+  $forms = array();
+  if (strpos($form_id, 'nodequeue_arrange_subqueue_form_') === 0) {
+    $forms[$form_id] = array(
+      'callback' => 'nodequeue_arrange_subqueue_form',
+    );
+  }
+  return $forms;
+}
+
+/**
+ * Creates array of existing nodequeue names and qids
+ */  
+function nodequeue_block_get_nodequeues() {
+  $sql = 'SELECT qid, title FROM {nodequeue_queue} WHERE show_in_ui = 1';
+  $theresult = db_query($sql);
+  $nodequeue_block_queues = array();
+  $key = 0;
+  while ($data = db_fetch_object($theresult)) {
+    $nodequeue_block_queues[$key]['qid'] = $data->qid;
+    $nodequeue_block_queues[$key]['name']= $data->title;
+    $key ++;
+  }
+  return $nodequeue_block_queues;  
+}
+
+/**
+ * Implementation of theme_registry_alter().
+ *
+ * Override nodequeues theme function
+ */
+
+function nodequeue_block_theme_registry_alter(&$theme_registry) {
+
+  $qids = nodequeue_get_all_qids();
+  if (!empty($theme_registry['nodequeue_arrange_subqueue_form'])) {
+    foreach ($qids as $qid) {
+      $theme_registry['nodequeue_arrange_subqueue_form_' . $qid]['function'] = 'nodequeue_block_arrange_subqueue_form';
+    }
+  }
+}
+
+/**
+ * Our new theme function to add unique ids to each table
+ * so add_tabledrag works on multiple tables on a single page.
+ * Almost all of this taken from the nodequeue module
+ * 
+ * @ingroup themeable
+ */
+ 
+function nodequeue_block_arrange_subqueue_form($form) {
+  $output = '';
+
+  $subqueue = $form['#subqueue'];
+
+  // get css to hide some of the help text if javascript is disabled
+  drupal_add_css(drupal_get_path('module', 'nodequeue') .'/nodequeue.css');
+
+  // TODO: Would be nice to expose qid, sqid, reference as classes for more custom theming :).
+  
+  // Added our own tabledrag class here
+  $tableid = 'nodequeue-dragdrop-' . $form['#queue']['qid'];
+  drupal_add_tabledrag($tableid, 'order', 'sibling', 'node-position');
+  drupal_add_js(drupal_get_path('module', 'nodequeue_block') .'/nodequeue_block_dragdrop.js');
+
+  drupal_add_js(array('nodequeue' => array('reverse' => (bool) $form['#queue']['reverse'])), 'setting');
+
+  // render form as table rows
+  $rows = array();
+  $counter = 1;
+  foreach (element_children($form) as $key) {
+    if (isset($form[$key]['title'])) {
+      $row = array();
+
+      $row[] = drupal_render($form[$key]['title']);
+      $row[] = drupal_render($form[$key]['author']);
+      $row[] = drupal_render($form[$key]['date']);
+      $row[] = drupal_render($form[$key]['position']);
+      $row[] = drupal_render($form[$key]['edit']);
+      $row[] = drupal_render($form[$key]['remove']);
+      $row[] = array(
+        'data' => $counter,
+        'class' => 'position'
+      );
+
+      $rows[] = array(
+        'data'  => $row,
+        'class' => 'draggable',
+      );
+    }
+
+    $counter++;
+  }
+  if (empty($rows)) {
+    $rows[] = array(array('data' => t('No nodes in this queue.'), 'colspan' => 7));
+  }
+
+  // render the main nodequeue table
+  $header = array(t('Title'), t('Author'), t('Post Date'), t('Position'), array('data' => t('Operations'), 'colspan' => 2), t('Position'));
+  $output .= theme('table', $header, $rows, array('id' => $tableid, 'class' => 'nodequeue-dragdrop'));
+
+  // render the autocomplete field for adding a node to the table
+  $output .= '<div class="container-inline">';
+  $output .= drupal_render($form['add']['nid']);
+  $output .= drupal_render($form['add']['submit']);
+  $output .= '</div>';
+
+  $form['form_id']['#id'] = 'nodequeue_arrange_subqueue_form_' . $form['#queue']['qid'];
+  $form['form_id']['#value'] = 'nodequeue_arrange_subqueue_form_' . $form['#queue']['qid'];
+  
+  // render the remaining form elements
+  $output .= drupal_render($form); 
+
+  return $output;
+}
