--- loncom/interface/lonextresedit.pm 2018/07/04 13:55:27 1.26 +++ loncom/interface/lonextresedit.pm 2023/07/12 00:05:02 1.34 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: lonextresedit.pm,v 1.26 2018/07/04 13:55:27 raeburn Exp $ +# $Id: lonextresedit.pm,v 1.34 2023/07/12 00:05:02 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -98,7 +98,18 @@ sub handler { } my %ltitools; if ($type eq 'tool') { - %ltitools = &Apache::lonnet::get_domain_lti($cdom,'consumer'); + my (%domtools,%crstools); + my %tooltypes = &Apache::loncommon::usable_exttools(); + if ($tooltypes{'dom'}) { + %domtools = &Apache::lonnet::get_domain_lti($cdom,'consumer'); + } + if ($tooltypes{'crs'}) { + %crstools = &Apache::lonnet::get_course_lti($cnum,$cdom,'consumer'); + } + %ltitools = ( + dom => \%domtools, + crs => \%crstools, + ); } my $js = &Apache::lonhtmlcommon::scripttag(&extedit_javascript()); my $pathitem = ''; - } - if ($ltitools->{$toolhash{'id'}}->{'url'} =~ m{://}) { - (my $prot,my $host,$providerurl) = ($ltitools->{$toolhash{'id'}}->{'url'} =~ m{^([^/]+)://([^/]+)(|/.+)$}); - } else { - $providerurl = $ltitools->{$toolhash{'id'}}->{'url'}; - } - $tooltarget = $toolhash{'target'}; - if ($tooltarget eq 'window') { - $dimendivstyle = 'display:block'; - $windivstyle = 'display:block'; - $chkstate{'window'} = 'checked="checked" '; - } elsif ($tooltarget eq 'tab') { - $windivstyle = 'display:block'; - $chkstate{'tab'} = 'checked="checked" '; - } else { - $chkstate{'iframe'} = 'checked="checked" '; - } - $width = $toolhash{'width'}; - $height = $toolhash{'height'}; - $linktext = $toolhash{'linktext'}; - $explanation = $toolhash{'explanation'}; - if ($toolhash{'gradable'}) { - $chkgrd = ' checked="checked"'; - } else { - $chknogrd = ' checked="checked"'; - } - if (ref($ltitools->{$toolhash{'id'}}->{'crsconf'}) eq 'HASH') { - if ($ltitools->{$toolhash{'id'}}->{'crsconf'}->{'title'}) { - $crstitle = $toolhash{'crstitle'}; - $titlestyle = 'display:inline'; - } - if ($ltitools->{$toolhash{'id'}}->{'crsconf'}->{'label'}) { - $crslabel = $toolhash{'crslabel'}; - $labelstyle = 'display:inline'; - } - if ($ltitools->{$toolhash{'id'}}->{'crsconf'}->{'append'}) { - $crsappend = $toolhash{'crsappend'}; - $appendstyle = 'display:inline'; - } - if ($ltitools->{$toolhash{'id'}}->{'crsconf'}->{'target'}) { - $dispdivstyle = 'display:block'; - } - if ($ltitools->{$toolhash{'id'}}->{'crsconf'}->{'linktext'}) { - $linktextstyle = 'padding:0;display:inline'; - } - if ($ltitools->{$toolhash{'id'}}->{'crsconf'}->{'explanation'}) { - $explanationstyle = 'padding:0;display:inline'; - } - } - $toolelem = ''.$image.' '.$tooltitle.'
'; - $gradablestyle = 'display:inline'; - } + if (ref($ltitools->{'crs'}) eq 'HASH') { + $ltihash = $ltitools->{'crs'}->{$tool}; } } + } elsif ($toolhash{'id'} =~/^\d+$/) { + $tooltype = 'dom'; + $tool = $toolhash{'id'}; + if (ref($ltitools) eq 'HASH') { + if (ref($ltitools->{'dom'}) eq 'HASH') { + $ltihash = $ltitools->{'dom'}->{$tool}; + } + } + } + if (($tool ne '') && (ref($ltihash) eq 'HASH')) { + my $tooltitle = $ltihash->{'title'}; + my $icon = $ltihash->{'image'}; + my $image; + if ($icon) { + $image = ''.$tooltitle.''; + } + if ($ltihash->{'url'} =~ m{://}) { + (my $prot,my $host,$providerurl) = ($ltihash->{'url'} =~ m{^([^/]+)://([^/]+)(|/.+)$}); + } else { + $providerurl = $ltihash->{'url'}; + } + $tooltarget = $toolhash{'target'}; + if ($tooltarget eq 'window') { + $dimendivstyle = 'display:block'; + $windivstyle = 'display:block'; + $chkstate{'window'} = 'checked="checked" '; + } elsif ($tooltarget eq 'tab') { + $windivstyle = 'display:block'; + $chkstate{'tab'} = 'checked="checked" '; + } else { + $chkstate{'iframe'} = 'checked="checked" '; + } + $width = $toolhash{'width'}; + $height = $toolhash{'height'}; + $linktext = $toolhash{'linktext'}; + $explanation = $toolhash{'explanation'}; + if ($toolhash{'gradable'}) { + $chkgrd = ' checked="checked"'; + } else { + $chknogrd = ' checked="checked"'; + } + if (ref($ltihash->{'crsconf'}) eq 'HASH') { + if ($ltihash->{'crsconf'}->{'title'}) { + $crstitle = $toolhash{'crstitle'}; + $titlestyle = 'display:inline'; + } + if ($ltihash->{'crsconf'}->{'label'}) { + $crslabel = $toolhash{'crslabel'}; + $labelstyle = 'display:inline'; + } + if ($ltihash->{'crsconf'}->{'append'}) { + $crsappend = $toolhash{'crsappend'}; + $appendstyle = 'display:inline'; + } + if ($ltihash->{'crsconf'}->{'target'}) { + $dispdivstyle = 'display:block'; + } + if ($ltihash->{'crsconf'}->{'linktext'}) { + $linktextstyle = 'padding:0;display:inline'; + } + if ($ltihash->{'crsconf'}->{'explanation'}) { + $explanationstyle = 'padding:0;display:inline'; + } + } + $toolelem = ''.$image.' '.$tooltitle.'
'; + $gradablestyle = 'display:inline'; } } } else { - $toolelem = ''."\n". - '
'; + foreach my $type ('crs','dom') { + $toolelem .= ' '."\n"; + } + $toolelem .= '
'. + '
'."\n". + '
'. + $exttypeofftext. + '
'."\n"; $crslabel = $env{'course.'.$cdom.'_'.$cnum.'.internal.coursecode'}; $crstitle = $env{'course.'.$cdom.'_'.$cnum.'.description'}; $crsappend = ''; @@ -640,13 +716,17 @@ $preview "; } + my $idattr; + unless ($subdivid eq '') { + $idattr = 'id="'.$subdivid.'"'; + } $form = <
$legend $active $chooser -
+
$title @@ -666,6 +746,35 @@ ENDFORM } } +sub ordered_tooloptions { + my ($toolsref) = @_; + my ($seloptions,@ids,@titles); + if (ref($toolsref) eq 'HASH') { + my %bynum; + foreach my $id (keys(%{$toolsref})) { + if (ref($toolsref->{$id}) eq 'HASH') { + my $order = $toolsref->{$id}->{'order'}; + $bynum{$order} = [$id,$toolsref->{$id}]; + } + } + foreach my $item (sort { $a <=> $b } keys(%bynum)) { + if (ref($bynum{$item}) eq 'ARRAY') { + if (ref($bynum{$item}->[1]) eq 'HASH') { + my $tooltitle = $bynum{$item}->[1]->{'title'}; + push(@titles,$tooltitle); + push(@ids,$bynum{$item}->[0]); + $seloptions .= ''."\n"; + } + } + } + } + if (wantarray) { + return (\@ids,\@titles); + } else { + return $seloptions; + } +} + sub display_editor { my ($url,$folderpath,$symb,$idx,$type,$cdom,$cnum,$hostname) = @_; my ($residx,$supplementalflag,$title,$pathitem,$output,$js,$navmap); @@ -681,9 +790,20 @@ sub display_editor { my $path = &Apache::loncommon::symb_to_docspath($symb,\$navmap); $pathitem = ''; } - my %ltitools; + my (%ltitools,%tooltypes); if ($type eq 'tool') { - %ltitools = &Apache::lonnet::get_domain_lti($cdom,'consumer'); + my (%domtools,%crstools); + %tooltypes = &Apache::loncommon::usable_exttools(); + if ($tooltypes{'dom'}) { + %domtools = &Apache::lonnet::get_domain_lti($cdom,'consumer'); + } + if ($tooltypes{'crs'}) { + %crstools = &Apache::lonnet::get_course_lti($cnum,$cdom,'consumer'); + } + %ltitools = ( + dom => \%domtools, + crs => \%crstools, + ); } $js = &Apache::lonhtmlcommon::scripttag(&extedit_javascript()); my $args = { 'force_register' => $env{'form.register'} }; @@ -704,69 +824,112 @@ sub display_editor { sub extedit_javascript { my ($toolsref) = @_; - my $toolsjs; + my ($toolsjs,$exttoolnums,$exttooloptions); if (ref($toolsref) eq 'HASH') { - my $num = scalar(keys(%{$toolsref})); - $toolsjs = " var ltitools = new Array($num);\n". - " var ltitoolsUrl = new Array($num);\n". - " var ltitoolsTarget = new Array($num);\n". - " var ltitoolsWidth = new Array($num);\n". - " var ltitoolsHeight = new Array($num);\n". - " var ltitoolsLinkDef = new Array($num);\n". - " var ltitoolsExplainDef = new Array($num);\n". - " var ltitoolsDisplay = new Array($num);\n". - " var ltitoolsLink = new Array($num);\n". - " var ltitoolsExplain = new Array($num);\n". - " var ltitoolsLabel = new Array($num);\n". - " var ltitoolsTitle = new Array($num);\n". - " var ltitoolsAppend = new Array($num);\n"; - my $i = 0; - foreach my $key (sort { $a <=> $b } keys(%{$toolsref})) { - if (ref($toolsref->{$key}) eq 'HASH') { - if (ref($toolsref->{$key}->{'display'}) eq 'HASH') { - my $target = $toolsref->{$key}->{'display'}->{'target'}; - my $width = $toolsref->{$key}->{'display'}->{'width'}; - my $height = $toolsref->{$key}->{'display'}->{'height'}; - my $linkdef = $toolsref->{$key}->{'display'}->{'linktext'}; - my $explaindef = $toolsref->{$key}->{'display'}->{'explanation'}; - my $providerurl; - if ($toolsref->{$key}->{'url'} =~ m{://}) { - (my $prot,my $host,$providerurl) = ($toolsref->{$key}->{'url'} =~ m{^([^/]+)://([^/]+)(|/.+)$}); - } else { - $providerurl = $toolsref->{$key}->{'url'}; + $toolsjs = " var ltitools = new Array();\n". + " var ltitoolsUrl = new Array();\n". + " var ltitoolsTarget = new Array();\n". + " var ltitoolsWidth = new Array();\n". + " var ltitoolsHeight = new Array();\n". + " var ltitoolsLinkDef = new Array();\n". + " var ltitoolsExplainDef = new Array();\n". + " var ltitoolsDisplay = new Array();\n". + " var ltitoolsLink = new Array();\n". + " var ltitoolsExplain = new Array();\n". + " var ltitoolsLabel = new Array();\n". + " var ltitoolsTitle = new Array();\n". + " var ltitoolsAppend = new Array();\n"; + $exttoolnums = " var ltitoolsnum = new Array();\n". + " var tooloptval = new Array();\n". + " var toolopttxt = new Array();\n"; + my $idx = 0; + foreach my $type ('crs','dom') { + if (ref($toolsref->{$type}) eq 'HASH') { + my $num = scalar(keys(%{$toolsref->{$type}})); + $toolsjs .= " ltitools[$idx] = new Array($num);\n". + " ltitoolsUrl[$idx] = new Array($num);\n". + " ltitoolsTarget[$idx] = new Array($num);\n". + " ltitoolsWidth[$idx] = new Array($num);\n". + " ltitoolsHeight[$idx] = new Array($num);\n". + " ltitoolsLinkDef[$idx] = new Array($num);\n". + " ltitoolsExplainDef[$idx] = new Array($num);\n". + " ltitoolsDisplay[$idx] = new Array($num);\n". + " ltitoolsLink[$idx] = new Array($num);\n". + " ltitoolsExplain[$idx] = new Array($num);\n". + " ltitoolsLabel[$idx] = new Array($num);\n". + " ltitoolsTitle[$idx] = new Array($num);\n". + " ltitoolsAppend[$idx] = new Array($num);\n"; + my $i=0; + foreach my $key (sort { $a <=> $b } keys(%{$toolsref->{$type}})) { + if (ref($toolsref->{$type}->{$key}) eq 'HASH') { + if (ref($toolsref->{$type}->{$key}->{'display'}) eq 'HASH') { + my $target = $toolsref->{$type}->{$key}->{'display'}->{'target'}; + my $width = $toolsref->{$type}->{$key}->{'display'}->{'width'}; + my $height = $toolsref->{$type}->{$key}->{'display'}->{'height'}; + my $linkdef = $toolsref->{$type}->{$key}->{'display'}->{'linktext'}; + my $explaindef = $toolsref->{$type}->{$key}->{'display'}->{'explanation'}; + my $providerurl; + if ($toolsref->{$type}->{$key}->{'url'} =~ m{://}) { + (my $prot,my $host,$providerurl) = + ($toolsref->{$type}->{$key}->{'url'} =~ m{^([^/]+)://([^/]+)(|/.+)$}); + } else { + $providerurl = $toolsref->{$type}->{$key}->{'url'}; + } + $providerurl = &LONCAPA::map::qtunescape($providerurl); + $toolsjs .= " ltitools[$idx][$i] = '$key';\n". + " ltitoolsTarget[$idx][$i] = '$target';\n". + " ltitoolsWidth[$idx][$i] = '$width';\n". + " ltitoolsHeight[$idx][$i] = '$height';\n". + " ltitoolsLinkDef[$idx][$i] = '$linkdef';\n". + " ltitoolsExplainDef[$idx][$i] = '$explaindef';\n". + " ltitoolsUrl[$idx][$i] = '$providerurl';\n"; + } + if (ref($toolsref->{$type}->{$key}->{'crsconf'}) eq 'HASH') { + my $display = $toolsref->{$type}->{$key}->{'crsconf'}->{'target'}; + $toolsjs .= " ltitoolsDisplay[$idx][$i] = '$display';\n"; + my $linktext = $toolsref->{$type}->{$key}->{'crsconf'}->{'linktext'}; + $toolsjs .= " ltitoolsLink[$idx][$i] = '$linktext';\n"; + my $explanation = $toolsref->{$type}->{$key}->{'crsconf'}->{'explanation'}; + $toolsjs .= " ltitoolsExplain[$idx][$i] = '$explanation';\n"; + my $label = $toolsref->{$type}->{$key}->{'crsconf'}->{'label'}; + $toolsjs .= " ltitoolsLabel[$idx][$i] = '$label';\n"; + my $title = $toolsref->{$type}->{$key}->{'crsconf'}->{'title'}; + $toolsjs .= " ltitoolsTitle[$idx][$i] = '$title';\n"; + my $append = $toolsref->{$type}->{$key}->{'crsconf'}->{'append'}; + $toolsjs .= " ltitoolsAppend[$idx][$i] = '$append';\n"; + } } - $providerurl = &LONCAPA::map::qtunescape($providerurl); - $toolsjs .= ' ltitools['.$i.'] = '."'$key';\n". - ' ltitoolsTarget['.$i.'] = '."'$target';\n". - ' ltitoolsWidth['.$i.'] = '."'$width';\n". - ' ltitoolsHeight['.$i.'] = '."'$height';\n". - ' ltitoolsLinkDef['.$i.'] = '."'$linkdef';\n". - ' ltitoolsExplainDef['.$i.'] = '."'$explaindef';\n". - ' ltitoolsUrl['.$i.'] = '."'$providerurl';\n"; - } - if (ref($toolsref->{$key}->{'crsconf'}) eq 'HASH') { - my $display = $toolsref->{$key}->{'crsconf'}->{'target'}; - $toolsjs .= ' ltitoolsDisplay['.$i.'] = '."'$display';\n"; - my $linktext = $toolsref->{$key}->{'crsconf'}->{'linktext'}; - $toolsjs .= ' ltitoolsLink['.$i.'] = '."'$linktext';\n"; - my $explanation = $toolsref->{$key}->{'crsconf'}->{'explanation'}; - $toolsjs .= ' ltitoolsExplain['.$i.'] = '."'$explanation';\n"; - my $label = $toolsref->{$key}->{'crsconf'}->{'label'}; - $toolsjs .= ' ltitoolsLabel['.$i.'] = '."'$label';\n"; - my $title = $toolsref->{$key}->{'crsconf'}->{'title'}; - $toolsjs .= ' ltitoolsTitle['.$i.'] = '."'$title';\n"; - my $append = $toolsref->{$key}->{'crsconf'}->{'append'}; - $toolsjs .= ' ltitoolsAppend['.$i.'] = '."'$append';\n"; + $i++; } - - $i++; + my $firstoption = ''; + my ($idsref,$titlesref) = &ordered_tooloptions($toolsref->{$type}); + if ((ref($idsref) eq 'ARRAY') && (ref($titlesref) eq 'ARRAY')) { + my $count = scalar(@{$idsref}); + $exttooloptions .= " tooloptval[$idx] = new Array($count);\n". + " toolopttxt[$idx] = new Array($count);\n"; + for (my $n=0; $n<@{$idsref}; $n++) { + my $id = $idsref->[$n]; + my $text = $titlesref->[$n]; + $exttooloptions .= " tooloptval[$idx][$n] = '$id';\n". + " toolopttxt[$idx][$n] = '$text';\n"; + } + } + $exttoolnums .= " ltitoolsnum[$idx] = $i;\n"; } + $idx ++; } } my %js_lt = &Apache::lonlocal::texthash( invurl => 'Invalid URL', titbl => 'Title is blank', invtool => 'Please select an external tool', + mixfra => 'Show preview in pop-up? (http in https page + no framing)', + mixonly => 'Show preview in pop-up? (http in https page)', + fraonly => 'Show preview in pop-up? (framing disallowed)', + nopopup => 'Pop-up blocked', + nopriv => 'Insufficient privileges to use preview', + badurl => 'URL is not: http://hostname/path or https://hostname/path', + sele => 'Select', ); &js_escape(\%js_lt); @@ -805,17 +968,29 @@ function setExternal(extform,residx,type } else { title = escape(title); var info = exttoolurl; + var prefix = ''; + if (supplementalflag == 1) { + prefix = 'supp'; + } if (residx == 0) { var toolid = parseInt(extform.exttoolid.options[extform.exttoolid.selectedIndex].value); if (isNaN(toolid)) { alert("$js_lt{'invtool'}"); return; } - info += ':'+toolid; - } - var prefix = ''; - if (supplementalflag == 1) { - prefix = 'supp'; + var typeelem = extform.elements[prefix+'exttooltype']; + if (typeelem.length) { + for (var i=0; i 0) { labelinput += '_'+residx; titleinput += '_'+residx; - appendinput += '_'+residx; + appendinput += '_'+residx; } if (document.getElementById(labelinput)) { var crslabel = document.getElementById(labelinput).value; @@ -941,14 +1116,14 @@ function setExternal(extform,residx,type } function editext(residx,type) { - if (document.getElementById('upload'+type+residx)) { - var curr = document.getElementById('upload'+type+residx).style.display; + if (document.getElementById('external'+type+residx)) { + var curr = document.getElementById('external'+type+residx).style.display; if (curr == 'none') { disp = 'block'; } else { disp = 'none'; } - document.getElementById('upload'+type+residx).style.display=disp; + document.getElementById('external'+type+residx).style.display=disp; } resize_scrollbox('contentscroll','1','1'); return; @@ -959,17 +1134,147 @@ function extUrlPreview(caller,protocol) var url = document.getElementById(caller).value; if (regexp.test(url)) { var http_regex = /^http\:\/\//gi; + var mixed = 0; + var noiframe = 0; + var nopriv = 0; + var badurl = 0; + var name = "externalpreview"; if ((protocol == 'https') && (http_regex.test(url))) { - window.open(url,"externalpreview","height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1"); - } else { - openMyModal(url,500,400,'yes'); + mixed = 1; } + var http = new XMLHttpRequest(); + var lcurl = "/adm/exturlcheck"; + var params = "exturl="+url; + http.open("POST",lcurl, true); + http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + http.onreadystatechange = function() { + if (http.readyState == 4) { + if (http.status == 200) { + if (http.responseText.length > 0) { + if (http.responseText == 1) { + noiframe = 1; + } else if (http.responseText == -1) { + nopriv = 1; + } else if (http.responseText == 0) { + badurl = 1; + } + } + openPreviewWindow(url,name,noiframe,mixed,nopriv,badurl); + } + } + } + http.send(params); } else { alert("$js_lt{'invurl'}"); } } } +var previewLCWindow = null; +function openPreviewWindow(url,name,noiframe,mixed,nopriv,badurl) { + if (previewLCWindow !=null) { + previewLCWindow.close(); + } + if (badurl) { + alert("$js_lt{'badurl'}"); + } else if (nopriv) { + alert("$js_lt{'nopriv'}"); + } else if ((noiframe == 1) || (mixed == 1)) { + var encurl = encodeURI(url); + var msg; + if (mixed == 1) { + if (noiframe == 1) { + msg = "$js_lt{'mixfra'}"; + } else { + msg = "$js_lt{'mixonly'}"; + } + } else { + msg = "$js_lt{'fraonly'}"; + } + if (confirm(msg)) { + previewLCWindow = window.open(url,name,"height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1"); + if (previewLCWindow != null) { + previewLCWindow.focus(); + } else { + alert("$js_lt{'nopopup'}"); + } + } + } else { + openMyModal(url,500,400,'yes'); + } +} + +function updateExttoolSel(form,radioname,supplementalflag) { + var prefix = ''; + var typepick; + var radelem = form.elements[radioname]; + if (radelem.length) { + for (var i=0; i=0) { + for (i = numopts; i >= 0; i--) { + selelem.remove(i); + } + } + if (ltitoolsnum[typepick]) { + if ((Array.isArray(tooloptval[typepick])) && (Array.isArray(toolopttxt[typepick]))) { + var len = tooloptval[typepick].length; + if (len) { + selelem.options[selelem.options.length] = new Option('$js_lt{sele}','',1,1); + var j; + for (j=0; j 0) { - for (var j=0; j 0) { + for (var j=0; j'; + if (document.getElementById(appenddiv)) { + if (ltitoolsAppend[i][j]) { + document.getElementById(appenddiv).style.display = 'inline'; + if (document.getElementById(providerurl)) { + if ((ltitoolsUrl[i][j] != '') && (ltitoolsUrl[i][j] != null)) { + document.getElementById(providerurl).innerHTML = ' ('+ltitoolsUrl[i][j]+')
'; + } + } + } else { + document.getElementById(appenddiv).style.display = 'none'; + if (document.getElementById(providerurl)) { + document.getElementById(providerurl).innerHTML = ''; } - } - } else { - document.getElementById(appenddiv).style.display = 'none'; - if (document.getElementById(providerurl)) { - document.getElementById(providerurl).innerHTML = ''; } } - } - if (document.getElementById(gradablediv)) { - if (supplementalflag != 1) { - document.getElementById(gradablediv).style.display = 'inline'; + if (document.getElementById(gradablediv)) { + if (supplementalflag != 1) { + document.getElementById(gradablediv).style.display = 'inline'; + } } + break; } - break; } } }