Tapestry has a really good example of what you are talking about in the first question. In fact its one of its standard components. That would be a good starting place. Its not really all that difficult, but is pretty tedious and involves a lot of javascript to accomplish. Here is the bulk of the javascript I use for manually implementing this:
function isBlank( s ) { if (s == null || s == "") { return true; } testString = s.replace( /\s/gi, "" ); if ( testString.length > 0 ) { return false; } else { return true; } } /* * Determines whether the passed value matches the opton.value for any * option currently in the passed select list. */ function isSelectOption( selectElement, value ) { for (var i = 0; i < selectElement.options.length; i++) { if (selectElement.options[i].value == value) { return true; } } } /* * Determines whether the passed select list currently has any selections. * It does take care to ensure that selected options have a non-blank value * prior to considering it selected */ function hasSelection( selectElement ) { if (selectElement.selectedIndex >= 0) { for (var i = 0; i < selectElement.options.length; i++) { if (selectElement.options[i].selected) { if (!isBlank( selectElement.options[i].value )) { return true; } } } } return false; } /* * Selects all elements in the given select list (provided it has a non-blank * option.value. */ function selectAll( selectElement ) { for (var i = 0; i < selectElement.options.length; i++) { if (!isBlank( selectElement.options[i].value )) { selectElement.options[i].selected = true; } } } /* * Moves all options in the passed fromSelectElement, which are marked as * selected, to the passed toSelectElement. */ function move( fromSelectElement, toSelectElement ) { if (!hasSelection( fromSelectElement )) { alert('No option was selected for move.'); return; } for (var j=0; j < toSelectElement.options.length; j++) { toSelectElement.options[j].selected = false; } for (var i = fromSelectElement.options.length - 1; i >= 0 ; i--) { if (fromSelectElement.options[i].selected) { if (!isBlank( fromSelectElement.options[i].value )) { if (!isSelectOption( toSelectElement, fromSelectElement.options[i].value )) { var new_option = new Option(); new_option.value = fromSelectElement.options[i].value; new_option.text = fromSelectElement.options[i].text; var index = toSelectElement.options.length toSelectElement.options[toSelectElement.options.length] = new_option; toSelectElement.options[index].selected = true; fromSelectElement.options[i] = null; } } } } } /* * Moves all options in the passed fromSelectElement, regardless of whether * they are marked as selected, to the passed toSelectElement (options with * a blank value will still not be moved). */ function moveAll( fromSelectElement, toSelectElement ) { selectAll( fromSelectElement ); move( fromSelectElement, toSelectElement ); } /* * Moves the option which is marked as selected in the passed select list * up one position within the list. Which one gets moved for multi-selects * will be browser dependent. This is useful for manually sorted/ordered lists. */ function moveOptionUp( selectElement ) { // First locate the selected option... var indx = selectElement.selectedIndex; if (indx <= -1) { alert( "No option selected to move up" ); return false; } if (indx == 0) { alert( "Cannot move the first item in list up any further" ); return false; } var optText = selectElement.options[indx].text; var optValue = selectElement.options[indx].value; selectElement.options[indx].text = selectElement.options[indx-1].text; selectElement.options[indx].value = selectElement.options[indx-1].value; selectElement.options[indx-1].text = optText; selectElement.options[indx-1].value = optValue; selectElement.options[indx-1].selected = true; selectElement.options[indx].selected = false; } /* * Moves the option which is marked as selected in the passed select list * down one position within the list. Which one gets moved for multi-selects * will be browser dependent. This is useful for manually sorted/ordered lists. */ function moveOptionDown( selectElement ) { // First locate the selected option... var indx = selectElement.selectedIndex; if (indx <= -1) { alert( "No option selected to move up" ); return false; } if (indx >= selectElement.options.length) { alert( "Cannot move the last item in list down any further" ); return false; } var optText = selectElement.options[indx].text; var optValue = selectElement.options[indx].value; selectElement.options[indx].text = selectElement.options[indx+1].text; selectElement.options[indx].value = selectElement.options[indx+1].value; selectElement.options[indx+1].text = optText; selectElement.options[indx+1].value = optValue; selectElement.options[indx+1].selected = true; selectElement.options[indx].selected = false; } The trick is to remember to select all elements in the "target" list prior to submitting form. For the second, you could also use the same basic premise as above. Have a text field and a multi-select field on the form. Disable the select and allow users to enter values into the text box, with a button to add the contents of the text field to the select list.... HTH -----Original Message----- From: Wendy Smoak [mailto:[EMAIL PROTECTED] Sent: Thursday, December 18, 2003 4:52 PM To: Struts Users Mailing List Subject: OT: Examples of HTML-based user interfaces? Does anyone have examples of some fancy things to do with HTML-based user interfaces? For example, I've currently got a request to show two "boxes" of items with add/remove arrows. So selecting in the left-hand box and clicking the arrow will move the item to the right hand box. I'm sure it's possible with CSS, JavaScript and hidden form fields. (I'm pretty sure they got the idea from adding recipients to an email in Outlook.) I also have a long-standing requirement to dynamically "grow" a field, when the user types something in a text box and clicks a button, that item "moves up" and a new, blank field appears. I'm currently doing this with an "add" button, which submits the form to the Struts app, the entry gets added to a session scope bean, then back to the form with read-only displays of the stuff in the bean and [the same] blank field. (Although it looks like a "new line", it isn't, it's the same form field.) Googling turns up a bunch of essays on what makes a good user interface, but not too much on tips and tricks. -- Wendy Smoak Application Systems Analyst, Sr. ASU IA Information Resources Management --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]