--- loncom/interface/lonhelper.pm 2006/03/07 21:36:49 1.134 +++ loncom/interface/lonhelper.pm 2006/05/09 18:15:39 1.143 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # .helper XML handler to implement the LON-CAPA helper # -# $Id: lonhelper.pm,v 1.134 2006/03/07 21:36:49 albertel Exp $ +# $Id: lonhelper.pm,v 1.143 2006/05/09 18:15:39 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -184,6 +184,7 @@ use Apache::lonxml; use Apache::lonlocal; use Apache::lonnet; + # Register all the tags with the helper, so the helper can # push and pop them @@ -573,26 +574,20 @@ sub display { } # Phase 4: Display. - my $html=&Apache::lonxml::xmlbegin(); my $stateTitle=&mt($state->title()); - my $helperTitle = &mt($self->{TITLE}); - my $browser_searcher_js = &Apache::loncommon::browser_and_searcher_javascript(); - my $bodytag = &Apache::loncommon::bodytag($helperTitle,'',''); + my $browser_searcher_js = + '<script type="text/javascript">'."\n". + &Apache::loncommon::browser_and_searcher_javascript(). + "\n".'</script>'; + + $result .= &Apache::loncommon::start_page($self->{TITLE}, + $browser_searcher_js); + my $previous = HTML::Entities::encode(&mt("<- Previous"), '<>&"'); my $next = HTML::Entities::encode(&mt("Next ->"), '<>&"'); # FIXME: This should be parameterized, not concatenated - Jeremy - my $loncapaHelper = &mt("LON-CAPA Helper:"); - $result .= <<HEADER; -$html - <head> - <title>$loncapaHelper: $helperTitle</title> - <script type="text/javascript"> -$browser_searcher_js - </script> - </head> - $bodytag -HEADER + if (!$state->overrideForm()) { $result.="<form name='helpform' method='POST'>"; } $result .= <<HEADER; <table border="0" width='100%'><tr><td> @@ -655,10 +650,9 @@ HEADER </tr> </table> </form> - </body> -</html> FOOTER + $result .= &Apache::loncommon::end_page(); # Handle writing out the vars to the file my $file = Apache::File->new('>'.$self->{FILENAME}); print $file $self->_varsInFile(); @@ -1076,6 +1070,16 @@ will be the state transistioned to if th the choice is not multichoice. This will override the nextstate passed to the parent C<choices> tag. +<choice> may optionally contain a 'relatedvalue' attribute, which +if present will cause a text entry to appear to the right of the +selection. The value of the relatedvalue attribute is a variable +into which the text entry will be stored e.g.: +<choice computer='numberprovided" relatedvalue="num">Type the number in:</choice> + +<choice> may contain a relatededefault atribute which, if the +relatedvalue attribute is present will be the initial value of the input +box. + =back To create the choices programmatically, either wrap the choices in @@ -1166,10 +1170,12 @@ sub start_choice { my $computer = $token->[2]{'computer'}; my $human = &mt(&Apache::lonxml::get_all_text('/choice', $parser)); - my $nextstate = $token->[2]{'nextstate'}; - my $evalFlag = $token->[2]{'eval'}; + my $nextstate = $token->[2]{'nextstate'}; + my $evalFlag = $token->[2]{'eval'}; + my $relatedVar = $token->[2]{'relatedvalue'}; + my $relatedDefault = $token->[2]{'relateddefault'}; push @{$paramHash->{CHOICES}}, [&mtn($human), $computer, $nextstate, - $evalFlag]; + $evalFlag, $relatedVar, $relatedDefault]; return ''; } @@ -1279,14 +1285,20 @@ BUTTONS } $result .= qq{id="id$id"}; my $choiceLabel = $choice->[0]; - if ($choice->[4]) { # if we need to evaluate this choice + if ($choice->[3]) { # if we need to evaluate this choice $choiceLabel = "sub { my $helper = shift; my $state = shift;" . $choiceLabel . "}"; $choiceLabel = eval($choiceLabel); $choiceLabel = &$choiceLabel($helper, $self); } $result .= "/></td><td> ".qq{<label for="id$id">}. - $choiceLabel. "</label></td></tr>\n"; + $choiceLabel. "</label></td>"; + if ($choice->[4]) { + $result .='<td><input type="text" size="5" name="' + .$choice->[4].'.forminput" value="' + .$choice->[5].'" /></td>'; + } + $result .= "</tr>\n"; } $result .= "</table>\n\n\n"; $result .= $buttons; @@ -1320,6 +1332,10 @@ sub postprocess { $helper->changeState($choice->[2]); } } + if ($choice->[4]) { + my $varname = $choice->[4]; + $helper->{'VARS'}->{$varname} = $env{'form.'."$varname.forminput"}; + } } return 1; } @@ -1561,23 +1577,39 @@ sub render { my $date; my $time=time; - $date = localtime($time); - $date->min(0); my ($anytime,$onclick); - if (defined($self->{DEFAULT_VALUE})) { + + # first check VARS for a valid new value from the user + # then check DEFAULT_VALUE for a valid default time value + # otherwise pick now as reasonably good time + + if (defined($helper->{VARS}{$var}) + && $helper->{VARS}{$var} > 0) { + $date = localtime($helper->{VARS}{$var}); + } elsif (defined($self->{DEFAULT_VALUE})) { my $valueFunc = eval($self->{DEFAULT_VALUE}); die('Error in default value code for variable ' . $self->{'variable'} . ', Perl said: ' . $@) if $@; $time = &$valueFunc($helper, $self); if (lc($time) eq 'anytime') { $anytime=1; - } else { + $date = localtime(time); + $date->min(0); + } elsif (defined($time) && $time ne 0) { $date = localtime($time); + } else { + # leave date undefined so it'll default to now } - } else { + } + if (!defined($date)) { + $date = localtime(time); + $date->min(0); } + + &Apache::lonnet::logthis("date mode "); + if ($anytime) { $onclick = "onclick=\"javascript:updateCheck(this.form,'${var}anytime',false)\""; } @@ -1685,7 +1717,7 @@ CHECK if ($anytime) { $result.=' checked="checked" ' } - $result.="name='${var}anytime'/>".&mt('Anytime').'</label>' + $result.="name='${var}anytime'/>".&mt('Any time').'</label>' } return $result; @@ -1732,6 +1764,16 @@ sub postprocess { $helper->{VARS}->{$var} = $chosenDate; } + if (defined($self->{VALIDATOR})) { + my $validator = eval($self->{VALIDATOR}); + die 'Died during evaluation of validator code; Perl said: ' . $@ if $@; + my $invalid = &$validator($helper, $state, $self, $self->getValue()); + if ($invalid) { + $self->{ERROR_MSG} = $invalid; + return 0; + } + } + if (defined($self->{NEXTSTATE})) { $helper->changeState($self->{NEXTSTATE}); } @@ -2233,6 +2275,120 @@ use strict; use Apache::lonlocal; use Apache::lonnet; +# +# Utility function used when rendering the <student> tag. +# This function renders a segment of course personel +# Personel are broken up by the helper into past, current and +# future...each one gets is own subpage of selection. +# This sub renders one of these pages. +# Parameters: +# $sections - Set of sections in the course (hash reference). +# $students - Students in the section. (ref to array of references +# to arrays). +# $formprefix - form path prefix for form element names +# This is used to make each form element +# so that the segments having to do with each +# set of students won't collide. +# $defaultusers - reference to a hash containng +# the set of users that should be on or off. +# Returns: +# HTML text to add to the rendering of the helper. +# +sub render_student_list { + my ($self, + $sections, $students, $formprefix, $defaultusers) = @_; + + my $multiselect = $self->{'multichoice'}; + my $result = ""; + + # If multiple selections are allowed, we have a listbox + # at the top which allows quick selections from each section + # as well as from categories of personnel. + + if ($multiselect) { + $result .= '<table><tr><td>'; + + my $size = scalar(keys(%$sections)); + $size += 3; # We have allstudents allpersonel nosection too. + if ($size > 5) { + $size = 5; + } + $result .= '<select multiple name="'.$formprefix + .'.chosensections" size="'.$size.'">'."\n"; + $result .= '<option name="allstudents">All Students</option>'; + $result .= '<option name="allpersonnel">All Course Personnel</option>'; + $result .= '<option name="nosection">No Section</option>'; + $result .= "\n"; + foreach my $sec (sort {lc($a) cmp lc($b)} (keys(%$sections))) { + $result .= '<option name="'.$sec.'">'.$sec.'</option>'."\n"; + } + $result .= '</td><td valign="top">'; + $result .= '<input type="button" name="'.$formprefix.'.select" value="Select" onclick=' + ."'selectSections(\"$formprefix.chosensections\", \"$formprefix\")'".' /></td>'; + $result .= '<td valign="top"><input type="button" name="'.$formprefix + .'.unselect" value="Unselect" onclick='. + "'unselectSections(\"$formprefix.chosensections\", \"$formprefix\")' ".' /></td></tr></table>'; + } + + # Now we list the students, but the form element type + # will depend on whether or not multiselect is true. + # True -> checkboxes. + # False -> radiobuttons. + + $result .= "<table border=\"2\">\n"; + $result .= '<tr><th></th><th align="center">Name</th>'."\n"; + $result .= ' <th align="center">Section</th>'."\n"; + $result .= ' <th align="center">Status</th>'."\n"; + $result .= ' <th align="center">Role</th>'."\n"; + $result .= ' <th align="center">Username : Domain</th></tr>'."\n"; + + my $input_type; + if ($multiselect) { + $input_type = "checkbox"; + } else { + $input_type = "radio"; + } + + my $checked = 0; + for my $student (@$students) { + $result .= '<tr><td><input type="'.$input_type.'" name="'. + $self->{'variable'}.".forminput".'"'; + my $user = $student->[0]; + + # Figure out which students are checked by default... + + if(%$defaultusers) { + if (exists ($defaultusers->{$user})) { + $result .= ' checked ="checked" '; + $checked = 1; + } + } elsif (!$self->{'multichoice'} && !$checked) { + $result .= ' checked="checked" '; + $checked = 1; # First one for radio if no default specified. + } + $result .= ' value="'. HTML::Entities::encode($user . ':' + .$student->[2] . ':' + .$student->[1] . ':' + .$student->[3] . ':' + .$student->[4] . ":" + .$formprefix, "<>&\"'") + ."\" /></td><td>\n"; + $result .= HTML::Entities::encode($student->[1], '<>&"') + . '</td><td align="center" >'."\n"; + $result .= HTML::Entities::encode($student->[2], '<>&"') + . '</td><td align="center">'."\n"; + $result .= HTML::Entities::encode($student->[3], '<>&"') + . '</td><td align="center">'."\n"; + $result .= HTML::Entities::encode($student->[4], '<>&"') + . '</td><td align="center">'."\n"; + $result .= HTML::Entities::encode($student->[0], '<>&"') + . '</td></tr>'."\n"; + } + $result .=" </table> <br /> <hr />\n"; + + return $result; +} + BEGIN { &Apache::lonhelper::register('Apache::lonhelper::student', ('student')); @@ -2281,82 +2437,105 @@ sub render { $result = <<SCRIPT; <script type="text/javascript"> // <!-- - function checkall(value, checkName) { - for (i=0; i<document.forms.helpform.elements.length; i++) { - ele = document.forms.helpform.elements[i]; - if (ele.name == checkName + '.forminput') { - document.forms.helpform.elements[i].checked=value; - } - } + + function findElement(name) { + var i; + var ele; + for(i =0; i < document.forms.helpform.elements.length; i++) { + ele = document.forms.helpform.elements[i]; + if(ele.name == name) { + return ele; + } + } + return null; } - function checksec(value) { - for (i=0; i<document.forms.helpform.elements.length; i++) { - comp = document.forms.helpform.elements.chksec.value; - if (document.forms.helpform.elements[i].value.indexOf(':'+comp+':') != -1) { - if (document.forms.helpform.elements[i].value.indexOf(':Active') != -1) { - document.forms.helpform.elements[i].checked=value; - } - } - } + function isStudent(element) { + if(element.value.indexOf(":Student") != -1) { + return 1; + } + return 0; } - function checkactive() { - for (i=0; i<document.forms.helpform.elements.length; i++) { - if (document.forms.helpform.elements[i].value.indexOf(':Active') != -1) { - document.forms.helpform.elements[i].checked=true; - } - } + function section(element) { + var i; + var info; + if (element.value.indexOf(':') != -1) { + info = element.value.split(':'); + return info[2]; + } else { + return ""; + } } - function checkexpired() { - for (i=0; i<document.forms.helpform.elements.length; i++) { - if (document.forms.helpform.elements[i].value.indexOf(':Expired') != -1) { - document.forms.helpform.elements[i].checked=true; - } - } + function rightSubForm(element, which) { + if (element.value.indexOf(which) != -1) { + return true; + } else { + return false; + } } - function uncheckexpired() { - for (i=0; i<document.forms.helpform.elements.length; i++) { - if (document.forms.helpform.elements[i].value.indexOf(':Expired') != -1) { - document.forms.helpform.elements[i].checked=false; - } - } + + function setAllStudents(value, which) { + var i; + var ele; + for (i =0; i < document.forms.helpform.elements.length; i++) { + ele = document.forms.helpform.elements[i]; + if(isStudent(ele) && rightSubForm(ele, which)) { + ele.checked=value; + } + } } - function getDesiredState() { // Return desired person state radio value. - numRadio = document.forms.helpform.personstate.length; - for (i =0; i < numRadio; i++) { - if (document.forms.helpform.personstate[i].checked) { - return document.forms.helpform.personstate[i].value; - } - } - return ""; + function setAllCoursePersonnel(value, which) { + var i; + var ele; + for (i =0; i < document.forms.helpform.elements.length; i++) { + ele = document.forms.helpform.elements[i]; + if(!isStudent(ele) && rightSubForm(ele, which)) { + ele.checked = value; + } + } } - - function checksections(value) { // Check selected sections. - numSections = document.forms.helpform.chosensections.length; - desiredState = getDesiredState(); - - for (var option = 0; option < numSections; option++) { - if(document.forms.helpform.chosensections.options[option].selected) { - section = document.forms.helpform.chosensections.options[option].text; - if (section == "none") { - section =""; + function setSection(which, value, subform) { + var i; + var ele; + for (i =0; i < document.forms.helpform.elements.length; i++) { + ele = document.forms.helpform.elements[i]; + if (ele.value.indexOf(':') != -1) { + if ((section(ele) == which) && rightSubForm(ele, subform)) { + ele.checked = value; } - for (i = 0; i < document.forms.helpform.elements.length; i++ ) { - if (document.forms.helpform.elements[i].value.indexOf(':') != -1) { - info = document.forms.helpform.elements[i].value.split(':'); - hisSection = info[2]; - hisState = info[4]; - if (desiredState == hisState || - desiredState == "All") { - if(hisSection == section || - section =="" ) { - document.forms.helpform.elements[i].checked = value; - } - } + } + } + } + + function setCheckboxes(listbox, which, value) { + var k; + var elem; + var what; + elem = findElement(listbox); + if (elem != null) { + for (k = 0; k < elem.length; k++) { + if (elem.options[k].selected) { + what = elem.options[k].text; + if (what == 'All Students') { + setAllStudents(value, which); + } else if (what == 'All Course Personnel') { + setAllCoursePersonnel(value, which); + } else if (what == 'No Section') { + setSection('',value, which); + } else { + setSection(what, value, which); } } - } + } } - } + } + function selectSections(listbox, which) { + setCheckboxes(listbox, which, true); + + } + function unselectSections(listbox, which) { + setCheckboxes(listbox, which, false); + } + // --> </script> SCRIPT @@ -2381,9 +2560,9 @@ SCRIPT </table> <br /> BUTTONS - $result .= $buttons; +# $result .= $buttons; - } +} if (defined $self->{ERROR_MSG}) { $result .= '<font color="#FF0000">' . $self->{ERROR_MSG} . '</font><br /><br />'; @@ -2401,8 +2580,28 @@ BUTTONS %defaultUsers = map { if ($_) {($_,1) } } @defaultUsers; delete($defaultUsers{''}); } - my $choices = []; - my $expired_students = []; # Will hold expired students. + + + + # my $choices = []; + + # + # We need to parcel out the personel in to three arrays: + # $current_members[] - Contains those whose roles are currently active. + # $expired_members[] - Contains those whose roles have expired. + # $future_members[] - Contains those whose roles will become active in the + # future. + # + # Constants + my $section = &Apache::loncoursedata::CL_SECTION(); + my $fullname = &Apache::loncoursedata::CL_FULLNAME(); + my $status = &Apache::loncoursedata::CL_STATUS(); + my $start_date = &Apache::loncoursedata::CL_START(); + + my $current_members = []; + my $expired_members = []; + my $future_members = []; + # Load up the non-students, if necessary if ($self->{'coursepersonnel'}) { @@ -2419,16 +2618,12 @@ BUTTONS @people = sort { $a->[0] cmp $b->[0] } @people; for my $person (@people) { - push @$choices, [join(':', @$person), $person->[0], '', $_]; + push @$current_members, [join(':', @$person), $person->[0], '', $_]; } } } } - # Constants - my $section = Apache::loncoursedata::CL_SECTION(); - my $fullname = Apache::loncoursedata::CL_FULLNAME(); - my $status = Apache::loncoursedata::CL_STATUS(); # Load up the students my $classlist = &Apache::loncoursedata::get_classlist(); @@ -2440,164 +2635,90 @@ BUTTONS } return $classlist->{$a}->[$fullname] cmp $classlist->{$b}->[$fullname]; } @keys; - # - # now add the fancy section choice... first enumerate the sections: - if ($self->{'multichoice'}) { - my %sections; - for my $key (@keys) { - my $section_name = $classlist->{$key}->[$section]; - if ($section_name ne "") { - $sections{$section_name} = 1; - } - } - # The variable $choice_widget will have the html to make the choice - # selector. - my $size=5; - if (scalar(keys(%sections)) < 5) { - $size=scalar(keys(%sections)); - } - my $choice_widget = '<select multiple name="chosensections" size="'.$size.'">'."\n"; - foreach my $sec (sort {lc($a) cmp lc($b)} (keys(%sections))) { - $choice_widget .= "<option name=\"$sec\">$sec</option>\n"; - } - $choice_widget .= "<option>none</option></select>\n"; + - # Build a table without any borders to contain the section based - # selection: - my $section_selectors =<<SECTIONSELECT; -<table border="0"> - <tr valign="top"> - <td>For Sections:</td><td>$choice_widget</td> - <td><label><input type="radio" name="personstate" value="Active" checked /> - Current Students</label></td> - <td><label><input type="radio" name="personstate" value="All" /> - All students</label></td> - <td><label><input type="radio" name="personstate" value="Expired" /> - Expired Students</label></td> - </tr> - <tr> - <td><input type="button" value="Select" onclick="checksections(true);" /></td> - <td><input type="button" value="Unselect" onclick="checksections(false);" /></td></tr> -</table> -<br /> -SECTIONSELECT - $result .= $section_selectors; - } - # username, fullname, section, type for (@keys) { - # We split the active students into the choices array and - # inactive ones into expired_students so that we can put them in 2 separate - # tables. - if ( $classlist->{$_}->[$status] eq 'Active') { - push @$choices, [$_, $classlist->{$_}->[$fullname], + push @$current_members, [$_, $classlist->{$_}->[$fullname], $classlist->{$_}->[$section], $classlist->{$_}->[$status], 'Student']; } else { - push @$expired_students, [$_, $classlist->{$_}->[$fullname], - $classlist->{$_}->[$section], - $classlist->{$_}->[$status], 'Student']; + # Need to figure out if this user is future or + # Expired... If the start date is in the future + # the user is future...else expired. + + my $now = time; + if ($classlist->{$_}->[$start_date] > $now) { + push @$future_members, [$_, $classlist->{$_}->[$fullname], + $classlist->{$_}->[$section], + "Future", "Student"]; + } else { + push @$expired_members, [$_, $classlist->{$_}->[$fullname], + $classlist->{$_}->[$section], + "Expired", "Student"]; + } + } } - my $name = $self->{'coursepersonnel'} ? &mt('Name') : &mt('Student Name'); - my $type = 'radio'; - if ($self->{'multichoice'}) { $type = 'checkbox'; } - $result .= "<table cellspacing='2' cellpadding='2' border='0'>\n"; - $result .= "<tr><td></td><td align='center'><b>$name</b></td>". - "<td align='center'><b>" . &mt('Section') . "</b></td>" . - "<td align='center'><b>".&mt('Status')."</b></td>" . - "<td align='center'><b>" . &mt("Role") . "</b></td>" . - "<td align='center'><b>".&mt('Username').":".&mt('Domain')."</b></td></tr>"; - my $checked = 0; - # - # Give the active students and staff: + # Create a list of the sections that can be used to create the section + # selection list boxes: # - for my $choice (@$choices) { - $result .= "<tr><td><input type='$type' name='" . - $self->{'variable'} . '.forminput' . "'"; - - if (%defaultUsers) { - my $user=$choice->[0]; - if (exists($defaultUsers{$user})) { - $result .= " checked='checked' "; - $checked = 1; - } - } elsif (!$self->{'multichoice'} && !$checked) { - $result .= " checked='checked' "; - $checked = 1; - } - $result .= - " value='" . HTML::Entities::encode($choice->[0] . ':' - .$choice->[2] . ':' - .$choice->[1] . ':' - .$choice->[3], "<>&\"'") - . "' /></td><td>" - . HTML::Entities::encode($choice->[1],'<>&"') - . "</td><td align='center'>" - . HTML::Entities::encode($choice->[2],'<>&"') - . "</td>\n<td>" - . HTML::Entities::encode($choice->[3],'<>&"') - . "</td>\n<td>" - . HTML::Entities::encode($choice->[4],'<>&"') - . "</td>\n<td>" - . HTML::Entities::encode($choice->[0],'<>&"') - . "</td></tr>\n"; + my %sections; + for my $key (@keys) { + my $section_name = $classlist->{$key}->[$section]; + if ($section_name ne "") { + $sections{$section_name} = 1; + } + } + + + if ($self->{'multichoice'}) { + + # The variable $choice_widget will have the html to make the choice + # selector. + my $size=5; + if (scalar(keys(%sections)) < 5) { + $size=scalar(keys(%sections)); + } + my $result = '<select multiple name="chosensections" size="'.$size.'">'."\n"; + foreach my $sec (sort {lc($a) cmp lc($b)} (keys(%sections))) { + $result .= "<option name=\"$sec\">$sec</option>\n"; + } + $result .= "<option>none</option></select>\n"; + + } - $result .= "</table>\n\n"; + + # Current personel + + $result .= $self->render_student_list(\%sections, + $current_members, + "current", + \%defaultUsers); + # If activeonly is not set then we can also give the expired students: # - if (!$self->{'activeonly'} && ((scalar @$expired_students) > 0)) { - $result .= "<p>Inactive students: </p>\n"; - $result .= <<INACTIVEBUTTONS; - <table> - <tr> - <td><input type="button" value="Select expired" onclick="checkexpired();" /> </td> - <td><input type="button" value="Unselect expired" onclick="uncheckexpired();" /></td> - </tr> - </table> -INACTIVEBUTTONS - $result .= "<table>\n"; - - for my $choice (@$expired_students) { - $result .= "<tr><td><input type='$type' name='" . - $self->{'variable'} . '.forminput' . "'"; - - if (%defaultUsers) { - my $user=$choice->[0]; - if (exists($defaultUsers{$user})) { - $result .= " checked='checked' "; - $checked = 1; - } - } elsif (!$self->{'multichoice'} && !$checked) { - $result .= " checked='checked' "; - $checked = 1; - } - $result .= - " value='" . HTML::Entities::encode($choice->[0] . ':' - .$choice->[2] . ':' - .$choice->[1] . ':' - .$choice->[3], "<>&\"'") - . "' /></td><td>" - . HTML::Entities::encode($choice->[1],'<>&"') - . "</td><td align='center'>" - . HTML::Entities::encode($choice->[2],'<>&"') - . "</td>\n<td>" - . HTML::Entities::encode($choice->[3],'<>&"') - . "</td>\n<td>" - . HTML::Entities::encode($choice->[4],'<>&"') - . "</td>\n<td>" - . HTML::Entities::encode($choice->[0],'<>&"') - . "</td></tr>\n"; - } - $result .= "</table>\n"; - + if (!$self->{'activeonly'} && ((scalar @$expired_members) > 0)) { + + # And future. + + $result .= $self->render_student_list(\%sections, + $future_members, + "future", + \%defaultUsers); + # Past + + $result .= $self->render_student_list(\%sections, + $expired_members, + "past", + \%defaultUsers); } @@ -3041,26 +3162,29 @@ sub start_section { my $section = Apache::loncoursedata::CL_SECTION(); my $classlist = Apache::loncoursedata::get_classlist(); - foreach (keys %$classlist) { - my $sectionName = $classlist->{$_}->[$section]; - if (!$sectionName) { + foreach my $user (keys(%$classlist)) { + my $section_name = $classlist->{$user}[$section]; + if (!$section_name) { $choices{"No section assigned"} = ""; } else { - $choices{$sectionName} = $sectionName; + $choices{$section_name} = $section_name; } } - for my $sectionName (sort(keys(%choices))) { - push @{$paramHash->{CHOICES}}, [$sectionName, $sectionName]; + if (exists($choices{"No section assigned"})) { + push(@{$paramHash->{CHOICES}}, + ['No section assigned','No section assigned']); + delete($choices{"No section assigned"}); + } + for my $section_name (sort {lc($a) cmp lc($b) } (keys(%choices))) { + push @{$paramHash->{CHOICES}}, [$section_name, $section_name]; } return if ($token->[2]{'onlysections'}); # add in groups to the end of the list - my %curr_groups; - if (&Apache::loncommon::coursegroups(\%curr_groups)) { - foreach my $group_name (sort(keys(%curr_groups))) { - push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]); - } + my %curr_groups = &Apache::loncommon::coursegroups(); + foreach my $group_name (sort(keys(%curr_groups))) { + push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]); } } @@ -3122,11 +3246,9 @@ sub start_group { # Populate the CHOICES element my %choices; - my %curr_groups; - if (&Apache::loncommon::coursegroups(\%curr_groups)) { - foreach my $group_name (sort(keys(%curr_groups))) { - push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]); - } + my %curr_groups = &Apache::loncommon::coursegroups(); + foreach my $group_name (sort {lc($a) cmp lc($b)} (keys(%curr_groups))) { + push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]); } } @@ -3233,7 +3355,7 @@ sub postprocess { if (defined($self->{VALIDATOR})) { my $validator = eval($self->{VALIDATOR}); - die 'Died during evaluation of evaulation code; Perl said: ' . $@ if $@; + die 'Died during evaluation of validator code; Perl said: ' . $@ if $@; my $invalid = &$validator($helper, $state, $self, $self->getValue()); if ($invalid) { $self->{ERROR_MSG} = $invalid;