[LON-CAPA-cvs] cvs: rat /client parameter.html loncom/interface courseprefs.pm lonhtmlcommon.pm lonparmset.pm
raeburn
raeburn at source.lon-capa.org
Thu Oct 29 19:24:13 EDT 2020
raeburn Thu Oct 29 23:24:13 2020 EDT
Modified files:
/loncom/interface lonhtmlcommon.pm courseprefs.pm lonparmset.pm
/rat/client parameter.html
Log:
- Bug 6907
- deeplink parameter incorporates four components:
(a) In Contents or Gradebook?, (b) Access scope via deep-link,
(c) Supported Link Types, (d) Menu Items Displayed
- Allowed values for (c) 'any','only','key','lti'
- If (c) set to key, ':key value' appended; characters allowed in key:
a-zA-Z\d_.!@#$%^&*()+=-
- (d) is either 0 (i.e., standard menu), or numbered menu collection from
Settings > Course Settings > Menu display
-------------- next part --------------
Index: loncom/interface/lonhtmlcommon.pm
diff -u loncom/interface/lonhtmlcommon.pm:1.396 loncom/interface/lonhtmlcommon.pm:1.397
--- loncom/interface/lonhtmlcommon.pm:1.396 Sun Aug 30 20:30:22 2020
+++ loncom/interface/lonhtmlcommon.pm Thu Oct 29 23:24:13 2020
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common html routines
#
-# $Id: lonhtmlcommon.pm,v 1.396 2020/08/30 20:30:22 raeburn Exp $
+# $Id: lonhtmlcommon.pm,v 1.397 2020/10/29 23:24:13 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -866,13 +866,14 @@
##############################################
sub pjump_javascript_definition {
my $Str = <<END;
- function pjump(type,dis,value,marker,ret,call,hour,min,sec) {
+ function pjump(type,dis,value,marker,ret,call,hour,min,sec,extra) {
openMyModal("/adm/rat/parameter.html?type="+escape(type)
+"&value="+escape(value)+"&marker="+escape(marker)
+"&return="+escape(ret)
+"&call="+escape(call)+"&name="+escape(dis)
+"&defhour="+escape(hour)+"&defmin="+escape(min)
- +"&defsec="+escape(sec)+"&modal=1",350,350,'no');
+ +"&defsec="+escape(sec)+"&extra="+escape(extra)
+ +"&modal=1",350,350,'no');
}
END
return $Str;
Index: loncom/interface/courseprefs.pm
diff -u loncom/interface/courseprefs.pm:1.90 loncom/interface/courseprefs.pm:1.91
--- loncom/interface/courseprefs.pm:1.90 Thu Oct 29 17:14:23 2020
+++ loncom/interface/courseprefs.pm Thu Oct 29 23:24:13 2020
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set configuration settings for a course
#
-# $Id: courseprefs.pm,v 1.90 2020/10/29 17:14:23 raeburn Exp $
+# $Id: courseprefs.pm,v 1.91 2020/10/29 23:24:13 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -367,7 +367,7 @@
my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);
my @prefs_order = ('courseinfo','localization','feedback','discussion',
'classlists','appearance','grading','printouts',
- 'spreadsheet','bridgetasks','lti','other');
+ 'menuitems','spreadsheet','bridgetasks','lti','other');
my %prefs = (
'courseinfo' =>
@@ -542,6 +542,21 @@
'lti.lcmenu' => 'Menu items',
},
},
+ 'menuitems' =>
+ {
+ text => 'Menu display',
+ help => 'Course_Prefs_Menus',
+ header => [{col1 => 'Default Menu',
+ col2 => 'Value',},
+ {col1 => 'Menu collections',
+ col2 => 'Settings',
+ }],
+ ordered => ['menudefault','menucollections'],
+ itemtext => {
+ menudefault => 'Choose default collection of menu items for course',
+ menucollections => 'Menu collections',
+ },
+ },
'other' =>
{ text => 'Other settings',
help => 'Course_Prefs_Other',
@@ -557,7 +572,13 @@
$cnum,undef,\@allitems,
'coursepref',$parm_permission);
} elsif (($phase eq 'display') && ($parm_permission->{'display'})) {
- my $jscript = &get_jscript($cid,$cdom,$phase,$crstype,\%values);
+ my $noedit;
+ if (ref($parm_permission) eq 'HASH') {
+ unless ($parm_permission->{'process'}) {
+ $noedit = 1;
+ }
+ }
+ my $jscript = &get_jscript($cid,$cdom,$phase,$crstype,\%values,$noedit);
my @allitems = &get_allitems(%prefs);
&Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context,
\@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems,$crstype,
@@ -634,7 +655,7 @@
}
$output .= '</span></th>'."\n".
'</tr>';
- if (($action eq 'feedback') || ($action eq 'classlists')) {
+ if (($action eq 'feedback') || ($action eq 'classlists') || ($action eq 'menuitems')) {
$output .= '
<tr>
<td>
@@ -659,6 +680,8 @@
$output .= &print_feedback('top',$cdom,$settings,$ordered,$itemtext,\$rowtotal,$noedit);
} elsif ($action eq 'classlists') {
$output .= &print_classlists('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);
+ } elsif ($action eq 'menuitems') {
+ $output .= &print_menuitems('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);
}
$output .= '
</table>
@@ -739,6 +762,8 @@
$output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
} elsif ($action eq 'lti') {
$output .= &print_lti($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
+ } elsif ($action eq 'menuitems') {
+ $output .= &print_menuitems('bottom',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);
} elsif ($action eq 'other') {
$output .= &print_other($cdom,$settings,$allitems,\$rowtotal,$crstype,$noedit);
}
@@ -831,6 +856,81 @@
$changes->{$ext_entry} = $newvalues{$ext_entry};
}
}
+ } elsif ($action eq 'menuitems') {
+ my (%current, at colls);
+ my $next = 1;
+ if ($values->{'menucollections'}) {
+ foreach my $item (split(/;/,$values->{'menucollections'})) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ unless (grep(/^$num$/, at colls)) {
+ push(@colls,$num);
+ }
+ my @entries = split(/\&/,$value);
+ foreach my $entry (@entries) {
+ my ($name,$fields) = split(/=/,$entry);
+ $current{$num}{$name} = $fields;
+ }
+ }
+ }
+ }
+ if (@colls) {
+ @colls = sort { $a <=> $b } @colls;
+ $next += $colls[-1];
+ }
+ if ($env{'form.menucollections_add'} eq $next) {
+ push(@colls,$next);
+ }
+ my $currdef = $values->{'menudefault'};
+ my $possdef = $env{'form.menudefault'};
+ if (($possdef =~ /^\d+$/) && (grep(/^$possdef$/, at colls))) {
+ if ($values->{'menudefault'} ne $possdef) {
+ $changes->{'menudefault'} = $possdef;
+ }
+ } elsif ($values->{'menudefault'}) {
+ $changes->{'menudefault'} = '';
+ }
+ my $menucoll;
+ if (@colls) {
+ my ($ordered,$cats) = &menuitems_categories();
+ my %shortcats = &menuitems_abbreviations();
+ foreach my $num (@colls) {
+ my ($entry,%include);
+ map { $include{$_}= 1; } &Apache::loncommon::get_env_multiple('form.menucollections_'.$num);
+ foreach my $item (@{$ordered}) {
+ if ($item eq 'shown') {
+ foreach my $type (@{$cats->{$item}}) {
+ $entry .= $type.'=';
+ if ($include{$type}) {
+ $entry .= 'y';
+ } else {
+ $entry .= 'n';
+ }
+ $entry .= '&';
+ }
+ } else {
+ $entry .= $shortcats{$item}.'=';
+ foreach my $type (@{$cats->{$item}}) {
+ if ($include{$type}) {
+ $entry .= $type.',';
+ }
+ }
+ $entry =~ s/,$//;
+ $entry .= '&';
+ }
+ }
+ $entry =~ s/\&$//;
+ if ($menucoll) {
+ $menucoll .= ';';
+ }
+ $menucoll .= $num.'%'.$entry;
+ }
+ if ($menucoll ne $values->{'menucollections'}) {
+ $changes->{'menucollections'} = $menucoll;
+ }
+ } elsif ($values->{'menucollections'}) {
+ $changes->{'menucollections'} = '';
+ }
} else {
foreach my $entry (@ordered) {
if ($entry eq 'cloners') {
@@ -1530,6 +1630,16 @@
}
}
$displayname = &mt($text);
+ } elsif ($item eq 'menuitems') {
+ unless ($changes->{$item}{$key} eq '') {
+ if ($key eq 'menudefault') {
+ $displayname = &mt('Default collection of menu items');
+ $displayval = &mt('Collection: [_1]',
+ $changes->{$item}{$key});
+ } elsif ($key eq 'menucollections') {
+ $displayval = &menucollections_display($changes->{$item}{$key});
+ }
+ }
} else {
$displayname = &mt($text);
}
@@ -1605,10 +1715,19 @@
} elsif (!exists($changes->{$item}{'lti.override'})) {
$output .= '<li>'.&mt('LTI settings only saved if Override is set to "Yes"').'</li>';
}
+ } elsif ($item eq 'menuitems') {
+ if ($key eq 'menudefault') {
+ $output .= '<li>'.&mt("Default collection of menu items set to: 'Standard' (all menus shown)").'</li>';
+ } elsif ($key eq 'menucollections') {
+ $output .= '<li>'.&mt('Specific collections of menus no longer available').'</li>';
+ }
} else {
$output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]',
'<i>'.$displayname.'</i>')).'</li>';
}
+ } elsif ($key eq 'menucollections') {
+ $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Numbered menu collections:')).'<br />'.
+ $displayval.'</li>';
} else {
$output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]',
'<i>'.$displayname.'</i>',
@@ -1838,7 +1957,7 @@
}
sub get_jscript {
- my ($cid,$cdom,$phase,$crstype,$settings) = @_;
+ my ($cid,$cdom,$phase,$crstype,$settings,$noedit) = @_;
my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype);
my ($jscript,$categorize_js,$loncaparev_js,$instcode_js);
my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript();
@@ -1964,11 +2083,94 @@
}
}
ENDSCRIPT
+ my $menuitems_js;
+ unless ($noedit) {
+ my $collections;
+ my $next = 1;
+ if (ref($settings) eq 'HASH') {
+ if ($settings->{'menucollections'} ne '') {
+ my @current;
+ foreach my $item (split(/;/,$settings->{'menucollections'})) {
+ my ($num) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ push(@current,$num);
+ }
+ }
+ $collections = join("','",sort { $a <=> $b } @current);
+ if ($collections) {
+ $collections = "'$collections'";
+ }
+ $next += $current[-1];
+ }
+ }
+ my $deftext = &mt('Standard (all menus shown)');
+ $menuitems_js = <<ENDSCRIPT;
+function toggleAddmenucoll() {
+ if (document.getElementById('menucollections_add')) {
+ var state = 'none';
+ var add = document.getElementById('menucollections_add').checked;
+ if (add) {
+ state = 'inline-block';
+ }
+ var fieldsets = new Array('shown','text','links','list','inline');
+ for (var i=0; i<fieldsets.length; i++) {
+ if (document.getElementById('addmenucoll_'+fieldsets[i])) {
+ document.getElementById('addmenucoll_'+fieldsets[i]).style.display = state;
+ }
+ }
+ var box = document.getElementsByClassName('LC_menucoll_add');
+ if (box.length) {
+ for (var i=0; i<box.length; i++) {
+ if (add) {
+ box[i].checked = true;
+ } else {
+ box[i].checked = false;
+ }
+ }
+ }
+ if (document.getElementById('menudefault')) {
+ var menudef = document.getElementById('menudefault');
+ var currsel = menudef.selectedIndex;
+ var colls = new Array($collections);
+ menudef.options.length = 0;
+ if (!add) {
+ if (currsel == 1 + colls.length) {
+ currsel = 0;
+ }
+ }
+ if (currsel == 0) {
+ menudef.options[0] = new Option('$deftext','',true,true);
+ } else {
+ menudef.options[0] = new Option('$deftext','',false,false);
+ }
+ if (colls.length) {
+ for (var i=0; i<colls.length; i++) {
+ var idx = i+1;
+ if (currsel == colls[i]) {
+ menudef.options[idx] = new Option(colls[i],colls[i],true,true);
+ } else {
+ menudef.options[idx] = new Option(colls[i],colls[i],false,false);
+ }
+ }
+ }
+ if (add) {
+ var addidx = 1 + colls.length;
+ if (currsel == addidx) {
+ menudef.options[addidx] = new Option('$next','$next',true,true);
+ } else {
+ menudef.options[addidx] = new Option('$next','$next',false,false);
+ }
+ }
+ }
+ }
+}
+ENDSCRIPT
+ }
$jscript = '<script type="text/javascript" language="Javascript">'."\n".
'// <![CDATA['."\n".
$browse_js."\n".$categorize_js."\n".$loncaparev_js."\n".
$cloners_js."\n".$instcode_js.
- $syllabus_js."\n".'//]]>'."\n".
+ $syllabus_js."\n".$menuitems_js."\n".'//]]>'."\n".
'</script>'."\n".$stubrowse_js."\n";
return $jscript;
}
@@ -4595,6 +4797,247 @@
);
}
+sub print_menuitems {
+ my ($position,$cdom,$settings,$itemtext,$rowtotal,$crstype,$noedit) = @_;
+ unless ((ref($settings) eq 'HASH') && (ref($itemtext) eq 'HASH')) {
+ return;
+ }
+ if ($position eq 'top') {
+ my (%defaultmenu_options, at defaultmenu_order,$addcollection);
+ if ($settings->{'menucollections'} ne '') {
+ foreach my $item (split(/;/,$settings->{'menucollections'})) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ $defaultmenu_options{$num} = $num;
+ }
+ }
+ @defaultmenu_order = sort { $a <=> $b } keys(%defaultmenu_options);
+ $addcollection = $defaultmenu_order[-1] + 1;
+ } else {
+ $addcollection = 1;
+ }
+ $defaultmenu_options{$addcollection} = $addcollection;
+ my %items = (
+ 'menudefault' => {
+ text => '<b>'.&mt($itemtext->{'menudefault'}).'</b><br />'.
+ &mt("(can be overriden in deep-link context)"),
+ input => 'selectbox',
+ options => \%defaultmenu_options,
+ order => \@defaultmenu_order,
+ nullval => &mt('Standard (all menus shown)'),
+ },
+ );
+ return &make_item_rows($cdom,\%items,['menudefault'],$settings,$rowtotal,$crstype,'menuitems',$noedit);
+ } else {
+ my %menu;
+ my $count = 0;
+ my $next = 1;
+ my ($datatable,$disabled);
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
+
+ my ($ordered,$cats) = &menuitems_categories();
+ my @order = @{$ordered};
+ my %categories = %{$cats};
+ my %menutitles = &menuitems_titles();
+ my %menufields = &menuitems_fields();
+
+ if ($settings->{'menucollections'} ne '') {
+ foreach my $item (split(/;/,$settings->{'menucollections'})) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ my @entries = split(/\&/,$value);
+ foreach my $entry (@entries) {
+ my ($name,$fields) = split(/=/,$entry);
+ $menu{$num}{$name} = $fields;
+ }
+ }
+ }
+ if (keys(%menu)) {
+ my @current = sort { $a <=> $b } keys(%menu);
+ $next += $current[-1];
+ foreach my $num (@current) {
+ my %checked;
+ my $on = ' checked="checked"';
+ foreach my $key (keys(%{$menu{$num}})) {
+ if (($key eq 'top') || ($key eq 'inline') || ($key eq 'main')) {
+ if ($menu{$num}{$key} eq 'y') {
+ $checked{$key} = $on;
+ }
+ } else {
+ foreach my $field (split(/,/,$menu{$num}{$key})) {
+ if (exists($menufields{$field})) {
+ $checked{$field} = $on;
+ }
+ }
+ }
+ }
+ if (ref($menu{$num}) eq 'HASH') {
+ $datatable .= &item_table_row_start('<em class="LC_nav_bar">'.$num.'</em>',$count,'','','','LC_left_item');
+ foreach my $category (@order) {
+ if ((ref($categories{$category}) eq 'ARRAY') && (@{$categories{$category}} > 0)) {
+ $datatable .= '<fieldset style="vertical-align:top; display:inline-block"><legend>'.$menutitles{$category}.'</legend>'."\n";
+ foreach my $field (@{$categories{$category}}) {
+ $datatable .= '<label><input type="checkbox" name="menucollections_'.$num.'" value="'.$field.'"'.$checked{$field}.$disabled.' />'.
+ $menufields{$field}.'</label><br />';
+ }
+ $datatable .= '</fieldset>';
+ }
+ }
+ $datatable .= &item_table_row_end();
+ $count ++;
+ }
+ }
+ }
+ } elsif ($noedit) {
+ my $text = &mt('No menu collections defined for this course.');
+ $datatable .= &item_table_row_start($text,$count);
+ }
+ unless ($noedit) {
+ my $add = '<label><input type="checkbox" name="menucollections_add" id="menucollections_add" value="'.$next.'" '.
+ 'onclick="javascript:toggleAddmenucoll();" />'.&mt('Add').'</label>';
+ $datatable .= &item_table_row_start($add,$count,'','','','LC_left_item');
+ foreach my $category (@order) {
+ if ((ref($categories{$category}) eq 'ARRAY') && (@{$categories{$category}} > 0)) {
+ $datatable .= '<fieldset id="addmenucoll_'.$category.'" style="display:none; vertical-align:top;"><legend>'.$menutitles{$category}.'</legend>'."\n";
+ foreach my $field (@{$categories{$category}}) {
+ $datatable .= '<label><input type="checkbox" class="LC_menucoll_add" name="menucollections_'.$next.'" value="'.$field.'"'.$disabled.' />'.
+ $menufields{$field}.'</label><br />';
+ }
+ $datatable .= '</fieldset>';
+ }
+ }
+ $datatable .= &item_table_row_end();
+ $count ++;
+ }
+ return $datatable;
+ }
+}
+
+sub menuitems_abbreviations {
+ my %briefcats = (
+ text => 'pt',
+ links => 'p',
+ list => 'ps',
+ inline => 's',
+ );
+ return %briefcats;
+}
+
+sub menuitems_categories {
+ my @order = ('shown','text','links','list','inline');
+ my %categories = (
+ shown => ['top','inline','main'],
+ text => ['name','role','crs'],
+ links => ['personal','menu','comm','roles','help','logout'],
+ list => ['about','prefs','port','wish','anno','rss'],
+ inline => ['cont','grades','chat','people','groups','resv','syll','feeds'],
+ );
+ return (\@order,\%categories);
+}
+
+sub menuitems_titles {
+ return &Apache::lonlocal::texthash (
+ shown => 'Hierarchy',
+ text => 'Header text',
+ links => 'Header links',
+ list => 'Drop-down list',
+ inline => 'Inline links',
+ );
+}
+
+sub menuitems_fields {
+ return &Apache::lonlocal::texthash (
+ top => 'Display header',
+ inline => 'Display inline menu',
+ main => 'Access to main menu',
+ personal => 'Personal',
+ menu => 'Home',
+ comm => 'Messages',
+ roles => 'Roles/Courses',
+ help => 'Help',
+ logout => 'Logout',
+ name => 'Fullname',
+ crs => 'Course Title',
+ role => 'Current Role',
+ about => 'Information',
+ prefs => 'Preferences',
+ port => 'Portfolio',
+ wish => 'Stored Links',
+ anno => 'Calendar',
+ rss => 'RSS Feeds',
+ cont => 'Contents',
+ grades => 'Grades',
+ chat => 'Chat',
+ people => 'People',
+ groups => 'Groups',
+ resv => 'Reservations',
+ syll => 'Syllabus',
+ feeds => 'Feeds',
+ );
+}
+
+sub menucollections_display {
+ my ($collections) = @_;
+ my %menu;
+ my ($ordered,$cats) = &menuitems_categories();
+ my @order = @{$ordered};
+ my %categories = %{$cats};
+ my %menutitles = &menuitems_titles();
+ my %menufields = &menuitems_fields();
+ foreach my $item (split(/;/,$collections)) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ my @entries = split(/\&/,$value);
+ foreach my $entry (@entries) {
+ my ($name,$fields) = split(/=/,$entry);
+ $menu{$num}{$name} = $fields;
+ }
+ }
+ }
+ my $output = '';
+ if (keys(%menu)) {
+ my @current = sort { $a <=> $b } keys(%menu);
+ foreach my $num (@current) {
+ my %checked;
+ foreach my $key (keys(%{$menu{$num}})) {
+ if (($key eq 'top') || ($key eq 'inline') || ($key eq 'main')) {
+ if ($menu{$num}{$key} eq 'y') {
+ $checked{$key} = 1;
+ }
+ } else {
+ foreach my $field (split(/,/,$menu{$num}{$key})) {
+ if (exists($menufields{$field})) {
+ $checked{$field} = 1;
+ }
+ }
+ }
+ }
+ if (ref($menu{$num}) eq 'HASH') {
+ $output .= '<fieldset><legend>'.&mt('Collection [_1]',$num).'</legend>';
+ foreach my $category (@order) {
+ if ((ref($categories{$category}) eq 'ARRAY') && (@{$categories{$category}} > 0)) {
+ $output .= '<fieldset style="vertical-align:top; display:inline-block">'.
+ '<legend>'.$menutitles{$category}.'</legend>'."\n";
+ foreach my $field (@{$categories{$category}}) {
+ if ($checked{$field}) {
+ $output .= &Apache::lonhtmlcommon::confirm_success($menufields{$field});
+ } else {
+ $output .= &Apache::lonhtmlcommon::confirm_success($menufields{$field},1);
+ }
+ $output .= '<br />';
+ }
+ $output .= '</fieldset>';
+ }
+ }
+ $output .= '</fieldset>';
+ }
+ }
+ }
+ return $output;
+}
+
sub print_other {
my ($cdom,$settings,$allitems,$rowtotal,$crstype,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) {
@@ -4646,17 +5089,23 @@
}
sub item_table_row_start {
- my ($text,$count,$add_class,$colspan) = @_;
+ my ($text,$count,$add_class,$colspan,$leftclass,$rightclass) = @_;
my $output;
my $css_class = ($count % 2) ? 'LC_odd_row' : 'LC_even_row';
$css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
+ if ($leftclass eq '') {
+ $leftclass = 'LC_left_item';
+ }
+ if ($rightclass eq '') {
+ $rightclass = 'LC_right_item';
+ }
$output .= '<tr class="'.$css_class.'">'."\n".
- '<td class="LC_left_item">'.$text.
+ '<td class="'.$leftclass.'">'.$text.
'</td>';
- if ($colspan) {
- $output .= '<td class="LC_right_item" colspan="'.$colspan.'">';
+ if ($colspan > 1) {
+ $output .= '<td class="'.$rightclass.'" colspan="'.$colspan.'">';
} else {
- $output .= '<td class="LC_right_item">';
+ $output .= '<td class="'.$rightclass.'">';
}
return $output;
}
@@ -4697,7 +5146,7 @@
}
sub select_from_options {
- my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange,$noedit) = @_;
+ my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange,$noedit,$id) = @_;
my $output;
my $disabled;
if ($noedit) {
@@ -4713,6 +5162,9 @@
$output .= ' size="'.$maxsize.'"';
}
}
+ if ($id ne '') {
+ $output .= ' id="'.$id.'"';
+ }
$output .= $disabled.'>'."\n";
if ($nullval ne '') {
$output .= '<option value=""';
@@ -4801,12 +5253,16 @@
}
$datatable .= &yesno_radio($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit);
} elsif ($items->{$item}{input} eq 'selectbox') {
+ my $id;
+ if ($caller eq 'menuitems') {
+ $id = $item;
+ }
my $curr = $settings->{$item};
$datatable .=
&select_from_options($item,$items->{$item}{'order'},
$items->{$item}{'options'},$curr,
$items->{$item}{'nullval'},
- undef,undef,undef,$noedit);
+ undef,undef,undef,$noedit,$id);
} elsif ($items->{$item}{input} eq 'textbox') {
my $disabled;
if ($noedit) {
Index: loncom/interface/lonparmset.pm
diff -u loncom/interface/lonparmset.pm:1.596 loncom/interface/lonparmset.pm:1.597
--- loncom/interface/lonparmset.pm:1.596 Wed Feb 12 16:25:47 2020
+++ loncom/interface/lonparmset.pm Thu Oct 29 23:24:13 2020
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set parameters for assessments
#
-# $Id: lonparmset.pm,v 1.596 2020/02/12 16:25:47 raeburn Exp $
+# $Id: lonparmset.pm,v 1.597 2020/10/29 23:24:13 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1241,12 +1241,16 @@
var tailLenient = /\.lenient$/;
var patternRelWeight = /^\-?[\d.]+$/;
var patternLenientStd = /^(yes|no|default)$/;
+ var ipRegExp = /^setip/;
var ipallowRegExp = /^setipallow_/;
var ipdenyRegExp = /^setipdeny_/;
- var deeplinkRegExp = /^deeplink_(listing|scope)_/;
- var deeplinkUrlsRegExp = /^deeplink_urls_/;
- var deeplinkltiRegExp = /^deeplink_lti_/;
- var deeplinkkeyRegExp = /^deeplink_key_/;
+ var deeplinkRegExp = /^deeplink_/;
+ var dlListScopeRegExp = /^deeplink_(listing|scope)_/;
+ var dlLinkUrlsRegExp = /^deeplink_urls_/;
+ var dlLtiRegExp = /^deeplink_lti_/;
+ var dlKeyRegExp = /^deeplink_key_/;
+ var dlMenusRegExp = /^deeplink_menus_/;
+ var dlCollsRegExp = /^deeplink_colls_/;
var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
if ((document.parmform.elements.length != 'undefined') && (document.parmform.elements.length) != 'null') {
if (document.parmform.elements.length) {
@@ -1275,61 +1279,117 @@
}
}
}
- } else if (ipallowRegExp.test(name)) {
- var identifier = name.replace(ipallowRegExp,'');
- var possallow = document.parmform.elements[i].value;
- possallow = possallow.replace(/^\s+|\s+$/g,'');
- if (patternIP.test(possallow)) {
- if (document.parmform.elements['set_'+identifier].value) {
- possallow = ','+possallow;
- }
- document.parmform.elements['set_'+identifier].value += possallow;
- }
- } else if (ipdenyRegExp.test(name)) {
- var identifier = name.replace(ipdenyRegExp,'');
- var possdeny = document.parmform.elements[i].value;
- possdeny = possdeny.replace(/^\s+|\s+$/g,'');
- if (patternIP.test(possdeny)) {
- possdeny = '!'+possdeny;
- if (document.parmform.elements['set_'+identifier].value) {
- possdeny = ','+possdeny;
+ } else if (ipRegExp.test(name)) {
+ if (ipallowRegExp.test(name)) {
+ var identifier = name.replace(ipallowRegExp,'');
+ var possallow = document.parmform.elements[i].value;
+ possallow = possallow.replace(/^\s+|\s+$/g,'');
+ if (patternIP.test(possallow)) {
+ if (document.parmform.elements['set_'+identifier].value) {
+ possallow = ','+possallow;
+ }
+ document.parmform.elements['set_'+identifier].value += possallow;
+ }
+ } else if (ipdenyRegExp.test(name)) {
+ var identifier = name.replace(ipdenyRegExp,'');
+ var possdeny = document.parmform.elements[i].value;
+ possdeny = possdeny.replace(/^\s+|\s+$/g,'');
+ if (patternIP.test(possdeny)) {
+ possdeny = '!'+possdeny;
+ if (document.parmform.elements['set_'+identifier].value) {
+ possdeny = ','+possdeny;
+ }
+ document.parmform.elements['set_'+identifier].value += possdeny;
}
- document.parmform.elements['set_'+identifier].value += possdeny;
}
} else if (deeplinkRegExp.test(name)) {
- var identifier = name.replace(deeplinkRegExp,'');
- var possdeeplink = document.parmform.elements[i].value;
- possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
- if (document.parmform.elements['set_'+identifier].value) {
- possdeeplink = ','+possdeeplink;
- }
- document.parmform.elements['set_'+identifier].value += possdeeplink;
- } else if (deeplinkUrlsRegExp.test(name)) {
- if (document.parmform.elements[i].checked) {
- var identifier = name.replace(deeplinkUrlsRegExp,'');
- var posslinkurl = document.parmform.elements[i].value;
- posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
- if (document.parmform.elements['set_'+identifier].value) {
- posslinkurl = ','+posslinkurl;
- }
- document.parmform.elements['set_'+identifier].value += posslinkurl;
- }
- } else if (deeplinkltiRegExp.test(name)) {
- var identifier = name.replace(deeplinkltiRegExp,'');
- var posslti = document.parmform.elements[i].value;
- posslti = posslti.replace(/\D+/g,'');
- if (document.parmform.elements['set_'+identifier].value) {
- posslti = ':'+posslti;
- }
- document.parmform.elements['set_'+identifier].value += posslti;
- } else if (deeplinkkeyRegExp.test(name)) {
- var identifier = name.replace(deeplinkkeyRegExp,'');
- var posskey = document.parmform.elements[i].value;
- posskey = posskey.replace(/\W+/g,'');
- if (document.parmform.elements['set_'+identifier].value) {
- posslti = ':'+posskey;
+ if (dlListScopeRegExp.test(name)) {
+ var identifier = name.replace(dlListScopeRegExp,'');
+ var idx = document.parmform.elements[i].selectedIndex;
+ if (idx > 0) {
+ var possdeeplink = document.parmform.elements[i].options[idx].value
+ possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
+ if (document.parmform.elements['set_'+identifier].value) {
+ possdeeplink = ','+possdeeplink;
+ }
+ document.parmform.elements['set_'+identifier].value += possdeeplink;
+ }
+ } else if (dlLinkUrlsRegExp.test(name)) {
+ if (document.parmform.elements[i].checked) {
+ var identifier = name.replace(dlLinkUrlsRegExp,'');
+ var posslinkurl = document.parmform.elements[i].value;
+ posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
+ if (document.parmform.elements['set_'+identifier].value) {
+ posslinkurl = ','+posslinkurl;
+ }
+ document.parmform.elements['set_'+identifier].value += posslinkurl;
+ }
+ } else if (dlLtiRegExp.test(name)) {
+ var identifier = name.replace(dlLtiRegExp,'');
+ if (isRadioSet('deeplink_urls_'+identifier,'lti')) {
+ var posslti = document.parmform.elements[i].value;
+ posslti = posslti.replace(/\D+/g,'');
+ if (posslti.length) {
+ if (document.parmform.elements['set_'+identifier].value) {
+ posslti = ':'+posslti;
+ }
+ document.parmform.elements['set_'+identifier].value += posslti;
+ } else {
+ document.parmform.elements['set_'+identifier].value = '';
+ alert("A link type of 'deep with LTI launch' was selected but no LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
+ return false;
+ }
+ }
+ } else if (dlKeyRegExp.test(name)) {
+ var identifier = name.replace(dlKeyRegExp,'');
+ if (isRadioSet('deeplink_urls_'+identifier,'key')) {
+ var posskey = document.parmform.elements[i].value;
+ posskey = posskey.replace(/^\s+|\s+$/g,'');
+ var origlength = posskey.length;
+ posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
+ var newlength = posskey.length;
+ if (newlength > 0) {
+ var change = origlength - newlength;
+ if (change) {
+ alert(change+' disallowed character(s) removed from deeplink key');
+ }
+ if (document.parmform.elements['set_'+identifier].value) {
+ posskey = ':'+posskey;
+ }
+ document.parmform.elements['set_'+identifier].value += posskey;
+ } else {
+ document.parmform.elements['set_'+identifier].value = '';
+ if (newlength < origlength) {
+ alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-");
+ } else {
+ alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
+ }
+ return false;
+ }
+ }
+ } else if (dlMenusRegExp.test(name)) {
+ if (document.parmform.elements[i].checked) {
+ var identifier = name.replace(dlMenusRegExp,'');
+ var posslinkmenu = document.parmform.elements[i].value;
+ posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
+ if (posslinkmenu == 'std') {
+ posslinkmenu = '0';
+ if (document.parmform.elements['set_'+identifier].value) {
+ posslinkmenu = ','+posslinkmenu;
+ }
+ document.parmform.elements['set_'+identifier].value += posslinkmenu;
+ }
+ }
+ } else if (dlCollsRegExp.test(name)) {
+ var identifier = name.replace(dlCollsRegExp,'');
+ if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
+ var posslinkmenu = document.parmform.elements[i].value;
+ if (document.parmform.elements['set_'+identifier].value) {
+ posslinkmenu = ','+posslinkmenu;
+ }
+ document.parmform.elements['set_'+identifier].value += posslinkmenu;
+ }
}
- document.parmform.elements['set_'+identifier].value += posskey;
}
}
}
@@ -1337,6 +1397,23 @@
return true;
}
+function isRadioSet(name,expected) {
+ var menuitems = document.getElementsByName(name);
+ var radioLength = menuitems.length;
+ result = false;
+ if (radioLength > 1) {
+ for (var j=0; j<radioLength; j++) {
+ if (menuitems[j].checked) {
+ if (menuitems[j].value == expected) {
+ result = true;
+ break;
+ }
+ }
+ }
+ }
+ return result;
+}
+
ENDSCRIPT
}
@@ -1401,25 +1478,37 @@
if (document.getElementById('deeplink_key_'+item+'_'+key)) {
keybox = document.getElementById('deeplink_key_'+item+'_'+key);
}
- var ltidiv;
- if (document.getElementById('deeplinkdiv_lti_'+item+'_'+key)) {
- ltidiv = document.getElementById('deeplinkdiv_lti_'+item+'_'+key);
+ var divoption;
+ if (item == 'urls') {
+ divoption = 'lti'
+ } else {
+ if (item == 'menus') {
+ divoption = 'colls';
+ }
+ }
+ var seldiv;
+ if (document.getElementById('deeplinkdiv_'+divoption+'_'+item+'_'+key)) {
+ seldiv = document.getElementById('deeplinkdiv_'+divoption+'_'+item+'_'+key);
}
for (var i=0; i<radios.length; i++) {
if (radios[i].checked) {
- if (radios[i].value == 'lti') {
- ltidiv.style.display = 'inline-block';
- keybox.type = 'hidden';
- keybox.value = '';
- } else {
- if (ltidiv != '') {
- ltidiv.style.display = 'none';
- form['deeplink_lti_'+key].selectedIndex = 0;
- }
- if (radios[i].value == 'key') {
- keybox.type = 'text';
- } else {
+ if (radios[i].value == divoption) {
+ seldiv.style.display = 'inline-block';
+ if (item == 'urls') {
keybox.type = 'hidden';
+ keybox.value = '';
+ }
+ } else {
+ if (seldiv != '') {
+ seldiv.style.display = 'none';
+ form['deeplink_'+divoption+'_'+key].selectedIndex = 0;
+ }
+ if (item == 'urls') {
+ if (radios[i].value == 'key') {
+ keybox.type = 'text';
+ } else {
+ keybox.type = 'hidden';
+ }
}
}
}
@@ -1629,10 +1718,25 @@
if (keys(%posslti)) {
$extra = 'lti_';
foreach my $lti (sort { $a <=> $b } keys(%posslti)) {
- $extra .= $lti.':'.&js_escape($posslti{$lti}).',';
+ $extra .= $lti.':'.&escape($posslti{$lti}).',';
}
$extra =~ s/,$//;
}
+ if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
+ my @colls;
+ foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ push(@colls,$num);
+ }
+ }
+ if (@colls) {
+ if ($extra) {
+ $extra .= '&';
+ }
+ $extra .= 'menus_'.join(',', at colls);
+ }
+ }
}
if ($parmlev eq 'general') {
if ($uname) {
@@ -1766,7 +1870,7 @@
# @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
# @param {boolean} $readonly -true if editing not allowed.
# @param {boolean} $ismaplevel - true if level is for a map.
-# @param {strring} $extra - extra informatio to pass to plink.
+# @param {string} $extra - extra information to pass to plink.
sub print_td {
my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
$noeditgrp,$readonly,$ismaplevel,$extra)=@_;
@@ -2517,7 +2621,7 @@
}
if (%grouphash) {
- $groups=&mt('Group:').' <select name="cgroup"';
+ $groups=&mt('Group').': <select name="cgroup"';
if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
$groups .= qq| onchange="group_or_section('cgroup')" |;
}
@@ -4869,17 +4973,20 @@
sub string_deeplink_selector {
my ($thiskey, $showval, $readonly) = @_;
- my (@components,%values, at current,%titles,%options,%optiontext,%defaults,%posslti);
- @components = ('listing','scope','urls');
+ my (@components,%values, at current,%titles,%options,%optiontext,%defaults,
+ %selectnull,%posslti, at possmenus);
+ @components = ('listing','scope','urls','menus');
%titles = &Apache::lonlocal::texthash (
listing => 'In Contents and/or Gradebook',
scope => 'Access scope for link',
urls => 'Supported link types',
+ menus => 'Menu Items Displayed',
);
%options = (
listing => ['full','absent','grades','details','datestatus'],
scope => ['res','map','rec'],
urls => ['any','only','key','lti'],
+ menus => ['std','colls'],
);
%optiontext = &Apache::lonlocal::texthash (
full => 'Listed (linked) in both',
@@ -4894,16 +5001,25 @@
only => 'deep only',
key => 'deep with key',
lti => 'deep with LTI launch',
+ std => 'Standard (all menus)',
+ colls => 'Numbered collection',
+ );
+ %selectnull = &Apache::lonlocal::texthash (
+ lti => 'Select Provider',
+ colls => 'Select',
);
if ($showval =~ /,/) {
+ %values=();
@current = split(/,/,$showval);
($values{'listing'}) = ($current[0] =~ /^(full|absent|grades|details|datestatus)$/);
($values{'scope'}) = ($current[1] =~ /^(res|map|rec)$/);
- ($values{'urls'}) = ($current[2] =~ /^(any|only|key:\w+|lti:\d+)$/);
+ ($values{'urls'}) = ($current[2] =~ /^(any|only|key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|lti:\d+)$/);
+ ($values{'menus'}) = ($current[3] =~ /^(\d+)$/);
} else {
$defaults{'listing'} = 'full';
$defaults{'scope'} = 'res';
$defaults{'urls'} = 'any';
+ $defaults{'menus'} = '0';
}
my $disabled;
if ($readonly) {
@@ -4919,21 +5035,41 @@
}
}
}
+ if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
+ foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ push(@possmenus,$num);
+ }
+ }
+ }
+
my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
- foreach my $item ('listing','scope','urls') {
+ foreach my $item (@components) {
$output .= '<th>'.$titles{$item}.'</th>';
}
$output .= '</tr><tr>';
foreach my $item (@components) {
$output .= '<td>';
- if ($item eq 'urls') {
+ if (($item eq 'urls') || ($item eq 'menus')) {
my $selected = $values{$item};
foreach my $option (@{$options{$item}}) {
- if ($option eq 'lti') {
+ if (($item eq 'urls') && ($option eq 'lti')) {
next unless (keys(%posslti));
+ } elsif (($item eq 'menus') && ($option eq 'colls')) {
+ next unless (@possmenus);
}
my $checked;
- if ($selected =~ /^\Q$option\E/) {
+ if ($item eq 'menus') {
+ if (($selected =~ /^\d+$/) && (@possmenus) &&
+ (grep(/^\Q$selected\E$/, at possmenus))) {
+ if ($option eq 'colls') {
+ $checked = ' checked="checked"';
+ }
+ } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
+ $checked = ' checked="checked"';
+ }
+ } elsif ($selected =~ /^\Q$option\E/) {
$checked = ' checked="checked"';
}
my $onclick;
@@ -4944,7 +5080,7 @@
$output .= '<span class="LC_nobreak"><label>'.
'<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
$optiontext{$option}.'</label>';
- if ($option eq 'key') {
+ if (($item eq 'urls') && ($option eq 'key')) {
my $visibility="hidden";
my $currkey;
if ($checked) {
@@ -4952,26 +5088,42 @@
$currkey = (split(/\:/,$values{$item}))[1];
}
$output .= ' '.
- '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="6"'.$disabled.' />';
- } elsif ($option eq 'lti') {
+ '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
+ } elsif (($option eq 'lti') || ($option eq 'colls')) {
my $display="none";
- my ($currlti,$blankcheck);
+ my ($current,$blankcheck, at possibles);
if ($checked) {
$display = 'inline-block';
- $currlti = (split(/\:/,$values{$item}))[1];
+ if ($option eq 'lti') {
+ $current = (split(/\:/,$selected))[1];
+ } else {
+ $current = $selected;
+ }
} else {
$blankcheck = ' selected="selected"';
}
+ if ($option eq 'lti') {
+ @possibles = keys(%posslti);
+ } else {
+ @possibles = @possmenus;
+ }
$output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
' style="display: '.$display.'"> <select name="'.
- 'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>'.
- '<option value=""'.$blankcheck.'>'.&mt('Select Provider').'</option>'."\n";
- foreach my $lti (sort { $a <=> $b } keys(%posslti)) {
+ 'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
+ if (@possibles > 1) {
+ $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
+ '</option>'."\n";
+ }
+ foreach my $poss (sort { $a <=> $b } @possibles) {
my $selected;
- if ($lti == $currlti) {
+ if (($poss == $current) || (scalar(@possibles) ==1)) {
$selected = ' selected="selected"';
}
- $output .= '<option value="'.$lti.'"'.$selected.'>'.$posslti{$lti}.'</option>';
+ my $shown = $poss;
+ if ($option eq 'lti') {
+ $shown = $posslti{$poss};
+ }
+ $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
}
$output .= '</select></div>';
}
@@ -5035,7 +5187,7 @@
=> [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']],
'string_deeplink'
- => [['on','Set choices for link protection, resource listing, and access scope']],
+ => [['on','Set choices for link protection, resource listing, access scope, and shown menu items']],
);
@@ -5046,7 +5198,7 @@
=> [['_allowfrom_','[^\!]+'],
['_denyfrom_','\!']],
'string_deeplink'
- => [['on','^(full|absent|grades|details|datestatus)\,(res|map|rec)\,(any|only|key\:\w+|lti\:\d+)$']],
+ => [['on','^(full|absent|grades|details|datestatus)\,(res|map|rec)\,(any|only|key\:\w+|lti\:\d+)\,(\d+|)$']],
);
my %stringtypes = (
Index: rat/client/parameter.html
diff -u rat/client/parameter.html:1.83 rat/client/parameter.html:1.84
--- rat/client/parameter.html:1.83 Wed Jun 3 12:58:32 2020
+++ rat/client/parameter.html Thu Oct 29 23:24:13 2020
@@ -5,7 +5,7 @@
The LearningOnline Network with CAPA
Parameter Input Window
//
-// $Id: parameter.html,v 1.83 2020/06/03 12:58:32 raeburn Exp $
+// $Id: parameter.html,v 1.84 2020/10/29 23:24:13 raeburn Exp $
//
// Copyright Michigan State University Board of Trustees
//
@@ -402,7 +402,7 @@
if (sform.donebutton[i].value == '_done_proctor') {
if ((sform.donebutton_proctorkey.value == '') ||
(sform.donebutton_proctorkey.value == null)) {
- alert('Please provide a key for a proctor to enter when a student uses the "Done" button.');
+ alert('Please enter a key for a proctor to enter when a student uses the "Done" button.');
return;
}
}
@@ -417,6 +417,8 @@
var sform=choices.document.forms.sch;
svalue = sform.deeplinklisted.options[sform.deeplinklisted.selectedIndex].value+',';
svalue += sform.deeplinkacc.options[sform.deeplinkacc.selectedIndex].value+',';
+ var keyRegExp = /^[a-zA-Z\d_.!@#$%^&*()+=-]+$/;
+ var numRegExp = /^\d+$/;
if (sform.deeplinktypes.length) {
for (var i=0; i<sform.deeplinktypes.length; i++) {
if (sform.deeplinktypes[i].checked) {
@@ -424,14 +426,39 @@
if (sform.deeplinktypes[i].value == 'key') {
var posskey = sform.deeplinkkey.value;
posskey = posskey.replace(/^\s+|\s+$/g,'');
- var keyRegExp = /^\w+$/;
if (keyRegExp.test(posskey)) {
svalue += ':'+posskey;
+ } else {
+ alert('Please enter a value for the key containing one or more of: a-zA-Z0-9_.!@#$%^&*()+=-\n'+
+ 'or choose a different supported link type.');
+ return;
}
} else if (sform.deeplinktypes[i].value == 'lti') {
var posslti = sform.linkposslti.options[sform.linkposslti.selectedIndex].value;
- if (posslti != '' && posslti != null) {
+ if ((numRegExp.test(posslti)) && (posslti > 0)) {
svalue += ':'+posslti;
+ } else {
+ alert('Please select an LTI launcher, or choose a different supported link type.');
+ return;
+ }
+ }
+ break;
+ }
+ }
+ }
+ svalue += ',';
+ if (sform.deeplinkmenus.length) {
+ for (var i=0; i<sform.deeplinkmenus.length; i++) {
+ if (sform.deeplinkmenus[i].checked) {
+ if (sform.deeplinkmenus[i].value == 'std') {
+ svalue += '0';
+ } else if (sform.deeplinkmenus[i].value == 'collnum') {
+ var posscoll = sform.linkpossmenu.options[sform.linkpossmenu.selectedIndex].value;
+ if ((numRegExp.test(posscoll)) && (posscoll > 0)) {
+ svalue += posscoll;
+ } else {
+ alert("Please select either a numbered collection or check 'Standard (all menus)'.");
+ return;
}
}
break;
@@ -441,9 +468,9 @@
assemble();
}
-function toggleDeepLink() {
+function toggleDeepLink(caller) {
var sform=choices.document.forms.sch;
- if (sform.deeplinktypes.length) {
+ if ((caller == 'types') && (sform.deeplinktypes.length)) {
var frame = window.frames["choices"];
for (var i=0; i<sform.deeplinktypes.length; i++) {
if (sform.deeplinktypes[i].checked) {
@@ -460,7 +487,7 @@
}
if (frame.document.getElementById('deeplinkltidiv')) {
if (sform.deeplinktypes[i].value == 'lti') {
- frame.document.getElementById('deeplinkltidiv').style.display='inline-block';
+ frame.document.getElementById('deeplinkltidiv').style.display='block';
} else {
frame.document.getElementById('deeplinkltidiv').style.display='none';
}
@@ -470,10 +497,25 @@
}
}
}
+ if ((caller == 'menus') && (sform.deeplinkmenus.length)) {
+ var frame = window.frames["choices"];
+ for (var i=0; i<sform.deeplinkmenus.length; i++) {
+ if (sform.deeplinkmenus[i].checked) {
+ if (frame.document.getElementById('deeplinkmenusdiv')) {
+ if (sform.deeplinkmenus[i].value == 'collnum') {
+ frame.document.getElementById('deeplinkmenusdiv').style.display='inline-block';
+ } else {
+ frame.document.getElementById('deeplinkmenusdiv').style.display='none';
+ }
+ }
+ break;
+ }
+ }
+ }
}
-function calldeeplink() {
- return 'onclick="parent.toggleDeepLink()"';
+function calldeeplink(caller) {
+ return 'onclick="parent.toggleDeepLink(\''+caller+'\')"';
}
function integereval() {
@@ -1127,8 +1169,9 @@
var linktypeparts = new Array();
var ltikeyRegExp = /^(lti|key):(\w+)$/;
var dlinkkeysty = 'hidden';
- var dlinkltidivsty = 'none';
var dlinkkeyval = '';
+ var dlinkltidivsty = 'none';
+ var dlinkmenusdivsty = 'none';
if ((svalue != '') && (svalue != null)) {
deeplinkvals = svalue.split(',');
if (ltikeyRegExp.test(deeplinkvals[2])) {
@@ -1138,11 +1181,14 @@
dlinkkeysty = 'text';
dlinkkeyval = linktypeparts[1];
} else if (linktypeparts[0] == 'lti') {
- dlinkltidivsty = 'inline-block';
+ dlinkltidivsty = 'block';
}
}
+ if (deeplinkvals[3] >= 1) {
+ dlinkmenusdivsty = 'inline-block';
+ }
} else {
- deeplinkvals = ['full','res','any'];
+ deeplinkvals = ['full','res','any','0'];
}
var deeplinklisting = new Array();
deeplinklisting = ['full','absent','grades','details','datestatus'];
@@ -1155,7 +1201,7 @@
var deeplinkurls = new Array();
deeplinkurls = ['any','only','key','lti'];
tablestart('Deep-linked items');
- choicewrite('<tr><td>In Contents or Gradebook?</td><td>');
+ choicewrite('<tr><td>In Contents + Gradebook?</td><td>');
choicewrite('<select name="deeplinklisted">');
for (var i=0; i<deeplinklisting.length; i++) {
choicewrite('<option value="'+deeplinklisting[i]+'"');
@@ -1178,65 +1224,106 @@
choicewrite('<tr><td>Supported Link Types</td><td>');
choicewrite('<span style="white-space: nowrap;"><label>');
choicewrite('<input name="deeplinktypes" value="any"'+
- ' type="radio" '+calldeeplink());
+ ' type="radio" '+calldeeplink('types'));
if (deeplinkvals[2]=='any') { choicewrite(' checked="checked"'); }
choicewrite(' /> regular + deep</label></span><br />');
choicewrite('<span style="white-space: nowrap;"><label>');
choicewrite('<input name="deeplinktypes" value="only"'+
- ' type="radio" '+calldeeplink());
+ ' type="radio" '+calldeeplink('types'));
if (deeplinkvals[2]=='only') { choicewrite(' checked="checked"'); }
choicewrite(' /> deep only</label></span><br />');
choicewrite('<span style="white-space: nowrap;"><label>');
choicewrite('<input name="deeplinktypes" value="key"'+
- ' type="radio" '+calldeeplink());
+ ' type="radio" '+calldeeplink('types'));
if (deeplinkvals[2]=='key') { choicewrite(' checked="checked"'); }
choicewrite(' /> deep with key</label>');
- choicewrite('<input type="'+dlinkkeysty+'" name="deeplinkkey" id="deeplinkkey" value="'+dlinkkeyval+'" size="6" />');
+ choicewrite('<input type="'+dlinkkeysty+'" name="deeplinkkey" id="deeplinkkey" value="'+dlinkkeyval+'" size="10" />');
choicewrite('</span><br />');
+
+ var possmenus = new Array();
if ((pextra != '') && (pextra != null)) {
var ltiRegExp = /^lti_/;
- if (ltiRegExp.test(pextra)) {
- pextra = pextra.replace(ltiRegExp,'');
- var posslti = pextra.split(',');
- if (posslti.length >= 1) {
- var ltinums = new Array();
- var ltititles = new Array();
- for (var i=0; i<posslti.length; i++) {
- var entries = posslti[i].split(':');
- ltinums[i] = entries[0];
- ltititles[i] = decodeURI(entries[1]);
- }
- if (ltinums.length) {
- choicewrite('<span style="white-space: nowrap;"><label>');
- choicewrite('<input name="deeplinktypes" value="lti"'+
- ' type="radio" '+calldeeplink());
- if (deeplinkvals[2]=='lti') { choicewrite(' checked="checked"'); }
- choicewrite(' /> deep with LTI launch</label>');
- choicewrite('<div id="deeplinkltidiv" style="display:'+dlinkltidivsty+'">');
- choicewrite('<select name="linkposslti">');
- var sel='';
- if (deeplinkvals[2]!='lti') {
- sel = ' selected="selected"';
+ var menusRegExp = /^menus_/;
+ var extras = pextra.split('&');
+ for (var i=0; i<extras.length; i++) {
+ if (ltiRegExp.test(extras[i])) {
+ extras[i] = extras[i].replace(ltiRegExp,'');
+ var posslti = extras[i].split(',');
+ if (posslti.length >= 1) {
+ var ltinums = new Array();
+ var ltititles = new Array();
+ for (var j=0; j<posslti.length; j++) {
+ var entries = posslti[j].split(':');
+ ltinums[j] = entries[0];
+ ltititles[j] = decodeURIComponent(entries[1]);
}
- if (ltinums.length > 1) {
- choicewrite('<option value=""'+sel+'>Please select</option>');
- }
- for (var i=0; i<ltinums.length; i++) {
- sel = '';
- if (deeplinkvals[2]=='lti') {
- if (linktypeparts.length) {
- if (ltinums[i] == linktypeparts[1]) {
- sel = ' selected="selected"';
+ if (ltinums.length) {
+ choicewrite('<span style="white-space: nowrap;"><label>');
+ choicewrite('<input name="deeplinktypes" value="lti"'+
+ ' type="radio" '+calldeeplink('types'));
+ if (deeplinkvals[2]=='lti') { choicewrite(' checked="checked"'); }
+ choicewrite(' /> deep with LTI launch</label>');
+ choicewrite('<div id="deeplinkltidiv" style="display:'+dlinkltidivsty+'">');
+ choicewrite('<select name="linkposslti">');
+ var sel='';
+ if (deeplinkvals[2]!='lti') {
+ sel = ' selected="selected"';
+ }
+ if (ltinums.length > 1) {
+ choicewrite('<option value=""'+sel+'>Select</option>');
+ }
+ for (var j=0; j<ltinums.length; j++) {
+ sel = '';
+ if (deeplinkvals[2]=='lti') {
+ if (linktypeparts.length) {
+ if (ltinums[j] == linktypeparts[1]) {
+ sel = ' selected="selected"';
+ }
}
}
+ choicewrite('<option value="'+ltinums[j]+'"'+sel+'>'+ltititles[j]+'</option>');
}
- choicewrite('<option value="'+ltinums[i]+'"'+sel+'>'+ltititles[i]+'</option>');
+ choicewrite('</select></div></span><br />');
}
- choicewrite('</select></div></span><br />');
}
+ } else if (menusRegExp.test(extras[i])) {
+ extras[i] = extras[i].replace(menusRegExp,'');
+ possmenus = extras[i].split(',');
}
}
}
+ choicewrite('<tr><td>Menu Items Displayed</td><td>');
+ choicewrite('<span style="white-space: nowrap;"><label>');
+ choicewrite('<input name="deeplinkmenus" value="std"'+
+ ' type="radio" '+calldeeplink('menus'));
+ if (deeplinkvals[3] == 0) {
+ choicewrite(' checked="checked"');
+ }
+ choicewrite(' /> Standard (all menus)</label></span><br />');
+ if (possmenus.length >= 1) {
+ choicewrite('<span style="white-space: nowrap;"><label>');
+ choicewrite('<input name="deeplinkmenus" value="collnum"'+
+ ' type="radio" '+calldeeplink('menus'));
+ if (deeplinkvals[3] > 0) { choicewrite(' checked="checked"'); }
+ choicewrite(' /> Numbered collection</label>');
+ choicewrite('<div id="deeplinkmenusdiv" style="display:'+dlinkmenusdivsty+'">');
+ choicewrite('<select name="linkpossmenu">');
+ var sel='';
+ if (deeplinkvals[3] == 0) {
+ sel = ' selected="selected"';
+ }
+ if (possmenus.length > 1) {
+ choicewrite('<option value=""'+sel+'>Select</option>');
+ }
+ for (var i=0; i<possmenus.length; i++) {
+ sel = '';
+ if (deeplinkvals[3] == possmenus[i]) {
+ sel = ' selected="selected"';
+ }
+ choicewrite('<option value="'+possmenus[i]+'"'+sel+'>'+possmenus[i]+'</option>');
+ }
+ choicewrite('</select></div></span><br />');
+ }
choicewrite('</td></tr></table>');
}
}
@@ -1628,6 +1715,9 @@
selwrite('</body></html>');
this.window.selector.document.close();
+ if (pscat == 'deeplink') {
+ document.getElementById("LCparampopup").rows="60,*";
+ }
draw();
}
@@ -1636,7 +1726,7 @@
</script>
</head>
-<frameset rows="125,*" onload="init();">
+<frameset id="LCparampopup" rows="125,*" onload="init();">
<frame name="selector" src="empty.html" />
<frame name="choices" src="empty.html" />
</frameset>
More information about the LON-CAPA-cvs
mailing list