-// $Id: book.module,v 1.1 2006/05/07 07:29:15 urbanfalcon Exp $
+// $Id: book.module,v 1.361 2006/04/17 20:48:26 dries Exp $
+// Edited to add page weights permissions in access control
+// Also modifed for new cascading book parenting dropdowns
 
 /**
  * @file
  * Allows users to collaboratively author a book.
  */
+ 
+/*
+* Custom function to aid javascript-based book parenting.
+* -returns the nid of the top level node of the book tree to which $nid belongs
+* -used as the initial value of the book select
+*/
+function book_top_level_book($nid) {
+  if ($nid){
+    $book_list_query = db_query('SELECT * FROM {book} ORDER BY nid');
+    while($book = db_fetch_object($book_list_query)) {
+      $book_list[$book->nid] = $book;
+      }
+    $current->nid = $nid;
+    while($book_list[$current->nid]->parent != 0) {
+      $current->nid = $book_list[$current->nid]->parent;
+      }
+    return $current->nid;
+    }
+  }
+  
+/**
+* Custom function to aid javascript-based book parenting.
+* -returns an array of all top level book nodes
+* -used to initialize the book select
+*/
+function book_top_level_booklist() {
+  $search = array('"', '(', ')', chr(10), chr(13));
+  $replace = array('\"', '\(', '\)', '', '');
+  if (user_access('administer nodes')) {
+    $root_books[0] = t('New book');
+    }
+  $book_list_query = db_query('SELECT b.*, n.title FROM {book} b JOIN {node} n ON n.nid = b.nid WHERE n.status = 1 ORDER BY b.weight, n.title');
+  while ($node = db_fetch_object($book_list_query)) {
+    $node->title = $node->title . (user_access('administer nodes') || user_access('adjust page weights') ? ' : '. $node->weight : ''); //show weights
+    if ($node->parent == 0){ //only show root books in this list
+      $root_books[$node->nid] = str_replace($search, $replace, $node->title);      
+      }
+    }
+  return $root_books;
+  }
+  
+/**
+* Custom function to aid javascript-based book parenting.
+* -returns the array of book data that everything else operates on.
+*/
+function book_booklist_query() {
+  $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE n.status = 1 ORDER BY b.weight, n.title'));
+  while ($node = db_fetch_object($result)) {
+    if (!$children[$node->parent]) {
+      $children[$node->parent] = array();
+      }
+    array_push($children[$node->parent], $node);
+    }
+  return $children;
+  }
+
+/**
+* Custom function to aid javascript-based book parenting.
+* -returns an array of all the books beneath $root_book_nid in the book tree.
+* -used to initialize the parent select
+* @param
+* $root_book_nid : the top level book
+* @param
+* $booklist: result of book_booklist_query()
+*/
+function book_current_book_chapters($booklist, $root_book_nid) {
+  if ($root_book_nid){
+    return book_toc_recurse($root_book_nid, '', array(), $booklist, $exclude);
+    } else {
+    return array();
+    }
+  }
+  
+/**
+* Custom function to aid javascript-based book parenting.
+* @param
+* $root_books: array of top level books
+* @param
+* $booklist: result of book_booklist_query()
+*/
+function book_insert_bookjs($booklist, $root_books, $default_parent = 0) {
+  $search = array('"', '(', ')', chr(10), chr(13));
+  $replace = array('\"', '\(', '\)', '', '');
+  foreach($root_books as $nid => $title) {
+    $root_book_pages[$nid] = book_toc_recurse($nid, '', array(), $booklist, $exclude);
+    }
+  $init_option .= "    case \"0\":\n";
+  $init_option .= '      parentSelect.options[0] = new Option("'. t('<top-level>') . "\", 0);\n";
+  $init_option .= "      break;\n";
+  foreach($root_book_pages as $key => $root_book) {    
+    if ($key) {
+      $init_option .= "    case \"$key\":\n";
+      $init_option .= '      parentSelect.options[0] = new Option("'. t('<top-level>') . "\", $key);\n";
+      foreach($root_book as $book_nid => $book_page_title) {
+        $book_nid == $default_parent ? $defaultSelected = ", true" : $defaultSelected = "";
+        $book_page_title = str_replace($search, $replace, $book_page_title);
+        if ($book_nid != arg(1)){
+          $init_option .= "      parentSelect.options[parentSelect.options.length] = new Option(\"".$book_page_title."\", ".$book_nid.$defaultSelected.");\n";
+          }
+        }
+      $init_option .= "      break;\n";
+      }
+    }
+  $jscript = "<script type=\"text/javascript\">
+<!--
+function setParentSelect(bookSelect) {
+  var bookOption = bookSelect.selectedIndex;
+  var bookOptionValue = bookSelect.options[bookOption].value;
+  var parentSelect = bookSelect.form['edit-parent'];
+  parentSelect.options.length = 0;
+  switch (bookOptionValue) {
+".$init_option."
+    }
+  }
+// -->
+</script>";
+  drupal_set_html_head($jscript);
+  } 
 
 /**
  * Implementation of hook_node_info().
@@ -17,7 +137,7 @@
  * Implementation of hook_perm().
  */
 function book_perm() {
-    return array('outline posts in books', 'create book pages', 'create new books', 'edit book pages', 'edit own book pages', 'see printer-friendly version');
+    return array('outline posts in books', 'create book pages', 'create new books', 'edit book pages', 'edit own book pages', 'see printer-friendly version', 'adjust page weights');
 }
 
 /**
@@ -231,61 +351,122 @@
 }
 
 /**
+ * Helper function for javascript form elements().
+ */
+function theme_book_script_form(&$form){
+  $output = "<script type=\"text/javascript\" language=\"javascript\">\n";
+  $output .= "document.write('<fieldset class=\" collapsible\"><legend>".t('Page hierarchy')."</legend>";
+  $output .= str_replace("\n","",form_render($form));
+  $output .= "</fieldset>');\n";
+  $output .= "if (isJsEnabled()) {\n";
+  $output .= "  setParentSelect(document.getElementById('edit-book'));\n";
+  $output .= "  }\n";  
+  $output .= "</script>\n";
+  return $output;
+  }
+
+/**
  * Implementation of hook_form().
  */
 function book_form(&$node) {
   if ($node->nid && !$node->parent && !user_access('create new books')) {
     $form['parent'] = array('#type' => 'value', '#value' => $node->parent);
-  }
-  else {
-    $form['parent'] = array('#type' => 'select',
-      '#title' => t('Parent'),
+    } else {
+    $book_list = book_booklist_query();
+    $top_level_book_list = book_top_level_booklist();
+    $top_level_book = $node->parent > 0 ? book_top_level_book($node->parent) : (arg(4) ? book_top_level_book(arg(4)) : $node->nid);
+    $default_parent = $node->parent ? $node->parent : arg(4);  
+    book_insert_bookjs($book_list, $top_level_book_list, $default_parent);
+    
+    //if javascript is turned on, display interactive form
+    //render fieldset group via theme_book_script_form
+    $form['script_wrapper'] = array(
+      '#type' => 'markup',
+      '#weight' => -4,    
+      '#theme' => book_script_form,
+      );  
+    $form['script_wrapper']['book'] = array(
+      '#type' => 'select',
+      '#title' => t('Book'),    
+      '#default_value' => $top_level_book,
+      '#options' => $top_level_book_list,
+      '#description' => user_access('administer nodes') || user_access('adjust page weights') ? t('The top level book of this page. Weights are shown following the semi-colon.') : t('The top level book of this page.'),
+      '#attributes' => array('onchange' => 'setParentSelect(this);'),
+      );  
+    $form['script_wrapper']['parent'] = array(
+      '#type' => 'select',
+      '#title' => t('Parent'),    
+      '#description' => user_access('administer nodes') || user_access('adjust page weights') ? t('The parent of this page. Weights are shown following the semi-colon.') : t('The parent that this page belongs in.'),
+      );
+      
+    //if javascript is turned off, then default to original
+    $form['noscript_wrapper'] = array(
+      '#type' => 'fieldset',
+      '#prefix' => "<noscript>\n",
+      '#title' => t('Page hierarchy'),
+      '#collapsible' => TRUE,
+      '#collapsed' => FALSE,
+      '#suffix' => "</noscript>\n",    
+      '#weight' => -4,    
+      );  
+    $form['noscript_wrapper']['parent'] = array('#type' => 'select',
+      '#title' => t('Parent'),    
       '#default_value' => ($node->parent ? $node->parent : arg(4)),
       '#options' => book_toc($node->nid),
-      '#weight' => -4,
       '#description' => user_access('create new books') ? t('The parent section in which to place this page.  Note that each page whose parent is &lt;top-level&gt; is an independent, top-level book.') : t('The parent that this page belongs in.'),
-    );
-  }
-
+      );
+    }
+  
   $form['title'] = array('#type' => 'textfield',
     '#title' => t('Title'),
     '#required' => TRUE,
     '#default_value' => $node->title,
     '#weight' => -5,
-  );
+    );
   $form['body_filter']['body'] = array('#type' => 'textarea',
     '#title' => t('Body'),
     '#default_value' => $node->body,
     '#rows' => 20,
     '#required' => TRUE,
-  );
+    );
   $form['body_filter']['format'] = filter_form($node->format);
