Additional Source Code - Zip file

Listing 1 - Jakarta Struts JSP

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<%@ taglib uri="/WEB-INF/tlds/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/tlds/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/tlds/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/tlds/c.tld" prefix="c" %>
<%@ taglib uri="/WEB-INF/tlds/fmt.tld" prefix="fmt" %>

<HTML>
<HEAD>
   <TITLE>Add-and-Remove Pattern</TITLE>
   <link rel="stylesheet" type="text/css" href=
      '<%= request.getContextPath() + "/stylesheet.css" %>'>
</HEAD>

<BODY BGCOLOR="white" onload="doUpdate( false, false );">
<fmt:setBundle basename="com.kowaldesign.example.example"/>

<html:form action="/exampleWrite.do">

<table border="0" cellpadding="0" cellspacing="5">

   <%-- Add-and-Remove Pattern --%>
   <tr align="middle" valign="center">
      <td>
         <fmt:message key="available"/><br />
         <html:select property="availableValues" 
            multiple="true" size="7" style="width:80px;" 
            styleId="available" 
            onchange="doUpdate( false, true );">
         <html:optionsCollection property="availableList"/>
         </html:select>
      </td>
      <td>
         <br />
         <input type="button" style="width:100px;" id="add" 
            onclick="doMove( 'available','chosen', false );" 
            value="<fmt:message key='add'/>"    /><br />
         <input type="button" style="width:100px;" id="addAll" onclick="doMove( 'available','chosen',  true );" 
            value="<fmt:message key='addAll'/>" /><br />
         <br />
         <input type="button" style="width:100px;" id="remove" 
            onclick="doMove( 'chosen','available', false );"
            value="<fmt:message key='remove'/>" /><br />
         <input type="button" style="width:100px;"
            id="removeAll"
            onclick="doMove( 'chosen','available',  true );"
            value="<fmt:message key='removeAll'/>" />
         <html:hidden styleId="chosenItem" property="chosenItem" />
      </td>
      <td>
         <fmt:message key="chosen"/><br />
         <html:select property="chosenValues" 
            multiple="true" size="7" style="width:80px;" 
            styleId="chosen" 
            onchange="doUpdate( true, false );">
            <html:optionsCollection property="chosenList"/>
         </html:select>
      </td>
   </tr>

   <%-- Submit button --%>
   <tr align="middle" valign="top">
      <td colspan="3">
         <input type="submit" value="<fmt:message key='submit'/>" />
      </td>
   </tr>
</table>

</html:form>

<script language="JavaScript">
<!--

   /**
    * Move selected items between lists.
    * <p>
    * @param  sourceId  ID of source list
    * @param  destId    ID of destination list
    * @param  all       true iff moving all
    */
   function doMove( sourceId, destId, all )
   {
      // Move the items between the lists.
      var sourceElem = document.getElementById( sourceId );
      var destElem = document.getElementById( destId );
      for( var i = 0; ( i < sourceElem.length ); )
      {  if( sourceElem.options[ i ].selected || all )
         {  var newOption = document.createElement( "OPTION" );
            newOption.text = sourceElem.options[ i ].text;
            newOption.value = sourceElem.options[ i ].value;
            destElem.options[ destElem.length ] = newOption;
            sourceElem.remove( i );
         }
         else
            i++;
      }

      // Update the button states.doUpdate( false, false );
      
      // Store the chosen items in a hidden field.
      var chosenItem = document.getElementById( "chosenItem" );
      var chosenList = document.getElementById( "chosen" );
      chosenItem.value = "";
      for( var i = 0; ( i < chosenList.length ); i++ ) 
      {  chosenItem.value += chosenList.options[ i ].value + '|';
      }
   }

   /**
    * Update the button states based on whether
    * lists have contents and selected items.
    * Deselect list items if requested to ensure
    * at most one list contains selections.
    * <p>
    * @param  offAvailable  deselecting available list
    * @param  offChosen     deselecting chosen list
    */
   function doUpdate( offAvailable, offChosen )
   {
      // Get the lists and deselect if requested.
      var availableList = document.getElementById( "available" );
      var chosenList = document.getElementById( "chosen" );
      if( offAvailable )
         availableList.selectedIndex = -1;
      if( offChosen )
         chosenList.selectedIndex = -1;

      // Update the button states.
      document.getElementById( "addAll" ).disabled =( availableList.length == 0 );
      document.getElementById( "removeAll" ).disabled =( chosenList.length == 0 );
      document.getElementById( "add" ).disabled =( availableList.selectedIndex < 0 );
      document.getElementById( "remove" ).disabled =( chosenList.selectedIndex < 0 );
   }

// -->
</script>

</BODY>
</HTML>


Listing 2.  JavaServer Faces JSP

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="/WEB-INF/tlds/c.tld" prefix="c" %>
<%@ taglib uri="/WEB-INF/tlds/fmt.tld" prefix="fmt" %>

