File:  [LON-CAPA] / loncom / interface / loncourserespicker.pm
Revision 1.11: download - view: text, annotated - select for diffs
Wed Jan 8 17:18:11 2014 UTC (10 years, 4 months ago) by bisitz
Branches: MAIN
CVS tags: version_2_11_0_RC3, version_2_11_0, HEAD
Consistent spelling (upper case): Authoring Space

    1: # The LearningOnline Network
    2: #
    3: # $Id: loncourserespicker.pm,v 1.11 2014/01/08 17:18:11 bisitz Exp $
    4: #
    5: # Copyright Michigan State University Board of Trustees
    6: #
    7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    8: #
    9: # LON-CAPA is free software; you can redistribute it and/or modify
   10: # it under the terms of the GNU General Public License as published by
   11: # the Free Software Foundation; either version 2 of the License, or
   12: # (at your option) any later version.
   13: #
   14: # LON-CAPA is distributed in the hope that it will be useful,
   15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17: # GNU General Public License for more details.
   18: #
   19: # You should have received a copy of the GNU General Public License
   20: # along with LON-CAPA; if not, write to the Free Software
   21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22: #
   23: # /home/httpd/html/adm/gpl.txt
   24: #
   25: # http://www.lon-capa.org/
   26: #
   27: 
   28: =pod
   29: 
   30: =head1 NAME
   31: 
   32: loncourserespicker - Utilities to choose folders and resources in a course.
   33: 
   34: =head1 SYNOPSIS
   35: 
   36: loncourserespicker provides an interface for selecting which folders and/or
   37: resources are to be either:
   38: 
   39: (a) exported to an IMS Content Package
   40: (b) subject to access blocking for the duriation of an exam/quiz.
   41: (c) dumped to an Authoring Space
   42: 
   43: =head1 DESCRIPTION
   44: 
   45: This module provides routines to generate a hierarchical display of folders
   46: and resources in a course which can be selected for specific actions.
   47: 
   48: The choice of items is copied back to the main window from which the pop-up
   49: window used to display the Course Contents was opened.
   50: 
   51: =head1 OVERVIEW
   52: 
   53: The main subroutine: &create_picker() will display the hierarchy of folders,
   54: sub-folders, and resources in the Main Content area.  Items can be selected
   55: using checkboxes, and/or a "Check All" button.  Selection of a folder
   56: causes the contents of the folder to also be selected automatically. The
   57: propagation of check status is recursive into sub-folders.  Likewise, if an
   58: item deep in a nested set of folders and sub-folders is unchecked, the 
   59: uncheck will propagate up through the hierarchy causing any folders at
   60: a higher level to become unchecked.
   61: 
   62: There is a submit button, which will be named differently according to the 
   63: context in which resource/folder selection is being made.
   64: 
   65: The three contexts currently supported are: IMS export, selection of
   66: content to be subject to access restructions for the duration of an
   67: exam, and selection of items for dumping to an Authoring Space.
   68: 
   69: =head1 INTERNAL SUBROUTINES
   70: 
   71: =item &create_picker()
   72: 
   73: Created HTML mark up to display contents of course with checkboxes to
   74: select items.  Checking a folder causes recursive checking of items
   75: within the folder. Unchecking a resource causing unchecking of folders
   76: containing the item back up to the top level.
   77: 
   78: Inputs: 9.
   79:    - $navmap  -- Reference to LON-CAPA navmap object 
   80:                 (encapsulates information about resources in the course). 
   81: 
   82:    - $context -- Context in which course resource selection is being made.
   83:                  Currently imsexport and examblock are supported.
   84: 
   85:    - $formname  -- Name of the form in the window from which the pop-up
   86:                    used to select course items was launched. 
   87: 
   88:    - $crstype  -- Course or Community
   89: 
   90:    - $blockedmaps -- Reference to hash of previously selected maps
   91:                      (e.g., for a live exam block).   
   92: 
   93:    - $blockedresources  -- Reference to hash of resources selected
   94:                            previously (e.g., for an exam block).  
   95: 
   96:    - $block  -- An internal ID (integer) used to track which exam
   97:                 block currently being configured.
   98: 
   99:    - $preamble -- HTML form elements used to select Authoring Space
  100:                   if more than one available, and also set name of 'Folder 
  101:                   in Authoring Space' where content will be dumped, when
  102:                   context is 'dumpdocs'.
  103: 
  104:    - $numhome -- number of possible Authoring Spaces where content could
  105:                  be dumped when context is 'dumpdocs'.
  106: 
  107:    - $uploadedfiles -- Reference to hash: keys are paths to files in
  108:                        /home/httpd/lonUsers/$cdom/$1/$2/$3/$cnum/userfiles.
  109: 
  110: 
  111: Output: $output is the HTML mark-up for display/selection of content
  112:         items in the pop-up window.
  113: 
  114: =item &respicker_javascript()
  115: 
  116: Creates javascript functions for checking/unchecking all items, and
  117: for recursive checking triggered by checking a folder, or recursive
  118: (upeards) unchecking of an item within a folder. 
  119: 
  120: Inputs: 7. 
  121:    - $startcount -- Starting offset of form element numbering for items  
  122: 
  123:    - $numcount -- Total numer of folders and resources in course.
  124: 
  125:    - $context -- Context in which resources are being displayed
  126:                  (imsexport, examblock or dumpdocs). 
  127: 
  128:    - $formname --  Name of form.
  129: 
  130:    - $children -- Reference to hash of items contained within a folder. 
  131: 
  132:    - $hierarchy -- Reference to hierarchy of folders containing an item.
  133: 
  134:    - $checked_maps -- Reference to array of folders currently checked.
  135: 
  136: Output: 1. Javascript (within <script></script> tags.
  137: 
  138: 
  139: =item &get_navmap_object() 
  140: 
  141: Instantiates a navmaps object, and generates an error message if
  142: no object instantiated.
  143: 
  144: Inputs: 2.
  145:    - $crstype -- Container type: Course or Community
  146: 
  147:    - $context -- Context: imsexport, examblock or dumpdocs
  148: 
  149: 
  150: =item &clean()
  151:  
  152: Takes incoming title and replaces non-alphanumeric characters with underscore,
  153: so title can be used as suggested file name (with appended extension) for file
  154: copied from course to Authoring Space.
  155: 
  156: 
  157: =item &enumerate_course_contents()
  158: 
  159: Create hashes of maps (for folders/pages) and symbs (for resources) in
  160: a course, where keys are numbers (starting with 1) and values are
  161: map url, or symb, for an iteration through the course, as seen by
  162: a Course Coordinator. Used to generate numerical IDs to facilitate
  163: (a) storage of lists of maps or resources to be blocked during an exam,
  164: (b) processing selected form element during dumping of selected course
  165:     content to Authoring Space.
  166: 
  167: Inputs: 7 
  168: 
  169:       $navmap - navmaps object
  170: 
  171:       $map_url - reference to hash to contain URLs of maps in course
  172: 
  173:       $resource_symb - reference to hash to contain symbs for
  174:                        resources in course
  175: 
  176:       $title_ref - reference to hash containing titles for items in
  177:                    course
  178: 
  179:       $context - examblock or dumpdocs
  180: 
  181:       $cdom - course's domain
  182: 
  183:       $cnum - courseID 
  184: 
  185: Outputs: None
  186: 
  187: Side Effects: $map_url and $resource_symb hashrefs are populated.
  188: 
  189: 
  190: =over
  191: 
  192: =back
  193: 
  194: =cut
  195: 
  196: 
  197: package Apache::loncourserespicker;
  198: 
  199: use strict;
  200: use Apache::lonnet;
  201: use Apache::loncommon;
  202: use Apache::lonhtmlcommon;
  203: use Apache::lonnavmaps;
  204: use Apache::londocs;
  205: use Apache::lonlocal;
  206: use LONCAPA qw(:DEFAULT :match);
  207: 
  208: sub create_picker {
  209:     my ($navmap,$context,$formname,$crstype,$blockedmaps,$blockedresources,$block,$preamble,$numhome,$uploadedfiles) = @_;
  210:     return unless (ref($navmap));
  211:     my ($it,$output,$numdisc,%maps,%resources,%discussiontime,%currmaps,%currresources,%files);
  212:     $it = $navmap->getIterator(undef,undef,undef,1,undef,undef);
  213:     if (ref($blockedmaps) eq 'HASH') {
  214:         %currmaps = %{$blockedmaps};
  215:     }
  216:     if (ref($blockedresources) eq 'HASH') {
  217:         %currresources = %{$blockedresources};
  218:     } elsif (ref($uploadedfiles) eq 'HASH') {
  219:         %files = %{$uploadedfiles};
  220:     }
  221:     my @checked_maps;
  222:     my $curRes;
  223:     my $numprobs = 0;
  224:     my $depth = 0;
  225:     my $count = 0;
  226:     my $boards = 0;
  227:     my $startcount = 1;
  228:     my %parent = ();
  229:     my %children = ();
  230:     my %hierarchy = ();
  231:     my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons");
  232:     my $whitespace =
  233:         '<img src="'.$location.'/whitespace_21.gif" class="LC_docs_spacer" alt="" />';
  234: 
  235:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
  236:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
  237:     my $crsprefix = &propath($cdom,$cnum).'/userfiles/';
  238: 
  239:     my ($info,$display,$onsubmit,$togglebuttons);
  240:     if ($context eq 'examblock') {
  241:         my $maps_elem = 'docs_maps_'.$block;
  242:         my $res_elem = 'docs_resources_'.$block;
  243:         $onsubmit = ' onsubmit="return writeToOpener('."'$maps_elem','$res_elem'".');"';
  244:         $info = &mt('Items in '.lc($crstype).' for which access will be blocked.');
  245:     }
  246:     if ($context eq 'dumpdocs') {
  247:         $info = '<span class="LC_fontsize_medium">'.
  248:                 &mt('Choose the uploaded course items and templated pages/problems to be copied to Authoring Space.').
  249:                 '</span><br /><br />';
  250:         $startcount = 3 + $numhome;
  251:         $onsubmit = ' onsubmit="return checkUnique(document.'.$formname.',document.'.$formname.'.archive);"';
  252:     } elsif ($context eq 'imsexport') {
  253:         $info = &mt('Choose which items you wish to export from your '.$crstype.'.');
  254:         $startcount = 5;
  255:     }
  256:     $togglebuttons = '<input type="button" value="'.&mt('check all').'" '.
  257:                      'onclick="javascript:checkAll(document.'.$formname.'.archive)" />'.
  258:                      '&nbsp;&nbsp;<input type="button" value="'.&mt('uncheck all').'"'.
  259:                      ' onclick="javascript:uncheckAll(document.'.$formname.'.archive)" />';
  260:     $display = '<form name="'.$formname.'" action="" method="post"'.$onsubmit.'>'."\n";
  261:     if ($context eq 'imsexport') {
  262:         $display .= $info.
  263:                     '<div class="LC_columnSection">'."\n".
  264:                     '<fieldset>'.
  265:                     '<legend>'.&mt('Content items').'</legend>'."\n".
  266:                     $togglebuttons.
  267:                     '</fieldset>';
  268:         %discussiontime = &Apache::lonnet::dump('discussiontimes',$cdom,$cnum);
  269:         $numdisc = keys(%discussiontime);
  270:         if ($numdisc > 0) {
  271:             $display .= 
  272:                 '<fieldset>'.
  273:                 '<legend>'.&mt('Discussion posts').'</legend>'.
  274:                 '<input type="button" value="'.&mt('check all').'"'.
  275:                 ' onclick="javascript:checkAll(document.'.$formname.'.discussion)" />'.
  276:                 '&nbsp;&nbsp;<input type="button" value="'.&mt('uncheck all').'"'.
  277:                 ' onclick="javascript:uncheckAll(document.'.$formname.'.discussion)" />'.
  278:                 '</fieldset>';
  279:         }
  280:         $display .= '</div>';
  281:     } elsif ($context eq 'examblock') {
  282:         $display .= $info.$togglebuttons;
  283:     } elsif ($context eq 'dumpdocs') {
  284:         $display .= $preamble.
  285:                     '<div class="LC_left_float">'.
  286:                     '<fieldset>'.
  287:                     '<legend>'.&mt('Content to copy').('&nbsp;'x4).$togglebuttons.'</legend>'.
  288:                     $info;
  289:     }
  290:     my $lastcontainer = $startcount;
  291:     $display .= &Apache::loncommon::start_data_table()
  292:                .&Apache::loncommon::start_data_table_header_row();
  293:     if ($context eq 'imsexport') {
  294:         $display .= '<th>'.&mt('Export content item?').'</th>';
  295:         if ($numdisc > 0) {
  296:             $display .= '<th>'.&mt('Export discussion posts?').'</th>';
  297:         }
  298:     } elsif ($context eq 'examblock') {
  299:         $display .= '<th>'.&mt('Access blocked?').'</th>';
  300:     } elsif ($context eq 'dumpdocs') {
  301:         $display .= '<th>'.&mt('Copy?').'</th>'.
  302:                     '<th>'.&mt("Title in $crstype").
  303:                     '<th>'.&mt('Internal Identifier').'</th>'.
  304:                     '<th>'.&mt('Save as ...').'</th>';
  305:     }
  306:     $display .= &Apache::loncommon::end_data_table_header_row();
  307:     while ($curRes = $it->next()) {
  308:         if ($curRes == $it->BEGIN_MAP()) {
  309:             $depth++;
  310:             $parent{$depth} = $lastcontainer;
  311:         }
  312:         if ($curRes == $it->END_MAP()) {
  313:             $depth--;
  314:             $lastcontainer = $parent{$depth};
  315:         }
  316:         if (ref($curRes)) {
  317:             my $symb = $curRes->symb();
  318:             my $ressymb = $symb;
  319:             if ($context eq 'dumpdocs') {
  320:                 next unless (($curRes->src() =~ m{^\Q/uploaded/$cdom/$cnum/\E(docs|supplemental|simplepage)}) ||
  321:                              ($curRes->src() =~ m{^\Q/uploaded/$cdom/$cnum/\E(default|supplemental)_\d+\.(sequence|page)}) ||
  322:                              ($curRes->src() eq '/res/lib/templates/simpleproblem.problem') ||
  323:                              ($curRes->src() =~ m{^/adm/$match_domain/$match_username/\d+/smppg}));
  324:             } elsif ($ressymb =~ m|adm/($match_domain)/($match_username)/(\d+)/bulletinboard$|) {
  325:                 unless ($ressymb =~ m|adm/wrapper/adm|) {
  326:                     $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard';
  327:                 }
  328:             }
  329:             $count ++;
  330:             my $currelem;
  331:             if ($context eq 'imsexport') {
  332:                 $currelem = $count+$boards+$startcount;
  333:             } else {
  334:                 $currelem = $count+$startcount;
  335:             }
  336:             $display .= &Apache::loncommon::start_data_table_row().
  337:                        '<td>'."\n".
  338:                        '<input type="checkbox" name="archive" value="'.$count.'" ';
  339:             if (($curRes->is_sequence()) || ($curRes->is_page())) {
  340:                 $lastcontainer = $currelem;
  341:                 $display .= 'onclick="javascript:checkFolder(document.'.$formname.','."'$currelem'".')" ';
  342:                 my $mapurl = (&Apache::lonnet::decode_symb($symb))[2];
  343:                 if ($currmaps{$mapurl}) {
  344:                     $display .= 'checked="checked"';
  345:                     push(@checked_maps,$currelem);
  346:                 }
  347:             } else {
  348:                 if ($curRes->is_problem()) {
  349:                     $numprobs ++;
  350:                 }
  351:                 $display .= 'onclick="javascript:checkResource(document.'.$formname.','."'$currelem'".')" ';
  352:                 if ($currresources{$symb}) {
  353:                     $display .= 'checked="checked"';
  354:                 }
  355:             }
  356:             $display .= ' />'."\n";
  357:             if ($context eq 'dumpdocs') {
  358:                 $display .= '</td><td valign="top">';
  359:             }
  360:             for (my $i=0; $i<$depth; $i++) {
  361:                 $display .= "$whitespace\n";
  362:             }
  363:             my $icon = 'src="'.$location.'/unknown.gif" alt=""';
  364:             if ($curRes->is_sequence()) {
  365:                 $icon = 'src="'.$location.'/navmap.folder.open.gif" alt="'.&mt('Folder').'"';
  366:             } elsif ($curRes->is_page()) {
  367:                 $icon = 'src="'.$location.'/navmap.page.open.gif" alt="'.&mt('Composite Page').'"';
  368:             } elsif ($curRes->is_problem()) {
  369:                 $icon = 'src="'.$location.'/problem.gif" alt="'.&mt('Problem').'"';
  370:             } elsif ($curRes->is_task()) {
  371:                 $icon = 'src="'.$location.'/task.gif" alt="'.&mt('Task').'"';
  372:             } elsif ($curRes->src ne '') {
  373:                 $icon = 'src="'.&Apache::loncommon::icon($curRes->src).'" alt=""';
  374:             }
  375:             $display .= '<img '.$icon.' />&nbsp;'."\n";
  376:             $children{$parent{$depth}} .= $currelem.':';
  377:             if ($context eq 'examblock') {
  378:                 if ($parent{$depth} > 1) {
  379:                     if ($hierarchy{$parent{$depth}}) {
  380:                         $hierarchy{$currelem} = $hierarchy{$parent{$depth}}.",'$parent{$depth}'";
  381:                     } else {
  382:                         $hierarchy{$currelem} = "'$parent{$depth}'";
  383:                     }
  384:                 }
  385:             }
  386:             $display .= '&nbsp;'.$curRes->title().$whitespace.'</td>'."\n";
  387: 
  388:             if ($context eq 'imsexport') {
  389: # Existing discussion posts?
  390:                 if ($discussiontime{$ressymb} > 0) {
  391:                     $boards ++;
  392:                     $display .= '<td align="right">'
  393:                                .'<input type="checkbox" name="discussion" value="'.$count.'" />'
  394:                                .'</td>'."\n";
  395:                 } elsif ($numdisc > 0) {
  396:                     $display .= '<td>&nbsp;</td>'."\n";
  397:                 }
  398:             } elsif ($context eq 'dumpdocs') {
  399:                 my $src = $curRes->src();
  400:                 my ($filepath,$title);
  401:                 if ($src =~ m{^\Q/uploaded/$cdom/$cnum/\E}) {
  402:                     $filepath = &Apache::lonnet::filelocation('',$src);
  403:                     $filepath =~ s/\Q$crsprefix\E//;
  404:                     if ($curRes->is_map()) {
  405:                         $title = $files{$filepath};
  406:                     } else {
  407:                         $filepath =~ s{docs/}{}; 
  408:                         $title = $filepath;
  409:                         $title =~ s{^(default|\d+)/\d*/?}{};
  410:                     }
  411:                 } else {
  412:                     $title = $curRes->title();
  413:                     $title =~ s{/}{_}g;
  414:                     $title = &clean($title);
  415:                     if ($src eq '/res/lib/templates/simpleproblem.problem') {
  416:                         my ($map,$id,$res) = &Apache::lonnet::decode_symb($symb);
  417:                         $map =~ s{^uploaded/$cdom/$cnum/}{};
  418:                         $filepath = $map.'_'.$id;
  419:                         $title .= '.problem';
  420:                     } elsif ($src =~ m{^/adm/$match_domain/$match_username/(\d+)/smppg}) {
  421:                         $filepath = 'smppage_'.$1.'.db';
  422:                         $title .= '.html';
  423:                     }
  424:                 }
  425:                 $display .= '<td>'.$filepath.'</td>'.
  426:                             '<td><input type="text" size="40" name="namefor_'.$count.'" id="namefor_'.$count.'" value="'.$title.'" /></td>'."\n";
  427:             }
  428:             $display .= &Apache::loncommon::end_data_table_row();
  429:         }
  430:     }
  431:     $display .= &Apache::loncommon::end_data_table();
  432:     if ($context eq 'imsexport') {
  433:         if ($numprobs > 0) {
  434:             $display .= '<p><span class="LC_nobreak">'.
  435:                         &mt('Export format for LON-CAPA problems:').
  436:                         '<label><input type="radio" name="format" value="xml" checked="checked" />'.
  437:                         '&nbsp;'.&mt('XML').'</label>'.('&nbsp;' x3).
  438:                         '<label><input type="radio" name="format" value="html" />'.
  439:                         '&nbsp;'.&mt('HTML').'</label>'.('&nbsp;' x3).
  440:                         '<label><input type="radio" name="format" value="plaintext" />'.
  441:                         '&nbsp;'.&mt('Text').'</label></span></p>';
  442:         }
  443:     }
  444:     my $numcount;
  445:     if ($context eq 'imsexport') {
  446:         $display .= 
  447:            '<p>'.
  448:            '<input type="hidden" name="finishexport" value="1" />'.
  449:            '<input type="submit" name="exportcourse" value="'.
  450:            &mt('Export').'" /></p>';
  451:         $numcount = $count + $boards + $startcount;
  452:     } elsif ($context eq 'examblock') {
  453:         $display .=
  454:             '<p>'.
  455:             '<input type="submit" name="resourceblocks" value="'.
  456:             &mt('Copy Choices to Main Window').'" /></p>';
  457:         $numcount = $count + $startcount;
  458:     } elsif ($context eq 'dumpdocs') {
  459:         $display .= '</fieldset>'.
  460:                     '</div><div style="padding:0;clear:both;margin:0;border:0"></div>'.
  461:                     '<div>'.
  462:                     '<input type="submit" name="dumpcourse" value="'.&mt("Copy $crstype Content").'" />'.
  463:                     '</div>';
  464:         $numcount = $count + $startcount;
  465:     }
  466:     $display .= '</form>';
  467:     my $scripttag = 
  468:         &respicker_javascript($startcount,$numcount,$context,$formname,\%children,
  469:                               \%hierarchy,\@checked_maps,$numhome);
  470:     if ($context eq 'dumpdocs') {
  471:         return $scripttag.$display; 
  472:     }
  473:     my ($title,$crumbs,$args);
  474:     if ($context eq 'imsexport') { 
  475:         $title = 'Export '.$crstype.' to IMS Package';
  476:     } elsif ($context eq 'examblock') {
  477:         $title = 'Resources with Access blocked';
  478:         $args = {'only_body'      => 1,
  479:                  'add_entries' => { onload => 'javascript:recurseFolders();' }, 
  480:                 };
  481:     }
  482:     $output = &Apache::loncommon::start_page($title,$scripttag,$args);
  483:     if ($context eq 'imsexport') {
  484:         $output .= &Apache::lonhtmlcommon::breadcrumbs('IMS Export').
  485:                    &Apache::londocs::startContentScreen('tools');
  486:     } elsif ($context eq 'dumpdocs') {
  487:          $output .= &Apache::lonhtmlcommon::breadcrumbs('Copying to Authoring Space').
  488:                     &Apache::londocs::startContentScreen('tools');
  489:     }
  490:     $output .= $display;
  491:     if ($context eq 'examblock') {
  492:         $output .= &Apache::loncommon::end_page();
  493:     } elsif ($context eq 'imsexport') {
  494:         $output .= &Apache::londocs::endContentScreen();
  495:     }
  496:     return $output;
  497: }
  498: 
  499: sub respicker_javascript {
  500:     my ($startcount,$numitems,$context,$formname,$children,$hierarchy,
  501:         $checked_maps,$numhome) = @_;
  502:     return unless ((ref($children) eq 'HASH') && (ref($hierarchy) eq 'HASH')
  503:                    && (ref($checked_maps) eq 'ARRAY'));
  504:     my ($elem,$nested,$nameforelem);
  505:     if ($context eq 'dumpdocs') {
  506:         $elem='((parseInt(item)-'.$startcount.')*2)+'.$startcount;
  507:         $nested='((parseInt(nesting[item][i])-'.$startcount.')*2)+'.$startcount;
  508:         $nameforelem=$elem+1;
  509:     } else {
  510:         $elem='parseInt(item)';
  511:         $nested='parseInt(nesting[item][i])';
  512:     }
  513:     my $scripttag = <<"START";
  514: <script type="text/javascript">
  515: // <![CDATA[
  516: function checkAll(field) {
  517:     if (field.length > 0) {
  518:         for (i = 0; i < field.length; i++) {
  519:             field[i].checked = true ;
  520:         }
  521:     } else {
  522:         field.checked = true
  523:     }
  524: }
  525: 
  526: function uncheckAll(field) {
  527:     if (field.length > 0) {
  528:         for (i = 0; i < field.length; i++) {
  529:             field[i].checked = false;
  530:         }
  531:     } else {
  532:         field.checked = false;
  533:     }
  534: }
  535: 
  536: function checkFolder(form,item) {
  537:     var elem = $elem;
  538:     if (form.elements[elem].checked == true) {
  539:         containerCheck(form,item);
  540:     } else {
  541:         containerUncheck(form,item);
  542:     }
  543: }
  544: 
  545: function checkResource(form,item) {
  546:     var elem = $elem;
  547:     if (form.elements[elem].checked == false) {
  548:         containerUncheck(form,item);
  549:     }
  550: }
  551: 
  552: numitems = $numitems;
  553: var parents = new Array(numitems);
  554: var nesting = new Array(numitems);
  555: var initial = new Array();
  556: for (var i=$startcount; i<numitems; i++) {
  557:     parents[i] = new Array();
  558:     nesting[i] = new Array();
  559: }
  560: 
  561: START
  562: 
  563:     foreach my $container (sort { $a <=> $b } (keys(%{$children}))) {
  564:         my @contents = split(/:/,$children->{$container});
  565:         for (my $i=0; $i<@contents; $i ++) {
  566:             $scripttag .= 'parents['.$container.']['.$i.'] = '.$contents[$i]."\n";
  567:         }
  568:     }
  569: 
  570:     if ($context eq 'examblock') {
  571:         foreach my $item (sort { $a <=> $b } (keys(%{$hierarchy}))) {
  572:             $scripttag .= "nesting[$item] = new Array($hierarchy->{$item});\n";
  573:         }
  574:          
  575:         my @sorted_maps = sort { $a <=> $b } (@{$checked_maps});
  576:         for (my $i=0; $i<@sorted_maps; $i++) {
  577:             $scripttag .= "initial[$i] = '$sorted_maps[$i]'\n";
  578:         }
  579:         $scripttag .= <<"EXTRA";
  580: 
  581: function recurseFolders() {
  582:     if (initial.length > 0) {
  583:         for (var i=0; i<initial.length; i++) {
  584:             containerCheck(document.$formname,initial[i]);
  585:         }
  586:     }
  587:     return;
  588: }
  589: 
  590: EXTRA
  591:     } elsif ($context eq 'dumpdocs') {
  592:         my $blankmsg = &mt('An item selected has no filename set in the "Save as ..." column.');
  593:         my $dupmsg = &mt('Items selected for copying need unique filenames in the "Save as ..." column.');
  594:         my $homemsg = &mt('An Authoring Space needs to be selected.');
  595:         $scripttag .= <<"EXTRA";
  596: 
  597: function checkUnique(form,field) {
  598:     var duplicate = 0;
  599:     var blank = 0;
  600:     var numhome = '$numhome';
  601:     if (field.length > 0) {
  602:         for (i=0; i<field.length; i++) {
  603:             if (field[i].checked) {
  604:                 var item = field[i].value;
  605:                 var namefor = document.getElementById('namefor_'+item);
  606:                 if (namefor) {
  607:                     var possval = namefor.value;
  608:                     if (!possval) {
  609:                         blank = item;
  610:                         break;
  611:                     }
  612:                     for (j=i+1; j<field.length; j++) {
  613:                         if (field[j].checked) {
  614:                             var curritem = field[j].value;
  615:                             var currnamefor = document.getElementById('namefor_'+curritem);
  616:                             if (currnamefor) {
  617:                                 var currval = currnamefor.value;
  618:                                 if (currval == possval) {
  619:                                     duplicate = curritem;
  620:                                     break;
  621:                                 }
  622:                             }
  623:                         }
  624:                     }
  625:                     if (duplicate) {
  626:                         break;
  627:                     }
  628:                 }
  629:             }
  630:         }
  631:     }
  632:     if (blank) {
  633:         alert('$blankmsg');
  634:         return false;
  635:     }
  636:     if (duplicate) {
  637:         alert('$dupmsg');
  638:         return false;
  639:     }
  640:     if (numhome > 1) {
  641:         if (!form.authorspace.options[form.authorspace.selectedIndex].value) {
  642:             alert('$homemsg');
  643:             return false;
  644:         }
  645:     }
  646:     return true;
  647: }
  648: 
  649: EXTRA
  650: 
  651:     }
  652: 
  653:     $scripttag .= <<"END";
  654: 
  655: function containerCheck(form,item) {
  656:     var elem = $elem;
  657:     form.elements[elem].checked = true;
  658:     if(Object.prototype.toString.call(parents[item]) === '[object Array]') {
  659:         if (parents[item].length > 0) {
  660:             for (var j=0; j<parents[item].length; j++) {
  661:                 containerCheck(form,parents[item][j]);
  662:             }
  663:         }
  664:     }
  665: }
  666: 
  667: function containerUncheck(form,item) {
  668:     if(Object.prototype.toString.call(nesting[item]) === '[object Array]') {
  669:         if (nesting[item].length > 0) {
  670:             for (var i=0; i<nesting[item].length; i++) {
  671:                 var nested = $nested;
  672:             }
  673:         }
  674:     }
  675:     return;
  676: }
  677: 
  678: END
  679: 
  680:     if ($context eq 'examblock') {
  681:         $scripttag .= <<ENDEX;
  682: function writeToOpener(maps,resources) {
  683:     var checkedmaps = '';
  684:     var checkedresources = '';
  685:     for (var i=0; i<document.$formname.archive.length; i++) {
  686:         if (document.$formname.archive[i].checked) {
  687:             var isResource = 1;
  688:             var include = 1;
  689:             var elemnum = i+1+$startcount;
  690:             if (Object.prototype.toString.call(parents[elemnum]) === '[object Array]') {
  691:                 if (parents[elemnum].length > 0) {
  692:                     isResource = 0;
  693:                 }
  694:             }
  695:             if (isResource == 1) {
  696:                 if (nesting[elemnum].length > 0) {
  697:                     var lastelem = nesting[elemnum].length-1;
  698:                     if (document.$formname.elements[nesting[elemnum][lastelem]].checked) {
  699:                         include = 0;
  700:                     }
  701:                 }
  702:             }
  703:             if (include == 1) {
  704:                 if (isResource == 1) {
  705:                     checkedresources += document.$formname.archive[i].value+',';
  706:                 } else {
  707:                     checkedmaps += document.$formname.archive[i].value+',';
  708:                 }
  709:             }
  710:         }
  711:     }
  712:     opener.document.getElementById(maps).value = checkedmaps;
  713:     opener.document.getElementById(resources).value = checkedresources;
  714:     window.close();
  715:     return false;
  716: }
  717: 
  718: ENDEX
  719:     }
  720: 
  721:     $scripttag .= '
  722: // ]]>
  723: </script>
  724: ';
  725:     return $scripttag;
  726: }
  727: 
  728: sub get_navmap_object {
  729:     my ($crstype,$context) = @_;
  730:     my $navmap = Apache::lonnavmaps::navmap->new();
  731:     my $outcome;
  732:     if (!defined($navmap)) {
  733:         if ($context eq 'imsexport') {
  734:             $outcome = &Apache::loncommon::start_page('Export '.$crstype.' to IMS Package').
  735:                       '<h2>'.&mt('IMS Export Failed').'</h2>';
  736:         } elsif ($context eq 'examblock') {
  737:             $outcome = &Apache::loncommon::start_page('Selection of Resources for Blocking',
  738:                                                        undef,{'only_body' => 1,}).
  739:                       '<h2>'.&mt('Resource Display Failed').'</h2>';  
  740:         } elsif ($context eq 'dumpdocs') {
  741:             $outcome = '<h2>'.&mt('Copying to Authoring Space unavailable');
  742:         }
  743:         $outcome .= '<div class="LC_error">';
  744:         if ($crstype eq 'Community') {
  745:             $outcome .= &mt('Unable to retrieve information about community contents');
  746:         } else {
  747:             $outcome .= &mt('Unable to retrieve information about course contents');
  748:         }
  749:         $outcome .= '</div>';
  750:         if (($context eq 'imsexport') || ($context eq 'dumpdocs')) {
  751:             $outcome .= '<a href="/adm/coursedocs">';
  752:             if ($crstype eq 'Community') {
  753:                 $outcome .= &mt('Return to Community Editor');
  754:             } else {
  755:                 $outcome .= &mt('Return to Course Editor');
  756:             }
  757:             $outcome .= '</a>';
  758:             if ($context eq 'imsexport') {
  759:                 &Apache::lonnet::logthis('IMS export failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
  760:             } else {
  761:                 &Apache::lonnet::logthis('Copying to Authoring Space failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
  762:             }
  763:         } elsif ($context eq 'examblock') {
  764:             $outcome .=  '<href="javascript:window.close();">'.&mt('Close window').'</a>';         
  765:         }
  766:         return (undef,$outcome);
  767:     } else {
  768:         return ($navmap);
  769:     }
  770: }
  771: 
  772: sub clean {
  773:     my ($title)=@_;
  774:     $title=~s/[^\w\/\!\$\%\^\*\-\_\=\+\;\:\,\\\|\`\~]+/\_/gs;
  775:     return $title;
  776: }
  777: 
  778: sub enumerate_course_contents {
  779:     my ($navmap,$map_url,$resource_symb,$titleref,$context,$cdom,$cnum) = @_;
  780:     if ((ref($navmap)) && (ref($map_url) eq 'HASH') &&
  781:         (ref($resource_symb) eq 'HASH') && (ref($titleref) eq 'HASH')) {
  782:         my $it = $navmap->getIterator(undef,undef,undef,1,undef,undef);
  783:         my $count = 0;
  784:         while (my $curRes = $it->next()) {
  785:             if (ref($curRes)) {
  786:                 my $symb = $curRes->symb();
  787:                 my $ressymb = $symb;
  788:                 if ($context eq 'dumpdocs') {
  789:                     next unless (($curRes->src() =~ m{^\Q/uploaded/$cdom/$cnum/\E(docs|supplemental|simplepage)/}) ||
  790:                                  ($curRes->src() =~ m{^\Q/uploaded/$cdom/$cnum/\E(default|supplemental)_\d+\.(sequence|page)}) ||
  791:                                  ($curRes->src() eq '/res/lib/templates/simpleproblem.problem') ||
  792:                                  ($curRes->src() =~ m{^/adm/$match_domain/$match_username/\d+/smppg}));
  793:                 } elsif ($ressymb =~ m{adm/($match_domain)/($match_username)/(\d+)/bulletinboard$}) {
  794:                     unless ($ressymb =~ m{adm/wrapper/adm}) {
  795:                         $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.
  796:                                    '/bulletinboard';
  797:                     }
  798:                 }
  799:                 $count ++;
  800:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
  801:                     $map_url->{$count} = (&Apache::lonnet::decode_symb($symb))[2];
  802:                 } else {
  803:                     $resource_symb->{$count} = $ressymb;
  804:                 }
  805:                 $titleref->{$count} = $curRes->title();
  806:             }
  807:         }
  808:     }
  809:     return;
  810: }
  811: 
  812: 1;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>