--- loncom/interface/lonrequestcourse.pm	2014/04/16 14:40:17	1.78
+++ loncom/interface/lonrequestcourse.pm	2015/05/21 23:40:09	1.87
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Request a course
 #
-# $Id: lonrequestcourse.pm,v 1.78 2014/04/16 14:40:17 raeburn Exp $
+# $Id: lonrequestcourse.pm,v 1.87 2015/05/21 23:40:09 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -172,13 +172,29 @@ sub handler {
                 if ($can_request{'textbook'}) {
                     &process_textbook_request($r,$dom,$action,\%domdefs,\%domconfig,\%can_request);
                 } else {
-                    &textbook_request_disabled($r,$dom,\%can_request);
+                    &textbook_request_disabled($r,$dom,$action,\%can_request);
+                }
+            } elsif ($action eq 'display') {
+               my ($uname,$udom,$result,$warning) = &domcoord_display($dom);
+               if ($warning ne '') {
+                   my $args = { only_body => 1 };
+                   $r->print(&header('Course/Community Requests','','' ,'',$args).
+                             '<h3>'.&mt('Course/Community Request Details').'</h3>'.
+                             '<div class="LC_warning">'.$warning.'</div>'.
+                             &close_popup_form());
+                } else {
+                    $states{'display'} = ['details'];
+                    my $loaditems = &onload_action($action,$state);
+                    my $page = 0;
+                    &request_administration($r,$action,$state,$page,\%states,$dom,$jscript,
+                                            $loaditems,'','','','','',$showcredits,'','',
+                                            $uname,$udom);
                 }
             } else {
                 if ($can_request{'textbook'}) {
                     &print_textbook_form($r,$dom,\@incdoms,\%domdefs,$domconfig{'requestcourses'},\%can_request);
                 } else {
-                    &textbook_request_disabled($r,$dom,\%can_request);
+                    &textbook_request_disabled($r,$dom,$action,\%can_request);
                 }
             }
             return OK;
