date_popup outputs a separate inline JS block to initialize each popup-enabled text field. This requires a separate jQuery() scan through the DOM for each one, which quickly gets unacceptably slow if you have a multiple date field (or several!).
The attached patch reduces this to one inline block/DOM scan for each unique combination of function/arguments to be called.
I wrote this last night and, this morning, I'm thinking there are at least two better approaches:
1. Attach the function(arguments) call (e.g. timeEntry({ ... settings ... })) to the DOM element directly as an event handler via onload or similar (or maybe even onfocus). This way, no scans through the DOM are required as each invoked event handler automatically identifies the DOM element to operate on.
2. If for some reason that does not work, output a single CSS class for all elements that should be initialized via this system, search for them all once, then invoke the correct function(arguments) on each one based on other CSS classes assigned to the element (the whole set of required function/arguments data having been output in a single call to drupal_add_js, probably by just adding it to Drupal.settings).
Anyway, here's my patch to get started.
| Comment | File | Size | Author |
|---|---|---|---|
| #17 | date-popup-id-244025-17.patch | 9.28 KB | yched |
| #15 | date-popup-id-244025-15.patch | 9.04 KB | yched |
| #14 | date-popup-id-244025-14.patch | 9.17 KB | yched |
| #11 | date-popup-id-244025-11.patch | 3.86 KB | bjaspan |
| date-popup-settings.patch | 3.21 KB | bjaspan |
Comments
Comment #1
bjaspan commentedComment #2
karens commentedI knew there was a better way to do this and was hoping someone would provide a patch :)
I'm sure there are lots of other ways to make this work better, but I'm no jquery expert so I'm not sure of the best approaches and am open to ideas.
I'm committing this much, if you have more ideas, please let me know. Thanks!
Comment #3
Anonymous (not verified) commentedAutomatically closed -- issue fixed for two weeks with no activity.
Comment #4
karens commentedThis works fine in the D5 version but breaks in D6 when new fields are added using the AHAH 'add more' button. Now when you add a new field, the jquery calendar completely stops working.
I need ideas on how to fix this to work in D6 with AHAH.
Comment #5
karens commentedChanging title.
Comment #6
karens commentedThis is pretty critical - you can't use popup dates with the AHAH add more button.
Comment #7
yched commentedKaren, this sort of bug often means the JS code has to be implemented as a "Drupal.behavior", allowing it to be automatically re-executed by the AHAH API whenever new content is updated.
http://www.raincitystudios.com/blogs-and-pods/katherine-bailey/the-lowdo...
and http://drupal.org/node/114774#javascript-behaviors have good info about it.
Comment #8
karens commentedThanks yched, I knew there must be some way. Now, if I only understood how it works :)
I'm hoping someone will provide a patch to get this working right. If not, I'll try to bulldoze my way through it later. If anyone does look at this, be sure to pick up code with today's commits. I found I had left out part of Barry's original patch initially and just got that fixed this morning.
Comment #9
yched commentedI'll try to look into it, but it might not be before 2-3 days :-/
Comment #10
bjaspan commentedIt's good that this issue got re-opened because it reminded me of something I learned about it 6 weeks after submitting the patch.
Performing a complete DOM scan in JS is very slow, and every jQuery top-level search for a class (e.g. $(".classname")) performs such a scan. Performing lots of scans on a single page is EXTREMELY slow. The date_popup module performs a DOM scan for every unique set of settings (with this patch) and for every date element (without the patch). On a node edit form with many date fields, the date_popup DOM scans can cost tens of seconds by itself.
Retrieving elements by id is *much* faster. I guess the browsers keep an internal dictionary of ids so the DOM method getElementById() is fast (I've heard that getElementByClass() will exist eventually but does not yet).
So, I backed out the patch I posted for this issue and replaced it with a different one that sets a unique id for every date element, and outputs a separate set of settings for each element (like the code did before my patch), and uses the id to figure out which settings to apply to each element. It is MUCH faster.
An even better approach would be to combine the two solutions. Output a unique id for every date element, a single block of JS for each unique combination of date_popup settings, and another array indicating which block of settings should be used for each date element id.
Does this make sense?
Comment #11
bjaspan commentedHere's my latest patch. It is not RTBC as is but shows the intermediate approach of using ids instead of classes.
Comment #12
karens commentedActually most of the settings are the same always and only a few settings need to change for each unique field or element. I know there is a way to set up some global settings for the calendar that will never change, then only worry about settings which are different in the individual ids/classes. I don't know how much that helps things, but that's another change to think about. Actually almost everything but the date format and the year range will never change.
I also need to bump up to the newer version of the jQuery calendar popup. I haven't so far because it has API changes so the settings are different, but it adds lots of new things, like the ability to select a date range as well as an individual date. And both the current and the new code have ways you can have the from and to dates restrict each other so you can't select a from date greater than a to date.
But the starting point is to get this much working.
Comment #13
yched commentedBarry, the patch in #11 doesn't seem to be generated against latest 6.x-2.x ?
Comment #14
yched commentedAttached keeps barry's approach in #11 and
- updates it to D6 (his patch was for D5),
- implements the JS calls as 'behaviors', so that they can be reattached after a JS-'add new'
(this also works thanks to jpetso's patch in http://drupal.org/node/275192, that got committed recently)
- drops the static $id count in favor of ids derived from the actual FAPI #id of the enclosing element, so that the same form element always gets the same settings no matter how the form gets AHAH-updated.
Seems to work OK for 'calendar' popups, but I couldn't get any 'timeEntry' stuff to display - dunno if it's normal in the current state of date.module.
Also, I'm not sure what Barry referred to when saying "It is not RTBC as is" in #11 above, so this patch might not be as well :-)
Patch is against 6.x-2.x-beta3 (I couldn't get HEAD to work at the time I started this).
Comment #15
yched commentedPrevious patch had some leftover cruft.
Comment #16
yched commentedHm, looks like I posted too soon. The patch actually doesn't completely work with JS-'add new', I must've broken something with a last minute change.
I'll come back to it tomorrow.
Comment #17
yched commentedThis was breaking because of http://drupal.org/node/273539, that now runs an additional form_builder() on js-'add more', so this was messing with js settings getting attached to form id's twice, resulting in invalid js settings array. I am not 100% sure the fix for #273539 is the right one, but the case also happens when using 'Preview' (the form gets built twice in the request)
Attached patch works around this by appending a static index to the #ids generated by date_popup_js_settings_id().
(note : this differs from Barry's #11 because we need those ids to be specific to a given field - if not, when a form has several date fields, you could end up with non-unique ids when playing with js-'add more')
Comment #18
gddPatch no longer applies against -dev, 2 hunks failed. Tried to sort it out but it looks like some stuff has moved around.
Comment #19
karens commentedI got everything working except for a problem with the timepicker which I'm going to open as a separate issue. I can now get the calendar popup working in multiple fields.
Thanks yched :)
Comment #20
Anonymous (not verified) commentedAutomatically closed -- issue fixed for two weeks with no activity.
Comment #21
alan d. commentedJust a side note, while this patch automatically means that 99% of the work is done for you, you must include
drupal_get_jsin your AHAH response for this to work.Eg: