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