Re: Help with extending HTML_QuickForm_select

From: Date: Tue, 08 Feb 2005 22:24:30 +0000
Subject: Re: Help with extending HTML_QuickForm_select
References: 1 2 3 4  Groups: php.pear.dev 
Request: Send a blank email to pear-dev+get-36075@lists.php.net to get a copy of this message
Ian Eure wrote:
On Monday 07 February 2005 02:03 pm, Jamie Alessio wrote:
I took Justin's idea and updated my code to use a hidden multi-select that gets updated via javascript on the onClick event of the button that actually moves the elements on the page for the user. It took me some time and off-list explanation to figure out that by "hidden multi-select" Justin meant an actual <select> element that has is hidden
from the user via a "hidden" style attribute and is not a <input
type="hidden"> form element. Once I got that straightened out the rest made sense and I was able to accomplish the same goal without relying on the onSubmit form attribute which is a much better solution.
I would suggest that you implement some mechanism for a graceful degradation for non-javascript browsers. For example, if you have an init function which sets up the scripted controls and hides the 'real' multiselect. In this way, non-javascript browsers only see a multi select which they can still use, while js-enabled browsers get the more sophisticated control.
What type of 'init function' are you suggesting? A PHP init function? A javascript init function? The only thing coming to mind is something like using the javascript onLoad event to call an init function but I don't think using that is realistic from a class within HTML_QuickForm since I'd need access to the <body> tag of the page that contains the form. I'd love to be wrong on this so please clarify what you are suggesting.
Certainly. I'm referring to a JavaScript initialization function which would: 1. Hide the real multiple select control. 2. Create the scripted control(s), buttons for interacting with them, etc. So your markup would be just the same as if you had a regular multiple select, and everything else would be handled by the script's initialization function. In this way, non-scripted browsers just see a regular multi-select, but script-enabled browsers hide that and create the enhanced controls to work with. Make sense?
I'm with you except for the part of how and when you propose actually calling the javascript initialization function. I'm not grasping how to fit this in with HTML_QuickForm. Any chance you could provide an example of how this might be implemented?
Take a look at this: http://www.websprockets.com/post/html_quickform-add-on-packages It's a script element I wrote for QF, which will help you out a lot in this case. So, what you want to do is trigger a JS function after your form is output. If you use the Script stuff I reference above, this happens automagically. So, you have a script like so: // Initialize a single advanced select control. // Takes the string ID of the regular multi-select as it's argument. function initAdvSelect(selectId) { // Hide the real multi-select. var select = document.getElementById(selectId); select.display = 'hidden'; // Create the advselect controls createAdvSelect(select); } function createAdvSelect(select) { // Clone the existing select. var newSelectLeft = select.clone(); var newSelectRight = document.createElement('select'); // Loop through newSelectLeft, move selected elements to newSelectRight // Create add/remove buttons & set up event handlers for them // Add elements to form } Stick all this in a <script/> element, then add another with: initAdvSelect('regularSelectId'); or whatever the id attr on the regular select element is. So script-enabled browsers hide the real select and have the controls the user will interact with generated by the script, so there's no clutter in the markup for browsers without scripting facilities. Non-JS browsers ignore the script elements, and only see a regular multi-select. Does that make sense? Yes, that makes perfect sense now. I was missing the fact that you can place a <script> tag in the middle of an HTML document and actually have it execute functions. I was stuck in the mindset that you could only embed functions in the <script> tag that could then only be called by a javascript event like onLoad, onClick, etc. That's why what you were suggesting wasn't clicking with me.
As far as I know, the hierselect stuff is not readily implementable without breaking things out to a multi-page form. This is obviously not practical, whereas your proposed control is imlpemented as an enhanced UI on top of an existing control.
The HTML_QuickForm_hierselect class can be created on a single page form, but requires javascript in order to work. See http://pear.php.net/manual/en/package.html.html-quickform.html-quickform-hi erselect.php for an example. This isn't necessarily relevant to this discussion - I was just pointing out that there are other form elements that are part of HTML_QuickForm that require javascript and don't do anything helpful in the event that javascript is not available in the browser. That leads me to think that maybe someone already went through this and decided it's not practical to handle that sort of thing from a subclass of HTML_QuickForm, but that's a total guess by me at that point.
Right, and I was just pointing out that those controls don't have any easy equivalent without scripting. To illustrate my point, this is how you'd have to implement both controls without any script support whatsoever: Your scripted multi-select: 1. Use a regular, non-scripted multi-select. A hierselect: 1. Load a page with the initial dataset for the first select. 2. Select option, submit. 3. Load intermediate page with data generated or affected by the previous selection. 4. Select new option, submit. 5. Repeat 3-4 for however many controls you have cascading 6. Submit to final form. This is my point - there's no practical way to have a hierselect gracefully degrade to something that can work with a non-JS browser, which explains why there's nothing to do that. This is not the case with your multiselect code, which is simply a script-enhanced normal multiselect control, which is why you should think about making it degrade gracefully. Well said. I missed the point you were trying to make the first time. Again, this is beside the point but you *could* degrade a hierselect from something like (from the hierselect example):
// first select $select1[0] = 'Pop'; $select1[1] = 'Classical'; $select1[2] = 'Funeral doom'; // second select $select2[0][0] = 'Red Hot Chili Peppers'; $select2[0][1] = 'The Pixies'; $select2[1][0] = 'Wagner'; $select2[1][1] = 'Strauss'; $select2[2][0] = 'Pantheist'; $select2[2][1] = 'Skepticism'; to something like: $select[] = 'Pop: Red Hot Chili Peppers'; $select[] = 'Pop: The Pixies'; $select[] = 'Classical: Wagner'; $select[] = 'Classical: Strauss'; $select[] = 'Funeral Doom: Pantheist'; $select[] = 'Funeral Doom: Skepticism'; where the user is presented with all the possible options at once that the hierselect would normally present in several <select> elements. Of course this could make for some gigantic lists, especially when you get past two levels of depth for a hierselect. But, I think it is possible to degrade the hierselect element to something usable for a non-javascript browser. Ian - I'll take a look at your HTML_QuickForm_script class and then tackle getting my stuff working for non-javascript browsers after I steal some of your ideas.. ;) - Jamie

« previous php.pear.dev (#36075) next »