@@ -232,46 +248,7 @@ sub handler {
     my ($page,$crumb,$newinstcode,$codechk,$checkedcode,$description) =
         &get_breadcrumbs($dom,$action,\$state,\%states,\%trail);
     if ($action eq 'display') {
-        if (($dom eq $env{'request.role.domain'}) && (&Apache::lonnet::allowed('ccc',$dom))) {
-            if ($env{'form.cnum'} ne '') {
-                my $cnum = $env{'form.cnum'};
-                my $queue = $env{'form.queue'};
-                my $reqkey = $cnum.'_'.$queue;
-                my $namespace = 'courserequestqueue';
-                my $domconfig = &Apache::lonnet::get_domainconfiguser($dom);
-                my %queued =
-                    &Apache::lonnet::get($namespace,[$reqkey],$dom,$domconfig);
-                if (ref($queued{$reqkey}) eq 'HASH') {
-                    $uname = $queued{$reqkey}{'ownername'};
-                    $udom  = $queued{$reqkey}{'ownerdom'};
-                    if (($udom =~ /^$match_domain$/) && ($uname =~ /^$match_username$/)) {
-                        $result = &retrieve_settings($dom,$cnum,$udom,$uname);
-                    } else {
-                        if ($env{'form.crstype'} eq 'community') {
-                            $warning = &mt('Invalid username or domain for community requestor');
-                        } else {
-                            $warning = &mt('Invalid username or domain for course requestor');
-                        }
-                    }
-                } else {
-                    if ($env{'form.crstype'} eq 'community') {
-                        $warning = &mt('No information was found for this community request.');
-                    } else {
-                        $warning = &mt('No information was found for this course request.');
-                    }
-                }
-            } else {
-                $warning = &mt('No course request ID provided.');
-            }
-        } else {
-            if ($env{'form.crstype'} eq 'any') {
-               $warning = &mt('You do not have rights to view course or community request information.');
-            } elsif ($env{'form.crstype'} eq 'community') {
-                $warning = &mt('You do not have rights to view community request information.');
-            } else {
-                $warning = &mt('You do not have rights to view course request information.');
-            }
-        }
+        ($uname,$udom,$result,$warning) = &domcoord_display($dom);
     } elsif ((defined($state)) && (defined($action))) {
         if (($action eq 'view') && ($state eq 'details')) {
             if ((defined($env{'form.showdom'})) && (defined($env{'form.cnum'}))) {
@@ -334,6 +311,8 @@ sub handler {
             $jscript = &Apache::lonhtmlcommon::set_form_elements($elementsref,\%stored);
             if ($state eq 'courseinfo') {
                 $jscript .= &cloning_javascript();
+            } elsif ($state eq 'process') {
+                $jscript .= &processing_javascript();
             }
         }
     }
@@ -436,7 +415,7 @@ function setCloneDisplay(courseForm) {
         for (var i=0; i<courseForm.cloning.length; i++) {
             if (courseForm.cloning[i].checked) {
                 if (courseForm.cloning[i].value == 1) {
-                    document.getElementById('cloneoptions').style.display="block";;
+                    document.getElementById('cloneoptions').style.display="block";
                 }
             }
         }
@@ -445,6 +424,17 @@ function setCloneDisplay(courseForm) {
 END
 }
 
+sub processing_javascript {
+    return <<"END";
+function hideProcessing() {
+    if (document.getElementById('processing')) {
+        document.getElementById('processing').style.display="none";
+    }
+}
+
+END
+}
+
 sub get_breadcrumbs {
     my ($dom,$action,$state,$states,$trail) = @_;
     my ($crumb,$newinstcode,$codechk,$checkedcode,$numtitles,$description);
@@ -486,27 +476,29 @@ sub get_breadcrumbs {
                     }
                 }
             }
-            for (my $i=0; $i<@{$states->{$action}}; $i++) {
-                if ($$state eq $states->{$action}[$i]) {
-                    &Apache::lonhtmlcommon::add_breadcrumb(
-                       {text=>"$trail->{$$state}"});
-                    $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course/Community Requests','Course_Requests');
-                    last;
-                } else {
-                    if (($$state eq 'process') || ($$state eq 'removal') || ($$state eq 'reqauthor')) {
+            if (ref($states->{$action}) eq 'ARRAY') {
+                for (my $i=0; $i<@{$states->{$action}}; $i++) {
+                    if ($$state eq $states->{$action}[$i]) {
                         &Apache::lonhtmlcommon::add_breadcrumb(
-                            { href => '/adm/requestcourse',
-                              text => "$trail->{$states->{$action}[$i]}",
-                            }
-                        );
+                           {text=>"$trail->{$$state}"});
+                        $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course/Community Requests','Course_Requests');
+                        last;
                     } else {
-                        &Apache::lonhtmlcommon::add_breadcrumb(
+                        if (($$state eq 'process') || ($$state eq 'removal') || ($$state eq 'reqauthor')) {
+                            &Apache::lonhtmlcommon::add_breadcrumb(
+                                { href => '/adm/requestcourse',
+                                  text => "$trail->{$states->{$action}[$i]}",
+                                }
+                           );
+                        } else {
+                            &Apache::lonhtmlcommon::add_breadcrumb(
      { href => "javascript:backPage(document.requestcrs,'$states->{$action}[$i]')",
        text => "$trail->{$states->{$action}[$i]}", }
-                       );
-                   }
-               }
-           }
+                           );
+                        }
+                    }
+                }
+            }
         } else {
             &Apache::lonhtmlcommon::add_breadcrumb(
                     {text=>'Pick Action'});
@@ -720,6 +712,9 @@ sub onload_action {
         if ($state eq 'courseinfo') {
             $loaditems{'onload'} .= 'javascript:setCloneDisplay(document.requestcrs);';
         }
+        if ($state eq 'process') {
+            $loaditems{'onload'} .= 'javascript:hideProcessing();';
+        }
     }
     return \%loaditems;
 }
@@ -944,7 +939,8 @@ END
     if ($action eq 'new') {
         my $jsextra;
         if (($state eq 'courseinfo') || ($state eq 'codepick')) {
-            $jsextra = "\n".&Apache::loncommon::coursebrowser_javascript($dom);
+            $jsextra = "\n".&Apache::loncommon::coursebrowser_javascript($dom,'','','','','',
+                                                                         $newinstcode);
         } elsif ($state eq 'enrollment') {
             if (($env{'form.crstype'} eq 'official') && 
                 (&Apache::lonnet::auto_run('',$dom))) {
@@ -1129,6 +1125,52 @@ END
     return;
 }
 
+sub domcoord_display {
+    my ($dom) = @_;
+    my ($uname,$udom,$result,$warning);
+    if (($dom eq $env{'request.role.domain'}) && (&Apache::lonnet::allowed('ccc',$dom))) {
+        if ($env{'form.cnum'} ne '') {
+            my $cnum = $env{'form.cnum'};
+            my $queue = $env{'form.queue'};
+            my $reqkey = $cnum.'_'.$queue;
+            my $namespace = 'courserequestqueue';
+            my $domconfig = &Apache::lonnet::get_domainconfiguser($dom);
+            my %queued =
+                &Apache::lonnet::get($namespace,[$reqkey],$dom,$domconfig);
+            if (ref($queued{$reqkey}) eq 'HASH') {
+                $uname = $queued{$reqkey}{'ownername'};
+                $udom  = $queued{$reqkey}{'ownerdom'};
+                if (($udom =~ /^$match_domain$/) && ($uname =~ /^$match_username$/)) {
+                    $result = &retrieve_settings($dom,$cnum,$udom,$uname);
+                } else {
+                    if ($env{'form.crstype'} eq 'community') {
+                        $warning = &mt('Invalid username or domain for community requestor');
+                    } else {
+                        $warning = &mt('Invalid username or domain for course requestor');
+                    }
+                }
+            } else {
+                if ($env{'form.crstype'} eq 'community') {
+                    $warning = &mt('No information was found for this community request.');
+                } else {
+                    $warning = &mt('No information was found for this course request.');
+                }
+            }
+        } else {
+            $warning = &mt('No course request ID provided.');
+        }
+    } else {
+        if ($env{'form.crstype'} eq 'any') {
+            $warning = &mt('You do not have rights to view course or community request information.');
+        } elsif ($env{'form.crstype'} eq 'community') {
+            $warning = &mt('You do not have rights to view community request information.');
+        } else {
+            $warning = &mt('You do not have rights to view course request information.');
+        }
+    }
+    return ($uname,$udom,$result,$warning);
+}
+
 sub enrollment_lcsec_js {
     my %alerts = &section_check_alerts();
     my $secname = $alerts{'badsec'};
@@ -1527,7 +1569,7 @@ sub print_request_form {
                                                      \%cat_order,\@code_order);
         }
         my $lonhost = $r->dir_config('lonHostID');
-        my ($storeresult,$result) = &print_request_outcome($lonhost,$dom,\@codetitles,
+        my ($storeresult,$result) = &print_request_outcome($r,$lonhost,$dom,\@codetitles,
                                                            \@code_order,$instcredits);
         $r->print($result);
         if (($storeresult eq 'ok') || ($storeresult eq 'created')) {
@@ -2747,6 +2789,7 @@ sub print_review {
 
     my $enrollrow_title = &mt('Default Access Dates').'<br />'.
                           '('.&Apache::lonnet::plaintext('st',$category).')';
+    my $instcode;
     if ($env{'form.crstype'} eq 'official') {
         if ((ref($codetitles) eq 'ARRAY') && (ref($cat_titles) eq 'HASH')) {
             foreach my $title (@{$codetitles}) {
@@ -2762,6 +2805,11 @@ sub print_review {
                 }
             }
         }
+        if (ref($code_order) eq 'ARRAY') {
+            foreach my $item (@{$code_order}) {
+                $instcode .= $env{'form.instcode_'.$item};
+            }
+        }
         $inst_headers .= '<th>'.&mt('Credits').'</th>';
         if ($instcredits) {
             $inst_values .= '<td>'.$instcredits.'</td>';
@@ -2849,7 +2897,7 @@ sub print_review {
         ($env{'form.clonedom'} =~ /^$match_domain$/)) {
         my $canclone = &Apache::loncoursequeueadmin::can_clone_course($uname,
                            $udom,$env{'form.clonecrs'},$env{'form.clonedom'},
-                           $env{'form.crstype'});
+                           $env{'form.crstype'},$dom,$instcode);
         if ($canclone) {
             my %courseenv = &Apache::lonnet::userenvironment($env{'form.clonedom'},
                               $env{'form.clonecrs'},('description','internal.coursecode'));
@@ -3336,7 +3384,7 @@ sub display_navbuttons {
 }
 
 sub print_request_outcome {
-    my ($lonhost,$dom,$codetitles,$code_order,$instcredits) = @_;
+    my ($r,$lonhost,$dom,$codetitles,$code_order,$instcredits) = @_;
     my ($output,$cnum,$now,$req_notifylist,$crstype,$enrollstart,$enrollend,
         %sections,%crosslistings,%personnel,@baduname,@missingdom,%domconfig,
         $uniquecode);
@@ -3547,7 +3595,7 @@ sub print_request_outcome {
             my $canclone =  
                 &Apache::loncoursequeueadmin::can_clone_course($env{'user.name'},
                         $env{'user.domain'},$env{'form.clonecrs'},$env{'form.clonedom'},
-                        $crstype);
+                        $crstype,$dom,$instcode);
             if ($canclone) {
                 $clonecrs = $env{'form.clonecrs'};
                 $clonedom = $env{'form.clonedom'};
@@ -3581,13 +3629,13 @@ sub print_request_outcome {
                     accessend      => $accessend,
                     personnel      => \%personnel,
                   };
-    my ($result,$output) = &process_request($lonhost,$dom,$cnum,$crstype,$now,$details,$instcode,
+    my ($result,$output) = &process_request($r,$lonhost,$dom,$cnum,$crstype,$now,$details,$instcode,
                                             $req_notifylist,\@instsections,\%domconfig);
     return ($result,$output);
 }
     
 sub process_request {
-    my ($lonhost,$dom,$cnum,$crstype,$now,$details,$instcode,$req_notifylist,$instsections,
+    my ($r,$lonhost,$dom,$cnum,$crstype,$now,$details,$instcode,$req_notifylist,$instsections,
         $domconfig) = @_; 
     my (@inststatuses,$storeresult,$creationresult,$output);
     my $val = 
@@ -3629,6 +3677,11 @@ sub process_request {
                                             $dom,$crstype,$limit,\$message);
         } elsif ($val eq 'validate') {
             my ($inststatuslist,$validationchk,$validation,%custominfo);
+            if (ref($details) eq 'HASH') {
+                if ($details->{'clonecrs'}) {
+                    $custominfo{'_LC_clonefrom'} = $details->{'clonedom'}.'_'.$details->{'clonecrs'};
+                }
+            }
             if (@inststatuses > 0) {
                 $inststatuslist = join(',',@inststatuses);
             }
@@ -3717,6 +3770,15 @@ sub process_request {
             foreach my $role (@roles) {
                 $longroles{$role}=&Apache::lonnet::plaintext($role,$type);
             }
+            $r->print('<div id="processing" style="display:block;">'."\n".
+                      &mt('Your request is being processed; this page will update when processing is complete.').
+                      '</div>');
+            $r->rflush();
+            if (ref($details) eq 'HASH') {
+                if ($details->{'clonecrs'}) {
+                    $customitems{'_LC_clonefrom'} = $details->{'clonedom'}.'_'.$details->{'clonecrs'};
+                }
+            }
             my ($result,$postprocess) = &Apache::loncoursequeueadmin::course_creation($dom,$cnum,
                                           'autocreate',$details,\$logmsg,\$newusermsg,\$addresult,
                                           \$enrollcount,\$response,\$keysmsg,\%domdefs,\%longroles,
@@ -3739,6 +3801,14 @@ sub process_request {
                 if ($code) {
                     $reqhash{'code'} = $code;
                 }
+                if (ref($postprocess) eq 'HASH') {
+                    if (ref($postprocess->{'createdactions'}) eq 'HASH') {
+                        if (ref($postprocess->{'createdactions'}{'environment'}) eq 'HASH') {
+                            &Apache::loncoursequeueadmin::postprocess_crsenv($dom,$cnum,
+                                                                             $postprocess->{'createdactions'}{'environment'});
+                        }
+                    }
+                }
                 $output .= '<br />'.$role_result.'</p>';
                 $creationresult = 'created';
             } else {
@@ -4385,25 +4455,26 @@ sub generate_date_items {
 
 sub print_textbook_form {
     my ($r,$dom,$incdoms,$domdefs,$settings,$can_request) = @_;
-    my ($bookshash,%ordered);
+    my (%prefab,%ordered,%numprefab);
     my $crstype = 'textbook';
 #
-#  Retrieve list of textbook courses cloneable by user
+#  Retrieve list of prefabricated courses (textbook courses and templates) cloneable by user
 #
-    my $numbook;
-    if (ref($settings) eq 'HASH') {
-        $bookshash = $settings->{'textbooks'};
-        if (ref($bookshash) eq 'HASH') {
-            foreach my $item (keys(%{$bookshash})) {
-                my ($clonedom,$clonecrs) = split(/_/,$item);
-                if (ref($bookshash->{$item}) eq 'HASH') {
+    foreach my $type ('textbooks','templates') {
+        $numprefab{$type} = 0;
+        if (ref($settings) eq 'HASH') {
+            $prefab{$type} = $settings->{$type};
+            if (ref($prefab{$type}) eq 'HASH') {
+                foreach my $item (keys(%{$prefab{$type}})) {
                     my ($clonedom,$clonecrs) = split(/_/,$item);
-                    if (&Apache::loncoursequeueadmin::can_clone_course($env{'user.name'},
-                                        $env{'user.domain'},$clonecrs,$clonedom,$crstype)) {
-
-                        my $num = $bookshash->{$item}{'order'};
-                        $ordered{$num} = $item;
-                        $numbook ++;
+                    if (ref($prefab{$type}{$item}) eq 'HASH') {
+                        if (&Apache::loncoursequeueadmin::can_clone_course($env{'user.name'},
+                                          $env{'user.domain'},$clonecrs,$clonedom,$crstype,$dom)) {
+
+                            my $num = $prefab{$type}{$item}{'order'};
+                            $ordered{$type}{$num} = $item;
+                            $numprefab{$type} ++;
+                        }
                     }
                 }
             }
@@ -4439,7 +4510,7 @@ sub print_textbook_form {
 
     my $numcurrent = scalar(keys(%cloneable));
 
-    my $jscript = &textbook_request_javascript($numbook,$numcurrent);
+    my $jscript = &textbook_request_javascript(\%numprefab,$numcurrent);
     my %loaditems;
     $loaditems{'onload'} = 'javascript:uncheckAllRadio();';
     $r->print(&header('Course Request',$jscript,\%loaditems));
@@ -4490,9 +4561,16 @@ sub print_textbook_form {
         $r->print('<div>'. 
                   '<fieldset><legend>'.&mt('Course Content').'</legend>');
         if (keys(%ordered)) {
-            $r->print('<span class="LC_nobreak"><label>'.
-                      '<input type="radio" name="cloning" value="textbook" onclick="javascript:cloneChoice();" />'.
-                      &mt('Load textbook content').'</span>'.('&nbsp;'x2).' ');
+            if (ref($ordered{'textbooks'}) eq 'HASH') {
+                $r->print('<span class="LC_nobreak"><label>'.
+                          '<input type="radio" name="cloning" value="textbook" onclick="javascript:cloneChoice();" />'.
+                          &mt('Load textbook content').'</span>'.('&nbsp;'x2).' ');
+            }
+            if (ref($ordered{'templates'}) eq 'HASH') {
+                $r->print('<span class="LC_nobreak"><label>'.
+                          '<input type="radio" name="cloning" value="template" onclick="javascript:cloneChoice();" />'.
+                          &mt('Load pre-existing template').'</span>'.('&nbsp;'x2).' ');
+            }
         }
         if (keys(%cloneable)) {
             $r->print('<span class="LC_nobreak"><label>'.
@@ -4510,31 +4588,51 @@ sub print_textbook_form {
 # Table of cloneable textbook courses
 #
     if (keys(%ordered)) {
-        $r->print('<div id="showtextbook" style="display:none">'.
-                  &Apache::loncommon::start_data_table().
-                  &Apache::loncommon::start_data_table_header_row().
-                  '<th>'.&mt('Title').'</th>'.
-                  '<th>'.&mt('Author(s)').'</th>'.
-                  '<th>'.&mt('Subject').'</th>'.
-                  '<th>'.&mt('Book').'</th>'.
-                  &Apache::loncommon::end_data_table_header_row());
-        my @items = sort { $a <=> $b } keys(%ordered);
-        foreach my $num (@items) {
-            my $item = $ordered{$num};
-            my $cleantitle=&HTML::Entities::encode($bookshash->{$item}->{'title'},'<>&"');
-            $cleantitle=~s/'/\\'/g;
-            $cleantitle =~ s/^\s+//;
-            $r->print(&Apache::loncommon::start_data_table_row().
-                      '<td><label><input type="radio" name="book" value="'.$item.'" />'.
-                      $cleantitle.'</label></td>'.
-                      '<td>'.$bookshash->{$item}->{'author'}.'</td>'.
-                      '<td>'.$bookshash->{$item}->{'subject'}.'</td>'.
-                      '<td><img border="0" src="'.$bookshash->{$item}->{'image'}.
-                      '" alt="'.$cleantitle.'" /></td>'. 
-                      &Apache::loncommon::end_data_table_row());
+        foreach my $type ('textbooks','templates') {
+            my $divid = 'showtextbook';
+            my $radioid = 'book';
+            if ($type eq 'templates') {
+                $divid = 'showtemplate'; 
+                $radioid = 'template';
+            }
+            if (ref($ordered{$type}) eq 'HASH') {
+                $r->print('<div id="'.$divid.'" style="display:none">'.
+                          &Apache::loncommon::start_data_table().
+                          &Apache::loncommon::start_data_table_header_row().
+                          '<th>'.&mt('Title').'</th>');
+                if ($type eq 'textbooks') {
+                    $r->print('<th>'.&mt('Author(s)').'</th>');
+                }
+                $r->print('<th>'.&mt('Subject').'</th>');
+                if ($type eq 'textbooks') {
+                    $r->print('<th>'.&mt('Publisher').'</th>'.
+                              '<th>'.&mt('Book').'</th>');
+                }
+                $r->print(&Apache::loncommon::end_data_table_header_row());
+                my @items = sort { $a <=> $b } keys(%{$ordered{$type}});
+                foreach my $num (@items) {
+                    my $item = $ordered{$type}{$num};
+                    my $cleantitle=&HTML::Entities::encode($prefab{$type}{$item}{'title'},'<>&"');
+                    $cleantitle=~s/'/\\'/g;
+                    $cleantitle =~ s/^\s+//;
+                    $r->print(&Apache::loncommon::start_data_table_row().
+                              '<td><label><input type="radio" name="'.$radioid.'" value="'.$item.'" />'.
+                              $cleantitle.'</label></td>');
+                    if ($type eq 'textbooks') {
+                         $r->print('<td>'.$prefab{$type}{$item}{'author'}.'</td>');
+                    }
+                    $r->print('<td>'.$prefab{$type}{$item}{'subject'}.'</td>');
+                    if ($type eq 'textbooks') {
+                        $r->print('<td>'.$prefab{$type}{$item}{'publisher'}.'</td>'.
+                                  '<td><img border="0" src="'.$prefab{$type}{$item}{'image'}.
+                                  '" alt="'.$cleantitle.'" /></td>');
+                    }
+                    $r->print(&Apache::loncommon::end_data_table_row());
+                }
+                $r->print(&Apache::loncommon::end_data_table().
+                          '</div>');
+            }
         }
-        $r->print(&Apache::loncommon::end_data_table().
-                  '</div>');
     }
 
 #
@@ -4702,6 +4800,8 @@ sub process_textbook_request {
     my ($clonefrom,$clonedom,$clonecrs);
     if ($reqtype eq 'textbook') {
         $clonefrom = $env{'form.book'};
+    } elsif ($reqtype eq 'template') {
+        $clonefrom = $env{'form.template'};
     } elsif ($reqtype eq 'existing') {
         $clonefrom = $env{'form.owned'};
     }
@@ -4711,7 +4811,7 @@ sub process_textbook_request {
         if (&Apache::lonnet::homeserver($clonecrs,$clonedom) ne 'no_host') {
             my $canclone =
                 &Apache::loncoursequeueadmin::can_clone_course($env{'user.name'},
-                            $env{'user.domain'},$clonecrs,$clonedom,$crstype);
+                            $env{'user.domain'},$clonecrs,$clonedom,$crstype,$dom);
             unless ($canclone) {
                 undef($clonecrs);
                 undef($clonedom);
@@ -4721,7 +4821,11 @@ sub process_textbook_request {
             undef($clonedom);
         }
     }
-    $r->print(&header('Course Creation'));
+    my $js = &processing_javascript();
+    my $loaditems = { 
+                      onload => 'javascript:hideProcessing();',
+                    };
+    $r->print(&header('Course Creation',$js,$loaditems));
 
     if (ref($can_request) eq 'HASH') {
         unless ((scalar(keys(%{$can_request})) == 1) && ($can_request->{'textbook'})) {
@@ -4760,7 +4864,8 @@ sub process_textbook_request {
         $details->{dateshift} = $env{'form.dateshift'};
     }
     my $lonhost = $r->dir_config('lonHostID');
-    my ($result,$output) = &process_request($lonhost,$dom,$cnum,$crstype,$now,$details,'',
+    $r->rflush();
+    my ($result,$output) = &process_request($r,$lonhost,$dom,$cnum,$crstype,$now,$details,'',
                                             $req_notifylist,[],$domconfig);
     $r->print($output);
     if (&Apache::loncoursequeueadmin::author_prompt()) {
@@ -4773,21 +4878,23 @@ sub process_textbook_request {
 }
 
 sub textbook_request_javascript {
-    my ($numbook,$numcurrent) = @_;
+    my ($numprefab,$numcurrent) = @_;
+    return unless (ref($numprefab) eq 'HASH');
+    return if (!$numprefab->{'textbooks'} && !$numprefab->{'templates'} && !$numcurrent);
     my %lt = &Apache::lonlocal::texthash(
                  choose   => 'Please select a content option.',
                  textbook => 'Please select a textbook, or choose a different option.',
+                 template => 'Please select a template, or choose a different option.',        
                  existing => 'Please select one of your existing courses to copy, or choose a different option.',
                  title    => 'Please enter a course title.',
              );
-    return if (!$numbook && !$numcurrent);
     return <<"ENDSCRIPT";
 function cloneChoice() {
     if (document.requestcourse.cloning) {
         var radioLength = document.requestcourse.cloning.length;
         if (radioLength == undefined) {
             var val = document.requestcourse.cloning.value;
-            if ((val == 'textbook') || (val == 'existing')) {
+            if ((val == 'textbook') || (val == 'template') || (val == 'existing')) {
                 var elem = document.getElementById('show'+val);
                 if (document.requestcourse.cloning.checked) {
                     elem.style.display = 'block';
@@ -4799,7 +4906,7 @@ function cloneChoice() {
         } else {
             for (var i=0; i<radioLength; i++) {
                 var val = document.requestcourse.cloning[i].value;
-                if ((val == 'textbook') || (val == 'existing')) {
+                if ((val == 'textbook') || (val == 'template') || (val == 'existing')) {
                     var elem = document.getElementById('show'+val);
                     if (document.requestcourse.cloning[i].checked) {
                         elem.style.display = 'block';
@@ -4807,6 +4914,9 @@ function cloneChoice() {
                         if (val == 'textbook') {
                             uncheckRadio('book');
                         }
+                        if (val == 'template') {
+                            uncheckRadio('template');
+                        }
                         if (val == 'existing') {
                             uncheckRadio('owned');
                         }
@@ -4834,11 +4944,15 @@ function uncheckRadio(radioGroupName) {
 
 function uncheckAllRadio() {
     uncheckRadio('cloning');
-    var numbook = $numbook;
+    var numbook = $numprefab->{'textbooks'};
+    var numtemplate = $numprefab->{'templates'};
     var numcurrent = $numcurrent;
     if (numbook > 0) {
         uncheckRadio('textbook'); 
     }
+    if (nutemplate > 0) {
+        uncheckRadio('template');
+    }m
     if (numcurrent > 0) {
         uncheckRadio('existing');
     }
@@ -4869,12 +4983,16 @@ function validTextbookReq() {
             }
         }
         var group;
-        if ((cloneChoice == 'textbook') || (cloneChoice == 'existing')) {
+        if ((cloneChoice == 'textbook') || (cloneChoice == 'template') || (cloneChoice == 'existing')) {
             var group;
             if (cloneChoice == 'textbook') {
                 group = document.getElementsByName('book');
             } else {
-                group = document.getElementsByName('owned');
+                if (cloneChoice == 'template') {
+                    group = document.getElementsByName('template');
+                } else {
+                    group = document.getElementsByName('owned');
+                }
             }
             var groupLength = group.length;
             var chosen = 0;
@@ -4894,7 +5012,11 @@ function validTextbookReq() {
                if (cloneChoice == 'textbook') {
                    alert("$lt{'textbook'}");
                } else {
-                   alert("$lt{'existing'}");
+                   if (cloneChoice == 'template') {
+                       alert("$lt{'template'}");
+                   } else {
+                       alert("$lt{'existing'}");
+                   }
                }
                return false;
             }
@@ -4911,6 +5033,33 @@ ENDSCRIPT
 
 }
 
+sub textbook_request_disabled {
+    my ($r,$dom,$action,$can_request) = @_;
+    if (ref($can_request) eq 'HASH') {
+        if ($action eq 'process') {
+            unless ((scalar(keys(%{$can_request})) == 1)) {
+                &Apache::lonhtmlcommon::add_breadcrumb(
+                   { href => '/adm/requestcourse',
+                     text => 'Pick action',
+                   });
+            }
+        }
+    }
+    $r->print(&header('Course Request'));
+    &Apache::lonhtmlcommon::add_breadcrumb({text=>'Course Request'});
+    $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests').
+              '<div>'.
+              '<p class="LC_info">'.&mt('You do not have privileges to request creation of textbook courses.').'</p>');
+    if (ref($can_request) eq 'HASH') {
+        if (scalar(keys(%{$can_request})) > 1) {
+            $r->print('<a href="/adm/requestcourse">'.&mt('Go back').'</a>');
+         }
+    }
+    $r->print('</div>'.
+              &Apache::loncommon::end_page());
+    return;
+}
+
 sub startContentScreen {
     my ($r,$mode)=@_;
     $r->print("\n".'<ul class="LC_TabContentBigger" id="textbookreq">'."\n");