Annotation of loncom/interface/loncourserespicker.pm, revision 1.8
1.1 raeburn 1: # The LearningOnline Network
2: #
1.8 ! raeburn 3: # $Id: loncourserespicker.pm,v 1.7 2013/11/12 14:36:07 raeburn Exp $
1.1 raeburn 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
1.7 raeburn 40: (b) subject to access blocking for the duriation of an exam/quiz.
41: (c) dumped to an Authoring Space
1.1 raeburn 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,
1.6 raeburn 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
1.1 raeburn 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
1.7 raeburn 63: context in which resource/folder selection is being made.
1.1 raeburn 64:
1.7 raeburn 65: The three contexts currently supported are: IMS export, selection of
1.1 raeburn 66: content to be subject to access restructions for the duration of an
1.7 raeburn 67: exam, and selection of items for dumping to an Authoring Space.
1.1 raeburn 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:
1.7 raeburn 78: Inputs: 9.
1.1 raeburn 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:
1.7 raeburn 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:
1.1 raeburn 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
1.7 raeburn 126: (imsexport, examblock or dumpdocs).
1.1 raeburn 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:
1.7 raeburn 136: Output: 1. Javascript (within <script></script> tags.
1.1 raeburn 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:
1.7 raeburn 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:
1.1 raeburn 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;
1.2 raeburn 204: use Apache::londocs;
1.1 raeburn 205: use Apache::lonlocal;
206: use LONCAPA qw(:DEFAULT :match);
207:
208: sub create_picker {
1.7 raeburn 209: my ($navmap,$context,$formname,$crstype,$blockedmaps,$blockedresources,$block,$preamble,$numhome,$uploadedfiles) = @_;
1.1 raeburn 210: return unless (ref($navmap));
1.7 raeburn 211: my ($it,$output,$numdisc,%maps,%resources,%discussiontime,%currmaps,%currresources,%files);
1.1 raeburn 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};
1.7 raeburn 218: } elsif (ref($uploadedfiles) eq 'HASH') {
219: %files = %{$uploadedfiles};
1.1 raeburn 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");
1.7 raeburn 232: my $whitespace =
1.1 raeburn 233: '<img src="'.$location.'/whitespace_21.gif" class="LC_docs_spacer" alt="" />';
234:
1.7 raeburn 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);
1.1 raeburn 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'".');"';
1.7 raeburn 244: $info = &mt('Items in '.lc($crstype).' for which access will be blocked.');
1.1 raeburn 245: }
1.7 raeburn 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.'.');
1.1 raeburn 254: $startcount = 5;
255: }
1.7 raeburn 256: $togglebuttons = '<input type="button" value="'.&mt('check all').'" '.
257: 'onclick="javascript:checkAll(document.'.$formname.'.archive)" />'.
258: ' <input type="button" value="'.&mt('uncheck all').'"'.
259: ' onclick="javascript:uncheckAll(document.'.$formname.'.archive)" />';
260: $display = '<form name="'.$formname.'" action="" method="post"'.$onsubmit.'>'."\n";
1.1 raeburn 261: if ($context eq 'imsexport') {
1.7 raeburn 262: $display .= $info.
263: '<div class="LC_columnSection">'."\n".
1.1 raeburn 264: '<fieldset>'.
1.7 raeburn 265: '<legend>'.&mt('Content items').'</legend>'."\n".
266: $togglebuttons.
267: '</fieldset>';
268: %discussiontime = &Apache::lonnet::dump('discussiontimes',$cdom,$cnum);
1.1 raeburn 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: ' <input type="button" value="'.&mt('uncheck all').'"'.
277: ' onclick="javascript:uncheckAll(document.'.$formname.'.discussion)" />'.
1.2 raeburn 278: '</fieldset>';
1.1 raeburn 279: }
1.7 raeburn 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').(' 'x4).$togglebuttons.'</legend>'.
288: $info;
1.1 raeburn 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>';
1.7 raeburn 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>';
1.1 raeburn 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;
1.7 raeburn 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$|) {
1.1 raeburn 325: unless ($ressymb =~ m|adm/wrapper/adm|) {
326: $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard';
327: }
328: }
1.7 raeburn 329: $count ++;
330: my $currelem;
331: if ($context eq 'imsexport') {
332: $currelem = $count+$boards+$startcount;
333: } else {
334: $currelem = $count+$startcount;
335: }
1.1 raeburn 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;
1.7 raeburn 341: $display .= 'onclick="javascript:checkFolder(document.'.$formname.','."'$currelem'".')" ';
1.1 raeburn 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: }
1.7 raeburn 351: $display .= 'onclick="javascript:checkResource(document.'.$formname.','."'$currelem'".')" ';
1.1 raeburn 352: if ($currresources{$symb}) {
353: $display .= 'checked="checked"';
354: }
355: }
356: $display .= ' />'."\n";
1.7 raeburn 357: if ($context eq 'dumpdocs') {
358: $display .= '</td><td valign="top">';
359: }
1.1 raeburn 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()) {
1.4 bisitz 365: $icon = 'src="'.$location.'/navmap.folder.open.gif" alt="'.&mt('Folder').'"';
1.1 raeburn 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.' /> '."\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: }
1.7 raeburn 386: $display .= ' '.$curRes->title().$whitespace.'</td>'."\n";
1.1 raeburn 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> </td>'."\n";
397: }
1.7 raeburn 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";
1.1 raeburn 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: ' '.&mt('XML').'</label>'.(' ' x3).
438: '<label><input type="radio" name="format" value="html" />'.
439: ' '.&mt('HTML').'</label>'.(' ' x3).
440: '<label><input type="radio" name="format" value="plaintext" />'.
441: ' '.&mt('Text').'</label></span></p>';
442: }
443: }
1.7 raeburn 444: my $numcount;
1.1 raeburn 445: if ($context eq 'imsexport') {
446: $display .=
1.7 raeburn 447: '<p>'.
1.1 raeburn 448: '<input type="hidden" name="finishexport" value="1" />'.
449: '<input type="submit" name="exportcourse" value="'.
1.7 raeburn 450: &mt('Export').'" /></p>';
451: $numcount = $count + $boards + $startcount;
1.1 raeburn 452: } elsif ($context eq 'examblock') {
453: $display .=
1.7 raeburn 454: '<p>'.
1.1 raeburn 455: '<input type="submit" name="resourceblocks" value="'.
1.7 raeburn 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>'.
1.8 ! raeburn 462: '<input type="submit" name="dumpcourse" value="'.&mt("Copy $crstype Content").'" />'.
1.7 raeburn 463: '</div>';
464: $numcount = $count + $startcount;
1.1 raeburn 465: }
1.7 raeburn 466: $display .= '</form>';
1.1 raeburn 467: my $scripttag =
468: &respicker_javascript($startcount,$numcount,$context,$formname,\%children,
469: \%hierarchy,\@checked_maps);
1.7 raeburn 470: if ($context eq 'dumpdocs') {
471: return $scripttag.$display;
472: }
1.1 raeburn 473: my ($title,$crumbs,$args);
1.7 raeburn 474: if ($context eq 'imsexport') {
1.1 raeburn 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: }
1.3 raeburn 482: $output = &Apache::loncommon::start_page($title,$scripttag,$args);
1.1 raeburn 483: if ($context eq 'imsexport') {
1.2 raeburn 484: $output .= &Apache::lonhtmlcommon::breadcrumbs('IMS Export').
485: &Apache::londocs::startContentScreen('tools');
1.7 raeburn 486: } elsif ($context eq 'dumpdocs') {
1.8 ! raeburn 487: $output .= &Apache::lonhtmlcommon::breadcrumbs('Copying to Authoring Space').
1.7 raeburn 488: &Apache::londocs::startContentScreen('tools');
1.1 raeburn 489: }
490: $output .= $display;
491: if ($context eq 'examblock') {
492: $output .= &Apache::loncommon::end_page();
1.2 raeburn 493: } elsif ($context eq 'imsexport') {
494: $output .= &Apache::londocs::endContentScreen();
1.1 raeburn 495: }
496: return $output;
497: }
498:
499: sub respicker_javascript {
500: my ($startcount,$numitems,$context,$formname,$children,$hierarchy,
501: $checked_maps) = @_;
502: return unless ((ref($children) eq 'HASH') && (ref($hierarchy) eq 'HASH')
503: && (ref($checked_maps) eq 'ARRAY'));
1.7 raeburn 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: }
1.1 raeburn 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) {
1.7 raeburn 537: var elem = $elem;
538: if (form.elements[elem].checked == true) {
1.1 raeburn 539: containerCheck(form,item);
540: } else {
541: containerUncheck(form,item);
542: }
543: }
544:
545: function checkResource(form,item) {
1.7 raeburn 546: var elem = $elem;
547: if (form.elements[elem].checked == false) {
1.1 raeburn 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
1.7 raeburn 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: $scripttag .= <<"EXTRA";
595:
596: function checkUnique(form,field) {
597: var duplicate = 0;
598: var blank = 0;
599: if (field.length > 0) {
600: for (i=0; i<field.length; i++) {
601: if (field[i].checked) {
602: var item = field[i].value;
603: var namefor = document.getElementById('namefor_'+item);
604: if (namefor) {
605: var possval = namefor.value;
606: if (!possval) {
607: blank = item;
608: break;
609: }
610: for (j=i+1; j<field.length; j++) {
611: if (field[j].checked) {
612: var curritem = field[j].value;
613: var currnamefor = document.getElementById('namefor_'+curritem);
614: if (currnamefor) {
615: var currval = currnamefor.value;
616: if (currval == possval) {
617: duplicate = curritem;
618: break;
619: }
620: }
621: }
622: }
623: if (duplicate) {
624: break;
625: }
626: }
627: }
628: }
629: }
630: if (blank) {
631: alert('$blankmsg');
632: return false;
633: }
634: if (duplicate) {
635: alert('$dupmsg');
636: return false;
637: }
638: return true;
639: }
640:
641: EXTRA
642:
1.1 raeburn 643: }
644:
645: $scripttag .= <<"END";
646:
647: function containerCheck(form,item) {
1.7 raeburn 648: var elem = $elem;
649: form.elements[elem].checked = true;
1.1 raeburn 650: if(Object.prototype.toString.call(parents[item]) === '[object Array]') {
651: if (parents[item].length > 0) {
652: for (var j=0; j<parents[item].length; j++) {
653: containerCheck(form,parents[item][j]);
654: }
655: }
656: }
657: }
658:
659: function containerUncheck(form,item) {
660: if(Object.prototype.toString.call(nesting[item]) === '[object Array]') {
661: if (nesting[item].length > 0) {
662: for (var i=0; i<nesting[item].length; i++) {
1.7 raeburn 663: var nested = $nested;
1.1 raeburn 664: }
665: }
666: }
667: return;
668: }
669:
670: END
671:
672: if ($context eq 'examblock') {
673: $scripttag .= <<ENDEX;
674: function writeToOpener(maps,resources) {
675: var checkedmaps = '';
676: var checkedresources = '';
677: for (var i=0; i<document.$formname.archive.length; i++) {
678: if (document.$formname.archive[i].checked) {
679: var isResource = 1;
680: var include = 1;
681: var elemnum = i+1+$startcount;
682: if (Object.prototype.toString.call(parents[elemnum]) === '[object Array]') {
683: if (parents[elemnum].length > 0) {
684: isResource = 0;
685: }
686: }
687: if (isResource == 1) {
688: if (nesting[elemnum].length > 0) {
689: var lastelem = nesting[elemnum].length-1;
690: if (document.$formname.elements[nesting[elemnum][lastelem]].checked) {
691: include = 0;
692: }
693: }
694: }
695: if (include == 1) {
696: if (isResource == 1) {
697: checkedresources += document.$formname.archive[i].value+',';
698: } else {
699: checkedmaps += document.$formname.archive[i].value+',';
700: }
701: }
702: }
703: }
704: opener.document.getElementById(maps).value = checkedmaps;
705: opener.document.getElementById(resources).value = checkedresources;
706: window.close();
707: return false;
708: }
709:
710: ENDEX
711: }
712:
713: $scripttag .= '
714: // ]]>
715: </script>
716: ';
717: return $scripttag;
718: }
719:
720: sub get_navmap_object {
721: my ($crstype,$context) = @_;
722: my $navmap = Apache::lonnavmaps::navmap->new();
723: my $outcome;
724: if (!defined($navmap)) {
725: if ($context eq 'imsexport') {
726: $outcome = &Apache::loncommon::start_page('Export '.$crstype.' to IMS Package').
727: '<h2>'.&mt('IMS Export Failed').'</h2>';
728: } elsif ($context eq 'examblock') {
729: $outcome = &Apache::loncommon::start_page('Selection of Resources for Blocking',
730: undef,{'only_body' => 1,}).
731: '<h2>'.&mt('Resource Display Failed').'</h2>';
1.7 raeburn 732: } elsif ($context eq 'dumpdocs') {
1.8 ! raeburn 733: $outcome = '<h2>'.&mt('Copying to Authoring Space unavilable');
1.7 raeburn 734: }
1.1 raeburn 735: $outcome .= '<div class="LC_error">';
736: if ($crstype eq 'Community') {
737: $outcome .= &mt('Unable to retrieve information about community contents');
738: } else {
739: $outcome .= &mt('Unable to retrieve information about course contents');
740: }
741: $outcome .= '</div>';
1.7 raeburn 742: if (($context eq 'imsexport') || ($context eq 'dumpdocs')) {
1.1 raeburn 743: $outcome .= '<a href="/adm/coursedocs">';
744: if ($crstype eq 'Community') {
745: $outcome .= &mt('Return to Community Editor');
746: } else {
747: $outcome .= &mt('Return to Course Editor');
748: }
749: $outcome .= '</a>';
1.7 raeburn 750: if ($context eq 'imsexport') {
751: &Apache::lonnet::logthis('IMS export failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
752: } else {
1.8 ! raeburn 753: &Apache::lonnet::logthis('Copying to Authoring Space failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
1.7 raeburn 754: }
1.1 raeburn 755: } elsif ($context eq 'examblock') {
756: $outcome .= '<href="javascript:window.close();">'.&mt('Close window').'</a>';
757: }
758: return (undef,$outcome);
759: } else {
760: return ($navmap);
761: }
762: }
763:
1.7 raeburn 764: sub clean {
765: my ($title)=@_;
766: $title=~s/[^\w\/\!\$\%\^\*\-\_\=\+\;\:\,\\\|\`\~]+/\_/gs;
767: return $title;
768: }
769:
770: sub enumerate_course_contents {
771: my ($navmap,$map_url,$resource_symb,$titleref,$context,$cdom,$cnum) = @_;
772: if ((ref($navmap)) && (ref($map_url) eq 'HASH') &&
773: (ref($resource_symb) eq 'HASH') && (ref($titleref) eq 'HASH')) {
774: my $it = $navmap->getIterator(undef,undef,undef,1,undef,undef);
775: my $count = 0;
776: while (my $curRes = $it->next()) {
777: if (ref($curRes)) {
778: my $symb = $curRes->symb();
779: my $ressymb = $symb;
780: if ($context eq 'dumpdocs') {
781: next unless (($curRes->src() =~ m{^\Q/uploaded/$cdom/$cnum/\E(docs|supplemental|simplepage)/}) ||
782: ($curRes->src() =~ m{^\Q/uploaded/$cdom/$cnum/\E(default|supplemental)_\d+\.(sequence|page)}) ||
783: ($curRes->src() eq '/res/lib/templates/simpleproblem.problem') ||
784: ($curRes->src() =~ m{^/adm/$match_domain/$match_username/\d+/smppg}));
785: } elsif ($ressymb =~ m{adm/($match_domain)/($match_username)/(\d+)/bulletinboard$}) {
786: unless ($ressymb =~ m{adm/wrapper/adm}) {
787: $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.
788: '/bulletinboard';
789: }
790: }
791: $count ++;
792: if (($curRes->is_sequence()) || ($curRes->is_page())) {
793: $map_url->{$count} = (&Apache::lonnet::decode_symb($symb))[2];
794: } else {
795: $resource_symb->{$count} = $ressymb;
796: }
797: $titleref->{$count} = $curRes->title();
798: }
799: }
800: }
801: return;
802: }
803:
1.1 raeburn 804: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>