I have found and fixed what appears to be a bug in the shuttle component JavaScript code. This bug might affect other components as well. Any component that uses the TrShuttleProxy._moveItems and the TrShuttleProxy._moveAllItems functions would be affected.
The problem is that the title attribute for the HTML option tag is not propagated from the leading to the trailing portion of the shuttle or vice-versa when the user selects move or move all. Therefore, the short description attribute in the shuttle tags are converted to title attributes on the HTML options and show a tooltip on initial page load but are lost as soon as the user moves one or more selections between the leading and trailing portions of the shuttle. This seems to occur because the JavaScript that handles item moving simply has no code to propagate the HTML title attribute between the leading and trailing portions of the shuttle. I have patched and overridden the generated JavaScript code as shown below to fix this problem (patched code demarcated by // gsl fix) and filed this as bug report: https://issues.apache.org/jira/browse/TRINIDAD-723 /* * Overridden method to fix bug in generated code. gsl * Remove this code when fix is incorporated into Trinidad. * Should be incorporated by version 1.2.3. * * _moveItems * * This function moves the selected items in the 'from' list to the * 'to' list. If no formName is supplied, the form is found when * this is called. The items are inserted in the 'to' list * at the bottom. The 'from' and 'to' parameters should be the * list names(i.e. "<shuttleName>:leading" or "<shuttleName>:trailing") */ TrShuttleProxy._moveItems = function( from, to, formName ) { //get the formName if needed if(formName == (void 0)) { formName = TrShuttleProxy._findFormNameContaining(from); } if(formName.length == 0) { alert(shuttle_no_form_available); return; } //store the from and to lists var fromList = document.forms[formName].elements[from]; var toList = document.forms[formName].elements[to]; if ( fromList == (void 0 ) || toList == (void 0 )) return; //get all the indexes of the selected items var selItems = TrShuttleProxy._getSelectedIndexes(formName, from); //if no items are selected, return with alert. if(selItems.length == 0) { if (_shuttle_no_items_selected.length > 0) alert(_shuttle_no_items_selected); return; } var fromDescArray = TrShuttleProxy._getDescArray(from); var toDescArray = TrShuttleProxy._getDescArray(to); //set no selection on toList so it will only have new items selected. toList.selectedIndex = -1; //get the index in the toList to start inserting at. Length-1 because of //bars. var insertAt = toList.length-1; //save bar text so you know how long it should be var barText = toList.options[insertAt].text; //insert the items at the end of the toList for(var i=0; i<selItems.length; i++) { var oText = fromList.options[selItems[i]].text; var oValue = fromList.options[selItems[i]].value; var oTitle = fromList.options[selItems[i]].title // gsl fix if(i == 0) { //replace the bars toList.options[insertAt].text = oText; toList.options[insertAt].value = oValue; } else { //have to make new item toList.options[insertAt] = new Option(oText, oValue, false, false); } toList.options[insertAt].title = oTitle; // gsl fix if ( toDescArray != (void 0) && fromDescArray != (void 0) ) toDescArray[insertAt] = fromDescArray[selItems[i]]; toList.options[insertAt].selected = true; insertAt++; } //insert a new bar at bottom of toList toList.options[insertAt] = new Option(barText, "", false, false); toList.options[insertAt].selected = false; //remove items from fromList. do this backward to maintain indices for( var i=selItems.length-1; i >= 0; i--) { if ( fromDescArray != (void 0) ) TrShuttleProxy._remove( fromDescArray, selItems[i], 1 ); fromList.options[selItems[i]] = null; } //make no selected on fromList fromList.selectedIndex = -1; TrShuttleProxy._clearDescAreas( formName, from); TrShuttleProxy._displayDesc( to, formName ); //make the new lists for submitting. TrShuttleProxy._makeList(formName, from); TrShuttleProxy._makeList(formName, to); } /* * Overridden method to fix bug in generated code. gsl * Remove this code when fix is incorporated into Trinidad. * Should be incorporated by version 1.2.3. * * _moveAllItems * * This function moves all the items in the 'from' list to the * 'to' list. If no formName is supplied, the form is found when * this is called. The items are inserted in the 'to' list * at the bottom. The 'from' and 'to' parameters should be the * list names(i.e. "<shuttleName>:leading" or "<shuttleName>:trailing") */ TrShuttleProxy._moveAllItems = function( from, to, formName ) { //get the formName is needed if(formName == (void 0)) { formName = TrShuttleProxy._findFormNameContaining(from); } //get the lists var fromList = document.forms[formName].elements[from]; var toList = document.forms[formName].elements[to]; //save the bar text for later use. var barText = toList.options[document.forms[formName].elements[to].length-1].text //get the index to start inserting at in the toList. length-1 because of //bars var insertAt = toList.length-1; var fromDescArray = TrShuttleProxy._getDescArray(from); var toDescArray = TrShuttleProxy._getDescArray(to); //move the items if (fromList.length > 1) { //move all but the last (bars). var initialLength = fromList.length for(var i=0; i<initialLength-1; i++) { var oText = fromList.options[0].text; var oValue = fromList.options[0].value; var oTitle = fromList.options[0].title // gsl fix fromList.options[0] = null; if(i == 0) { //replace the bars toList.options[insertAt].text = oText; toList.options[insertAt].value = oValue; } else { //make new option toList.options[insertAt] = new Option (oText,oValue,false,false); } toList.options[insertAt].title = oTitle; // gsl fix if ( toDescArray != (void 0) && fromDescArray != (void 0) ) toDescArray[insertAt] = fromDescArray[i]; insertAt++; } //insert a new bar: toList.options[insertAt] = new Option(barText, "", false, false); toList.options[insertAt].selected = false; if ( fromDescArray != (void 0) ) { var len = fromDescArray.length; TrShuttleProxy._remove(fromDescArray, 0, len); } //set no selection on both lists fromList.selectedIndex = -1; toList.selectedIndex = -1; TrShuttleProxy._clearDescAreas( formName, from, to ); //make the lists for submission TrShuttleProxy._makeList(formName, from); TrShuttleProxy._makeList(formName, to); } else if (_shuttle_no_items.length > 0) { alert(_shuttle_no_items); }
signature.asc
Description: OpenPGP digital signature

