As seen here: http://drupal.org/node/54017 I've recreated the method as a patch on the stable 4.7 edition of book.module. The patch is a melting pot of various snippets published by myself, coreyp_1, and Prometheus6.

Additions include the ability to see weights inside the parenting dropdown (for at-a-glance positioning). The weights are hidden unless the user has the proper permissions (a new permission was added to give users the ability to control weights as well). Also, using javascript, the parenting box is now split into two - book and parent. All top-level nodes are in book and, upon selection, the parent box automatically displays the corresponding nodes parented beneath it. This prevents seeing the hierarchy of all books at once in one enormous dropdown. For those with javascript disabled, the original dropdown displays via the 'noscript' html tag. It took me many hours to figure out how to get this to work with the new form API, but it seems to be working as planned (and a little better polished than the 4.6 version I created as bookplus.module). Would be great to have someone else test it and possibly add to core...I know a lot of people feel burndened by the current state of the parenting dropdown.

Comments

urbanfalcon’s picture

StatusFileSize
new46.7 KB

Found a way to slim it down just a hair by moving the javascript call that used to be in hook_footer. Attached is a new patch (not cumulative...this replaces the patch posted above).

urbanfalcon’s picture

StatusFileSize
new16.05 KB

Oops. That's what I get for staying up so late - I attach the wrong file! It was easy as the preview area doesn't show filenames...oh well. Hopefully someone with the ability to edit these posts can remove it so that no one gets confused by it. Here's the actual patch - and I did search + replace to convert tabs to spaces (although this added a bit of file bloat).

urbanfalcon’s picture

StatusFileSize
new16.12 KB

So, I learned that a 'select' form element must pass at least 'array()' via #options or it'll post this to the logs:

Invalid argument supplied for foreach() in /var/www/html/drupal/includes/form.inc on line 637.

I guess my case of not having options in a select element is singular as the cascading menus require javascript to do that portion of form creation. The form API wasn't so happy with it, though...at least until I passed it an empty array versus a NULL value by ignoring #options altogether. Attached is the patch that supercedes the others.

Jaza’s picture

Version: 4.7.0 » x.y.z
Status: Needs review » Needs work

I have a number of comments to make about this patch:

1. This is clearly new functionality, and so is only a candidate for HEAD, not for 4.7. I've marked it as such.

2. We NEVER embed JavaScript directly into a module's code, and we most certainly NEVER output JS as part of a themed HTML page. All JS in Drupal is written in separate .js files, which are stored in the /misc directory for core JS, and in a module's directory for contrib JS. These files are included using the drupal_add_js() function.

3. This is an extremely unclean and non-reusable version of what is available when you use the category module and the activeselect module. If you must implement dynamically linked select lists in the book module, please do so by utilising the API provided by the activeselect module.

