--- loncom/interface/lonextresedit.pm	2019/07/28 04:10:31	1.8.2.3
+++ loncom/interface/lonextresedit.pm	2016/11/29 03:01:04	1.12
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Documents
 #
-# $Id: lonextresedit.pm,v 1.8.2.3 2019/07/28 04:10:31 raeburn Exp $
+# $Id: lonextresedit.pm,v 1.12 2016/11/29 03:01:04 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -56,15 +56,19 @@ sub handler {
     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
     my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
-    my ($supplementalflag,$updated,$output,$errormsg,$residx,$url,$title,$symb);
+    my ($supplementalflag,$updated,$output,$errormsg,$residx,$url,$title,
+        $symb,$type);
     if (($env{'form.folderpath'} =~ /^supplemental/) && ($env{'form.suppurl'})) {
         $supplementalflag = 1;
+        if (&unescape($env{'form.suppurl'}) =~ m{^/adm/$cdom/$cnum/\d+/exttools?$}) {
+            $type = 'tool';
+        }
     }
     if (($supplementalflag) || ($env{'form.symb'} =~ /^uploaded/)) {
         ($updated,$output,$errormsg,$residx,$url,$title,$symb) =
             &process_changes($supplementalflag,$cdom,$cnum,$chome);
         if ($supplementalflag) {
-            if ($url ne $env{'form.suppurl'}) {
+            if ($url ne &unescape($env{'form.suppurl'})) {
                  $env{'form.suppurl'} = $url;
             }
             if ($title ne $env{'form.title'}) {
@@ -75,33 +79,48 @@ sub handler {
             if ($symb ne $env{'form.symb'}) {
                 $env{'form.symb'} = $symb;
             }
+            if ($url =~ m{/adm/$cdom/$cnum/\d+/exttools?$}) {
+                $type = 'tool';
+            }
         }
     } else {
         $errormsg = &mt('Information about external resource to edit is missing.');
     }
     if ($updated) {
-        $output = &Apache::lonhtmlcommon::confirm_success(&mt('External Resource updated'));
+        my $msg = &mt('External Resource updated');
+        if ($type eq 'tool') {
+            $msg = &mt('External Tool updated');
+        }
+        $output = &Apache::lonhtmlcommon::confirm_success($msg);
     }
     if ($errormsg) {
         $errormsg = '<p class="LC_error">'.$errormsg.'</p>';
     }
+    my %ltitools;
+    if ($type eq 'tool') {
+        %ltitools = &Apache::lonnet::get_domain_ltitools($cdom);
+    }
     my $js = &Apache::lonhtmlcommon::scripttag(&extedit_javascript());
     my $pathitem = '<input type="hidden" name="folderpath" value="'.
                    &HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" />';
-    $r->print(&Apache::loncommon::start_page('External Resource Editor',$js).
+    my $description = 'External Resource Editor';
+    if ($type eq 'tool') {
+        $description = 'External Tool Editor'; 
+    }
+    $r->print(&Apache::loncommon::start_page($description,$js).
               '<div class="LC_left_float">'.
               $output.
               $errormsg.
               &extedit_form($supplementalflag,$residx,$url,$title,$pathitem,undef,
-                           'direct',$env{'form.symb'}).
+                           'direct',$env{'form.symb'},$type,$cdom,$cnum,\%ltitools).
               '</div>'.&Apache::loncommon::end_page());
     return OK;
 }
 
 sub process_changes {
     my ($supplementalflag,$cdom,$cnum,$chome) = @_;
-    my ($folder,$container,$output,$errormsg,$updated,$symb,$oldidx,$oldurl,
-        $oldtitle,$newidx,$newurl,$newtitle,$residx,$url,$title);
+    my ($folder,$container,$output,$errormsg,$updated,$symb,$oldidx,$oldurl,$type,
+        $oldtitle,$newidx,$newurl,$newtitle,$residx,$url,$title,$marker,$args);
     if ($env{'form.symb'}) {
         $symb = $env{'form.symb'};
         (my $map,$oldidx,$oldurl)=&Apache::lonnet::decode_symb($symb);
@@ -110,19 +129,27 @@ sub process_changes {
             $container = $3;
         }
         $oldtitle = &Apache::lonnet::gettitle($env{'form.symb'});
+        if ($oldurl =~ m{^ext/(.+)$}) {
+            my $external = $1;
+            if ($external =~ m{^https://}) {
+                $oldurl = $external;
+            } else {
+                $oldurl = 'http://'.$oldurl;
+            }
+            $type = 'ext';
+        } else {
+            $type = 'tool';
+        }
     } elsif ($env{'form.folderpath'}) {
         $folder = &unescape( (split('&',$env{'form.folderpath'}))[-2] );
         $oldurl = &unescape($env{'form.suppurl'});
         $oldtitle = &unescape($env{'form.title'});
         $container = 'sequence';
         $supplementalflag = 1;
-    }
-    if ($oldurl =~ m{^ext/(.+)$}) {
-        my $external = $1; 
-        if ($external =~ m{^https://}) {
-            $oldurl = $external;
+        if ($oldurl =~ m{^/adm/$cdom/$cnum/\d+/exttools?$}) {
+            $type = 'tool';
         } else {
-            $oldurl = 'http://'.$oldurl;
+            $type = 'ext';
         }
     }
     $url = $oldurl;
@@ -130,6 +157,11 @@ sub process_changes {
     if ($env{'form.importdetail'}) {
         ($newtitle,$newurl,$newidx) =
             map {&unescape($_)} split(/\=/,$env{'form.importdetail'});
+        if ($newurl =~ m{^(/adm/$cdom/$cnum/(\d+)/exttools?)\:?(.*)$}) {
+            $newurl = $1;
+            $marker = $2;
+            $args = $3;
+        }
     }
     if ($supplementalflag) {
         $residx = $newidx;
@@ -147,7 +179,18 @@ sub process_changes {
             if ($mismatchedid) {
                 $errormsg = 'Wrong item identifier';
             } elsif (($newtitle eq $oldtitle) && ($newurl eq $oldurl)) {
-                $output = &mt('No change');
+                if ($type eq 'tool') {
+                    if ($args) {
+                        ($updated,$errormsg) = &update_exttool($marker,$cdom,$cnum,$args);
+                        unless ($updated) {
+                            $output = &mt('No change');      
+                        }
+                    } else {
+                        $output = &mt('No change');
+                    }
+                } else {
+                    $output = &mt('No change');
+                }
             } else {
                 my $map = "/uploaded/$cdom/$cnum/$folder.$container";
                 my ($errtext,$fatal) = &LONCAPA::map::mapread($map);
@@ -156,8 +199,15 @@ sub process_changes {
                 } else {
                     my $saveurl = &LONCAPA::map::qtunescape($newurl);
                     my $savetitle = &LONCAPA::map::qtunescape($newtitle);
+                    my $ext = 'true';
+                    if ($type eq 'tool') {
+                        if ($args) {
+                            ($updated,$errormsg) = &update_exttool($marker,$cdom,$cnum,$args);
+                        }
+                        $ext = 'false';
+                    }
                     $LONCAPA::map::resources[$residx] =
-                        join(':', ($savetitle,$saveurl,'true','normal','res'));
+                        join(':', ($savetitle,$saveurl,$ext,'normal','res'));
                     my ($outtext,$errtext) = &LONCAPA::map::storemap($map,1);
                     if ($errtext) {
                         $errormsg = &mt('Update failed: [_1].',$errtext);
@@ -166,8 +216,10 @@ sub process_changes {
                         $title = $newtitle;
                         if ($newurl ne $oldurl) {
                             $url = $newurl;
-                            $newurl =~ s{^http://}{};
-                            $newurl = "ext/$newurl";
+                            if ($ext eq 'true') {
+                                $newurl =~ s{^http://}{};
+                                $newurl = "ext/$newurl";
+                            }
                         }
                         if (!$supplementalflag) {
                             if ($newurl ne $oldurl) {
@@ -195,46 +247,116 @@ sub process_changes {
             $output = &mt('No change');
         }
     } else {
-        $errormsg = &mt('Information about current external resource is incomplete.');
+        if ($type eq 'tool') {
+            $errormsg = &mt('Information about current external tool is incomplete.');
+        } else {
+            $errormsg = &mt('Information about current external resource is incomplete.');
+        }
     }
     return ($updated,$output,$errormsg,$residx,$url,$title,$symb);
 }
 
+sub update_exttool {
+    my ($marker,$cdom,$cnum,$args) = @_;
+    my %toolhash=&Apache::lonnet::dump('exttool_'.$marker,$cdom,$cnum);
+    my (%newhash,$changed,@deleted,$errormsg);
+    ($newhash{'target'},$newhash{'width'},$newhash{'height'},$newhash{'crslabel'},$newhash{'crstitle'}) = split(/:/,$args);
+    $newhash{'crslabel'} = &unescape($newhash{'crslabel'});
+    $newhash{'crstitle'} = &unescape($newhash{'crstitle'});
+    my %toolhash=&Apache::lonnet::dump('exttool_'.$marker,$cdom,$cnum);
+    foreach my $item ('target','width','height','crslabel','crstitle') {
+        $newhash{$item} =~ s/^\s+//;
+        $newhash{$item} =~ s/\s+$//;
+        if (($item eq 'width') || ($item eq 'height')) {
+            if ($newhash{'target'} eq 'iframe') {
+                $newhash{$item} = '';
+            }
+        }
+        if ($toolhash{$item} ne $newhash{$item}) {
+            if ($newhash{$item} eq '') {
+                unless (($item eq 'target') ||
+                        ((($item eq 'width') || ($item eq 'height')) &&
+                         (($newhash{'target'} eq 'window') || 
+                          (($newhash{'target'} eq '') && ($toolhash{'target'} eq 'window'))))) {
+                    delete($toolhash{$item});
+                    push(@deleted,$item);
+                    $changed = 1;
+                }
+            } else {
+                $toolhash{$item} = $newhash{$item};
+                $changed = 1; 
+            }
+        }
+    }
+    if ($changed) {
+        my $putres = &Apache::lonnet::put('exttool_'.$marker,\%toolhash,$cdom,$cnum);
+        unless ($putres eq 'ok') {
+            $errormsg = &mt('Failed to save updated settings.').' '.&mt('Error: [_1].',$putres);
+        }
+    }
+    if (@deleted) {
+        &Apache::lonnet::del('exttool_'.$marker,\@deleted,$cdom,$cnum);
+    }
+    return ($changed,$errormsg);
+}
+
 sub extedit_form {
-    my ($supplementalflag,$residx,$orig_url,$orig_title,$pathitem,$helpitem,$caller,$symb,$disabled) = @_;
+    my ($supplementalflag,$residx,$orig_url,$orig_title,$pathitem,$helpitem,$caller,
+        $symb,$type,$cdom,$cnum,$ltitools,$disabled) = @_;
+    if ($type ne 'tool') {
+        $type = 'ext';
+    }
     my %lt = &Apache::lonlocal::texthash(
         ex => 'External Resource',
+        et => 'External Tool',
         ed => 'Edit',
         ee => 'External Resource Editor',
+        te => 'External Tool Editor',
         pr => 'Preview',
         sv => 'Save',
         ul => 'URL',
         ti => 'Title',
         al => 'Add Link',
+        at => 'Add Tool',
     );
-    my $formname = 'newext';
     my $tabid = 'aa';
-    my $toggle = 'ext';
-    my $fieldsetid = 'uploadextform';
-    my $urlid = 'exturl';
     my $size = 60;
     if ($supplementalflag) {
-        $formname = 'newsuppext';
         $tabid = 'ee';
-        $toggle = 'suppext';
-        $fieldsetid = 'uploadsuppextform';
-        $urlid = 'suppexturl';
     }
-    my ($link,$legend,$active,$srcclass,$extsrc,$preview,$title,$save,
-        $fieldsetstyle,$action,$hiddenelem,$form);
+    my ($formname,$formid,$toggle,$fieldsetid,$urlid,$dispdivstyle,$dimendivstyle,
+        $labelstyle,$titlestyle,$legend,$urlelem,$toolelem,%toolattr);
+    $formname = 'new'.$type;
+    $toggle = $type;
+    $fieldsetid = 'upload'.$type.'form';
+    $urlid = $type.'url';
+    map { $toolattr{$_} = $type.$_; } ('dispdiv','dimendiv','dimenwidth','dimenheight',
+                                       'crstitlediv','crslabeldiv','crstitle','crslabel');
+    $dispdivstyle = 'display:none';
+    $dimendivstyle = 'display:none';
+    $labelstyle = 'display:none';
+    $titlestyle = 'display:none';
+    if ($supplementalflag) {
+        $formname = 'newsupp'.$type;
+        $toggle = 'supp'.$type;
+        $fieldsetid = 'uploadsupp'.$type.'form';
+        $urlid = 'supp'.$type.'url';
+        map { $toolattr{$_} = 'supp'.$toolattr{$_}; } (keys(%toolattr));
+    }
+    my ($link,$legend,$active,$srcclass,$extsrc,$preview,$title,$save,$crstitle,$crslabel,
+        $fieldsetstyle,$action,$hiddenelem,$form,$width,$height,$tooltarget,%chkstate);
     $fieldsetstyle = 'display: none;';
     $action = '/adm/coursedocs';
-    my $protocol = ($ENV{'SERVER_PORT'} == 443?'https':'http');
     if ($residx) {
         if ($caller eq 'direct') {
             $fieldsetstyle = 'display: block;';
             $action = '/adm/extresedit';
-            $legend = "<legend>$lt{'ee'}</legend>";
+            if ($type eq 'tool') {
+                $legend = $lt{'ee'};
+            } else {
+                $legend = $lt{'te'};
+            }
+            $legend = '<legend>'.$legend.'</legend>';
             if ($symb) {
                 $hiddenelem = '<input type="hidden" name="symb" value="'.$symb.'" />';
             } elsif ($supplementalflag) {
@@ -243,50 +365,172 @@ sub extedit_form {
                               '<input type="hidden" name="title" value="'.
                               &HTML::Entities::encode(&escape($orig_title),'<>&"').'" />';
             }
-        } else {        
-            $link = '<a class="LC_docs_ext_edit" href="javascript:editext('."'$residx'".');">'.$lt{'ed'}.'</a>&nbsp;'."\n";
+        } else {
+            $link = '<a class="LC_docs_ext_edit" href="javascript:editext('."'$residx','$type'".');">'.$lt{'ed'}.'</a>&nbsp;'."\n";
             $size = 40;
             $active = '<input type="hidden" name="active" value="'.$tabid.'" />';
         }
-        $formname = "editext_$residx";
-        $fieldsetid = "uploadext$residx";
-        $urlid = "exturl_$residx";
+        $formname = 'edit'.$type.'_'.$residx;
+        $fieldsetid = 'upload'.$type.$residx;
+        $urlid = $type.'url_'.$residx;
+        map { $toolattr{$_} .= '_'.$residx; } (keys(%toolattr));
         $srcclass = ' class="LC_nobreak"';
-        $extsrc = '<span class="LC_docs_ext_edit">'.$lt{'ul'}.'&nbsp;</span>';
-        $preview = '&nbsp;<a class="LC_docs_ext_edit" href="javascript:extUrlPreview('."'$urlid','$protocol'".');">'.$lt{'pr'}.'</a>';
+        if ($type eq 'ext') {
+            $extsrc = '<span class="LC_docs_ext_edit">'.$lt{'ul'}.'&nbsp;</span>';
+            $preview = '&nbsp;<a class="LC_docs_ext_edit" href="javascript:extUrlPreview('."'$urlid'".');">'.$lt{'pr'}.'</a>';
+        }
         $title = '<span class="LC_docs_ext_edit">'.$lt{'ti'}.'&nbsp;</span>';
         $save = $lt{'sv'};
     } else {
-        $link = '<a class="LC_menubuttons_link" href="javascript:toggleUpload('."'$toggle'".');">'.$lt{'ex'}.'</a>'.$helpitem;
-        $legend = "<legend>$lt{'ex'}</legend>";
-        $extsrc = $lt{'ul'}.':<br />';
+        $link = $lt{'ex'};
+        if ($type eq 'tool') {
+            $link = $lt{'et'};
+        }
+        $link = '<a class="LC_menubuttons_link" href="javascript:toggleUpload('."'$toggle'".');">'.$link.'</a>'.$helpitem;
+        if ($type eq 'tool') {
+            $legend = $lt{'te'};
+        } else {
+            $legend = $lt{'ee'};
+        }
+        $legend = '<legend>'.$legend.'</legend>';
         $title = $lt{'ti'}.':<br />';
         $residx = 0;
-        $orig_url = 'http://';
-        $orig_title = $lt{'ex'};
-        $preview = '<input type="button" name="view" value="'.$lt{'pr'}.'" onclick="javascript:extUrlPreview('."'$urlid','$protocol'".');"'.$disabled.' />';
-        $save = $lt{'al'};
+        if ($type eq 'ext') {
+            $orig_url = 'http://';
+            $orig_title = $lt{'ex'};
+            $extsrc = $lt{'ul'}.':<br />';
+            $preview = '<input type="button" name="view" value="'.$lt{'pr'}.'" onclick="javascript:extUrlPreview('."'$urlid'".');"'.$disabled.' />';
+            $save = $lt{'al'};
+        } else {
+            $orig_title = $lt{'et'};
+            $save = $lt{'at'};
+            $orig_url = "/adm/$cdom/$cnum/new/exttool"; 
+        }
         $pathitem .= '<br />';
     }
+    $formid = $formname;
+    if ($type eq 'ext') {
+        $urlelem = '<input type="text" size="'.$size.'" name="exturl" id="'.$urlid.'" value="'.$orig_url.'"'.$disabled.' />';
+    } else {
+        my $class = 'LC_nobreak';
+        if ($residx) {
+            $class = 'LC_docs_ext_edit LC_nobreak'; 
+            if ($orig_url =~ m{^/adm/$cdom/$cnum/(\d+)/exttools?$}) {
+                my $marker = $1;
+                my %toolhash=&Apache::lonnet::dump('exttool_'.$marker,$cdom,$cnum);
+                if ($toolhash{'id'}) {
+                    if (ref($ltitools) eq 'HASH') {
+                        if (keys(%{$ltitools})) {
+                            if (ref($ltitools->{$toolhash{'id'}}) eq 'HASH') {
+                                my $tooltitle = $ltitools->{$toolhash{'id'}}->{'title'};
+                                my $icon = $ltitools->{$toolhash{'id'}}->{'image'};
+                                my $image;
+                                if ($icon) {
+                                    $image = '<img src="'.$icon.'" alt="'.$tooltitle.'" />';
+                                }
+                                $tooltarget = $toolhash{'target'};
+                                if ($tooltarget eq 'window') {
+                                    $dimendivstyle = 'display:block';
+                                    $chkstate{'window'} = 'checked="checked" ';
+                                } else {
+                                    $chkstate{'iframe'} = 'checked="checked" ';
+                                }
+                                $width = $toolhash{'width'};
+                                $height = $toolhash{'height'};
+                                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'}->{'target'}) {
+                                        $dispdivstyle = 'display:block';
+                                    }
+                                }
+                                $toolelem = '<span class="LC_nobreak">'.$image.'&nbsp;'.$tooltitle.'</span><br />';
+                            }
+                        }
+                    }
+                }
+            }
+        } else {
+            $toolelem = '<span class="LC_docs_ext_edit">'."\n".
+                       '<select name="exttoolid" id="LC_exttoolid" onchange="javascript:updateExttool(this,'.
+                       'this.form,'."'$supplementalflag'".');"'.$disabled.'>'."\n".
+                       '<option value="" selected="selected">'.&mt('Select').'</option>';
+            my %bynum;
+            if (ref($ltitools) eq 'HASH') {
+                foreach my $id (keys(%{$ltitools})) {
+                    if (ref($ltitools->{$id}) eq 'HASH') {
+                        my $order = $ltitools->{$id}->{'order'};
+                        $bynum{$order} = [$id,$ltitools->{$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'};
+                        my $icon =  $bynum{$item}->[1]->{'image'};
+                        $toolelem .= '<option value="'.$bynum{$item}->[0].'">'.$tooltitle.'</option>';
+                    }
+                }
+            }
+            $toolelem .= '</select></span><br />';
+            $crslabel = $env{'course.'.$cdom.'_'.$cnum.'.internal.coursecode'};
+            $crstitle = $env{'course.'.$cdom.'_'.$cnum.'.description'};
+        }
+        $toolelem .= '<div id="'.$toolattr{'dispdiv'}.'" style="'.$dispdivstyle.'">'.
+                    '<span class="'.$class.'">'.&mt('Display target:').'&nbsp;'.
+                    '<label><input type="radio" name="exttooltarget" value="iframe" '.$chkstate{'iframe'}.'onclick="updateTooldim(this.form,'.
+                    "'$toolattr{dimendiv}','$toolattr{dimenwidth}','$toolattr{dimenheight}'".');"'.$disabled.'>'.&mt('iframe').'</label>'.('&nbsp;'x2).
+                    '<label><input type="radio" name="exttooltarget" value="window" '.$chkstate{'window'}.'onclick="updateTooldim(this.form,'.
+                    "'$toolattr{dimendiv}','$toolattr{dimenwidth}','$toolattr{dimenheight}'".');"'.$disabled.'>'.&mt('window').'</label>'.
+                    '</span><div id="'.$toolattr{'dimendiv'}.'" style="'.$dimendivstyle.'">'. 
+                    '<span class="'.$class.'">'.
+                    &mt('Width').'<input type="text" id="'.$toolattr{'dimenwidth'}.'" name="exttoolwidth" value="'.$width.'"'.$disabled.'>'.('&nbsp;'x2).
+                    &mt('Height').'<input type="text" id="'.$toolattr{'dimenheight'}.'" name="exttoolheight" value="'.$height.'"'.$disabled.'></span>'."\n".
+                    '</div></div>'.
+                    '<div id="'.$toolattr{'crslabeldiv'}.'" style="'.$labelstyle.'">'.
+                    '<span class="'.$class.'">'.&mt('Course label:').'&nbsp;'.
+                    '<input type="text" id="'.$toolattr{'crslabel'}.'" name="exttoollabel" value="'.$crslabel.'"'.$disabled.'><br />'.
+                    '</div>'.
+                    '<div id="'.$toolattr{'crstitlediv'}.'" style="'.$titlestyle.'">'.
+                    '<span class="'.$class.'">'.&mt('Course title:').'&nbsp;'.
+                    '<input type="text" id="'.$toolattr{'crstitle'}.'" name="exttooltitle" value="'.$crstitle.'"'.$disabled.'><br />'.
+                    '</div>';
+    }
+    my $chooser = $toolelem;
+    if ($type eq 'ext') {
+        $chooser = "
+<div>
+<span$srcclass>
+$extsrc
+$urlelem
+$preview
+</span>
+</div>
+";
+    }
     $form = <<ENDFORM;
-<form action="$action" method="post" name="$formname">
+<form action="$action" method="post" name="$formname" id="$formid">
 <fieldset id="$fieldsetid" style="$fieldsetstyle">
 $legend
 $active
-<span$srcclass>
-$extsrc
-<input type="text" size="$size" name="exturl" id="$urlid" value="$orig_url" $disabled />
-$preview
-</span> 
-<br />
+$chooser
+<div>
 <span$srcclass>
 $title
 <input type="text" size="$size" name="exttitle" value="$orig_title" $disabled />
 <input type="hidden" name="importdetail" value="" />
 $pathitem
 $hiddenelem
-<input type="button" value="$save" onclick="javascript:setExternal(this.form,'$residx');" $disabled />
+<input type="button" value="$save" onclick="javascript:setExternal(this.form,'$residx','$type','$orig_url','$supplementalflag');"'.$disabled.' />
 </span>
+</div>
 </fieldset>
 </form>
 ENDFORM
@@ -298,7 +542,7 @@ ENDFORM
 }
 
 sub display_editor {
-    my ($url,$folderpath,$symb,$idx,$type,$cdom,$cnum,$hostname) = @_;
+    my ($url,$folderpath,$symb,$idx,$type,$cdom,$cnum) = @_;
     my ($residx,$supplementalflag,$title,$pathitem,$output,$js,$navmap);
     if ($folderpath =~ /^supplemental/) {
         $supplementalflag = 1;
@@ -312,22 +556,63 @@ sub display_editor {
         my $path = &Apache::loncommon::symb_to_docspath($symb,\$navmap);
         $pathitem = '<input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($path,'<>&"').'" />';
     }
+    my %ltitools;
+    if ($type eq 'tool') {
+        %ltitools = &Apache::lonnet::get_domain_ltitools($cdom);
+    }
     $js = &Apache::lonhtmlcommon::scripttag(&extedit_javascript());
     my $args = { 'force_register' => $env{'form.register'} };
-    if ($hostname) {
-        $args->{'hostname'} = $hostname;
+    my $description = 'External Resource Editor';
+    if ($type eq 'tool') {
+        $description = 'External Tool Editor';
     }
-    return &Apache::loncommon::start_page('External Resource Editor',$js,$args).
+    return &Apache::loncommon::start_page($description,$js,$args).
            '<div class="LC_left_float">'.
-           &extedit_form($supplementalflag,$residx,$url,$title,$pathitem,undef,'direct',$symb).
+           &extedit_form($supplementalflag,$residx,$url,$title,$pathitem,undef,'direct',
+                         $symb,$type,$cdom,$cnum,\%ltitools).
            '</div>'.
            &Apache::loncommon::end_page();
 }
 
 sub extedit_javascript {
+    my ($toolsref) = @_;
+    my $toolsjs;
+    if (ref($toolsref) eq 'HASH') {
+        my $num = scalar(keys(%{$toolsref}));
+        $toolsjs = "        var ltitools = new Array($num);\n".
+                   "        var ltitoolsTarget = new Array($num);\n".
+                   "        var ltitoolsWidth = new Array($num);\n".
+                   "        var ltitoolsHeight = new Array($num);\n".
+                   "        var ltitoolsDisplay = new Array($num);\n".
+                   "        var ltitoolsLabel = new Array($num);\n".
+                   "        var ltitoolsTitle = new Array($num);\n";
+        my $i = 0;
+        foreach my $key (sort { $a <=> $b } keys(%{$toolsref})) {
+            if (ref($toolsref->{$key})) {
+                my $target = $toolsref->{$key}->{'target'};
+                my $width = $toolsref->{$key}->{'width'};
+                my $height = $toolsref->{$key}->{'height'};
+                $toolsjs .= '        ltitools['.$i.'] = '."'$key';\n".
+                            '        ltitoolsTarget['.$i.'] = '."'$target';\n".
+                            '        ltitoolsWidth['.$i.'] = '."'$width';\n".
+                            '        ltitoolsHeight['.$i.'] = '."'$height';\n";
+                my %courseconfig;
+                if (ref($toolsref->{$key}->{'crsconf'}) eq 'HASH') {
+                    my $display = $toolsref->{$key}->{'crsconf'}->{'target'};
+                    $toolsjs .= '         ltitoolsDisplay['.$i.'] = '."'$display';\n";
+                    my $label = $toolsref->{$key}->{'crsconf'}->{'label'};
+                    $toolsjs .= '         ltitoolsLabel['.$i.'] = '."'$label';\n";
+                    my $title = $toolsref->{$key}->{'crsconf'}->{'title'};
+                    $toolsjs .= '         ltitoolsTitle['.$i.'] = '."'$title';\n";
+                }
+                $i++;
+            }
+        }
+    }
     my %js_lt = &Apache::lonlocal::texthash(
         invurl  => 'Invalid URL',
         titbl   => 'Title is blank',
+        invtool => 'Please select an external tool',
     );
     &js_escape(\%js_lt);
 
@@ -339,60 +624,235 @@ ENDREGEXP
 
 var regexp = $urlregexp;
 
-function setExternal(extform,residx) {
+function setExternal(extform,residx,type,exttoolurl,supplementalflag) {
     var title=extform.exttitle.value;
     if (!String.trim) {
         String.prototype.trim = function() {return this.replace(\/^\\s+|\\s+$\/g, "");};    }
-    var url=extform.exturl.value;
     if (title == null || title.trim()=="") {
         alert("$js_lt{'titbl'}");
         extform.exttitle.focus();
         return;
     }
-    if (regexp.test(url)) {
-        url = escape(url);
+    if (type == 'ext') {
+        var url=extform.exturl.value;
+        if (!regexp.test(url)) {
+            alert("$js_lt{'invurl'}");
+            extform.exturl.focus();
+            return;
+        } else {
+            url = escape(url);
+            title = escape(title);
+            if (residx > 0) {
+               eval("extform.importdetail.value=title+'='+url+'='+residx;extform.submit();");
+            } else {
+               eval("extform.importdetail.value=title+'='+url;extform.submit();");
+            }
+        }
+    } else {
         title = escape(title);
+        var info = exttoolurl;
+        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 dispdiv = prefix+'tooldispdiv';
         if (residx > 0) {
-            eval("extform.importdetail.value=title+'='+url+'='+residx;extform.submit();");
+            dispdiv += '_'+residx;
+        }
+        if (document.getElementById(dispdiv)) {
+            if (document.getElementById(dispdiv).style.display == 'block') {
+                if (extform.exttooltarget.length) {
+                    for (var i=0; i<extform.exttooltarget.length; i++) {
+                        if (extform.exttooltarget[i].checked) {
+                            if (extform.exttooltarget[i].value == 'window') {
+                                var width = extform.exttoolwidth.value;
+                                width.trim();
+                                var height = extform.exttoolheight.value;
+                                height.trim();
+                                info += ':window:'+width+':'+height;  
+                            } else {
+                                info += ':iframe::';
+                            }
+                        }
+                    }
+                }
+            } else {
+                info += ':::';
+            }
         } else {
-            eval("extform.importdetail.value=title+'='+url;extform.submit();");
+            info += ':::';
+        }
+        var labelinput = prefix+'toolcrslabel';
+        var titleinput = prefix+'toolcrstitle';
+        if (residx > 0) {
+            labelinput += '_'+residx;
+            titleinput += '_'+residx;
+        }
+        if (document.getElementById(labelinput)) {
+            var crslabel = document.getElementById(labelinput).value;
+            crslabel.trim();
+            info += ':'+escape(crslabel);
+        } else {
+            info += ':';
+        } 
+        if (document.getElementById(titleinput)) {
+            var crstitle = document.getElementById(titleinput).value;
+            crstitle.trim();
+            info += ':'+escape(crstitle);
+        } else {
+            info += ':';
+        }
+        info=escape(info);
+        if (residx > 0) {
+            eval("extform.importdetail.value=title+'='+info+'='+residx;extform.submit();");
+        } else {
+            eval("extform.importdetail.value=title+'='+info;extform.submit();");
         }
-    } else {
-        alert("$js_lt{'invurl'}");
-        extform.exturl.focus();
-        return;
     }
 }
 
-function editext(residx) {
-    if (document.getElementById('uploadext'+residx)) {
-        var curr = document.getElementById('uploadext'+residx).style.display;
+function editext(residx,type) {
+    if (document.getElementById('upload'+type+residx)) {
+        var curr = document.getElementById('upload'+type+residx).style.display;
         if (curr == 'none') {
             disp = 'block';
         } else {
             disp = 'none';
         }
-        document.getElementById('uploadext'+residx).style.display=disp;
+        document.getElementById('upload'+type+residx).style.display=disp;
     }
     resize_scrollbox('contentscroll','1','1');
     return;
 }
 
-function extUrlPreview(caller,protocol) {
+function extUrlPreview(caller) {
     if (document.getElementById(caller)) {
         var url = document.getElementById(caller).value;
         if (regexp.test(url)) {
-            var http_regex = /^http\:\/\//gi;
-            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');
-            }
+            openMyModal(url,500,400,'yes');
         } else {
             alert("$js_lt{'invurl'}");
         }
     }
 }
+
+function updateExttool(caller,form,supplementalflag) {
+    var prefix = '';
+    if (supplementalflag == 1) {
+        prefix = 'supp';
+    }
+    dispdiv = prefix+'tooldispdiv';
+    dimendiv = prefix+'tooldimendiv';
+    widthinput = prefix+'toolwidth';
+    heightinput = prefix+'toolheight';
+    labeldiv = prefix+'toolcrslabeldiv';
+    titlediv = prefix+'toolcrstitlediv';
+    labelinput = prefix+'toolcrslabel';
+    titleinput = prefix+'toolcrstitle';
+    if (document.getElementById(dispdiv)) {
+        var toolpick = caller.options[caller.selectedIndex].value;
+        $toolsjs
+        if (toolpick == '') {
+            if (document.getElementById(dispdiv)) {
+                document.getElementById(dispdiv).style.display = 'none';    
+            }
+            if (document.getElementById(dimendiv)) {
+                document.getElementById(dimendiv).style.display = 'none';
+            }
+            if (document.getElementById(labeldiv)) {
+                document.getElementById(labeldiv).style.display = 'none';
+            }
+            if (document.getElementById(titlediv)) {
+                document.getElementById(titlediv).style.display = 'none';
+            }
+        } else {
+            if (ltitools.length > 0) {
+                for (var j=0; j<ltitools.length; j++) {
+                    if (ltitools[j] == toolpick) {
+                        if (document.getElementById(dispdiv)) {
+                            if (ltitoolsDisplay[j]) {
+                                document.getElementById(dispdiv).style.display = 'block';
+                                if (form.exttooltarget.length) {
+                                    for (var k=0; k<form.exttooltarget.length; k++) {
+                                        if (form.exttooltarget[k].value == ltitoolsTarget[j]) {
+                                            form.exttooltarget[k].checked = true;
+                                            break;
+                                        }
+                                    }
+                                }
+                                if (ltitoolsTarget[j] == 'window') {
+                                    dimen = 'block';
+                                    dimenwidth = ltitoolsWidth[j];
+                                    dimenheight = ltitoolsHeight[j];                    
+                                } else {
+                                    dimen = 'none';
+                                    dimenwidth = '';
+                                    dimenheight = '';
+                                }
+                                if (document.getElementById(dimendiv)) {
+                                    document.getElementById(dimendiv).style.display = dimen;
+                                }
+                                if (document.getElementById(widthinput)) {
+                                    document.getElementById(widthinput).value = dimenwidth;
+                                }
+                                if (document.getElementById(heightinput)) {
+                                    document.getElementById(heightinput).value = dimenheight;
+                                }
+                            }
+                        }
+                        if (document.getElementById(labeldiv)) {
+                            if (ltitoolsLabel[j]) {
+                                document.getElementById(labeldiv).style.display = 'inline';
+                            } else {
+                                document.getElementById(labeldiv).style.display = 'none';
+                            } 
+                        }
+                        if (document.getElementById(titlediv)) {
+                            if (ltitoolsTitle[j]) {
+                                document.getElementById(titlediv).style.display = 'inline';
+                            } else {
+                                document.getElementById(titlediv).style.display = 'none';
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
+
+function updateTooldim(form,dimendiv,widthinput,heightinput) {
+    if (form.exttooltarget.length) {
+        for (var i=0; i<form.exttooltarget.length; i++) {
+            if (form.exttooltarget[i].checked) {
+                var dimen = 'none';
+                if (form.exttooltarget[i].value == 'window') {
+                    dimen = 'block';
+                } else {
+                    if (document.getElementById(widthinput)) {
+                        document.getElementById(widthinput).value = '';
+                    }
+                    if (document.getElementById(heightinput)) {
+                        document.getElementById(heightinput).value = '';
+                    }
+                }
+                if (document.getElementById(dimendiv)) {
+                    document.getElementById(dimendiv).style.display = dimen;
+                }
+                break;
+            }
+        }
+    }
+}
 
 ENDJS