[LON-CAPA-cvs] cvs: loncom / loncapa_apache.conf startup.pl /html/res/adm/pages edit-mode-22x22.png folder-new-22x22.png link-new-22x22.png move-22x22.png save-22x22.png view-mode-22x22.png wishlist-link.png wishlist.png /interface lonwishlist.pm mydesk.tab doc/loncapafiles loncapafiles.lpml
wenzelju
wenzelju@source.lon-capa.org
Tue, 10 Aug 2010 14:30:46 -0000
This is a MIME encoded message
--wenzelju1281450646
Content-Type: text/plain
wenzelju Tue Aug 10 14:30:46 2010 EDT
Added files:
/loncom/interface lonwishlist.pm
/loncom/html/res/adm/pages edit-mode-22x22.png folder-new-22x22.png
link-new-22x22.png move-22x22.png
save-22x22.png view-mode-22x22.png
wishlist-link.png wishlist.png
Modified files:
/loncom/interface mydesk.tab
/loncom loncapa_apache.conf startup.pl
/doc/loncapafiles loncapafiles.lpml
Log:
Add new module lonwishlist:
- This module will replace the bookmark-collection. Bookmark-collection is out of use because it's partly faulty and intricate to use.
- The wishlist will offer a possibility to link resources on a hierarchal list. The list can be modified by adding new links and folder, to structure the list. Existing entries can be renamed, moved, sorted and deleted. Additional information can be attached for each entry by adding a note. Linked resources from the wishlist can be imported into courses. The wishlist is only available for roles with access to the resource-pool.
Still under progress! Function for setting a link to wishlist, when viewing a resource, and import-functionality will follow!
--wenzelju1281450646
Content-Type: text/plain
Content-Disposition: attachment; filename="wenzelju-20100810143046.txt"
Index: loncom/interface/mydesk.tab
diff -u loncom/interface/mydesk.tab:1.136 loncom/interface/mydesk.tab:1.137
--- loncom/interface/mydesk.tab:1.136 Sun Jun 6 11:56:12 2010
+++ loncom/interface/mydesk.tab Tue Aug 10 14:30:20 2010
@@ -199,6 +199,7 @@
8:1:tools:reqcrsshc:rcrs.png:request[_1]:course[_16]:go('/adm/requestcourse');:Course/Community requests:rcr
8:1:tools:reqcrsnsc:rcrs.png:request[_1]:course[_16]:go('/adm/requestcourse');:Course/Community requests:rol
9:2:any:any:vbkm.png:view[_1]:bookmark[_1]:edit_bookmarks():Use or edit my bookmark collection:set
+9:3:pbre:$requested_domain:wishlist.png:view[_1]:wishlist[_1]:go('/adm/wishlist'):Wishlist:set
10:1:clear
10:1:any:any:anno.png:calendar[_1]:announce[_1]:go('/adm/announcements');:Announcements and my calendar:com
10:1:course:any:anno.png:calendar[_1]:announce[_1]:go('/adm/announcements');:Course anouncements and my calendar:com
Index: loncom/loncapa_apache.conf
diff -u loncom/loncapa_apache.conf:1.196 loncom/loncapa_apache.conf:1.197
--- loncom/loncapa_apache.conf:1.196 Wed Jul 7 16:30:44 2010
+++ loncom/loncapa_apache.conf Tue Aug 10 14:30:28 2010
@@ -1,7 +1,7 @@
##
## loncapa_apache.conf -- Apache HTTP LON-CAPA configuration file
##
-## $Id: loncapa_apache.conf,v 1.196 2010/07/07 16:30:44 raeburn Exp $
+## $Id: loncapa_apache.conf,v 1.197 2010/08/10 14:30:28 wenzelju Exp $
##
#
@@ -1225,6 +1225,17 @@
ErrorDocument 500 /adm/errorhandler
</Location>
+<Location /adm/wishlist>
+AuthType LONCAPA
+Require valid-user
+PerlAuthzHandler Apache::lonacc
+SetHandler perl-script
+PerlHandler Apache::lonwishlist
+ErrorDocument 403 /adm/login
+ErrorDocument 406 /adm/roles
+ErrorDocument 500 /adm/errorhandler
+</Location>
+
<Location /adm/blockingstatus>
PerlAccessHandler Apache::publiccheck
AuthType LONCAPA
Index: loncom/startup.pl
diff -u loncom/startup.pl:1.35 loncom/startup.pl:1.36
--- loncom/startup.pl:1.35 Mon Apr 26 21:10:13 2010
+++ loncom/startup.pl Tue Aug 10 14:30:28 2010
@@ -1,5 +1,5 @@
#!/usr/bin/perl
-# $Id: startup.pl,v 1.35 2010/04/26 21:10:13 faziophi Exp $
+# $Id: startup.pl,v 1.36 2010/08/10 14:30:28 wenzelju Exp $
BEGIN {
eval "use Apache2::compat();";
@@ -115,6 +115,7 @@
use Apache::lonwrapper();
use Apache::admannotations();
use Apache::admbookmarks();
+use Apache::lonwishlist();
use Apache::style();
use Apache::lontex();
use Apache::matchresponse();
Index: doc/loncapafiles/loncapafiles.lpml
diff -u doc/loncapafiles/loncapafiles.lpml:1.695 doc/loncapafiles/loncapafiles.lpml:1.696
--- doc/loncapafiles/loncapafiles.lpml:1.695 Sun Aug 8 02:01:03 2010
+++ doc/loncapafiles/loncapafiles.lpml Tue Aug 10 14:30:37 2010
@@ -2,7 +2,7 @@
"http://lpml.sourceforge.net/DTD/lpml.dtd">
<!-- loncapafiles.lpml -->
-<!-- $Id: loncapafiles.lpml,v 1.695 2010/08/08 02:01:03 raeburn Exp $ -->
+<!-- $Id: loncapafiles.lpml,v 1.696 2010/08/10 14:30:37 wenzelju Exp $ -->
<!--
@@ -6746,6 +6746,7 @@
edit-copy.png;
edit-find-replace.png;
edit-find.png;
+edit-mode-22x22.png;
edit-redo.png;
edit-select-all.png;
edit-undo.png;
@@ -6754,6 +6755,7 @@
emblem-system.png;
extres.png;
folder-new.png;
+folder-new-22x22.png;
format-justify-fill.png;
fromfile.png;
groupportfolio.png;
@@ -6763,12 +6765,14 @@
grp_tools.png;
ims.png;
imsexport.png;
+link-new-22x22.png;
list-add.png;
log.png;
mail-message-new.png;
mail-reply-all.png;
mail-reply-sender.png;
messalog.png;
+move-22x22.png;
myaboutme.png;
navigation.png;
network-workgroup.png;
@@ -6782,6 +6786,7 @@
recover.png;
remotecontrol.png;
resversion.png;
+save-22x22.png;
scoreupfrm.png;
selfenrl-queue.png;
sequence.png;
@@ -6796,6 +6801,9 @@
uplcrs.png;
uploadscores.png;
verify.png;
+view-mode-22x22.png;
+wishlist.png;
+wishlist-link.png;
</filenames>
</fileglob>
<file>
@@ -7367,6 +7375,16 @@
</description>
</file>
<file>
+<source>loncom/interface/lonwishlist.pm</source>
+<target dist='default'>home/httpd/lib/perl/Apache/lonwishlist.pm</target>
+<categoryname>handler</categoryname>
+<description>
+Interface to modify the wishlist (add new links and folders,
+edit, move, sort or delete existing links and folders).
+Links from the wishlist can be imported into courses.</description>
+<status>works/unverified</status>
+</file>
+<file>
<source>loncom/automation/Autocreate.pl</source>Autocreate.pl
<target dist='default'>home/httpd/perl/Autocreate.pl</target>
<categoryname>script</categoryname>
Index: loncom/interface/lonwishlist.pm
+++ loncom/interface/lonwishlist.pm
# The LearningOnline Network with CAPA
# Routines to control the wishlist
#
# $Id: lonwishlist.pm,v 1.1 2010/08/10 14:30:20 wenzelju Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
package Apache::lonwishlist;
use strict;
use Apache::Constants qw(:common);
use Apache::lonnet;
use Apache::loncommon();
use Apache::lonhtmlcommon;
use Apache::lonlocal;
use Tree;
# Global variables
my $root;
my @childrenRt;
my %TreeHash;
my %TreeToHash;
my @allFolders;
my @allNodes;
my $indentConst = 20;
# Read wishlist from user-data
sub getWishlist {
my @wishlistkeys = &Apache::lonnet::getkeys('wishlist');
my %wishlist = &Apache::lonnet::get('wishlist',\@wishlistkeys);
foreach my $i (%wishlist) {
#File not found. This appears at the first time using the wishlist
#Create file and put 'root' into it
if ($i =~m/^error:No such file/) {
&Apache::lonnet::logthis($i.'! Create file by putting in the "root" of the directory tree.');
&Apache::lonnet::put('wishlist', {'root' => ''});
@wishlistkeys = &Apache::lonnet::getkeys('wishlist');
%wishlist = &Apache::lonnet::get('wishlist',\@wishlistkeys);
}
elsif ($i =~ /^(con_lost|error|no_such_host)/i) {
&Apache::lonnet::logthis('ERROR while attempting to get wishlist: '.$i);
return 'error';
}
}
#If hash is empty, put 'root' into it, so we got a node to start the tree
if ((keys %wishlist) == 0) {
&Apache::lonnet::logthis('ERROR while attempting to get wishlist: no keys retrieved!');
return 'error';
}
return %wishlist;
}
# Write wishlist to user-data
sub putWishlist {
my $wishlist = shift;
&Apache::lonnet::put('wishlist',$wishlist);
}
# Removes all existing entrys for wishlist in user-data
sub deleteWishlist {
my @wishlistkeys = &Apache::lonnet::getkeys('wishlist');
my %wishlist = &Apache::lonnet::del('wishlist',\@wishlistkeys);
}
# Create a new entry
sub newEntry() {
my ($title, $path, $note) = @_;
my $date = gmtime();
# Create Entry-Object
my $entry = Entry->new(title => $title, path => $path, note => $note, date => $date);
# Create Tree-Object, this correspones a node in the wishlist-tree
my $tree = Tree->new($entry);
# Add this node to wishlist-tree
my $folderIndex = $env{'form.folders'};
if ($folderIndex ne '') {
@allFolders = ();
&getFoldersToArray(\@childrenRt);
my $folderToInsertOn = &Tree::getNodeByIndex($folderIndex,\@allFolders);
$folderToInsertOn->add_child($tree);
}
else {
$root->add_child($tree);
}
&saveChanges();
}
# Delete entries
sub deleteEntries {
my $marked = shift;
&getNodesToArray(\@childrenRt);
foreach my $m (@$marked) {
my $found = &Tree::getNodeByIndex($m, \@allNodes);
&Tree::removeNode($found);
}
@allNodes = ();
&saveChanges();
}
# Sort entries
sub sortEntries {
my $indexNode = shift;
my $at = shift;
&getNodesToArray(\@childrenRt);
my $foundNode = &Tree::getNodeByIndex($indexNode, \@allNodes);
&Tree::moveNode($foundNode,$at,undef);
@allNodes = ();
}
# Move entries
sub moveEntries {
my $indexNodesToMove = shift;
my $indexParent = shift;
my @nodesToMove = ();
&getNodesToArray(\@childrenRt);
foreach my $index (@$indexNodesToMove) {
my $foundNode = &Tree::getNodeByIndex($index, \@allNodes);
push(@nodesToMove, $foundNode);
}
foreach my $node (@nodesToMove) {
my $foundParent;
my $parentIsIn = 0;
foreach my $n (@nodesToMove) {
if ($node->parent()->value() ne "root") {
if ($node->parent()->value()->nindex() == $n->value()->nindex()) {
$parentIsIn = 1;
}
}
}
if (!$parentIsIn) {
if ($indexParent ne "root") {
$foundParent = &Tree::getNodeByIndex($indexParent, \@allNodes);
&Tree::moveNode($node,undef,$foundParent);
}
else {
&Tree::moveNode($node,undef,$root);
}
}
}
@allNodes = ();
}
# Set a new title for an entry
sub setNewTitle {
my ($nodeindex, $newTitle) = @_;
&getNodesToArray(\@childrenRt);
my $found = &Tree::getNodeByIndex($nodeindex, \@allNodes);
$found->value()->title($newTitle);
@allNodes = ();
}
# Set a new note for an entry
sub setNewNote {
my ($nodeindex, $newNote) = @_;
&getNodesToArray(\@childrenRt);
my $found = &Tree::getNodeByIndex($nodeindex, \@allNodes);
$found->value()->note($newNote);
@allNodes = ();
}
# Save all changes
sub saveChanges {
@childrenRt = $root->children();
&Tree::TreeIndex(\@childrenRt);
&Tree::setCountZero();
&Tree::RootToHash(\@childrenRt);
&Tree::TreeToHash(\@childrenRt);
&deleteWishlist();
&putWishlist(\%TreeToHash);
}
# Return the names for all exiting folders in option-tags, so
# a new link or a new folder can be created in an existing folder
my $indent = 0;
my $foldersOption;
sub getFoldersForOption {
my $nodes = shift;
foreach my $n (@$nodes) {
if ($n->value()->path() eq '') {
$foldersOption .= '<option value="'.$n->value()->nindex().'" style="margin-left:'.$indent.'px">'.
$n->value()->title().
'</option>';
my @children = $n->children();
if ($#children >=0) {
$indent += 10;
&getFoldersForOption(\@children);
$indent -= 10;
}
}
}
}
sub getfoldersOption {
if (&getWishlist ne 'error') {
%TreeHash = &getWishlist();
$root = &Tree::HashToTree();
@childrenRt = $root->children();
&getFoldersForOption(\@childrenRt);
my $options = '<option value="" selected="selected"></option>'.$foldersOption;
$foldersOption = '';
return $options;
}
else {
return '';
}
}
# Put all folder-nodes to an array
sub getFoldersToArray {
my $children = shift;
foreach my $c (@$children) {
if ($c->value()->path() eq '') {
push(@allFolders,$c);
}
my @newchildren = $c->children();
if ($#newchildren >= 0) {
&getFoldersToArray(\@newchildren);
}
}
}
# Put all nodes to an array
sub getNodesToArray {
my $children = shift;
foreach my $c (@$children) {
push(@allNodes,$c);
my @newchildren = $c->children();
if ($#newchildren >= 0) {
&getNodesToArray(\@newchildren);
}
}
}
# Return a script-tag containing Javascript-function
# needed for wishlist actions like 'new link' ect.
sub JSforWishlist {
my $startPagePopup = &Apache::loncommon::start_page('Wishlist',undef,
{'only_body' => 1,
'js_ready' => 1,
'bgcolor' => '#FFFFFF',});
my $endPagePopup = &Apache::loncommon::end_page({'js_ready' => 1});
@allFolders = ();
&getFoldersToArray(\@childrenRt);
&getFoldersForOption(\@childrenRt);
# texthash
my %lt = &Apache::lonlocal::texthash(
'nl' => 'New Link',
'nf' => 'New Folder',
'lt' => 'Link Title',
'ft' => 'Folder Title',
'pa' => 'Path',
'nt' => 'Note',
'si' => 'Save in',
'cl' => 'Cancel');
my $inPageNewLink = '<h1>'.$lt{'nl'}.'</h1>'.
'<form method="post" name="newlink" action="/adm/wishlist" target="wishlist" '.
'onsubmit="return newlinksubmit();" >'.
&Apache::lonhtmlcommon::start_pick_box().
&Apache::lonhtmlcommon::row_title($lt{'lt'}).
'<input type="text" name="title" size="45" value="" />'.
&Apache::lonhtmlcommon::row_closure().
&Apache::lonhtmlcommon::row_title($lt{'pa'}).
'<input type="text" name="path" size="45" value="" />'.
&Apache::lonhtmlcommon::row_closure().
&Apache::lonhtmlcommon::row_title($lt{'nt'}).
'<textarea name="note" rows="3" cols="35" style="width:100%"></textarea>'.
&Apache::lonhtmlcommon::row_closure(1).
&Apache::lonhtmlcommon::end_pick_box().
'<br/><br/>'.
'<input type="submit" value="'.$lt{'si'}.'" />'.
'<select name="folders">'.
'<option value="" selected="selected"></option>'.
$foldersOption.
'</select>'.
'<input type="button" value="'.$lt{'cl'}.'" onclick="javascript:window.close();" />'.
'</form>';
my $inPageNewFolder = '<h1>'.$lt{'nf'}.'</h1>'.
'<form method="post" name="newfolder" action="/adm/wishlist" target="wishlist" '.
'onsubmit="return newfoldersubmit();" >'.
&Apache::lonhtmlcommon::start_pick_box().
&Apache::lonhtmlcommon::row_title($lt{'ft'}).
'<input type="text" name="title" size="45" value="" /><br />'.
&Apache::lonhtmlcommon::row_closure().
&Apache::lonhtmlcommon::row_title($lt{'nt'}).
'<textarea name="note" rows="3" cols="35" style="width:100%"></textarea><br />'.
&Apache::lonhtmlcommon::row_closure(1).
&Apache::lonhtmlcommon::end_pick_box().
'<br/><br/>'.
'<input type="submit" value="'.$lt{'si'}.'" />'.
'<select name="folders">'.
'<option value="" selected="selected"></option>'.
$foldersOption.
'</select>'.
'<input type="button" value="'.$lt{'cl'}.'" onclick="javascript:window.close();" />'.
'</form>';
# Remove all \n for inserting on javascript document.write
$inPageNewLink =~ s/\n//g;
$inPageNewFolder =~ s/\n//g;
my $warningLink = &mt('You must insert a title and a path!');
my $warningFolder = &mt('You must insert a title!');
my $warningDelete = &mt('Are you sure you want to delete the selected entries? Deleting a folder also deletes all entries within this folder!');
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.');
my $warningMove = &mt('You must select a destination folder!');
$foldersOption = '';
my $js = &Apache::lonhtmlcommon::scripttag(<<JAVASCRIPT);
function newLink() {
newlinkWin=window.open('','newlinkWin','width=580,height=320,scrollbars=yes');
newlinkWin.document.write('$startPagePopup'
+'<script type="text\/javascript">'
+'function newlinksubmit(){'
+'var path = document.getElementsByName("path")[0].value;'
+'var title = document.getElementsByName("title")[0].value;'
+'if (!path || !title) {'
+'alert("$warningLink");'
+'return false;}'
+'else {'
+'window.close();'
+'return true;}}'
+'<\/scr'+'ipt>'
+'$inPageNewLink'
+'$endPagePopup');
newlinkWin.document.close();
}
function newFolder() {
newfolderWin=window.open('','newfolderWin','width=580,height=270, scrollbars=yes');
newfolderWin.document.write('$startPagePopup'
+'<script type="text\/javascript">'
+'function newfoldersubmit(){'
+'var title = document.getElementsByName("title")[0].value;'
+'if (!title) {'
+'alert("$warningFolder");'
+'return false;}'
+'else {'
+'window.close();'
+'return true;}}'
+'<\/scr'+'ipt>'
+'$inPageNewFolder'
+'$endPagePopup');
newfolderWin.document.close();
}
function setFormAction(action,mode) {
var r = true;
setAction('');
if (action == 'delete') {
r = confirm("$warningDelete");
setAction('delete');
}
else if (action == 'save') {
var d = getDifferences();
if (d) {
if (!confirm('$warningSave')) {
setAction('noSave');
}
}
r = true;
}
document.getElementsByName('list')[0].setAttribute("action", "/adm/wishlist?mode="+mode);
if(r){
document.getElementsByName('list')[0].submit();
}
}
function setAction(action) {
document.getElementById('action').value = action;
}
function getDifferences() {
var newtitles = document.getElementsByName('newtitle');
var i = 0;
for (i=0;i<newtitles.length;i++) {
var newt = newtitles[i].value;
var oldt = newtitles[i].alt;
if (newt != oldt) {
return true;
}
}
var newnote = document.getElementsByName('newnote');
var i = 0;
for (i=0;i<newnote.length;i++) {
var newn = newnote[i].value;
var oldn = newnote[i].innerHTML;
if (newn != oldn) {
return true;
}
}
return false;
}
function onLoadAction(mode) {
window.name = 'wishlist';
if (mode == "edit") {
var deepestRows = getDeepestRows();
setDisplaySelect(deepestRows, '');
}
}
function folderAction(rowid) {
var row = document.getElementById(rowid);
var indent = getIndent(row);
var displ;
var status;
if (getImage(row) == 'closed') {
displ = '';
status = 'open';
}
else {
displ = 'LC_hidden';
status = 'closed';
}
setImage(row,status);
if (getNextRow(row) != null) {
var nextIndent = getIndent(getNextRow(row));
row = getNextRow(row);
while (nextIndent > indent) {
if (displ == '') {
row.className = (row.className).replace('LC_hidden','');
}
else if (displ != '' && !((row.className).match('LC_hidden'))) {
var oldClass = row.className;
row.className = oldClass+' LC_hidden';
setDisplayNote(row.id.replace('row','note'),'LC_hidden');
}
if (status == 'open' && getImage(row).match('closed')) {
row = getNextRowWithIndent(row, getIndent(row));
}
else {
row = getNextRow(row);
}
if (row != null) {
nextIndent = getIndent(row);
}
else {
nextIndent = indent;
}
}
}
setClasses();
var newtitles = document.getElementsByName('newtitle');
if (newtitles.length>0) {
var deepestRows = getDeepestRows();
var otherRows = getOtherRows(deepestRows);
setDisplaySelect(deepestRows,'');
setDisplaySelect(otherRows,'LC_hidden');
}
}
function selectAction(rowid) {
var row = document.getElementById(rowid);
var indent = getIndent(row);
var checked = getChecked(row);
var previousFolderRows = new Array();
if (indent != 0) {
previousFolderRows = getPreviousFolderRows(row);
}
if (getNextRow(row) != null) {
var nextIndent = getIndent(getNextRow(row));
row = getNextRow(row);
while (nextIndent > indent) {
setChecked(row,checked);
if (status == 'open' && getImage(row).match('closed')) {
row = getNextRowWithIndent(row, getIndent(row));
}
else {
row = getNextRow(row);
}
if (row != null) {
nextIndent = getIndent(row);
}
else {
nextIndent = indent;
}
}
}
if (!checked) {
var i = 0;
for (i=0;i<previousFolderRows.length;i++) {
setChecked(previousFolderRows[i], false);
}
}
}
function getNextNote(row) {
var rowId = row.id;
var nextRowId = parseInt(rowId.substr(3,rowId.length))+1;
nextRowId = "note"+nextRowId;
var nextRow = document.getElementById(nextRowId);
return nextRow;
}
function getNextRow(row) {
var rowId = row.id;
var nextRowId = parseInt(rowId.substr(3,rowId.length))+1;
nextRowId = "row"+nextRowId;
var nextRow = document.getElementById(nextRowId);
return nextRow;
}
function getPreviousRow(row) {
var rowId = row.id;
var previousRowId = parseInt(rowId.substr(3,rowId.length))-1;
previousRowId = "row"+previousRowId;
var previousRow =document.getElementById(previousRowId);
return previousRow;
}
function getIndent(row) {
var childPADD = document.getElementById(row.id.replace('row','padd'));
indent = childPADD.style.paddingLeft;
indent = parseInt(indent.substr(0,(indent.length-2)));
if (getImage(row).match('link')) {
indent -= $indentConst;
}
return indent;
}
function getNextRowWithIndent(row, indent) {
var nextRow = getNextRow(row);
if (nextRow != null) {
var nextIndent = getIndent(nextRow);
while (nextIndent >= indent) {
if (nextIndent == indent) {
return nextRow;
}
nextRow = getNextRow(nextRow);
if (nextRow == null) {
return null;
}
nextIndent = getIndent(nextRow);
}
}
return nextRow;
}
function getImage(row) {
var childIMG = document.getElementById(row.id.replace('row','img'));
if ((childIMG.src).match('closed')) {
return 'closed';
}
else if ((childIMG.src).match('open')) {
return 'open;'
}
else {
return 'link';
}
}
function setImage(row, status) {
var childIMG = document.getElementById(row.id.replace('row','img'));
var childIMGFolder = document.getElementById(row.id.replace('row','imgFolder'));
childIMG.src = "/adm/lonIcons/arrow."+status+".gif";
childIMGFolder.src="/adm/lonIcons/navmap.folder."+status+".gif";
}
function getChecked(row) {
var childCHECK = document.getElementById(row.id.replace('row','check'));
var checked = childCHECK.checked;
return checked;
}
function setChecked(row,checked) {
var childCHECK = document.getElementById(row.id.replace('row','check'));
childCHECK.checked = checked;
}
function getPreviousFolderRows(row) {
var previousRow = getPreviousRow(row);
var indent = getIndent(previousRow);
var kindOfEntry = getImage(previousRow);
var rows = new Array();
if (kindOfEntry != 'link') {
rows.push(previousRow);
}
while (indent >0) {
previousRow = getPreviousRow(previousRow);
if (previousRow != null) {
indent = getIndent(previousRow);
kindOfEntry = getImage(previousRow);
if (kindOfEntry != 'link') {
rows.push(previousRow);
}
}
else {
indent = 0;
}
}
return rows;
}
function getDeepestRows() {
var row = document.getElementById('row0');
var firstRow = row;
var indent = getIndent(row);
var maxIndent = indent;
while (getNextRow(row) != null) {
row = getNextRow(row);
indent = getIndent(row);
if (indent>maxIndent && !((row.className).match('LC_hidden'))) {
maxIndent = indent;
}
}
var deepestRows = new Array();
row = firstRow;
var rowIndent;
while (getNextRow(row) != null) {
rowIndent = getIndent(row);
if (rowIndent == maxIndent) {
deepestRows.push(row);
}
row = getNextRow(row);
}
rowIndent = getIndent(row);
if (rowIndent == maxIndent) {
deepestRows.push(row);
}
return deepestRows;
}
function getOtherRows(deepestRows) {
var row = document.getElementById('row0');
var otherRows = new Array();
var isIn = false;
while (getNextRow(row) != null) {
var i = 0;
for (i=0; i < deepestRows.length; i++) {
if (row.id == deepestRows[i].id) {
isIn = true;
}
}
if (!isIn) {
otherRows.push(row);
}
row = getNextRow(row);
isIn = false;
}
for (i=0; i < deepestRows.length; i++) {
if (row.id == deepestRows[i].id) {
isIn = true;
}
}
if (!isIn) {
otherRows.push(row);
}
return otherRows;
}
function setDisplaySelect(deepestRows, displ) {
var i = 0;
for (i = 0; i < deepestRows.length; i++) {
var row = deepestRows[i];
var childSEL = document.getElementById(row.id.replace('row','sel'));
childSEL.className = displ;
}
}
function submitSelect() {
var list = document.getElementsByName('list')[0];
list.setAttribute("action","/adm/wishlist?mode=edit");
list.submit();
}
function setDisplayNote(rowid, displ) {
var row = document.getElementById(rowid);
if (!displ) {
if ((row.className).match('LC_hidden')) {
row.className = (row.className).replace('LC_hidden','');
}
else {
var oldClass = row.className;
row.className = oldClass+' LC_hidden';
}
}
else {
if (displ == '') {
row.className = (row.className).replace('LC_hidden','');
}
else if (displ != '' && !((row.className).match('LC_hidden'))) {
var oldClass = row.className;
row.className = oldClass+' LC_hidden';
}
}
var noteText = document.getElementById(rowid.replace('note','noteText'));
var noteImg = document.getElementById(rowid.replace('note','noteImg'));
if (noteText.value) {
noteImg.src = "/res/adm/pages/anot2.png";
}
else {
noteImg.src = "/res/adm/pages/anot.png";
}
}
function setClasses() {
var row = document.getElementById("row0");
var note = document.getElementById("note0");
var LC_class = 0;
if (getNextRow(row) != null) {
while (getNextRow(row) != null) {
if (!(row.className).match('LC_hidden')) {
note.className = (note.className).replace('LC_even_row','');
note.className = (note.className).replace('LC_odd_row','');
if (LC_class) {
row.className = 'LC_even_row';
note.className = 'LC_even_row'+note.className;
}
else {
row.className = 'LC_odd_row';
note.className = 'LC_odd_row'+note.className;;
}
LC_class = !LC_class;
}
note = getNextNote(row);
row = getNextRow(row);
}
}
if (!(row.className).match('LC_hidden')) {
note.className = (note.className).replace('LC_even_row','');
note.className = (note.className).replace('LC_odd_row','');
if (LC_class) {
row.className = 'LC_even_row';
note.className = 'LC_even_row'+note.className;
}
else {
row.className = 'LC_odd_row';
note.className = 'LC_odd_row'+note.className;
}
}
}
function selectDestinationFolder() {
var mark = document.getElementsByName('mark');
var i = 0;
for (i = 0; i < mark.length; i++) {
if (mark[i].checked) {
document.getElementsByName('list')[0].submit();
return true;
}
}
alert('$warningMove');
return false;
}
JAVASCRIPT
return $js;
}
# HTML-Markup for table if in view-mode
my $wishlistHTMLview;
my $indent = $indentConst;
sub wishlistView {
my $nodes = shift;
foreach my $n (@$nodes) {
my $index = $n->value()->nindex();
# 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.
# only display the top level entries on load
$wishlistHTMLview .= ($n->parent()->value() eq 'root')?&Apache::loncommon::start_data_table_row('','row'.$index)
:&Apache::loncommon::continue_data_table_row('LC_hidden','row'.$index);
# checkboxes
$wishlistHTMLview .= '<td><input type="checkbox" name="mark" id="check'.$index.'" value="'.$index.'" '.
'onclick="selectAction('."'row".$index."'".')"/></td>';
# entry is a folder
if ($n->value()->path() eq '') {
$wishlistHTMLview .= '<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<0?0:($indent-$indentConst)).'px; min-width: 220px;">'.
'<a href="javascript:;" onclick="folderAction('."'row".$index."'".')" style="vertical-align:top">'.
'<img src="/adm/lonIcons/arrow.closed.gif" id="img'.$index.'" alt = "" class="LC_icon"/>'.
'<img src="/adm/lonIcons/navmap.folder.closed.gif" id="imgFolder'.$index.'" alt="folder"/>'.
$n->value()->title().'</a></td>';
}
# entry is a link
else {
$wishlistHTMLview .= '<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<=0?$indentConst:$indent).'px; min-width: 220px;">'.
'<img src="/res/adm/pages/wishlist-link.png" id="img'.$index.'" alt="link" />'.
'<a href="'.$n->value()->path().'">'.$n->value()->title().'</a></td>';
}
# note-icon, different icons for an entries with note and those without
my $noteIMG = 'anot.png';
if ($n->value()->note() ne '') {
$noteIMG = 'anot2.png';
}
$wishlistHTMLview .= '<td style="padding-left:10px;"><a href="javascript:;" onclick="setDisplayNote('."'note".$index."'".')">'.
'<img id="noteImg'.$index.'" src="/res/adm/pages/'.$noteIMG.'" alt="'.&mt('Note').'" title="'.&mt('Note').'" '.
' class="LC_icon"/></a></td>';
$wishlistHTMLview .= &Apache::loncommon::end_data_table_row();
# start row containing the textarea for the note, do not display note on default
$wishlistHTMLview .= &Apache::loncommon::continue_data_table_row('LC_hidden','note'.$index).
'<td></td><td>'.
'<textarea id="noteText'.$index.'" cols="25" rows="3" style="width:100%" '.
'name="newnote" >'.
$n->value()->note().'</textarea></td><td></td>';
$wishlistHTMLview .= &Apache::loncommon::end_data_table_row();
# if the entry is a folder, it could have other entries as content. if it has, call wishlistView for those entries
my @children = $n->children();
if ($#children >=0) {
$indent += 20;
&wishlistView(\@children);
$indent -= 20;
}
}
}
# HTML-Markup for table if in edit-mode
my $wishlistHTMLedit;
my $indent = $indentConst;
sub wishlistEdit {
my $nodes = shift;
my $curNode = 1;
foreach my $n (@$nodes) {
my $index = $n->value()->nindex();
# start row, use data_table routines to set class to LC_even or LC_odd automatically.
# this rows contains a checkbox, a select-field for sorting entries, the title in an input-field and the note-icon.
# only display the top level entries on load
$wishlistHTMLedit .= ($n->parent()->value() eq 'root')?&Apache::loncommon::start_data_table_row('','row'.$index)
:&Apache::loncommon::continue_data_table_row('LC_hidden','row'.$index);
# checkboxes
$wishlistHTMLedit .= '<td><input type="checkbox" name="mark" id="check'.$index.'" value="'.$index.'" '.
'onclick="selectAction('."'row".$index."'".')"/></td>';
# 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.
# set the number for the current entry into brackets
my $options;
for (my $i = 1; $i < ((scalar @{$nodes})+1); $i++) {
if ($i == $curNode) {
$options .= '<option selected="selected" value="">('.$i.')</option>';
}
else {
$options .= '<option value="'.$i.'">'.$i.'</option>';
}
}
$curNode++;
# entry is a folder
if ($n->value()->path() eq '') {
$wishlistHTMLedit .= '<td><select class="LC_hidden" name="sel" id="sel'.$index.'" onchange="submitSelect();">'.
$options.'</select></td>'.
'<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<0?0:($indent-$indentConst)).'px;">'.
'<a href="javascript:;" onclick="folderAction('."'row".$index."'".')" style="vertical-align:top" >'.
'<img src="/adm/lonIcons/arrow.closed.gif" id="img'.$index.'" alt = "" class="LC_icon"/>'.
'<img src="/adm/lonIcons/navmap.folder.closed.gif" id="imgFolder'.$index.'" alt="folder"/></a>';
}
# entry is a link
else {
$wishlistHTMLedit .= '<td><select class="LC_hidden" name="sel" id="sel'.$index.'" onchange="submitSelect();">'.
$options.'</select></td>'.
'<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<=0?$indentConst:$indent).'px;">'.
'<img src="/res/adm/pages/wishlist-link.png" id="img'.$index.'" alt="link"/>';
}
# input-field for title
$wishlistHTMLedit .= '<input type="text" name="newtitle" value="'.$n->value()->title().'" alt = "'.$n->value()->title().'"/></td>';
# note-icon, different icons for an entries with note and those without
my $noteIMG = 'anot.png';
if ($n->value()->note() ne '') {
$noteIMG = 'anot2.png';
}
$wishlistHTMLedit .= '<td style="padding-left:10px;"><a href="javascript:;" onclick="setDisplayNote('."'note".$index."'".')">'.
'<img id="noteImg'.$index.'" src="/res/adm/pages/'.$noteIMG.'" alt="'.&mt('Note').'" title="'.&mt('Note').'" '.
' class="LC_icon"/></a></td>';
$wishlistHTMLedit .= &Apache::loncommon::end_data_table_row();
# start row containing the textarea for the note
$wishlistHTMLedit .= &Apache::loncommon::continue_data_table_row('LC_hidden','note'.$index).
'<td></td><td></td><td>'.
'<textarea id="noteText'.$index.'" cols="25" rows="3" style="width:100%" '.
'name="newnote">'.
$n->value()->note().'</textarea></td><td></td>';
$wishlistHTMLedit .= &Apache::loncommon::end_data_table_row();
# if the entry is a folder, it could have other entries as content. if it has, call wishlistEdit for those entries
my @children = $n->children();
if ($#children >=0) {
$indent += 20;
&wishlistEdit(\@children);
$indent -= 20;
}
}
}
# HTML-Markup for table if in move-mode
my $wishlistHTMLmove ='<tr id="root" class="LC_odd_row"><td><input type="radio" name="mark" id="radioRoot" value="root" /></td>'.
'<td>'.&mt('Top level').'</td><td></td></tr>';
my $indent = $indentConst;
sub wishlistMove {
my $nodes = shift;
my $marked = shift;
foreach my $n (@$nodes) {
my $index = $n->value()->nindex();
#find out wether the current entry was marked to be moved.
my $isIn = 0;
foreach my $m (@$marked) {
if ($index == $m) {
$isIn = 1;
}
}
# 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
$wishlistHTMLmove .= &Apache::loncommon::start_data_table_row('','row'.$index);
# entry is a folder
if ($n->value()->path() eq '') {
# display a radio-button, if the folder was not selected to be moved
if (!$isIn) {
$wishlistHTMLmove .= '<td><input type="radio" name="mark" id="radio'.$index.'" value="'.$index.'" /></td>'.
'<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<0?0:($indent-$indentConst)).'px; min-width: 220px;">';
}
# higlight the title, if the folder was selected to be moved
else {
$wishlistHTMLmove .= '<td></td>'.
'<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<0?0:($indent-$indentConst)).'px; min-width: 220px;'.
'color:red;">';
}
#arrow- and folder-image, all folders are open, and title
$wishlistHTMLmove .= '<img src="/adm/lonIcons/arrow.open.gif" id="img'.$index.'" alt = "" />'.
'<img src="/adm/lonIcons/navmap.folder.open.gif" id="imgFolder'.$index.'" alt="folder"/>'.
$n->value()->title().'</td>';
}
# entry is a link
else {
if (!$isIn) {
$wishlistHTMLmove .= '<td></td>'.
'<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<=0?$indentConst:$indent).'px; min-width: 220px;">';
}
# higlight the title, if the link was selected to be moved
else {
$wishlistHTMLmove .= '<td></td>'.
'<td id="padd'.$index.'" style="padding-left:'.(($indent-$indentConst)<=0?$indentConst:$indent).'px; min-width: 220px;'.
'color:red;">';
}
# link-image and title
$wishlistHTMLmove .= '<img src="/res/adm/pages/wishlist-link.png" id="img'.$index.'" alt="link"/>'.
$n->value()->title().'</td>';
}
# note-icon, different icons for an entries with note and those without
my $noteIMG = 'anot.png';
if ($n->value()->note() ne '') {
$noteIMG = 'anot2.png';
}
$wishlistHTMLmove .= '<td style="padding-left:10px;"><a href="javascript:;" onclick="setDisplayNote('."'note".$index."'".')">'.
'<img id="noteImg'.$index.'" src="/res/adm/pages/'.$noteIMG.'" alt="'.&mt('Note').'" title="'.&mt('Note').'" '.
' class="LC_icon"/></a></td>';
$wishlistHTMLmove .= &Apache::loncommon::end_data_table_row();
# start row containing the textarea for the note, readonly in move-mode
$wishlistHTMLmove .= &Apache::loncommon::continue_data_table_row('LC_hidden','note'.$index).
'<td></td><td>'.
'<textarea id="noteText'.$index.'" cols="25" rows="3" style="width:100%" '.
'name="newnote" readonly="readonly">'.
$n->value()->note().'</textarea></td><td></td>'.
&Apache::loncommon::end_data_table_row();
# if the entry is a folder, it could have other entries as content. if it has, call wishlistMove for those entries
my @children = $n->children();
if ($#children >=0) {
$indent += 20;
&wishlistMove(\@children, $marked);
$indent -= 20;
}
}
}
# Returns the HTML-Markup for wishlist
sub makePage {
my $mode = shift;
my $marked = shift;
# breadcrumbs and start_page
&Apache::lonhtmlcommon::clear_breadcrumbs();
&Apache::lonhtmlcommon::add_breadcrumb(
{ href => '/adm/wishlist?mode='.$mode,
text => 'Wishlist'});
my $startPage = &Apache::loncommon::start_page('Wishlist',undef,
{'add_entries' => {
'onload' => 'javascript:onLoadAction('."'".$mode."'".');',
'onunload' => 'javascript:window.name = '."'loncapaclient'"}});
my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Wishlist '.
'<a title="Online-Hilfe" href="/adm/help/Wishlist.hlp" target="_top">'.
'<img src="/adm/help/help.png" alt="'.&mt('Help').'" '.
'title="'.&mt('Help').'" class="LC_icon" /></a>');
# get javascript-code for wishlist-interactions
my $js = &JSforWishlist();
# texthash for items in funtionlist
my %lt = &Apache::lonlocal::texthash(
'ed' => 'Edit',
'vw' => 'View',
'al' => 'Add Link',
'af' => 'Add Folder',
'mv' => 'Move Selected',
'dl' => 'Delete Selected',
'sv' => 'Save');
# start functionlist
my $functions = &Apache::lonhtmlcommon::start_funclist();
# icon for edit-mode, display when in view-mode
if ($mode eq 'view') {
$functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
'onclick="setFormAction('."'save','edit'".'); list.submit();" class="LC_menubuttons_link">'.
'<img src="/res/adm/pages/edit-mode-22x22.png" alt="'.$lt{'ed'}.'" '.
'title="'.$lt{'ed'}.'" class="LC_icon"/> '.
'<span class="LC_menubuttons_inline_text">'.$lt{'ed'}.'</span></a>');
}
# icon for view-mode, display when in edit-mode
else {
$functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
'onclick="setFormAction('."'save','view'".'); list.submit();" class="LC_menubuttons_link">'.
'<img src="/res/adm/pages/view-mode-22x22.png" alt="'.$lt{'vw'}.'" '.
'title="'.$lt{'vw'}.'" class="LC_icon"/> '.
'<span class="LC_menubuttons_inline_text">'.$lt{'vw'}.'</span></a>');
}
# icon for adding a new link
$functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
'onclick="newLink();" class="LC_menubuttons_link">'.
'<img src="/res/adm/pages/link-new-22x22.png" alt="'.$lt{'al'}.'" '.
'title="'.$lt{'al'}.'" class="LC_icon"/>'.
'<span class="LC_menubuttons_inline_text">'.$lt{'al'}.'</span></a>');
# icon for adding a new folder
$functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
'onclick="newFolder();" class="LC_menubuttons_link">'.
'<img src="/res/adm/pages/folder-new-22x22.png" alt="'.$lt{'af'}.'" '.
'title="'.$lt{'af'}.'" class="LC_icon"/>'.
'<span class="LC_menubuttons_inline_text">'.$lt{'af'}.'</span></a>');
# icon for moving entries
$functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
'onclick="setFormAction('."'move','move'".'); " class="LC_menubuttons_link">'.
'<img src="/res/adm/pages/move-22x22.png" alt="'.$lt{'mv'}.'" '.
'title="'.$lt{'mv'}.'" class="LC_icon" />'.
'<span class="LC_menubuttons_inline_text">'.$lt{'mv'}.'</span></a>');
# icon for deleting entries
$functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
'onclick="setFormAction('."'delete','".$mode."'".'); " class="LC_menubuttons_link">'.
'<img src="/res/adm/pages/del.png" alt="'.$lt{'dl'}.'" '.
'title="'.$lt{'dl'}.'" class="LC_icon" />'.
'<span class="LC_menubuttons_inline_text">'.$lt{'dl'}.'</span></a>');
# icon for saving changes
$functions .= &Apache::lonhtmlcommon::add_item_funclist('<a href="javascript:;" '.
'onclick="setFormAction('."'','".$mode."'".'); " class="LC_menubuttons_link">'.
'<img src="/res/adm/pages/save-22x22.png" alt="'.$lt{'sv'}.'" '.
'title="'.$lt{'sv'}.'" class="LC_icon" />'.
'<span class="LC_menubuttons_inline_text">'.$lt{'sv'}.'</span></a>');
# end funtionlist and generate subbox
$functions.= &Apache::lonhtmlcommon::end_funclist();
my $subbox = &Apache::loncommon::head_subbox($functions);
# start form
my $inner .= '<form name="list" action ="/adm/wishlist" method="post">'.
'<input type="hidden" id="action" name="action" value=""/>';
# only display subbox in view- or edit-mode
if ($mode ne 'move') {
$inner .= $subbox;
}
# generate table-content depending on mode
if ($mode eq 'edit') {
&wishlistEdit(\@childrenRt);
if ($wishlistHTMLedit ne '') {
$inner .= &Apache::loncommon::start_data_table("LC_tableOfContent");
$inner .= $wishlistHTMLedit;
$inner .= &Apache::loncommon::end_data_table();
}
else {
$inner .= '<span class="LC_info">'.&mt("Your wihlist ist currently empty.").'</span>';
}
$wishlistHTMLedit = '';
}
elsif ($mode eq 'view') {
&wishlistView(\@childrenRt);
if ($wishlistHTMLview ne '') {
$inner .= '<table class="LC_data_table LC_tableOfContent">'.$wishlistHTMLview.'</table>';
}
else {
$inner .= '<span class="LC_info">'.&mt("Your wihlist ist currently empty.").'</span>';
}
$wishlistHTMLview = '';
}
else {
my $markStr = '';
foreach my $m (@$marked) {
$markStr .= $m.',';
}
if ($markStr) {
$markStr = substr($markStr, 0, length($markStr)-1);
$inner .= '<input type="hidden" value="'.$markStr.'" name="markedToMove"/>';
$inner .= '<span class="LC_info">'.&mt('You have selected the red marked entries to be moved to another folder. '.
'Now choose the new destination folder.').'</span><br/><br/>';
&wishlistMove(\@childrenRt, $marked);
$inner .= '<table class="LC_data_table LC_tableOfContent">'.$wishlistHTMLmove.'</table><br/><br/>';
$inner .= '<input type="button" value="'.&mt('Move').'" onclick="setFormAction('."'','view'".'); selectDestinationFolder()"/>'.
'<input type="button" value="'.&mt('Cancel').'" onclick="go('."'/adm/wishlist'".')"/>';
$wishlistHTMLmove ='<tr id="root" class="LC_odd_row"><td><input type="radio" name="mark" id="radioRoot" value="root" /></td>'.
'<td>'.&mt('Top level').'</td><td></td></tr>';
}
else {
$inner .= '<span class="LC_info">'.&mt("You haven't marked any entry to move.").'</span><br/>'.
'<input type="button" value="'.&mt('Back').'" onclick="go('."'/adm/wishlist'".')"/>';
}
}
# end form
$inner .= '</form>';
# end_page
my $endPage = &Apache::loncommon::end_page();
# put all page-elements togther
my $page = $startPage.$breadcrumbs.$js.$inner.$endPage;
return $page;
}
# Returns the HTML-Markup for the page, shown when a link was set
sub makePageSet {
# start_page
my $startPage = &Apache::loncommon::start_page('Wishlist',undef,
{'only_body' => 1});
# confirm success and offer link to wishlist
my $message = &Apache::lonhtmlcommon::confirm_success(&mt('Link successfully set!'));
$message = &Apache::loncommon::confirmwrapper($message);
my $inner .= '<br>'.$message.'<br/><br/>'.
'<a href="javascript:;" onclick="opener.open('."'/adm/wishlist'".');window.close();">'.&mt('Go to wishlist').'</a>'.
' <a href="javascript:;" onclick="window.close();">'.&mt('Close this window').'</a>';
# end_page
my $endPage = &Apache::loncommon::end_page();
# put all page-elements togther
my $page = $startPage.$inner.$endPage;
return $page;
}
# Returns the HTML-Markup for error-page
sub makeErrorPage {
# breadcrumbs and start_page
&Apache::lonhtmlcommon::add_breadcrumb(
{ href => '/adm/wishlist',
text => 'Wishlist'});
my $startPage = &Apache::loncommon::start_page('Wishlist');
my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Wishlist '.
'<a title="Online-Hilfe" href="/adm/help/Wishlist.hlp" target="_top">'.
'<img src="/adm/help/help.png" alt="'.&mt('Help').'" '.
'title="'.&mt('Help').'" class="LC_icon" /></a>');
&Apache::lonhtmlcommon::clear_breadcrumbs();
# error-message
my $inner .= '<span class="LC_error">'.&mt('An error occurred! Please try again later.').'</span>';
# end_page
my $endPage = &Apache::loncommon::end_page();
# put all page-elements togther
my $page = $startPage.$breadcrumbs.$inner.$endPage;
return $page;
}
# ----------------------------------------------------- Main Handler, package lonwishlist
sub handler {
my ($r) = @_;
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
if (&getWishlist() ne 'error') {
# get wishlist entries from user-data db-file and build a tree out of these entries
%TreeHash = &getWishlist();
$root = &Tree::HashToTree();
@childrenRt = $root->children();
# greate a new entry
if ($env{'form.title'}) {
&newEntry($env{'form.title'}, $env{'form.path'}, $env{'form.note'});
}
# get unprocessed_cgi (i.e. marked entries, mode ...)
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['action','mark','markedToMove','mode','newtitle','note']);
# change the order of entries within a level, that means sorting the entries
my $changeOrder = 0;
if (defined $env{'form.sel'}) {
my @sel = &Apache::loncommon::get_env_multiple('form.sel');
my $indexNode;
my $at;
for (my $s=0; $s<($#sel+1); $s++) {
if ($sel[$s] ne '') {
$indexNode = $s;
$at = $sel[$s]-1;
}
}
if ($at ne '') {
$changeOrder = 1;
&sortEntries($indexNode,$at);
&saveChanges();
}
}
# get all marked (checkboxes) entries
my @marked = ();
if (defined $env{'form.mark'}) {
@marked = &Apache::loncommon::get_env_multiple('form.mark');
}
# move entries from one folder to another
if (defined $env{'form.markedToMove'}) {
my $markedToMove = $env{'form.markedToMove'};
my @ToMove = split(/\,/,$markedToMove);
my $moveTo = $env{'form.mark'};
if (defined $moveTo){
&moveEntries(\@ToMove,$moveTo);
&saveChanges();
}
$changeOrder = 1;
}
# delete entries
if ($env{'form.action'} eq 'delete') {
&deleteEntries(\@marked);
}
# get all titles and notes and save them
# only save, if user wants to save changes
# do not save, when current action is 'delete' or 'sort' or 'move'
my @newTitles = ();
my @newNotes = ();
if ((defined $env{'form.newtitle'} || defined $env{'form.newnote'}) && ($env{'form.action'} ne 'noSave') && ($env{'form.action'} ne 'delete') && !$changeOrder) {
@newTitles = &Apache::loncommon::get_env_multiple('form.newtitle');
@newNotes = &Apache::loncommon::get_env_multiple('form.newnote');
my $node = 0;
foreach my $t (@newTitles) {
&setNewTitle($node, $t);
$node++;
}
$node = 0;
foreach my $n (@newNotes) {
&setNewNote($node, $n);
$node++;
}
&saveChanges();
}
# Create HTML-markup
my $page;
if ($env{'form.mode'} eq 'edit') {
$page = &makePage("edit");
}
elsif ($env{'form.mode'} eq 'move') {
$page = &makePage("move", \@marked);
}
elsif ($env{'form.mode'} eq 'set') {
$page = &makePageSet();
}
else {
$page = &makePage("view");
}
@marked = ();
$r->print($page);
}
# An error occured, print an error-page
else {
my $errorPage = &makeErrorPage();
$r->print($errorPage);
}
return OK;
}
# ----------------------------------------------------- package Tree
# Extend CPAN-Module Tree by function like 'moveNode' or 'deleteNode'
package Tree;
# returns the node with a given index from a list of nodes
sub getNodeByIndex {
my $index = shift;
my $nodes = shift;
my $found;
for my $n (@$nodes) {
my $curIndex = $n->value()->nindex();
if ($n->value()->nindex() == $index) {
$found = $n;
}
}
return $found;
}
# moves a given node to a new parent or change the position from a node
# within its siblings (sorting)
sub moveNode {
my $node = shift;
my $at = shift;
my $newParent = shift;
if (!$newParent) {
$newParent = $node->parent();
}
$node->parent()->remove_child($node);
if (defined $at) {
$newParent->add_child({at => $at},$node);
}
else {
$newParent->add_child($node);
}
# updating root's children
@childrenRt = $root->children();
}
# removes a given node
sub removeNode() {
my $node = shift;
my @children = $node->children();
if ($#children >= 0) {
foreach my $c (@children) {
&removeNode($c);
}
}
$node->parent()->remove_child($node);
# updating root's children
@childrenRt = $root->children();
}
# set an index for every node in the tree, beginning with 0
my $count = 0;
sub TreeIndex {
my $children = shift;
foreach my $n (@$children) {
my @children = $n->children();
$n->value()->nindex($count);$count++;
if ($#children>=0) {
&TreeIndex(\@children);
}
}
}
# reset index counter
sub setCountZero {
$count = 0;
}
# convert the tree to a hash
# each node is one hash-entry
# keys are the indices, values are all other attributes
# (containing tile, path, note, date and indices for all direct children)
# except for root: the key is root and values are
# just the indices of root's children
sub RootToHash {
my $childrenRt = shift;
my @indexarr = ();
foreach my $c (@$childrenRt) {
push (@indexarr, $c->value()->nindex());
}
$TreeToHash{'root'} = [@indexarr];
}
sub TreeToHash {
my $childrenRt = shift;
foreach my $n (@$childrenRt) {
my @arrtmp = ();
$arrtmp[0] = $n->value()->title();
$arrtmp[1] = $n->value()->path();
$arrtmp[2] = $n->value()->note();
$arrtmp[3] = $n->value()->date();
my @childrenRt = $n->children();
my $co = 4;
foreach my $c (@childrenRt) {
my $i = $c->value()->nindex();
$arrtmp[$co] = $i;
$co++;
}
$TreeToHash{$n->value()->nindex} = [ @arrtmp];
if ($#childrenRt>=0) {
&TreeToHash(\@childrenRt);
}
}
}
# convert the hash to a tree
# build a tree-object for each entry in the hash
# afterwards call &buildTree to connect the tree-objects
sub HashToTree {
my @TreeNodes = ();
my $root;
foreach my $key (keys %TreeHash) {
if ($key eq 'root') {
$root = Tree->new("root");
}
else {
my @attributes = @{ $TreeHash{$key} };
my $tmpNode;
$tmpNode = Tree->new(Entry->new(title=>$attributes[0],
path=>$attributes[1],
note=>$attributes[2],
date=>$attributes[3],
nindex=>$key));
push(@TreeNodes, $tmpNode);
# shift all attributes except for
# the indices representing the children of a node
shift(@attributes);
shift(@attributes);
shift(@attributes);
shift(@attributes);
$TreeHash{$key} = [ @attributes ];
}
}
# if there are nodes, build up the tree-structure
if (defined $TreeHash{'root'}) {
my @childrenRtIn = @{ $TreeHash{'root'} };
&buildTree(\$root, \@childrenRtIn,\@TreeNodes,\%TreeHash);
}
return $root;
}
# join the nodes to a tree
sub buildTree {
my ($node, $childrenIn, $TreeNodes, $TreeHash) = @_;
bless($node, 'Tree');
foreach my $c (@$childrenIn) {
my $tmpNode = &getNodeByIndex($c,$TreeNodes);
$$node->add_child($tmpNode);
my @childrenIn = @{ $$TreeHash{$tmpNode->value()->nindex()} };
&buildTree(\$tmpNode,\@childrenIn,$TreeNodes,$TreeHash);
}
}
# ----------------------------------------------------- package Entry
# package that defines the entrys a wishlist could have
# i.e. folders and links
package Entry;
# constructor
sub new {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
my $self = { @_ }; #set attributes
bless($self, $class);
return $self;
}
# getter and setter
sub title {
my $self = shift;
if ( @_ ) { $self->{title} = shift}
return $self->{title};
}
sub date {
my $self = shift;
if ( @_ ) { $self->{date} = shift}
return $self->{date};
}
sub note {
my $self = shift;
if ( @_ ) { $self->{note} = shift}
return $self->{note};
}
sub path {
my $self = shift;
if ( @_ ) { $self->{path} = shift}
return $self->{path};
}
sub nindex {
my $self = shift;
if ( @_ ) { $self->{nindex} = shift}
return $self->{nindex};
}
1;
__END__
--wenzelju1281450646--