-
-  $form['log'] = array(
-    '#type' => 'textarea',
+  
+  $form['log_wrapper'] = array(
+    '#type' => 'fieldset',
     '#title' => t('Log message'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+    '#weight' => 5,  
+    );    
+  $form['log_wrapper']['log'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Document history'),
     '#default_value' => $node->log,
-    '#weight' => 5,
     '#description' => t('An explanation of the additions or updates being made to help other authors understand your motivations.'),
-  );
-
-  if (user_access('administer nodes')) {
-    $form['weight'] = array('#type' => 'weight',
+    );
+  
+  if (user_access('administer nodes') || user_access('adjust page weights')) {
+    $form['weight_wrapper'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Page ordering'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#weight' => 4,    
+      );    
+    $form['weight_wrapper']['weight'] = array('#type' => 'weight',
       '#title' => t('Weight'),
       '#default_value' => $node->weight,
       '#delta' => 15,
-      '#weight' => 5,
       '#description' => t('Pages at a given level are ordered first by weight and then by title.'),
-    );
-  }
-  else {
+      );
+    } else {
     // If a regular user updates a book page, we create a new revision
     // authored by that user:
     $form['revision'] = array('#type' => 'hidden', '#value' => 1);
-  }
-
+    }
+  
   return $form;
-}
+  }
 
 /**
  * Implementation of function book_outline()
@@ -294,41 +475,103 @@
 function book_outline($nid) {
   $node = node_load($nid);
   $page = book_load($node);
-
-  $form['parent'] = array('#type' => 'select',
-    '#title' => t('Parent'),
+  $book_list = book_booklist_query();
+  $top_level_book_list = book_top_level_booklist();
+  $top_level_book = $page->parent > 0 ? book_top_level_book($page->parent) : (arg(4) ? book_top_level_book(arg(4)) : $page->nid);
+  $default_parent = $page->parent ? $page->parent : arg(4);  
+  book_insert_bookjs($book_list, $top_level_book_list, $default_parent);
+  
+  //if javascript is turned on, display interactive form
+  //render fieldset group via theme_book_script_form
+  $form['script_wrapper'] = array(
+    '#type' => 'markup',
+    '#weight' => -4,    
+    '#theme' => book_script_form,
+    );  
+    $form['script_wrapper']['book'] = array(
+    '#type' => 'select',
+    '#title' => t('Book'),    
+    '#default_value' => $top_level_book,
+    '#options' => $top_level_book_list,
+    '#description' => user_access('administer nodes') || user_access('adjust page weights') ? t('The top level book of this page. Weights are shown following the semi-colon.') : t('The top level book of this page.'),
+    '#attributes' => array('onchange' => 'setParentSelect(this);'),
+    );  
+  $form['script_wrapper']['parent'] = array(
+    '#type' => 'select',
+    '#title' => t('Parent'),    
+    '#description' => user_access('administer nodes') || user_access('adjust page weights') ? t('The parent section in which to place this page. Weights are shown following the semi-colon.') : t('The parent section in which to place this page.'),
+    );
+    
+  //if javascript is turned off, then default to original
+  $form['noscript_wrapper'] = array(
+    '#type' => 'fieldset',
+    '#prefix' => "<noscript>\n",
+    '#title' => t('Page hierarchy'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+    '#suffix' => "</noscript>\n",    
+    '#weight' => -4,    
+    );  
+  $form['noscript_wrapper']['parent'] = array('#type' => 'select',
+    '#title' => t('Parent'),    
     '#default_value' => $page->parent,
     '#options' => book_toc($node->nid),
-    '#description' => t('The parent page in the book.'),
-  );
-  $form['weight'] = array('#type' => 'weight',
-    '#title' => t('Weight'),
-    '#default_value' => $page->weight,
-    '#delta' => 15,
-    '#description' => t('Pages at a given level are ordered first by weight and then by title.'),
-  );
-  $form['log'] = array('#type' => 'textarea',
+    '#description' => user_access('create new books') ? t('The parent section in which to place this page.  Note that each page whose parent is &lt;top-level&gt; is an independent, top-level book.') : t('The parent that this page belongs in.'),
+    );  
+    
+  $form['log_wrapper'] = array(
+    '#type' => 'fieldset',
     '#title' => t('Log message'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+    '#weight' => 5,    
+    );    
+  $form['log_wrapper']['log'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Document history'),
     '#default_value' => $node->log,
     '#description' => t('An explanation to help other authors understand your motivations to put this post into the book.'),
-  );
-
+    );
+    
+  if (user_access('administer nodes') || user_access('adjust page weights')) {
+    $form['weight_wrapper'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Page ordering'),
+      '#collapsible' => TRUE,
+      '#collapsed' => FALSE,  
+      '#weight' => 4,      
+      );    
+    $form['weight_wrapper']['weight'] = array('#type' => 'weight',
+      '#title' => t('Weight'),
+      '#default_value' => $page->weight,
+      '#delta' => 15,
+      '#description' => t('Pages at a given level are ordered first by weight and then by title.'),
+      );
+    }
+    
   $form['nid'] = array('#type' => 'value', '#value' => $nid);
   if ($page->nid) {
-    $form['update'] = array('#type' => 'submit',
+    $form['update'] = array(
+      '#type' => 'submit',
       '#value' => t('Update book outline'),
-    );
-    $form['remove'] = array('#type' => 'submit',
+      '#weight' => 6,  
+      );
+    $form['remove'] = array(
+      '#type' => 'submit',
       '#value' => t('Remove from book outline'),
-    );
-  }
-  else {
-    $form['add'] = array('#type' => 'submit', '#value' => t('Add to book outline'));
-  }
-
+      '#weight' => 6,        
+      );
+    } else {
+    $form['add'] = array(
+      '#type' => 'submit', 
+      '#value' => t('Add to book outline'),
+      '#weight' => 6,        
+      );
+    }
+  
   drupal_set_title(check_plain($node->title));
   return drupal_get_form('book_outline', $form);
-}
+  }
 
 /**
  * Handles book outline form submissions.
@@ -547,7 +790,7 @@
   if ($children[$nid]) {
     foreach ($children[$nid] as $foo => $node) {
       if (!$exclude || $exclude != $node->nid) {
-        $toc[$node->nid] = $indent .' '. $node->title;
+       $toc[$node->nid] = $indent .' '. $node->title . (user_access('administer nodes') || user_access('adjust page weights') ? ' : '. $node->weight : '');
         $toc = book_toc_recurse($node->nid, $indent .'--', $toc, $children, $exclude);
       }
     }
@@ -1034,6 +1277,4 @@
   if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'outline') {
     return t('The outline feature allows you to include posts in the <a href="%book">book hierarchy</a>.', array('%book' => url('book')));
   }
-}
-
-
+}