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.
| Comment | File | Size | Author |
|---|---|---|---|
| #3 | book_47.patch | 16.12 KB | urbanfalcon |
| #2 | book_46.patch | 16.05 KB | urbanfalcon |
| #1 | book_2.module | 46.7 KB | urbanfalcon |
| book_45.patch | 17.91 KB | urbanfalcon |
Comments
Comment #1
urbanfalcon commentedFound 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).
Comment #2
urbanfalcon commentedOops. 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).
Comment #3
urbanfalcon commentedSo, 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.
Comment #4
Jaza commentedI 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.
Comment #5
urbanfalcon commented1. 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.
Comment #6
urbanfalcon commentedI 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.
Comment #7
moshe weitzman commentednot 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.
Comment #8
beginner commentedI 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:
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:
WHERE bid=$bidThis 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?
Comment #9
urbanfalcon commentedWhat 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.
Comment #10
beginner commentedIf 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).
Comment #11
urbanfalcon commentedYou 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).
Comment #12
urbanfalcon commentedMade 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.
Comment #13
catchBook module has been rewritten in 6.x, fixing this.