<HTML>
<HEAD>
   <TITLE>Add-and-Remove Pattern</TITLE>
   <link rel="stylesheet" type="text/css" href=
      '<%= request.getContextPath() + "/stylesheet.css" %>'>
</HEAD>

<BODY BGCOLOR="white" onload="doUpdate( false, false );">
<f:loadBundle basename="com.kowaldesign.example.example" var="bundle"/>
<fmt:setBundle basename="com.kowaldesign.example.example"/>

<f:view>
   <h:form id="form">
      <h:panelGrid columns="1" rowClasses="center">
   
      <%-- Add-and-Remove Pattern --%>
      <h:panelGrid columns="3" rowClasses="center">
         <h:outputText value="#{bundle.available}" />
         <h:outputText value="" />
         <h:outputText value="#{bundle.chosen}" />
	      <h:selectManyListbox id="available" 
               style="width:100px; height:120px;"
	         value="#{example.availableValues}" 
               onchange="doUpdate( false, true );">
	         <f:selectItems value="#{example.availableList}"/>
	     </h:selectManyListbox>
	     <h:panelGrid columns="1">
		  <f:verbatim>
		     <input type="button" style="width:100px;" 
                    id="add" onclick="doMove( 
                    'form:available','form:chosen',false );" 
		        value="<fmt:message key='add'/>"    />
                 <br />
		     <input type="button" style="width:100px;" 
                    id="addAll" onclick="doMove( 
                    'form:available','form:chosen', true );" 
		        value="<fmt:message key='addAll'/>" />
		     <br /><br />
		     <input type="button" style="width:100px;" 
                    id="remove" onclick="doMove( 
                    'form:chosen','form:available',false );" 
		        value="<fmt:message key='remove'/>" />
                 <br />
		     <input type="button" style="width:100px;" 
                    id="removeAll" onclick="doMove( 
                    'form:chosen','form:available', true );" 
		        value="<fmt:message key='removeAll'/>" />
		  </f:verbatim>
	     <h:inputHidden id="chosenItem" 
              value="#{example.chosenItem}" />
	     </h:panelGrid>
	     <h:selectManyListbox id="chosen" 
              style="width:100px; height:120px;"
	        value="#{example.chosenValues}" 
              onchange="doUpdate( true, false );">
	        <f:selectItems value="#{example.chosenList}"/>
	     </h:selectManyListbox>
      </h:panelGrid>

      <%-- Submit button --%>
      <h:panelGrid columns="1">
         <h:commandButton action="#{example.submit}" value="#{bundle.submit}" />
      </h:panelGrid>
      </h:panelGrid>
   </h:form>
</f:view>

<script language="JavaScript">
<!--

   /**
    * Move selected items between lists.
    * <p>
    * @param  sourceId  ID of source list
    * @param  destId    ID of destination list
    * @param  all       true iff moving all
    */
   function doMove( sourceId, destId, all )
   {
      // Move the items between the lists.
      var sourceElem = document.getElementById( sourceId );
      var destElem = document.getElementById( destId );
      for( var i = 0; ( i < sourceElem.length ); )
      {  if( sourceElem.options[ i ].selected || all )
         {  var newOption = document.createElement( "OPTION" );
            newOption.text = sourceElem.options[ i ].text;
            newOption.value = sourceElem.options[ i ].value;
            destElem.options[ destElem.length ] = newOption;
            sourceElem.remove( i );
         }
         else
            i++;
      }

      // Update the button states.doUpdate();

      // Store the chosen items in a hidden field.
      var chosenItem = document.getElementById( "form:chosenItem" );
      var chosenList = document.getElementById( "form:chosen" );
      chosenItem.value = "";
      for( var i = 0; ( i < chosenList.length ); i++ ) 
      {  chosenItem.value += chosenList.options[ i ].value + '|';
      }
   }

   /**
    * Update the button states based on whether
    * lists have contents and selected items.
    * Deselect list items if requested.
    * <p>
    * @param  offAvailable  deselecting available list
    * @param  offChosen     deselecting chosen list
    */
   function doUpdate( offAvailable, offChosen )
   { 
      // Get the lists and deselect if requested.
      var availableList = document.getElementById( "form:available" );
      var chosenList = document.getElementById( "form:chosen" );
      if( offAvailable )
         availableList.selectedIndex = -1;
      if( offChosen )
         chosenList.selectedIndex = -1;

      // Update the button states.
      document.getElementById( "addAll" ).disabled =( availableList.length == 0 );
      document.getElementById( "removeAll" ).disabled =( chosenList.length == 0 );
      document.getElementById( "add" ).disabled = ( availableList.selectedIndex < 0 );
      document.getElementById( "remove" ).disabled = ( chosenList.selectedIndex < 0 );
   }

// -->
</script>
</BODY>
</HTML>

Additional Source Code - Zip file