I'm currently working on adding drag-n-drop reordering of CCK field values for multiple fields on the node edit form.
When a node has several multiple fields, this of course leads to several separate dnd-enabled tables (a value from one field cannot be dropped into another field - thus differing from the blocks admin page).
It seems the drag-n-drop feature only works on the last table where the tabledrag behavior has been attached, be it when 1st building the page, or when reattaching to an ahah-updated subpart of the form.
No easy way to test right now, I'm posting this here as a placeholder until I can publish my code either in CCK HEAD or as a patch in the CCK queue - it still needs a little polishing.
Comment | File | Size | Author |
---|---|---|---|
#19 | drupal_tabledrag_IE7.patch | 726 bytes | quicksketch |
#17 | tabledrag_ie7.patch | 881 bytes | yched |
#9 | drupal_tabledrag_multiple.patch | 533 bytes | quicksketch |
#5 | tabledrag.patch | 1.73 KB | yched |
#4 | drupal_tabledrag_multiple.patch | 1.5 KB | quicksketch |
Comments
Comment #1
yched CreditAttribution: yched commentedA 1st pass of firebugging through dragtable.js showed this :
the function dragRow() (the mousemove event handler) starts by checking the existence of self.dragObject, wich seems to only exist when trying to drag from the last attached table.
Time to go to bed, I'll try dig more tomorrow.
Comment #2
yched CreditAttribution: yched commentedThe bug lies in these lines in tabledrag.js :
When executed with different values of self (different table), jquery considers that you're re-binding the same handler (dragRow) to the same object (document), and thus overrides the previous binding instead of adding a new one (dragRow function already has a guid - uncompressed jquery.js, line 1582)
Attached patch fixes this by having dragRow / dropRow take self as a param, and return a new handler function for every value of self :
It does work, but I'm absolutely not sure it's the cleanest/proper way to fix this. Reviews welcome (... Nate ? :-)
PS : I published the 'drag-n-drop field values' patch for CCK HEAD in http://drupal.org/node/195268 - I'm not committing it until we have a fix for this.
In order to test : grab CCK HEAD, apply the patch, add 2 or 3 multiple fields to a content type, and play with the node edit form.
Without the tabledrag fix, only the last table (or the last on which you hit the AHAH-'add new values' button) gets correct d-n-d.
As a side note, I guess fixing this might not only benefit CCK, but also maybe Views UI (seperately reorder filters, fields, sorts, etc) ? Not sure what is in the works about that...
Comment #3
quicksketchEaton pointed this patch out to me. I'm having a look at it, though right off it seems a bit unconventional. A function that does nothing but return an anonymous function... seems like there must be a clearer solution, but I've seen this sort of weirdness before when working with multiple object instances.
Comment #4
quicksketchThis patch should fix the problem.
jQuery has a (very neat) ability to not only attach functions to events, but also to remove them also. However, setting two functions with the same name (such as "dragRow") will over-write the previous function stored in that binding. I was not aware that this would occur even if it was separate instances of an object like ours.
So, rather than attaching a named "dragRow" function to the document, this creates an anonymous function with no name to bind to the document, so we won't run into these conflicts. It's actually less code, so cheers to that.
I'm bumping up to critical, because tabledrag.js was always intended to be used on multiple tables on a single page. This flaw is a critical bug that needs to get fixed ASAP.
Comment #5
yched CreditAttribution: yched commentedOf course, much cleaner than my original patch. And works perfectly.
Attached patch updates the signature of the call to dropRow in the blur handler (was missing in my patch too)
Aside from that, I think this is ready, but I cannot RTBC this new patch.
Comment #6
Gábor HojtsyLooks good, thanks, committed.
Comment #7
yched CreditAttribution: yched commentedCool :-) Thanks Nate !
Comment #8
yched CreditAttribution: yched commentedmultiple values reordering is committed to CCK HEAD :-)
Comment #9
quicksketchNice catch yched on the other call to dropRow. We can remove one more line that is no longer needed. Previously we were setting the 'self' variable to 'event.data.tableDrag'. But now we're passing it in directly so we don't need to be making this assignment.
Comment #10
yched CreditAttribution: yched commentedAh, true. It was a nice catch, but an incomplete one...
This is straightforward. RTBC.
Comment #11
Gábor HojtsyCommitted, thanks.
Comment #12
(not verified) CreditAttribution: commentedAutomatically closed -- issue fixed for two weeks with no activity.
Comment #13
yched CreditAttribution: yched commentedActually this seems to have broken tabledrag in IE7.
When you click a dnd handler, the moment your pointer leaves the handler area, dragRow() (mousemove handler) is not called anymore, until you unclick, which does not trigger dropRow() (mouseup handler) but lets dragRow() be called again
Reopening, and leaving the 'critical' priority on.
Comment #14
Gábor HojtsyComment #15
yched CreditAttribution: yched commentedRight, sorry about the title.
So. This doesn't make any sense.
If I simply comment out these lines from current HEAD tabledrag.js :
this of course breaks the functionality *but* the event handlers are called the way they're supposed to.
Uncommenting either one of these lines makes event handlers break again.
Appending an _ after the variable names (this.group_, this.table_), makes the thing work again...
Beats me for now...
Comment #16
yched CreditAttribution: yched commentedSide note : everything works fine in IE6.
Comment #17
yched CreditAttribution: yched commentedOK, I'm not sure exactly what is happening, but after a couple hours trying to follow the evenements flow, I tried preventing the mousedown event from bubbling up, and this fixed it.
Of course it's only afterwards that I that I noticed the 'return false' at the end of dragRow() which was there precisely to this intent, but wasn't effective anymore after the patch in #5 above got committed...
Tested to work in FF2, IE7, IE6, Opera...
Comment #18
starbow CreditAttribution: starbow commentedI just tested this patch. Before, I experienced the problem with IE7, after the patch it seemed to work fine. I also tested on FF2 after the patch, and it still works fine.
Comment #19
quicksketchWow, I'm glad we've got you checking on this yched. If this would've gone unnoticed it would've taken a hella lot more work to get this fixed looking for the problem.
So here's the deal, previously dragRow() was returning FALSE, which prevented the mousemove event from exiting out. I don't quite understand why IE7 requires this, but it makes sense for things like .click(), where if you return FALSE the normal click operation by the browser doesn't execute. When we made anonymous functions wrapped around dragRow(), I forgot to return the value from dragRow(). Adding a return seems to correct the problem.
dropRow() doesn't need the return because it doesn't return anything anyway.
Comment #20
quicksketchHa, looks like we cross-posted. Either solution works fine. I like yched's patch in #17 more because it's more clear and affects the mousedown event directly.
Comment #21
quicksketchTested Safari, IE6, Firefox, Opera with no negative side-effects. IE7 works properly. #17 is good to go.
Comment #22
Dries CreditAttribution: Dries commentedI've committed this patch to CVS HEAD. Thanks again folks.
Comment #23
quicksketchThanks Dries :)
Putting title back to original for posterity.
Comment #24
(not verified) CreditAttribution: commentedAutomatically closed -- issue fixed for two weeks with no activity.