4. I don't think that this functionality belongs in the book module anyway. Book does not have a clear distinction between 'top-level book pages' and 'other book pages' - they're all just book pages. This is much more suitable for the category module, where there IS a clear distinction between categories and containers (they're two separate node types), and where the user must select a container and a parent, in separate select lists, for every category (even when not using activeselect). If you want this functionality, install category and activeselect, and use category_legacy to import your existing books into the category system.

urbanfalcon’s picture

1. It's not really "new" functionality but rather a different method of viewing old data, but that's fine...

2. How do you deal with javascript that's created dynamically on a per-node basis via PHP? The php "creators" won't function inside a .js file. I guess I could have just stripped out the functions that deal with js and put them in a separate php file, but that still wouldn't achieve what you're talking about. If you have pointers as to the best way of dealing with these two conflicting paradigms, please send me an email.

3. What do you mean non-reusable? As to using the two modules you suggested: The category module doesn't seem to maintain heirarchies at all (book->chapter->subchapter->page) without a lot of overhead. None of my users would understand nor be willing to build what amounts to a creating a book/chapter/subchapter title node before creating their subsequent content page. The current book page creation method is completely straightforward and turnkey.

4. I disagree. I've seen a lot of posts where people are using book.module and fighting the length of the parenting dropdown. And while you're right, there's no immediate distinction between new book page nodes and their roles as book/chapter/subchapter/page, the distinction is made when a user places them in the parenting hierarchy. That said, the first page in the heirarchy is always and the default interface even states that is an independent book. So I don't see how breaking it down by books wouldn't apply in all cases.

urbanfalcon’s picture

I have an updated version which disables the "parent" dropdown on a "book" node when user is attempting to parent a book to itself. There was already protection against letting a user parent a "page" against itself. I believe this takes care of a Drupal validation/security message as well. I'm not going to keep posting patches/upgrades/tweaks here, though, as the coders don't seem to believe that there's anything wrong with the original parenting select box (even if the users do). If anyone is actually interested, I'll probably keep an updated copy on my homepage...or they're welcome to email me.

moshe weitzman’s picture

not so fast. there is a real UI problem with the hugely long book parent dropdown. it will take some iterations to get it right, but i do think this is core worthy.

beginner’s picture

I was thinking about another way, not to solve the problem altogether, but to alleviate it.

My solution doesn't use javascript at all, and could be complementary to the one proposed above.

Most sites won't have ONE book but SEVERAL:
http://drupal.org/book ,
http://www.wechange.org/book .

The problem is made worse by the fact that the drop-down list include ALL pages from ALL books.
I propose a way to separate altogether each book, so that when creating a child page, one gets only the pages of that one book.

When adding a new page, one would have to select the book first, THEN decide where in the outline of that book, the new book page should be.

If going to node/add/book, we would get a list of the available books and choose one.
If going to node/add/book/3, we would be adding a page in book $bid == 3.

It could be fairly easy to implement by adding a few fields in the {book} table:

  • Book id
  • book title (?)
  • book permission (?)
  • book author uid

I am not sure about the second~fourth field above, but the 1st is required.

This solution doesn't involve javascript, which could be added on top of that.

With this solution, we can add quite a few new functionalities to book.module:

  • a new access control: "create new book" in addition to the existing "create book pages"
  • the "create book page" permission could be set per book.
  • and of course... drop down menu would be much shorter and...
  • amount of data to process would be less, because we would select WHERE bid=$bid
  • different design/theme per book
  • and other ways others will find to use this new feature

This solution seems to be more elegant, and not only does it lessen a useability nightmare (without solving it completely, though) while introducing the possibility for nice new features.

Should I propose a patch here, or create a new issue for that?

urbanfalcon’s picture

What you're proposing seems like it would really lock down the book hierarchy. Right now, you can move an entire book so that it becomes a chapter (subchapter, etc.) of another. You can also move pages from one book to another. To do it your way, you'd lose that flexibility. Also, in 4.7 there is already a 'create new book' permission. The javascript alternative does exactly what you're talking about, as far as the interface goes, without creating limitations on book page portability...and it obeys the new permission. It's not possible to change the theme per book without a lot of hacking, but I'm not sure how many people truly need that finite level of visual control.

beginner’s picture

If you change a page from one book to the other, it's only one line of code to change the book-id field of all its children. The flexibility is maintained and the possibility of new cool features is introduced without the need for javascript (which can be used on top of that).

urbanfalcon’s picture

You said, "When adding a new page, one would have to select the book first, THEN decide where in the outline of that book, the new book page should be." Without javascript, that means one form (and submission) to select the book and a second to select a place in the outline of that book. For pre-existing nodes, you're right...you could use good old HTML to pre-select the appropriate book in "Form A" and, if the book was not changed, pre-select the prior weighted location in the book's outline via "Form B". But that still leaves you with having to juggle two concurrent forms, as without javascript they wouldn't be able to "talk" to each other on the same page. How would you get around that given the current hook-based editing scheme? I don't think I've actually seen that work in this environment (yet).

urbanfalcon’s picture

Made some updates to this module, including the addition of javascript-expandable/collapsible tables of contents. Visit my homepage to download a copy. Tested on Firefox and IE, and since the javascript interactivity is applied after-the-fact, it degrades nicely to a full table of contents.

catch’s picture

Version: x.y.z » 6.x-dev
Status: Needs work » Closed (duplicate)

Book module has been rewritten in 6.x, fixing this.