Annotation of loncom/interface/lonwishlist.pm, revision 1.2
1.1 wenzelju 1: # The LearningOnline Network with CAPA
2: # Routines to control the wishlist
3: #
1.2 ! wenzelju 4: # $Id: lonwishlist.pm,v 1.1 2010/08/10 14:30:20 wenzelju Exp $
1.1 wenzelju 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
28:
29:
30:
31: package Apache::lonwishlist;
32:
33: use strict;
34: use Apache::Constants qw(:common);
35: use Apache::lonnet;
36: use Apache::loncommon();
37: use Apache::lonhtmlcommon;
38: use Apache::lonlocal;
1.2 ! wenzelju 39: use LONCAPA;
1.1 wenzelju 40: use Tree;
41:
42:
43: # Global variables
44: my $root;
45: my @childrenRt;
46: my %TreeHash;
47: my %TreeToHash;
48: my @allFolders;
49: my @allNodes;
50: my $indentConst = 20;
51:
52:
53: # Read wishlist from user-data
54: sub getWishlist {
1.2 ! wenzelju 55: my %wishlist = &Apache::lonnet::dump('wishlist');
! 56: foreach my $i ( keys %wishlist) {
1.1 wenzelju 57: #File not found. This appears at the first time using the wishlist
58: #Create file and put 'root' into it
59: if ($i =~m/^error:No such file/) {
60: &Apache::lonnet::logthis($i.'! Create file by putting in the "root" of the directory tree.');
61: &Apache::lonnet::put('wishlist', {'root' => ''});
1.2 ! wenzelju 62: %wishlist = &Apache::lonnet::dump('wishlist');
1.1 wenzelju 63: }
64: elsif ($i =~ /^(con_lost|error|no_such_host)/i) {
65: &Apache::lonnet::logthis('ERROR while attempting to get wishlist: '.$i);
66: return 'error';
67: }
68: }
69:
1.2 ! wenzelju 70: # if we got no keys in hash returned by dump(), return error.
! 71: # wishlist will not be loaded, instead the user will be asked to try again later
1.1 wenzelju 72: if ((keys %wishlist) == 0) {
73: &Apache::lonnet::logthis('ERROR while attempting to get wishlist: no keys retrieved!');
74: return 'error';
75: }
76:
77: return %wishlist;
78: }
79:
80:
81: # Write wishlist to user-data
82: sub putWishlist {
83: my $wishlist = shift;
84: &Apache::lonnet::put('wishlist',$wishlist);
85: }
86:
87:
88: # Removes all existing entrys for wishlist in user-data
89: sub deleteWishlist {
90: my @wishlistkeys = &Apache::lonnet::getkeys('wishlist');
91: my %wishlist = &Apache::lonnet::del('wishlist',\@wishlistkeys);
92: }
93:
94:
95: # Create a new entry
96: sub newEntry() {
97: my ($title, $path, $note) = @_;
98: my $date = gmtime();
99: # Create Entry-Object
100: my $entry = Entry->new(title => $title, path => $path, note => $note, date => $date);
101: # Create Tree-Object, this correspones a node in the wishlist-tree
102: my $tree = Tree->new($entry);
103: # Add this node to wishlist-tree
104: my $folderIndex = $env{'form.folders'};
105: if ($folderIndex ne '') {
106: @allFolders = ();
107: &getFoldersToArray(\@childrenRt);
108: my $folderToInsertOn = &Tree::getNodeByIndex($folderIndex,\@allFolders);
109: $folderToInsertOn->add_child($tree);
110: }
111: else {
112: $root->add_child($tree);
113: }
114: &saveChanges();
115: }
116:
117:
118: # Delete entries
119: sub deleteEntries {
120: my $marked = shift;
121: &getNodesToArray(\@childrenRt);
122:
123: foreach my $m (@$marked) {
124: my $found = &Tree::getNodeByIndex($m, \@allNodes);
125: &Tree::removeNode($found);
126: }
127: @allNodes = ();
128: &saveChanges();
129: }
130:
131:
132: # Sort entries
133: sub sortEntries {
134: my $indexNode = shift;
135: my $at = shift;
136:
137: &getNodesToArray(\@childrenRt);
138: my $foundNode = &Tree::getNodeByIndex($indexNode, \@allNodes);
139:
140: &Tree::moveNode($foundNode,$at,undef);
141: @allNodes = ();
142: }
143:
144:
145: # Move entries
146: sub moveEntries {
147: my $indexNodesToMove = shift;
148: my $indexParent = shift;
149: my @nodesToMove = ();
150:
1.2 ! wenzelju 151: # get all nodes that should be moved
1.1 wenzelju 152: &getNodesToArray(\@childrenRt);
153: foreach my $index (@$indexNodesToMove) {
154: my $foundNode = &Tree::getNodeByIndex($index, \@allNodes);
155: push(@nodesToMove, $foundNode);
156: }
157:
158: foreach my $node (@nodesToMove) {
159: my $foundParent;
160: my $parentIsIn = 0;
161: foreach my $n (@nodesToMove) {
162: if ($node->parent()->value() ne "root") {
163: if ($node->parent()->value()->nindex() == $n->value()->nindex()) {
164: $parentIsIn = 1;
165: }
166: }
167: }
168: if (!$parentIsIn) {
169: if ($indexParent ne "root") {
170: $foundParent = &Tree::getNodeByIndex($indexParent, \@allNodes);
171: &Tree::moveNode($node,undef,$foundParent);
172: }
173: else {
174: &Tree::moveNode($node,undef,$root);
175: }
176: }
177: }
178: @allNodes = ();
179: }
180:
181:
182: # Set a new title for an entry
183: sub setNewTitle {
184: my ($nodeindex, $newTitle) = @_;
185: &getNodesToArray(\@childrenRt);
186: my $found = &Tree::getNodeByIndex($nodeindex, \@allNodes);
187: $found->value()->title($newTitle);
188: @allNodes = ();
189: }
190:
191:
192: # Set a new note for an entry
193: sub setNewNote {
194: my ($nodeindex, $newNote) = @_;
195: &getNodesToArray(\@childrenRt);
196: my $found = &Tree::getNodeByIndex($nodeindex, \@allNodes);
197: $found->value()->note($newNote);
198: @allNodes = ();
199: }
200:
201:
202: # Save all changes
203: sub saveChanges {
204: @childrenRt = $root->children();
205: &Tree::TreeIndex(\@childrenRt);
206: &Tree::setCountZero();
207: &Tree::RootToHash(\@childrenRt);
208: &Tree::TreeToHash(\@childrenRt);
209: &deleteWishlist();
210: &putWishlist(\%TreeToHash);
211:
212: }
213:
214:
215: # Return the names for all exiting folders in option-tags, so
216: # a new link or a new folder can be created in an existing folder
217: my $indent = 0;
218: my $foldersOption;
219: sub getFoldersForOption {
220: my $nodes = shift;
221:
222: foreach my $n (@$nodes) {
223: if ($n->value()->path() eq '') {
224: $foldersOption .= '<option value="'.$n->value()->nindex().'" style="margin-left:'.$indent.'px">'.
225: $n->value()->title().
226: '</option>';
227:
228: my @children = $n->children();
229: if ($#children >=0) {
230: $indent += 10;
231: &getFoldersForOption(\@children);
232: $indent -= 10;
233: }
234: }
235: }
236: }
237:
238:
239: sub getfoldersOption {
240: if (&getWishlist ne 'error') {
241: %TreeHash = &getWishlist();
242: $root = &Tree::HashToTree();
243: @childrenRt = $root->children();
244: &getFoldersForOption(\@childrenRt);
1.2 ! wenzelju 245: my $options = '<option value="" selected="selected">('.&mt('Top level').')</option>'.$foldersOption;
1.1 wenzelju 246: $foldersOption = '';
247: return $options;
248: }
249: else {
250: return '';
251: }
252: }
253:
254:
255: # Put all folder-nodes to an array
256: sub getFoldersToArray {
257: my $children = shift;
258: foreach my $c (@$children) {
259: if ($c->value()->path() eq '') {
260: push(@allFolders,$c);
261: }
262: my @newchildren = $c->children();
263: if ($#newchildren >= 0) {
264: &getFoldersToArray(\@newchildren);
265: }
266: }
267: }
268:
269:
270: # Put all nodes to an array
271: sub getNodesToArray {
272: my $children = shift;
273: foreach my $c (@$children) {
274: push(@allNodes,$c);
275: my @newchildren = $c->children();
276: if ($#newchildren >= 0) {
277: &getNodesToArray(\@newchildren);
278: }
279: }
280: }
281:
282:
283: # Return a script-tag containing Javascript-function
284: # needed for wishlist actions like 'new link' ect.
285: sub JSforWishlist {
286: my $startPagePopup = &Apache::loncommon::start_page('Wishlist',undef,
287: {'only_body' => 1,
288: 'js_ready' => 1,
289: 'bgcolor' => '#FFFFFF',});
290: my $endPagePopup = &Apache::loncommon::end_page({'js_ready' => 1});
291:
292: @allFolders = ();
293: &getFoldersToArray(\@childrenRt);
294: &getFoldersForOption(\@childrenRt);
295:
296: # texthash
297: my %lt = &Apache::lonlocal::texthash(
298: 'nl' => 'New Link',
299: 'nf' => 'New Folder',
300: 'lt' => 'Link Title',
301: 'ft' => 'Folder Title',
302: 'pa' => 'Path',
303: 'nt' => 'Note',
304: 'si' => 'Save in',
305: 'cl' => 'Cancel');
306:
307:
308: my $inPageNewLink = '<h1>'.$lt{'nl'}.'</h1>'.
309: '<form method="post" name="newlink" action="/adm/wishlist" target="wishlist" '.
310: 'onsubmit="return newlinksubmit();" >'.
311: &Apache::lonhtmlcommon::start_pick_box().
312: &Apache::lonhtmlcommon::row_title($lt{'lt'}).
313: '<input type="text" name="title" size="45" value="" />'.
314: &Apache::lonhtmlcommon::row_closure().
315: &Apache::lonhtmlcommon::row_title($lt{'pa'}).
316: '<input type="text" name="path" size="45" value="" />'.
317: &Apache::lonhtmlcommon::row_closure().
318: &Apache::lonhtmlcommon::row_title($lt{'nt'}).
319: '<textarea name="note" rows="3" cols="35" style="width:100%"></textarea>'.
320: &Apache::lonhtmlcommon::row_closure(1).
321: &Apache::lonhtmlcommon::end_pick_box().
322: '<br/><br/>'.
323: '<input type="submit" value="'.$lt{'si'}.'" />'.
324: '<select name="folders">'.
1.2 ! wenzelju 325: '<option value="" selected="selected">('.&mt('Top level').')</option>'.
1.1 wenzelju 326: $foldersOption.
327: '</select>'.
328: '<input type="button" value="'.$lt{'cl'}.'" onclick="javascript:window.close();" />'.
329: '</form>';
330:
331: my $inPageNewFolder = '<h1>'.$lt{'nf'}.'</h1>'.
332: '<form method="post" name="newfolder" action="/adm/wishlist" target="wishlist" '.
333: 'onsubmit="return newfoldersubmit();" >'.
334: &Apache::lonhtmlcommon::start_pick_box().
335: &Apache::lonhtmlcommon::row_title($lt{'ft'}).
336: '<input type="text" name="title" size="45" value="" /><br />'.
337: &Apache::lonhtmlcommon::row_closure().
338: &Apache::lonhtmlcommon::row_title($lt{'nt'}).
339: '<textarea name="note" rows="3" cols="35" style="width:100%"></textarea><br />'.
340: &Apache::lonhtmlcommon::row_closure(1).
341: &Apache::lonhtmlcommon::end_pick_box().
342: '<br/><br/>'.
343: '<input type="submit" value="'.$lt{'si'}.'" />'.
344: '<select name="folders">'.
1.2 ! wenzelju 345: '<option value="" selected="selected">('.&mt('Top level').')</option>'.
1.1 wenzelju 346: $foldersOption.
347: '</select>'.
348: '<input type="button" value="'.$lt{'cl'}.'" onclick="javascript:window.close();" />'.
349: '</form>';
350:
351: # Remove all \n for inserting on javascript document.write
352: $inPageNewLink =~ s/\n//g;
353: $inPageNewFolder =~ s/\n//g;
354:
355: my $warningLink = &mt('You must insert a title and a path!');
356: my $warningFolder = &mt('You must insert a title!');
357: my $warningDelete = &mt('Are you sure you want to delete the selected entries? Deleting a folder also deletes all entries within this folder!');
358: my $warningSave = &mt('You have unsaved changes. You can either save these changes now by clicking "ok" or click "cancel" if you do not want to save your changes.');
359: my $warningMove = &mt('You must select a destination folder!');
360: $foldersOption = '';
361:
362: my $js = &Apache::lonhtmlcommon::scripttag(<<JAVASCRIPT);
363: function newLink() {
364: newlinkWin=window.open('','newlinkWin','width=580,height=320,scrollbars=yes');
365: newlinkWin.document.write('$startPagePopup'
366: +'<script type="text\/javascript">'
367: +'function newlinksubmit(){'
368: +'var path = document.getElementsByName("path")[0].value;'
369: +'var title = document.getElementsByName("title")[0].value;'
370: +'if (!path || !title) {'
371: +'alert("$warningLink");'
372: +'return false;}'
373: +'else {'
374: +'window.close();'
375: +'return true;}}'
376: +'<\/scr'+'ipt>'
377: +'$inPageNewLink'
378: +'$endPagePopup');
379: newlinkWin.document.close();
380: }
381:
382: function newFolder() {
383: newfolderWin=window.open('','newfolderWin','width=580,height=270, scrollbars=yes');
384: newfolderWin.document.write('$startPagePopup'
385: +'<script type="text\/javascript">'
386: +'function newfoldersubmit(){'
387: +'var title = document.getElementsByName("title")[0].value;'
388: +'if (!title) {'
389: +'alert("$warningFolder");'
390: +'return false;}'
391: +'else {'
392: +'window.close();'
393: +'return true;}}'
394: +'<\/scr'+'ipt>'
395: +'$inPageNewFolder'
396: +'$endPagePopup');
397: newfolderWin.document.close();
398: }
399:
400: function setFormAction(action,mode) {
401: var r = true;
402: setAction('');
403: if (action == 'delete') {
404: r = confirm("$warningDelete");
405: setAction('delete');
406: }
407: else if (action == 'save') {
408: var d = getDifferences();
409: if (d) {
410: if (!confirm('$warningSave')) {
411: setAction('noSave');
412: }
413: }
414: r = true;
415: }
416: document.getElementsByName('list')[0].setAttribute("action", "/adm/wishlist?mode="+mode);
1.2 ! wenzelju 417: if (r) {
1.1 wenzelju 418: document.getElementsByName('list')[0].submit();
419: }
420: }
421:
422: function setAction(action) {
423: document.getElementById('action').value = action;
424: }
425:
426: function getDifferences() {
427: var newtitles = document.getElementsByName('newtitle');
428: var i = 0;
429: for (i=0;i<newtitles.length;i++) {
430: var newt = newtitles[i].value;
431: var oldt = newtitles[i].alt;
432: if (newt != oldt) {
433: return true;
434: }
435: }
436: var newnote = document.getElementsByName('newnote');
437: var i = 0;
438: for (i=0;i<newnote.length;i++) {
439: var newn = newnote[i].value;
440: var oldn = newnote[i].innerHTML;
441: if (newn != oldn) {
442: return true;
443: }
444: }
445: return false;
446: }
447:
448: function onLoadAction(mode) {
449: window.name = 'wishlist';
450: if (mode == "edit") {
451: var deepestRows = getDeepestRows();
452: setDisplaySelect(deepestRows, '');
453: }
454: }
455:
456: function folderAction(rowid) {
457: var row = document.getElementById(rowid);
458: var indent = getIndent(row);
459: var displ;
460: var status;
461: if (getImage(row) == 'closed') {
462: displ = '';
463: status = 'open';
464: }
465: else {
466: displ = 'LC_hidden';
467: status = 'closed';
468: }
469: setImage(row,status);
470: if (getNextRow(row) != null) {
471: var nextIndent = getIndent(getNextRow(row));
472: row = getNextRow(row);
473: while (nextIndent > indent) {
474: if (displ == '') {
475: row.className = (row.className).replace('LC_hidden','');
476: }
477: else if (displ != '' && !((row.className).match('LC_hidden'))) {
478: var oldClass = row.className;
479: row.className = oldClass+' LC_hidden';
480: setDisplayNote(row.id.replace('row','note'),'LC_hidden');
481: }
482: if (status == 'open' && getImage(row).match('closed')) {
483: row = getNextRowWithIndent(row, getIndent(row));
484: }
485: else {
486: row = getNextRow(row);
487: }
488: if (row != null) {
489: nextIndent = getIndent(row);
490: }
491: else {
492: nextIndent = indent;
493: }
494: }
495: }
496: setClasses();
497: var newtitles = document.getElementsByName('newtitle');
498: if (newtitles.length>0) {
499: var deepestRows = getDeepestRows();
500: var otherRows = getOtherRows(deepestRows);
501: setDisplaySelect(deepestRows,'');
502: setDisplaySelect(otherRows,'LC_hidden');
503: }
504: }
505:
506: function selectAction(rowid) {
507: var row = document.getElementById(rowid);
508: var indent = getIndent(row);
509: var checked = getChecked(row);
510: var previousFolderRows = new Array();
511: if (indent != 0) {
512: previousFolderRows = getPreviousFolderRows(row);
513: }
514: if (getNextRow(row) != null) {
515: var nextIndent = getIndent(getNextRow(row));
516: row = getNextRow(row);
517: while (nextIndent > indent) {
518: setChecked(row,checked);
519: if (status == 'open' && getImage(row).match('closed')) {
520: row = getNextRowWithIndent(row, getIndent(row));
521: }
522: else {
523: row = getNextRow(row);
524: }
525: if (row != null) {
526: nextIndent = getIndent(row);
527: }
528: else {
529: nextIndent = indent;
530: }
531: }
532: }
533: if (!checked) {
534: var i = 0;
535: for (i=0;i<previousFolderRows.length;i++) {
536: setChecked(previousFolderRows[i], false);
537: }
538: }
539: }
540:
541: function getNextNote(row) {
542: var rowId = row.id;
543: var nextRowId = parseInt(rowId.substr(3,rowId.length))+1;
544: nextRowId = "note"+nextRowId;
545: var nextRow = document.getElementById(nextRowId);
546: return nextRow;
547: }
548:
549: function getNextRow(row) {
550: var rowId = row.id;
551: var nextRowId = parseInt(rowId.substr(3,rowId.length))+1;
552: nextRowId = "row"+nextRowId;
553: var nextRow = document.getElementById(nextRowId);
554: return nextRow;
555: }
556:
557: function getPreviousRow(row) {
558: var rowId = row.id;
559: var previousRowId = parseInt(rowId.substr(3,rowId.length))-1;
560: previousRowId = "row"+previousRowId;
561: var previousRow =document.getElementById(previousRowId);
562: return previousRow;
563: }
564:
565: function getIndent(row) {
566: var childPADD = document.getElementById(row.id.replace('row','padd'));
567: indent = childPADD.style.paddingLeft;
568: indent = parseInt(indent.substr(0,(indent.length-2)));
569:
570: if (getImage(row).match('link')) {
571: indent -= $indentConst;
572: }
573: return indent;
574: }
575:
576: function getNextRowWithIndent(row, indent) {
577: var nextRow = getNextRow(row);
578: if (nextRow != null) {
579: var nextIndent = getIndent(nextRow);
580: while (nextIndent >= indent) {
581: if (nextIndent == indent) {
582: return nextRow;
583: }
584: nextRow = getNextRow(nextRow);
585: if (nextRow == null) {
586: return null;
587: }
588: nextIndent = getIndent(nextRow);
589: }
590: }
591: return nextRow;
592: }
593:
594: function getImage(row) {
595: var childIMG = document.getElementById(row.id.replace('row','img'));
596: if ((childIMG.src).match('closed')) {
597: return 'closed';
598: }
599: else if ((childIMG.src).match('open')) {
600: return 'open;'
601: }
602: else {
603: return 'link';
604: }
605: }
606:
607: function setImage(row, status) {
608: var childIMG = document.getElementById(row.id.replace('row','img'));
609: var childIMGFolder = document.getElementById(row.id.replace('row','imgFolder'));
610: childIMG.src = "/adm/lonIcons/arrow."+status+".gif";
611: childIMGFolder.src="/adm/lonIcons/navmap.folder."+status+".gif";
612: }
613:
614: function getChecked(row) {
615: var childCHECK = document.getElementById(row.id.replace('row','check'));
616: var checked = childCHECK.checked;
617: return checked;
618: }
619:
620: function setChecked(row,checked) {
621: var childCHECK = document.getElementById(row.id.replace('row','check'));
622: childCHECK.checked = checked;
623: }
624:
625: function getPreviousFolderRows(row) {
626: var previousRow = getPreviousRow(row);
627: var indent = getIndent(previousRow);
628: var kindOfEntry = getImage(previousRow);
629: var rows = new Array();
630: if (kindOfEntry != 'link') {
631: rows.push(previousRow);
632: }
633:
634: while (indent >0) {
635: previousRow = getPreviousRow(previousRow);
636: if (previousRow != null) {
637: indent = getIndent(previousRow);
638: kindOfEntry = getImage(previousRow);
639: if (kindOfEntry != 'link') {
640: rows.push(previousRow);
641: }
642: }
643: else {
644: indent = 0;
645: }
646: }
647: return rows;
648: }
649:
650: function getDeepestRows() {
651: var row = document.getElementById('row0');
652: var firstRow = row;
653: var indent = getIndent(row);
654: var maxIndent = indent;
655: while (getNextRow(row) != null) {
656: row = getNextRow(row);
657: indent = getIndent(row);
658: if (indent>maxIndent && !((row.className).match('LC_hidden'))) {
659: maxIndent = indent;
660: }
661: }
662: var deepestRows = new Array();
663: row = firstRow;
664: var rowIndent;
665: while (getNextRow(row) != null) {
666: rowIndent = getIndent(row);
667: if (rowIndent == maxIndent) {
668: deepestRows.push(row);
669: }
670: row = getNextRow(row);
671: }
672: rowIndent = getIndent(row);
673: if (rowIndent == maxIndent) {
674: deepestRows.push(row);
675: }
676: return deepestRows;
677: }
678:
679: function getOtherRows(deepestRows) {
680: var row = document.getElementById('row0');
681: var otherRows = new Array();
682: var isIn = false;
683: while (getNextRow(row) != null) {
684: var i = 0;
685: for (i=0; i < deepestRows.length; i++) {
686: if (row.id == deepestRows[i].id) {
687: isIn = true;
688: }
689: }
690: if (!isIn) {
691: otherRows.push(row);
692: }
693: row = getNextRow(row);
694: isIn = false;
695: }
696: for (i=0; i < deepestRows.length; i++) {
697: if (row.id == deepestRows[i].id) {
698: isIn = true;
699: }
700: }
701: if (!isIn) {
702: otherRows.push(row);
703: }
704: return otherRows;
705: }
706:
707: function setDisplaySelect(deepestRows, displ) {
708: var i = 0;
709: for (i = 0; i < deepestRows.length; i++) {
710: var row = deepestRows[i];
711: var childSEL = document.getElementById(row.id.replace('row','sel'));
712: childSEL.className = displ;
713: }
714: }
715:
716: function submitSelect() {
717: var list = document.getElementsByName('list')[0];
718: list.setAttribute("action","/adm/wishlist?mode=edit");
719: list.submit();
720: }
721:
722: function setDisplayNote(rowid, displ) {
723: var row = document.getElementById(rowid);
724: if (!displ) {
725: if ((row.className).match('LC_hidden')) {
726: row.className = (row.className).replace('LC_hidden','');
727: }
728: else {
729: var oldClass = row.className;
730: row.className = oldClass+' LC_hidden';
731: }
732: }
733: else {
734: if (displ == '') {
735: row.className = (row.className).replace('LC_hidden','');
736: }
737: else if (displ != '' && !((row.className).match('LC_hidden'))) {
738: var oldClass = row.className;
739: row.className = oldClass+' LC_hidden';
740: }
741: }
742: var noteText = document.getElementById(rowid.replace('note','noteText'));
743: var noteImg = document.getElementById(rowid.replace('note','noteImg'));
744: if (noteText.value) {
745: noteImg.src = "/res/adm/pages/anot2.png";
746: }
747: else {
748: noteImg.src = "/res/adm/pages/anot.png";
749: }
750:
751: }
752:
753: function setClasses() {
754: var row = document.getElementById("row0");
755: var note = document.getElementById("note0");
756: var LC_class = 0;
757: if (getNextRow(row) != null) {
758: while (getNextRow(row) != null) {
759: if (!(row.className).match('LC_hidden')) {
760: note.className = (note.className).replace('LC_even_row','');
761: note.className = (note.className).replace('LC_odd_row','');
762: if (LC_class) {
763: row.className = 'LC_even_row';
764: note.className = 'LC_even_row'+note.className;
765: }
766: else {
767: row.className = 'LC_odd_row';
768: note.className = 'LC_odd_row'+note.className;;
769: }
770: LC_class = !LC_class;
771: }
772: note = getNextNote(row);
773: row = getNextRow(row);
774: }
775: }
776: if (!(row.className).match('LC_hidden')) {
777: note.className = (note.className).replace('LC_even_row','');
778: note.className = (note.className).replace('LC_odd_row','');
779: if (LC_class) {
780: row.className = 'LC_even_row';
781: note.className = 'LC_even_row'+note.className;
782: }
783: else {
784: row.className = 'LC_odd_row';
785: note.className = 'LC_odd_row'+note.className;
786: }
787: }
788: }
789:
790: function selectDestinationFolder() {
791: var mark = document.getElementsByName('mark');
792: var i = 0;
793: for (i = 0; i < mark.length; i++) {
794: if (mark[i].checked) {
795: document.getElementsByName('list')[0].submit();
796: return true;
797: }
798: }
799: alert('$warningMove');
800: return false;
801: }
802:
1.2 ! wenzelju 803: function preview(url) {
! 804: var newWin = window.open(url+'?inhibitmenu=yes','preview','width=560,height=350,scrollbars=yes');
! 805: newWin.focus();
! 806: }
! 807:
! 808: function finish_import() {
! 809: opener.document.forms.simpleedit.importdetail.value='';
! 810: for (var num = 0; num < document.forms.groupsort.fnum.value; num++) {
! 811: if (eval("document.forms.groupsort.check"+num+".checked") && eval("document.forms.groupsort.filelink"+num+".value") != '') {
! 812: opener.document.forms.simpleedit.importdetail.value+='&'+
! 813: eval("document.forms.groupsort.title"+num+".value")+'='+
! 814: eval("document.forms.groupsort.filelink"+num+".value")+'='+
! 815: eval("document.forms.groupsort.id"+num+".value");
! 816: }
! 817: }
! 818: opener.document.forms.simpleedit.submit();
! 819: self.close();
! 820: }
! 821:
! 822: function checkAll() {
! 823: var checkboxes = document.getElementsByName('check');
! 824: for (var i = 0; i < checkboxes.length; i++) {
! 825: checkboxes[i].checked = "checked";
! 826: }
! 827: }
! 828:
! 829: function uncheckAll() {
! 830: var checkboxes = document.getElementsByName('check');
! 831: for (var i = 0; i < checkboxes.length; i++) {
! 832: checkboxes[i].checked = "";
! 833: }
! 834: }
! 835:
1.1 wenzelju 836: JAVASCRIPT
837: return $js;
838: }
839:
840:
841: # HTML-Markup for table if in view-mode
842: my $wishlistHTMLview;
843: my $indent = $indentConst;
844: sub wishlistView {
845: my $nodes = shift;
846:
847: foreach my $n (@$nodes) {
848: my $index = $n->value()->nindex();
849:
850: # start row, use data_table routines to set class to LC_even or LC_odd automatically. this row contains a checkbox, the title and the note-icon.
851: # only display the top level entries on load
852: $wishlistHTMLview .= ($n->parent()->value() eq 'root')?&Apache::loncommon::start_data_table_row('','row'.$index)
853: :&Apache::loncommon::continue_data_table_row('LC_hidden','row'.$index);
854:
855:
856: # checkboxes
857: $wishlistHTMLview .= '<td><input type="checkbox" name="mark" id="check'.$index.'" value="'.$index.'" '.
858: 'onclick="selectAction('."'row".$index."'".')"/></td>';
859:
860: # entry is a folder
861: if ($n->value()->path() eq '') {
862: $wishlistHTMLview .= '<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<0?0:($indent-$indentConst)).'px; min-width: 220px;">'.
863: '<a href="javascript:;" onclick="folderAction('."'row".$index."'".')" style="vertical-align:top">'.
864: '<img src="/adm/lonIcons/arrow.closed.gif" id="img'.$index.'" alt = "" class="LC_icon"/>'.
865: '<img src="/adm/lonIcons/navmap.folder.closed.gif" id="imgFolder'.$index.'" alt="folder"/>'.
866: $n->value()->title().'</a></td>';
867: }
868: # entry is a link
869: else {
870: $wishlistHTMLview .= '<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<=0?$indentConst:$indent).'px; min-width: 220px;">'.
1.2 ! wenzelju 871: '<a href="javascript:preview('."'".$n->value()->path()."'".');">'.
1.1 wenzelju 872: '<img src="/res/adm/pages/wishlist-link.png" id="img'.$index.'" alt="link" />'.
1.2 ! wenzelju 873: $n->value()->title().'</a></td>';
1.1 wenzelju 874: }
875:
876: # note-icon, different icons for an entries with note and those without
877: my $noteIMG = 'anot.png';
878:
879: if ($n->value()->note() ne '') {
880: $noteIMG = 'anot2.png';
881: }
882:
883: $wishlistHTMLview .= '<td style="padding-left:10px;"><a href="javascript:;" onclick="setDisplayNote('."'note".$index."'".')">'.
884: '<img id="noteImg'.$index.'" src="/res/adm/pages/'.$noteIMG.'" alt="'.&mt('Note').'" title="'.&mt('Note').'" '.
885: ' class="LC_icon"/></a></td>';
886:
887: $wishlistHTMLview .= &Apache::loncommon::end_data_table_row();
888:
889: # start row containing the textarea for the note, do not display note on default
890: $wishlistHTMLview .= &Apache::loncommon::continue_data_table_row('LC_hidden','note'.$index).
891: '<td></td><td>'.
892: '<textarea id="noteText'.$index.'" cols="25" rows="3" style="width:100%" '.
893: 'name="newnote" >'.
894: $n->value()->note().'</textarea></td><td></td>';
895: $wishlistHTMLview .= &Apache::loncommon::end_data_table_row();
896:
897: # if the entry is a folder, it could have other entries as content. if it has, call wishlistView for those entries
898: my @children = $n->children();
899: if ($#children >=0) {
900: $indent += 20;
901: &wishlistView(\@children);
902: $indent -= 20;
903: }
904: }
905: }
906:
907:
908: # HTML-Markup for table if in edit-mode
909: my $wishlistHTMLedit;
910: my $indent = $indentConst;
911: sub wishlistEdit {
912: my $nodes = shift;
913: my $curNode = 1;
914:
915: foreach my $n (@$nodes) {
916: my $index = $n->value()->nindex();
917:
918: # start row, use data_table routines to set class to LC_even or LC_odd automatically.
919: # this rows contains a checkbox, a select-field for sorting entries, the title in an input-field and the note-icon.
920: # only display the top level entries on load
921: $wishlistHTMLedit .= ($n->parent()->value() eq 'root')?&Apache::loncommon::start_data_table_row('','row'.$index)
922: :&Apache::loncommon::continue_data_table_row('LC_hidden','row'.$index);
923:
924: # checkboxes
925: $wishlistHTMLedit .= '<td><input type="checkbox" name="mark" id="check'.$index.'" value="'.$index.'" '.
926: 'onclick="selectAction('."'row".$index."'".')"/></td>';
927:
928: # option-tags for sorting entries. we need the numbers from 1 to n with n being the number of entries on the same level as the current entry.
929: # set the number for the current entry into brackets
930: my $options;
931: for (my $i = 1; $i < ((scalar @{$nodes})+1); $i++) {
932: if ($i == $curNode) {
933: $options .= '<option selected="selected" value="">('.$i.')</option>';
934: }
935: else {
936: $options .= '<option value="'.$i.'">'.$i.'</option>';
937: }
938: }
939: $curNode++;
940:
941: # entry is a folder
942: if ($n->value()->path() eq '') {
943: $wishlistHTMLedit .= '<td><select class="LC_hidden" name="sel" id="sel'.$index.'" onchange="submitSelect();">'.
944: $options.'</select></td>'.
945: '<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<0?0:($indent-$indentConst)).'px;">'.
946: '<a href="javascript:;" onclick="folderAction('."'row".$index."'".')" style="vertical-align:top" >'.
947: '<img src="/adm/lonIcons/arrow.closed.gif" id="img'.$index.'" alt = "" class="LC_icon"/>'.
948: '<img src="/adm/lonIcons/navmap.folder.closed.gif" id="imgFolder'.$index.'" alt="folder"/></a>';
949:
950: }
951: # entry is a link
952: else {
953: $wishlistHTMLedit .= '<td><select class="LC_hidden" name="sel" id="sel'.$index.'" onchange="submitSelect();">'.
954: $options.'</select></td>'.
955: '<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<=0?$indentConst:$indent).'px;">'.
956: '<img src="/res/adm/pages/wishlist-link.png" id="img'.$index.'" alt="link"/>';
957: }
958:
959: # input-field for title
960: $wishlistHTMLedit .= '<input type="text" name="newtitle" value="'.$n->value()->title().'" alt = "'.$n->value()->title().'"/></td>';
961:
962: # note-icon, different icons for an entries with note and those without
963: my $noteIMG = 'anot.png';
964:
965: if ($n->value()->note() ne '') {
966: $noteIMG = 'anot2.png';
967: }
968:
969: $wishlistHTMLedit .= '<td style="padding-left:10px;"><a href="javascript:;" onclick="setDisplayNote('."'note".$index."'".')">'.
970: '<img id="noteImg'.$index.'" src="/res/adm/pages/'.$noteIMG.'" alt="'.&mt('Note').'" title="'.&mt('Note').'" '.
971: ' class="LC_icon"/></a></td>';
972:
973: $wishlistHTMLedit .= &Apache::loncommon::end_data_table_row();
974:
975: # start row containing the textarea for the note
976: $wishlistHTMLedit .= &Apache::loncommon::continue_data_table_row('LC_hidden','note'.$index).
977: '<td></td><td></td><td>'.
978: '<textarea id="noteText'.$index.'" cols="25" rows="3" style="width:100%" '.
979: 'name="newnote">'.
980: $n->value()->note().'</textarea></td><td></td>';
981: $wishlistHTMLedit .= &Apache::loncommon::end_data_table_row();
982:
983: # if the entry is a folder, it could have other entries as content. if it has, call wishlistEdit for those entries
984: my @children = $n->children();
985: if ($#children >=0) {
986: $indent += 20;
987: &wishlistEdit(\@children);
988: $indent -= 20;
989: }
990: }
991: }
992:
993:
994:
995: # HTML-Markup for table if in move-mode
996: my $wishlistHTMLmove ='<tr id="root" class="LC_odd_row"><td><input type="radio" name="mark" id="radioRoot" value="root" /></td>'.
997: '<td>'.&mt('Top level').'</td><td></td></tr>';
998: my $indent = $indentConst;
999: sub wishlistMove {
1000: my $nodes = shift;
1001: my $marked = shift;
1002:
1003: foreach my $n (@$nodes) {
1004: my $index = $n->value()->nindex();
1005:
1006: #find out wether the current entry was marked to be moved.
1007: my $isIn = 0;
1008: foreach my $m (@$marked) {
1009: if ($index == $m) {
1010: $isIn = 1;
1011: }
1012: }
1013: # start row and set class for even or odd row. this rows contains the title and the note-icon and can contain a radio-button
1014: $wishlistHTMLmove .= &Apache::loncommon::start_data_table_row('','row'.$index);
1015:
1016:
1017: # entry is a folder
1018: if ($n->value()->path() eq '') {
1019: # display a radio-button, if the folder was not selected to be moved
1020: if (!$isIn) {
1021: $wishlistHTMLmove .= '<td><input type="radio" name="mark" id="radio'.$index.'" value="'.$index.'" /></td>'.
1022: '<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<0?0:($indent-$indentConst)).'px; min-width: 220px;">';
1023: }
1024: # higlight the title, if the folder was selected to be moved
1025: else {
1026: $wishlistHTMLmove .= '<td></td>'.
1027: '<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<0?0:($indent-$indentConst)).'px; min-width: 220px;'.
1028: 'color:red;">';
1029: }
1030: #arrow- and folder-image, all folders are open, and title
1031: $wishlistHTMLmove .= '<img src="/adm/lonIcons/arrow.open.gif" id="img'.$index.'" alt = "" />'.
1032: '<img src="/adm/lonIcons/navmap.folder.open.gif" id="imgFolder'.$index.'" alt="folder"/>'.
1033: $n->value()->title().'</td>';
1034: }
1035: # entry is a link
1036: else {
1037: # higlight the title, if the link was selected to be moved
1.2 ! wenzelju 1038: my $highlight = '';
! 1039: if ($isIn) {
! 1040: $highlight = 'style="color:red;"';
1.1 wenzelju 1041: }
1042: # link-image and title
1.2 ! wenzelju 1043: $wishlistHTMLmove .= '<td></td>'.
! 1044: '<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<=0?$indentConst:$indent).'px; min-width: 220px;">'.
! 1045: '<a href="javascript:preview('."'".$n->value()->path()."'".');" '.$highlight.'>'.
! 1046: '<img src="/res/adm/pages/wishlist-link.png" id="img'.$index.'" alt="link"/>'.
! 1047: $n->value()->title().'</a></td>';
1.1 wenzelju 1048: }
1049:
1050: # note-icon, different icons for an entries with note and those without
1051: my $noteIMG = 'anot.png';
1052:
1053: if ($n->value()->note() ne '') {
1054: $noteIMG = 'anot2.png';
1055: }
1056:
1057: $wishlistHTMLmove .= '<td style="padding-left:10px;"><a href="javascript:;" onclick="setDisplayNote('."'note".$index."'".')">'.
1058: '<img id="noteImg'.$index.'" src="/res/adm/pages/'.$noteIMG.'" alt="'.&mt('Note').'" title="'.&mt('Note').'" '.
1059: ' class="LC_icon"/></a></td>';
1060:
1061: $wishlistHTMLmove .= &Apache::loncommon::end_data_table_row();
1062:
1063: # start row containing the textarea for the note, readonly in move-mode
1064: $wishlistHTMLmove .= &Apache::loncommon::continue_data_table_row('LC_hidden','note'.$index).
1065: '<td></td><td>'.
1066: '<textarea id="noteText'.$index.'" cols="25" rows="3" style="width:100%" '.
1067: 'name="newnote" readonly="readonly">'.
1068: $n->value()->note().'</textarea></td><td></td>'.
1069: &Apache::loncommon::end_data_table_row();
1070:
1071: # if the entry is a folder, it could have other entries as content. if it has, call wishlistMove for those entries
1072: my @children = $n->children();
1073: if ($#children >=0) {
1074: $indent += 20;
1075: &wishlistMove(\@children, $marked);
1076: $indent -= 20;
1077: }
1078: }
1079: }
1080:
1.2 ! wenzelju 1081:
! 1082:
! 1083: # HTML-Markup for table if in import-mode
! 1084: my $wishlistHTMLimport;
! 1085: my $indent = $indentConst;
! 1086: my $form = 1;
! 1087: sub wishlistImport {
! 1088: my $nodes = shift;
! 1089:
! 1090: foreach my $n (@$nodes) {
! 1091: my $index = $n->value()->nindex();
! 1092:
! 1093: # start row, use data_table routines to set class to LC_even or LC_odd automatically. this row contains a checkbox, the title and the note-icon.
! 1094: # only display the top level entries on load
! 1095: $wishlistHTMLimport .= ($n->parent()->value() eq 'root')?&Apache::loncommon::start_data_table_row('','row'.$index)
! 1096: :&Apache::loncommon::continue_data_table_row('LC_hidden','row'.$index);
! 1097:
! 1098:
! 1099: # checkboxes
! 1100: $wishlistHTMLimport .= '<td>'.
! 1101: '<input type="checkbox" name="check" id="check'.$index.'" value="'.$index.'" '.
! 1102: 'onclick="selectAction('."'row".$index."'".')"/>'.
! 1103: '<input type="hidden" name="title'.$index.'" value="'.&escape($n->value()->title()).'">'.
! 1104: '<input type="hidden" name="filelink'.$index.'" value="'.&escape($n->value()->path()).'">'.
! 1105: '<input type="hidden" name="id'.$index.'">'.
! 1106: '</td>';
! 1107:
! 1108: # entry is a folder
! 1109: if ($n->value()->path() eq '') {
! 1110: $wishlistHTMLimport .= '<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<0?0:($indent-$indentConst)).'px; min-width: 220px;">'.
! 1111: '<a href="javascript:;" onclick="folderAction('."'row".$index."'".')" style="vertical-align:top">'.
! 1112: '<img src="/adm/lonIcons/arrow.closed.gif" id="img'.$index.'" alt = "" class="LC_icon"/>'.
! 1113: '<img src="/adm/lonIcons/navmap.folder.closed.gif" id="imgFolder'.$index.'" alt="folder"/>'.
! 1114: $n->value()->title().'</a></td>';
! 1115: }
! 1116: # entry is a link
! 1117: else {
! 1118: $wishlistHTMLimport .= '<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<=0?$indentConst:$indent).'px; min-width: 220px;">'.
! 1119: '<a href="javascript:preview('."'".$n->value()->path()."'".');">'.
! 1120: '<img src="/res/adm/pages/wishlist-link.png" id="img'.$index.'" alt="link" />'.
! 1121: $n->value()->title().'</a></td>';
! 1122: $form++;
! 1123: }
! 1124:
! 1125: # note-icon, different icons for an entries with note and those without
! 1126: my $noteIMG = 'anot.png';
! 1127:
! 1128: if ($n->value()->note() ne '') {
! 1129: $noteIMG = 'anot2.png';
! 1130: }
! 1131:
! 1132: $wishlistHTMLimport .= '<td style="padding-left:10px;"><a href="javascript:;" onclick="setDisplayNote('."'note".$index."'".')">'.
! 1133: '<img id="noteImg'.$index.'" src="/res/adm/pages/'.$noteIMG.'" alt="'.&mt('Note').'" title="'.&mt('Note').'" '.
! 1134: ' class="LC_icon"/></a></td>';
! 1135:
! 1136: $wishlistHTMLimport .= &Apache::loncommon::end_data_table_row();
! 1137:
! 1138: # start row containing the textarea for the note, do not display note on default, readonly in import-mode
! 1139: $wishlistHTMLimport .= &Apache::loncommon::continue_data_table_row('LC_hidden','note'.$index).
! 1140: '<td></td><td>'.
! 1141: '<textarea id="noteText'.$index.'" cols="25" rows="3" style="width:100%" '.
! 1142: 'name="newnote" readonly="readonly">'.
! 1143: $n->value()->note().'</textarea></td><td></td>';
! 1144: $wishlistHTMLimport .= &Apache::loncommon::end_data_table_row();
! 1145:
! 1146: # if the entry is a folder, it could have other entries as content. if it has, call wishlistImport for those entries
! 1147: my @children = $n->children();
! 1148: if ($#children >=0) {
! 1149: $indent += 20;
! 1150: &wishlistImport(\@children);
! 1151: $indent -= 20;
! 1152: }
! 1153: }
! 1154: }
! 1155:
1.1 wenzelju 1156: # Returns the HTML-Markup for wishlist
1157: sub makePage {
1158: my $mode = shift;
1159: my $marked = shift;
1160:
1161: # breadcrumbs and start_page
1162: &Apache::lonhtmlcommon::clear_breadcrumbs();
1163: &Apache::lonhtmlcommon::add_breadcrumb(
1164: { href => '/adm/wishlist?mode='.$mode,
1165: text => 'Wishlist'});
1166: my $startPage = &Apache::loncommon::start_page('Wishlist',undef,
1167: {'add_entries' => {
1168: 'onload' => 'javascript:onLoadAction('."'".$mode."'".');',
1169: 'onunload' => 'javascript:window.name = '."'loncapaclient'"}});
1170:
1171: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Wishlist '.
1172: '<a title="Online-Hilfe" href="/adm/help/Wishlist.hlp" target="_top">'.
1173: '<img src="/adm/help/help.png" alt="'.&mt('Help').'" '.
1174: 'title="'.&mt('Help').'" class="LC_icon" /></a>');
1175:
1176: # get javascript-code for wishlist-interactions
1177: my $js = &JSforWishlist();
1178:
1179: # texthash for items in funtionlist
1180: my %lt = &Apache::lonlocal::texthash(
1181: 'ed' => 'Edit',
1182: 'vw' => 'View',
1183: 'al' => 'Add Link',
1184: 'af' => 'Add Folder',
1185: 'mv' => 'Move Selected',
1186: 'dl' => 'Delete Selected',
1187: 'sv' => 'Save');
1188:
1189: # start functionlist
1190: my $functions = &Apache::lonhtmlcommon::start_funclist();
1191:
1192: # icon for edit-mode, display when in view-mode
1193: if ($mode eq 'view') {
1194: $functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
1195: 'onclick="setFormAction('."'save','edit'".'); list.submit();" class="LC_menubuttons_link">'.
1196: '<img src="/res/adm/pages/edit-mode-22x22.png" alt="'.$lt{'ed'}.'" '.
1197: 'title="'.$lt{'ed'}.'" class="LC_icon"/> '.
1198: '<span class="LC_menubuttons_inline_text">'.$lt{'ed'}.'</span></a>');
1199: }
1200: # icon for view-mode, display when in edit-mode
1201: else {
1202: $functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
1203: 'onclick="setFormAction('."'save','view'".'); list.submit();" class="LC_menubuttons_link">'.
1204: '<img src="/res/adm/pages/view-mode-22x22.png" alt="'.$lt{'vw'}.'" '.
1205: 'title="'.$lt{'vw'}.'" class="LC_icon"/> '.
1206: '<span class="LC_menubuttons_inline_text">'.$lt{'vw'}.'</span></a>');
1207: }
1208:
1209: # icon for adding a new link
1210: $functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
1211: 'onclick="newLink();" class="LC_menubuttons_link">'.
1212: '<img src="/res/adm/pages/link-new-22x22.png" alt="'.$lt{'al'}.'" '.
1213: 'title="'.$lt{'al'}.'" class="LC_icon"/>'.
1214: '<span class="LC_menubuttons_inline_text">'.$lt{'al'}.'</span></a>');
1215:
1216: # icon for adding a new folder
1217: $functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
1218: 'onclick="newFolder();" class="LC_menubuttons_link">'.
1219: '<img src="/res/adm/pages/folder-new-22x22.png" alt="'.$lt{'af'}.'" '.
1220: 'title="'.$lt{'af'}.'" class="LC_icon"/>'.
1221: '<span class="LC_menubuttons_inline_text">'.$lt{'af'}.'</span></a>');
1222:
1223: # icon for moving entries
1224: $functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
1225: 'onclick="setFormAction('."'move','move'".'); " class="LC_menubuttons_link">'.
1226: '<img src="/res/adm/pages/move-22x22.png" alt="'.$lt{'mv'}.'" '.
1227: 'title="'.$lt{'mv'}.'" class="LC_icon" />'.
1228: '<span class="LC_menubuttons_inline_text">'.$lt{'mv'}.'</span></a>');
1229:
1230: # icon for deleting entries
1231: $functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
1232: 'onclick="setFormAction('."'delete','".$mode."'".'); " class="LC_menubuttons_link">'.
1233: '<img src="/res/adm/pages/del.png" alt="'.$lt{'dl'}.'" '.
1234: 'title="'.$lt{'dl'}.'" class="LC_icon" />'.
1235: '<span class="LC_menubuttons_inline_text">'.$lt{'dl'}.'</span></a>');
1236:
1237: # icon for saving changes
1238: $functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
1239: 'onclick="setFormAction('."'','".$mode."'".'); " class="LC_menubuttons_link">'.
1240: '<img src="/res/adm/pages/save-22x22.png" alt="'.$lt{'sv'}.'" '.
1241: 'title="'.$lt{'sv'}.'" class="LC_icon" />'.
1242: '<span class="LC_menubuttons_inline_text">'.$lt{'sv'}.'</span></a>');
1243:
1244: # end funtionlist and generate subbox
1245: $functions.= &Apache::lonhtmlcommon::end_funclist();
1246: my $subbox = &Apache::loncommon::head_subbox($functions);
1247:
1248: # start form
1249: my $inner .= '<form name="list" action ="/adm/wishlist" method="post">'.
1250: '<input type="hidden" id="action" name="action" value=""/>';
1251:
1252: # only display subbox in view- or edit-mode
1.2 ! wenzelju 1253: if ($mode eq 'view' || $mode eq 'edit') {
1.1 wenzelju 1254: $inner .= $subbox;
1255: }
1256:
1257: # generate table-content depending on mode
1258: if ($mode eq 'edit') {
1259: &wishlistEdit(\@childrenRt);
1260: if ($wishlistHTMLedit ne '') {
1261: $inner .= &Apache::loncommon::start_data_table("LC_tableOfContent");
1262: $inner .= $wishlistHTMLedit;
1263: $inner .= &Apache::loncommon::end_data_table();
1264: }
1265: else {
1.2 ! wenzelju 1266: $inner .= '<span class="LC_info">'.&mt("Your wishlist ist currently empty.").'</span>';
1.1 wenzelju 1267: }
1268: $wishlistHTMLedit = '';
1269: }
1270: elsif ($mode eq 'view') {
1271: &wishlistView(\@childrenRt);
1272: if ($wishlistHTMLview ne '') {
1273: $inner .= '<table class="LC_data_table LC_tableOfContent">'.$wishlistHTMLview.'</table>';
1274: }
1275: else {
1.2 ! wenzelju 1276: $inner .= '<span class="LC_info">'.&mt("Your wishlist ist currently empty.").'</span>';
1.1 wenzelju 1277: }
1278: $wishlistHTMLview = '';
1279: }
1280: else {
1281: my $markStr = '';
1282: foreach my $m (@$marked) {
1283: $markStr .= $m.',';
1284: }
1285: if ($markStr) {
1286: $markStr = substr($markStr, 0, length($markStr)-1);
1287: $inner .= '<input type="hidden" value="'.$markStr.'" name="markedToMove"/>';
1.2 ! wenzelju 1288: $inner .= '<p><span class="LC_info">'.&mt('You have selected the red marked entries to be moved to another folder. '.
! 1289: 'Now choose the new destination folder.').'</span></p>';
1.1 wenzelju 1290: &wishlistMove(\@childrenRt, $marked);
1291: $inner .= '<table class="LC_data_table LC_tableOfContent">'.$wishlistHTMLmove.'</table><br/><br/>';
1292: $inner .= '<input type="button" value="'.&mt('Move').'" onclick="setFormAction('."'','view'".'); selectDestinationFolder()"/>'.
1293: '<input type="button" value="'.&mt('Cancel').'" onclick="go('."'/adm/wishlist'".')"/>';
1294:
1295: $wishlistHTMLmove ='<tr id="root" class="LC_odd_row"><td><input type="radio" name="mark" id="radioRoot" value="root" /></td>'.
1296: '<td>'.&mt('Top level').'</td><td></td></tr>';
1297: }
1298: else {
1.2 ! wenzelju 1299: $inner .= '<p><span class="LC_info">'.&mt("You haven't marked any entry to move.").'</span></p>'.
1.1 wenzelju 1300: '<input type="button" value="'.&mt('Back').'" onclick="go('."'/adm/wishlist'".')"/>';
1301: }
1302: }
1303:
1304: # end form
1305: $inner .= '</form>';
1306:
1307: # end_page
1308: my $endPage = &Apache::loncommon::end_page();
1309:
1.2 ! wenzelju 1310: # put all page-elements together
1.1 wenzelju 1311: my $page = $startPage.$breadcrumbs.$js.$inner.$endPage;
1312:
1313: return $page;
1314: }
1315:
1316:
1317: # Returns the HTML-Markup for the page, shown when a link was set
1318: sub makePageSet {
1319: # start_page
1320: my $startPage = &Apache::loncommon::start_page('Wishlist',undef,
1321: {'only_body' => 1});
1322:
1323: # confirm success and offer link to wishlist
1324: my $message = &Apache::lonhtmlcommon::confirm_success(&mt('Link successfully set!'));
1325: $message = &Apache::loncommon::confirmwrapper($message);
1326:
1327: my $inner .= '<br>'.$message.'<br/><br/>'.
1328: '<a href="javascript:;" onclick="opener.open('."'/adm/wishlist'".');window.close();">'.&mt('Go to wishlist').'</a>'.
1329: ' <a href="javascript:;" onclick="window.close();">'.&mt('Close this window').'</a>';
1330:
1331: # end_page
1332: my $endPage = &Apache::loncommon::end_page();
1333:
1.2 ! wenzelju 1334: # put all page-elements together
1.1 wenzelju 1335: my $page = $startPage.$inner.$endPage;
1336:
1337: return $page;
1338: }
1339:
1340:
1.2 ! wenzelju 1341: # Returns the HTML-Markup for the page, shown when links should be imported into a course
! 1342: sub makePageImport {
! 1343: # start_page
! 1344: my $startPage = &Apache::loncommon::start_page('Wishlist',undef,
! 1345: {'only_body' => 1});
! 1346:
! 1347: # get javascript-code for wishlist-interactions
! 1348: my $js = &JSforWishlist();
! 1349:
! 1350: my $inner = '<h1>'.&mt('Import Resources from Wishlist').'</h1>';
! 1351: $inner .= '<p><span class="LC_info">'.&mt("Please note that you can use the checkboxes corresponding to a folder to ".
! 1352: "easily check all links within this folder. The folder structure itself can't be imported. ".
! 1353: "All checked links will be imported into the current folder of your course.").'</span></p>';
! 1354:
! 1355: my %wishlist = &getWishlist();
! 1356: my $fnum = (keys %wishlist)-1;
! 1357:
! 1358: $inner .= '<form method="post" name="groupsort">'.
! 1359: '<input type="hidden" value="'.$fnum.'" name="fnum">'.
! 1360: '<input type="button" onclick="javascript:checkAll()" id="checkallbutton" value="'.&mt('Check All').'">'.
! 1361: '<input type="button" onclick="javascript:uncheckAll()" id="uncheckallbutton" value="'.&mt('Uncheck All').'">'.
! 1362: '<input type="button" value="'.&mt('Import Checked').'" onclick="finish_import();">'.
! 1363: '<input type="button" value="'.&mt('Cancel').'" onclick="window.close();"><br/><br/>';
! 1364:
! 1365:
! 1366: # wishlist-table
! 1367: &wishlistImport(\@childrenRt);
! 1368: if ($wishlistHTMLimport ne '') {
! 1369: $inner .= '<table class="LC_data_table LC_tableOfContent">'.$wishlistHTMLimport.'</table>';
! 1370: }
! 1371: else {
! 1372: $inner .= '<span class="LC_info">'.&mt("Your wishlist ist currently empty.").'</span>';
! 1373: }
! 1374: $wishlistHTMLimport = '';
! 1375:
! 1376: $inner .= '</form>';
! 1377:
! 1378: # end_page
! 1379: my $endPage = &Apache::loncommon::end_page();
! 1380:
! 1381: # put all page-elements together
! 1382: my $page = $startPage.$js.$inner.$endPage;
! 1383:
! 1384: return $page;
! 1385: }
! 1386:
! 1387:
1.1 wenzelju 1388: # Returns the HTML-Markup for error-page
1389: sub makeErrorPage {
1390: # breadcrumbs and start_page
1391: &Apache::lonhtmlcommon::add_breadcrumb(
1392: { href => '/adm/wishlist',
1393: text => 'Wishlist'});
1394: my $startPage = &Apache::loncommon::start_page('Wishlist');
1395:
1396: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Wishlist '.
1397: '<a title="Online-Hilfe" href="/adm/help/Wishlist.hlp" target="_top">'.
1398: '<img src="/adm/help/help.png" alt="'.&mt('Help').'" '.
1399: 'title="'.&mt('Help').'" class="LC_icon" /></a>');
1400: &Apache::lonhtmlcommon::clear_breadcrumbs();
1401:
1402: # error-message
1403: my $inner .= '<span class="LC_error">'.&mt('An error occurred! Please try again later.').'</span>';
1404:
1405: # end_page
1406: my $endPage = &Apache::loncommon::end_page();
1407:
1.2 ! wenzelju 1408: # put all page-elements together
1.1 wenzelju 1409: my $page = $startPage.$breadcrumbs.$inner.$endPage;
1410:
1411: return $page;
1412: }
1413:
1414: # ----------------------------------------------------- Main Handler, package lonwishlist
1415: sub handler {
1416: my ($r) = @_;
1417: &Apache::loncommon::content_type($r,'text/html');
1418: $r->send_http_header;
1419:
1420: if (&getWishlist() ne 'error') {
1421: # get wishlist entries from user-data db-file and build a tree out of these entries
1422: %TreeHash = &getWishlist();
1423: $root = &Tree::HashToTree();
1424: @childrenRt = $root->children();
1425:
1426: # greate a new entry
1427: if ($env{'form.title'}) {
1428: &newEntry($env{'form.title'}, $env{'form.path'}, $env{'form.note'});
1429: }
1430:
1431: # get unprocessed_cgi (i.e. marked entries, mode ...)
1432: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['action','mark','markedToMove','mode','newtitle','note']);
1433:
1434: # change the order of entries within a level, that means sorting the entries
1435: my $changeOrder = 0;
1436: if (defined $env{'form.sel'}) {
1437: my @sel = &Apache::loncommon::get_env_multiple('form.sel');
1438: my $indexNode;
1439: my $at;
1440: for (my $s=0; $s<($#sel+1); $s++) {
1441: if ($sel[$s] ne '') {
1442: $indexNode = $s;
1443: $at = $sel[$s]-1;
1444: }
1445: }
1446: if ($at ne '') {
1447: $changeOrder = 1;
1448: &sortEntries($indexNode,$at);
1449: &saveChanges();
1450: }
1451: }
1452:
1453: # get all marked (checkboxes) entries
1454: my @marked = ();
1455: if (defined $env{'form.mark'}) {
1456: @marked = &Apache::loncommon::get_env_multiple('form.mark');
1457: }
1458:
1459: # move entries from one folder to another
1460: if (defined $env{'form.markedToMove'}) {
1461: my $markedToMove = $env{'form.markedToMove'};
1462: my @ToMove = split(/\,/,$markedToMove);
1463: my $moveTo = $env{'form.mark'};
1464: if (defined $moveTo){
1465: &moveEntries(\@ToMove,$moveTo);
1466: &saveChanges();
1467: }
1468: $changeOrder = 1;
1469:
1470: }
1471:
1472: # delete entries
1473: if ($env{'form.action'} eq 'delete') {
1474: &deleteEntries(\@marked);
1475: }
1476:
1477:
1478: # get all titles and notes and save them
1479: # only save, if user wants to save changes
1480: # do not save, when current action is 'delete' or 'sort' or 'move'
1481: my @newTitles = ();
1482: my @newNotes = ();
1483: if ((defined $env{'form.newtitle'} || defined $env{'form.newnote'}) && ($env{'form.action'} ne 'noSave') && ($env{'form.action'} ne 'delete') && !$changeOrder) {
1484: @newTitles = &Apache::loncommon::get_env_multiple('form.newtitle');
1485: @newNotes = &Apache::loncommon::get_env_multiple('form.newnote');
1486: my $node = 0;
1487: foreach my $t (@newTitles) {
1488: &setNewTitle($node, $t);
1489: $node++;
1490: }
1491: $node = 0;
1492: foreach my $n (@newNotes) {
1493: &setNewNote($node, $n);
1494: $node++;
1495: }
1496: &saveChanges();
1497: }
1498:
1499: # Create HTML-markup
1500: my $page;
1501: if ($env{'form.mode'} eq 'edit') {
1502: $page = &makePage("edit");
1503: }
1504: elsif ($env{'form.mode'} eq 'move') {
1505: $page = &makePage("move", \@marked);
1506: }
1.2 ! wenzelju 1507: elsif ($env{'form.mode'} eq 'import') {
! 1508: $page = &makePageImport();
! 1509: }
1.1 wenzelju 1510: elsif ($env{'form.mode'} eq 'set') {
1511: $page = &makePageSet();
1512: }
1513: else {
1514: $page = &makePage("view");
1515: }
1516: @marked = ();
1517: $r->print($page);
1518: }
1519: # An error occured, print an error-page
1520: else {
1521: my $errorPage = &makeErrorPage();
1522: $r->print($errorPage);
1523: }
1524: return OK;
1525: }
1526:
1527: # ----------------------------------------------------- package Tree
1528: # Extend CPAN-Module Tree by function like 'moveNode' or 'deleteNode'
1529: package Tree;
1530:
1531: # returns the node with a given index from a list of nodes
1532: sub getNodeByIndex {
1533: my $index = shift;
1534: my $nodes = shift;
1535: my $found;
1536:
1537: for my $n (@$nodes) {
1538: my $curIndex = $n->value()->nindex();
1539: if ($n->value()->nindex() == $index) {
1540: $found = $n;
1541: }
1542: }
1543: return $found;
1544: }
1545:
1546: # moves a given node to a new parent or change the position from a node
1547: # within its siblings (sorting)
1548: sub moveNode {
1549: my $node = shift;
1550: my $at = shift;
1551: my $newParent = shift;
1552:
1553:
1554: if (!$newParent) {
1555: $newParent = $node->parent();
1556: }
1557:
1558: $node->parent()->remove_child($node);
1559:
1560: if (defined $at) {
1561: $newParent->add_child({at => $at},$node);
1562: }
1563: else {
1564: $newParent->add_child($node);
1565: }
1566:
1567: # updating root's children
1568: @childrenRt = $root->children();
1569: }
1570:
1571: # removes a given node
1572: sub removeNode() {
1573: my $node = shift;
1574: my @children = $node->children();
1575:
1576: if ($#children >= 0) {
1577: foreach my $c (@children) {
1578: &removeNode($c);
1579: }
1580: }
1581: $node->parent()->remove_child($node);
1582:
1583: # updating root's children
1584: @childrenRt = $root->children();
1585: }
1586:
1587:
1588: # set an index for every node in the tree, beginning with 0
1589: my $count = 0;
1590: sub TreeIndex {
1591: my $children = shift;
1592:
1593: foreach my $n (@$children) {
1594: my @children = $n->children();
1595: $n->value()->nindex($count);$count++;
1596:
1597: if ($#children>=0) {
1598: &TreeIndex(\@children);
1599: }
1600: }
1601: }
1602:
1603: # reset index counter
1604: sub setCountZero {
1605: $count = 0;
1606: }
1607:
1608:
1609: # convert the tree to a hash
1610: # each node is one hash-entry
1611: # keys are the indices, values are all other attributes
1612: # (containing tile, path, note, date and indices for all direct children)
1613: # except for root: the key is root and values are
1614: # just the indices of root's children
1615: sub RootToHash {
1616: my $childrenRt = shift;
1617: my @indexarr = ();
1618:
1619: foreach my $c (@$childrenRt) {
1620: push (@indexarr, $c->value()->nindex());
1621: }
1622: $TreeToHash{'root'} = [@indexarr];
1623: }
1624:
1625: sub TreeToHash {
1626: my $childrenRt = shift;
1627:
1628: foreach my $n (@$childrenRt) {
1629: my @arrtmp = ();
1630: $arrtmp[0] = $n->value()->title();
1631: $arrtmp[1] = $n->value()->path();
1632: $arrtmp[2] = $n->value()->note();
1633: $arrtmp[3] = $n->value()->date();
1634: my @childrenRt = $n->children();
1635: my $co = 4;
1636: foreach my $c (@childrenRt) {
1637: my $i = $c->value()->nindex();
1638: $arrtmp[$co] = $i;
1639: $co++;
1640: }
1641: $TreeToHash{$n->value()->nindex} = [ @arrtmp];
1642: if ($#childrenRt>=0) {
1643: &TreeToHash(\@childrenRt);
1644: }
1645: }
1646: }
1647:
1648:
1649: # convert the hash to a tree
1650: # build a tree-object for each entry in the hash
1651: # afterwards call &buildTree to connect the tree-objects
1652: sub HashToTree {
1653: my @TreeNodes = ();
1654: my $root;
1655:
1656: foreach my $key (keys %TreeHash) {
1657: if ($key eq 'root') {
1658: $root = Tree->new("root");
1659: }
1660: else {
1661: my @attributes = @{ $TreeHash{$key} };
1662: my $tmpNode;
1663: $tmpNode = Tree->new(Entry->new(title=>$attributes[0],
1664: path=>$attributes[1],
1665: note=>$attributes[2],
1666: date=>$attributes[3],
1667: nindex=>$key));
1668: push(@TreeNodes, $tmpNode);
1669: # shift all attributes except for
1670: # the indices representing the children of a node
1671: shift(@attributes);
1672: shift(@attributes);
1673: shift(@attributes);
1674: shift(@attributes);
1675: $TreeHash{$key} = [ @attributes ];
1676: }
1677: }
1678: # if there are nodes, build up the tree-structure
1.2 ! wenzelju 1679: if (defined $TreeHash{'root'} && $TreeHash{'root'} ne '') {
1.1 wenzelju 1680: my @childrenRtIn = @{ $TreeHash{'root'} };
1681: &buildTree(\$root, \@childrenRtIn,\@TreeNodes,\%TreeHash);
1682: }
1683: return $root;
1684: }
1685:
1686:
1687: # join the nodes to a tree
1688: sub buildTree {
1689: my ($node, $childrenIn, $TreeNodes, $TreeHash) = @_;
1690: bless($node, 'Tree');
1691: foreach my $c (@$childrenIn) {
1692: my $tmpNode = &getNodeByIndex($c,$TreeNodes);
1693: $$node->add_child($tmpNode);
1694: my @childrenIn = @{ $$TreeHash{$tmpNode->value()->nindex()} };
1695: &buildTree(\$tmpNode,\@childrenIn,$TreeNodes,$TreeHash);
1696: }
1697:
1698: }
1699:
1700:
1701: # ----------------------------------------------------- package Entry
1702: # package that defines the entrys a wishlist could have
1703: # i.e. folders and links
1704: package Entry;
1705:
1706: # constructor
1707: sub new {
1708: my $invocant = shift;
1709: my $class = ref($invocant) || $invocant;
1710: my $self = { @_ }; #set attributes
1711: bless($self, $class);
1712: return $self;
1713: }
1714:
1715: # getter and setter
1716: sub title {
1717: my $self = shift;
1718: if ( @_ ) { $self->{title} = shift}
1719: return $self->{title};
1720: }
1721:
1722: sub date {
1723: my $self = shift;
1724: if ( @_ ) { $self->{date} = shift}
1725: return $self->{date};
1726: }
1727:
1728: sub note {
1729: my $self = shift;
1730: if ( @_ ) { $self->{note} = shift}
1731: return $self->{note};
1732: }
1733:
1734: sub path {
1735: my $self = shift;
1736: if ( @_ ) { $self->{path} = shift}
1737: return $self->{path};
1738: }
1739:
1740: sub nindex {
1741: my $self = shift;
1742: if ( @_ ) { $self->{nindex} = shift}
1743: return $self->{nindex};
1744: }
1745:
1746:
1747: 1;
1748: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>