--- loncom/interface/lonwishlist.pm 2010/08/10 14:30:20 1.1
+++ loncom/interface/lonwishlist.pm 2011/01/27 14:38:44 1.9
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
-# Routines to control the wishlist
+# Utility-routines for wishlist
#
-# $Id: lonwishlist.pm,v 1.1 2010/08/10 14:30:20 wenzelju Exp $
+# $Id: lonwishlist.pm,v 1.9 2011/01/27 14:38:44 wenzelju Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -26,16 +26,31 @@
# http://www.lon-capa.org/
#
+=pod
+=head1 NAME
+
+Apache::lonwishlist - Wishlist-Module
+
+=head1 SYNOPSIS
+
+The wishlist offers a possibility to store links to resources from the resource-pool and external websites in a hierarchical list.
+It is only available for user with access to the resource-pool. The list can be structured by folders.
+
+The wishlist-module uses the CPAN-module "Tree" for easily handling the directory-structure of the wishlist. Each node in the tree has an index to be referenced by.
+
+=back
+
+=cut
package Apache::lonwishlist;
use strict;
-use Apache::Constants qw(:common);
use Apache::lonnet;
use Apache::loncommon();
use Apache::lonhtmlcommon;
use Apache::lonlocal;
+use LONCAPA;
use Tree;
@@ -47,20 +62,48 @@ my %TreeToHash;
my @allFolders;
my @allNodes;
my $indentConst = 20;
+my $foldersOption;
+
+=pod
+
+=head2 Routines for getting and putting the wishlist data from and accordingly to users data.
+
+=over 4
+
+=item * &getWishlist()
+
+ Get the wishlist-data via lonnet::getkeys() and lonnet::get() and returns the got data in a hash.
+
+
+=item * &putWishlist(wishlist)
+
+ Parameter is a reference to a hash. Puts the wishlist-data contained in the given hash via lonnet::put() to user-data.
+
+
+=item * &deleteWishlist()
+
+ Deletes all entries from the user-data for wishlist. Do this before putting in new data.
+
+
+=back
+
+=cut
# Read wishlist from user-data
sub getWishlist {
- my @wishlistkeys = &Apache::lonnet::getkeys('wishlist');
- my %wishlist = &Apache::lonnet::get('wishlist',\@wishlistkeys);
- foreach my $i (%wishlist) {
+ my @keys = &Apache::lonnet::getkeys('wishlist');
+ my %wishlist = &Apache::lonnet::get('wishlist',\@keys);
+ foreach my $i ( keys %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);
+ my $options = '';
+ &Apache::lonnet::put('wishlist', {'folders' => $options});
+ @keys = &Apache::lonnet::getkeys('wishlist');
+ %wishlist = &Apache::lonnet::get('wishlist',\@keys);
}
elsif ($i =~ /^(con_lost|error|no_such_host)/i) {
&Apache::lonnet::logthis('ERROR while attempting to get wishlist: '.$i);
@@ -68,7 +111,8 @@ sub getWishlist {
}
}
- #If hash is empty, put 'root' into it, so we got a node to start the tree
+ # if we got no keys in hash returned by get(), return error.
+ # wishlist will not be loaded, instead the user will be asked to try again later
if ((keys %wishlist) == 0) {
&Apache::lonnet::logthis('ERROR while attempting to get wishlist: no keys retrieved!');
return 'error';
@@ -92,9 +136,64 @@ sub deleteWishlist {
}
+=pod
+
+=head2 Routines for changing the directory struture of the wishlist.
+
+=over 4
+
+=item * &newEntry(title, path, note)
+
+ Creates a new entry in the wishlist containing the given informations. Additionally saves the date of creation in the entry.
+
+
+=item * &deleteEntries(marked)
+
+ Parameter is a reference to an array containing the indices of all nodes that should be removed from the tree.
+
+
+=item * &sortEntries(indexNode, at)
+
+ Changes the position of a node given by indexNode within its siblings. New position is given by at.
+
+
+=item * &moveEntries(indexNodesToMove, indexParent)
+
+ Parameter is a reference to an array containing the indices of all nodes that should be moved. indexParent specifies the node that will become the new Parent for these nodes.
+
+
+=item * &setNewTitle(nodeindex, newTitle)
+
+ Sets the title for the node given by nodeindex to newTitle.
+
+
+=item * &setNewPath(nodeindex, newPath)
+
+ Sets the path for the node given by nodeindex to newPath.
+
+
+=item * &setNewNote(nodeindex, newNote)
+
+ Sets the note for the node given by nodeindex to newNote.
+
+
+=item * &saveChanges()
+
+ Prepares the wishlist-hash to save it via &putWishlist(wishlist).
+
+
+=back
+
+=cut
+
+
# Create a new entry
sub newEntry() {
- my ($title, $path, $note) = @_;
+ my ($rootgiven, $title, $path, $note) = @_;
+
+ $root = $rootgiven;
+ @childrenRt = $root->children();
+
my $date = gmtime();
# Create Entry-Object
my $entry = Entry->new(title => $title, path => $path, note => $note, date => $date);
@@ -105,52 +204,69 @@ sub newEntry() {
if ($folderIndex ne '') {
@allFolders = ();
&getFoldersToArray(\@childrenRt);
- my $folderToInsertOn = &Tree::getNodeByIndex($folderIndex,\@allFolders);
+ my $folderToInsertOn = &Apache::Tree::getNodeByIndex($folderIndex,\@allFolders);
$folderToInsertOn->add_child($tree);
}
else {
$root->add_child($tree);
}
- &saveChanges();
+ return &saveChanges();
}
# Delete entries
sub deleteEntries {
+ my $rootgiven = shift;
my $marked = shift;
- &getNodesToArray(\@childrenRt);
+ $root = $rootgiven;
+ @childrenRt = $root->children();
+
+ &getNodesToArray(\@childrenRt);
foreach my $m (@$marked) {
- my $found = &Tree::getNodeByIndex($m, \@allNodes);
- &Tree::removeNode($found);
+ my $found = &Apache::Tree::getNodeByIndex($m, \@allNodes);
+ # be sure, that entry exists (may have been deleted before, e.g. in an other browsertab)
+ if (defined $found) {
+ &Apache::Tree::removeNode($found);
+ }
}
@allNodes = ();
- &saveChanges();
+ return &saveChanges();
}
# Sort entries
sub sortEntries {
+ my $rootgiven = shift;
my $indexNode = shift;
my $at = shift;
+
+ $root = $rootgiven;
+ @childrenRt = $root->children();
&getNodesToArray(\@childrenRt);
- my $foundNode = &Tree::getNodeByIndex($indexNode, \@allNodes);
+ my $foundNode = &Apache::Tree::getNodeByIndex($indexNode, \@allNodes);
- &Tree::moveNode($foundNode,$at,undef);
+ &Apache::Tree::moveNode($foundNode,$at,undef);
@allNodes = ();
+ return &saveChanges();
}
# Move entries
sub moveEntries {
+ my $rootgiven = shift;
my $indexNodesToMove = shift;
my $indexParent = shift;
my @nodesToMove = ();
+ $root = $rootgiven;
+ @childrenRt = $root->children();
+
+ # get all nodes that should be moved
&getNodesToArray(\@childrenRt);
foreach my $index (@$indexNodesToMove) {
- my $foundNode = &Tree::getNodeByIndex($index, \@allNodes);
+ my $foundNode = &Apache::Tree::getNodeByIndex($index, \@allNodes);
push(@nodesToMove, $foundNode);
}
@@ -166,55 +282,113 @@ sub moveEntries {
}
if (!$parentIsIn) {
if ($indexParent ne "root") {
- $foundParent = &Tree::getNodeByIndex($indexParent, \@allNodes);
- &Tree::moveNode($node,undef,$foundParent);
+ $foundParent = &Apache::Tree::getNodeByIndex($indexParent, \@allNodes);
+ &Apache::Tree::moveNode($node,undef,$foundParent);
}
else {
- &Tree::moveNode($node,undef,$root);
+ &Apache::Tree::moveNode($node,undef,$root);
}
}
}
@allNodes = ();
+ return &saveChanges();
}
# Set a new title for an entry
sub setNewTitle {
- my ($nodeindex, $newTitle) = @_;
+ my ($rootgiven, $nodeindex, $newTitle) = @_;
+
+ $root = $rootgiven;
+ @childrenRt = $root->children();
+
&getNodesToArray(\@childrenRt);
- my $found = &Tree::getNodeByIndex($nodeindex, \@allNodes);
+ my $found = &Apache::Tree::getNodeByIndex($nodeindex, \@allNodes);
$found->value()->title($newTitle);
@allNodes = ();
+ return &saveChanges();
+}
+
+
+# Set a new path for an entry
+sub setNewPath {
+ my ($rootgiven, $nodeindex, $newPath) = @_;
+
+ $root = $rootgiven;
+ @childrenRt = $root->children();
+
+ &getNodesToArray(\@childrenRt);
+ my $found = &Apache::Tree::getNodeByIndex($nodeindex, \@allNodes);
+ if ($found->value()->path()) {
+ $found->value()->path($newPath);
+ return &saveChanges();
+ }
+ @allNodes = ();
+ return 0;
}
# Set a new note for an entry
sub setNewNote {
- my ($nodeindex, $newNote) = @_;
+ my ($rootgiven, $nodeindex, $newNote) = @_;
+
+ $root = $rootgiven;
+ @childrenRt = $root->children();
+
&getNodesToArray(\@childrenRt);
- my $found = &Tree::getNodeByIndex($nodeindex, \@allNodes);
+ my $found = &Apache::Tree::getNodeByIndex($nodeindex, \@allNodes);
$found->value()->note($newNote);
@allNodes = ();
+ return &saveChanges();
}
# Save all changes
sub saveChanges {
@childrenRt = $root->children();
- &Tree::TreeIndex(\@childrenRt);
- &Tree::setCountZero();
- &Tree::RootToHash(\@childrenRt);
- &Tree::TreeToHash(\@childrenRt);
+ &Apache::Tree::TreeIndex(\@childrenRt);
+ &Apache::Tree::setCountZero();
+ &Apache::Tree::RootToHash(\@childrenRt);
+ &Apache::Tree::TreeToHash(\@childrenRt);
&deleteWishlist();
&putWishlist(\%TreeToHash);
+ return $root;
}
+=pod
+
+=head2 Routines for handling the directory structure
+
+=over 4
+
+=item * &getFoldersForOption(nodes)
+
+ Return the titles for all exiting folders in an option-tag, used to offer the users a possibility to create a new link or folder in an existing folder.
+ Recursive call starting with all children of the root of the tree (parameter nodes is reference to an array containing the nodes of the current level).
+
+
+=item * &getFoldersToArray(children)
+
+ Puts all nodes that represent folders in the wishlist into an array.
+ Recursive call starting with all children of the root of the tree (parameter nodes is reference to an array containing the nodes of the current level).
+
+
+=item * &getNodesToArray(children)
+
+ Puts all existing nodes into an array (apart from the root node, because this one does not represent an entry in the wishlist).
+ Recursive call starting with all children of the root of the tree (parameter nodes is reference to an array containing the nodes of the current level).
+
+
+=back
+
+=cut
+
+
# 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;
@@ -235,22 +409,6 @@ sub getFoldersForOption {
}
-sub getfoldersOption {
- if (&getWishlist ne 'error') {
- %TreeHash = &getWishlist();
- $root = &Tree::HashToTree();
- @childrenRt = $root->children();
- &getFoldersForOption(\@childrenRt);
- my $options = ''.$foldersOption;
- $foldersOption = '';
- return $options;
- }
- else {
- return '';
- }
-}
-
-
# Put all folder-nodes to an array
sub getFoldersToArray {
my $children = shift;
@@ -279,6 +437,67 @@ sub getNodesToArray {
}
+=pod
+
+=head2 Routines for the user-interface of the wishlist
+
+=over 4
+
+=item * &JSforWishlist()
+
+ Returns JavaScript-functions needed for wishlist actions like open and close folders.
+
+
+=item * &wishlistView(nodes)
+
+ Returns the table-HTML-markup for the wishlist in mode "view".
+ Recursive call starting with all children of the root of the tree (parameter nodes is reference to an array containing the nodes of the current level).
+
+
+=item * &wishlistEdit(nodes)
+
+ Returns the table-HTML-markup for the wishlist in mode "edit".
+ Recursive call starting with all children of the root of the tree (parameter nodes is reference to an array containing the nodes of the current level).
+
+
+=item * &wishlistMove(nodes, marked)
+
+ Returns the table-HTML-markup for the wishlist in mode "move". Highlights all entry "selected to move" contained in marked (reference to array).
+ Recursive call starting with all children of the root of the tree (parameter nodes is reference to an array containing the nodes of the current level).
+
+
+=item * &wishlistImport(nodes)
+
+ Returns the table-HTML-markup for the wishlist in mode "import".
+ Recursive call starting with all children of the root of the tree (parameter nodes is reference to an array containing the nodes of the current level).
+
+
+=item * &makePage(mode, marked)
+
+ Returns the HTML-markup for the whole wishlist depending on mode. If mode is "move" we need the marked entries to be highlighted a "selected to move".
+ Calls &wishlistView(nodes), &wishlistEdit(nodes) or &wishlistMove(nodes, marked).
+
+
+=item * &makePageSet()
+
+ Returns the HTML-Markup for the page shown when a link was set by using the icon when viewing a resource.
+
+
+=item * &makePageImport()
+
+ Returns the HTML-Markup for the page shown when links should be imported into courses.
+
+
+=item * &makeErrorPage ()
+
+ Returns the HTML-Markup for an error-page shown if the wishlist could not be loaded.
+
+
+=back
+
+=cut
+
+
# Return a script-tag containing Javascript-function
# needed for wishlist actions like 'new link' ect.
sub JSforWishlist {
@@ -321,7 +540,7 @@ sub JSforWishlist {
'
'.
''.
''.
''.
@@ -351,11 +570,23 @@ sub JSforWishlist {
$inPageNewLink =~ s/\n//g;
$inPageNewFolder =~ s/\n//g;
+ # it is checked, wether a path links to a LON-CAPA-resource or an external website. links to course-contents are not allowed
+ # because they probably will return a kind of 'no access' (unless the user is already in the course, the path links to).
+ # also importing these kind of links into a course does not make much sense.
+ # to find out if a path (not starting with /res/...) links to course-contents, the same filter as in lonwrapper is used,
+ # that means that it is checked wether a path contains .problem, .quiz, .exam etc.
+ # this is good for most cases but crashes as soon as a real external website contains one of this pattern in its URL.
+ # so maybe there's a better way to find out wether a given URL belongs to a LON-CAPA-server or not ...?
+ my $warningLinkNotAllowed1 = &mt('You can only insert links to LON-CAPA resources from the resource-pool '.
+ 'or to external websites. Paths to LON-CAPA resources must be of the form /res/dom/usr... . '.
+ 'Paths to external websites must contain the network protocol (e.g. http://...).');
+ my $warningLinkNotAllowed2 = &mt('The following link is not allowed: ');
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!');
+ my $warningMoveS = &mt('You must select at minimum one entry to move!');
+ my $warningMoveD = &mt('You must select a destination folder!');
$foldersOption = '';
my $js = &Apache::lonhtmlcommon::scripttag(<'.
+ 'value()->path()."'".');">'.
''.
- ''.$n->value()->title().'';
+ $n->value()->title().'';
}
# note-icon, different icons for an entries with note and those without
@@ -910,7 +1280,9 @@ sub wishlistEdit {
'
';
}
# entry is a link
@@ -918,12 +1290,11 @@ sub wishlistEdit {
$wishlistHTMLedit .= '
'.
'
'.
- '';
+ ''.
+ '
'.
+ '
';
}
-
- # input-field for title
- $wishlistHTMLedit .= '';
-
+
# note-icon, different icons for an entries with note and those without
my $noteIMG = 'anot.png';
@@ -939,7 +1310,7 @@ sub wishlistEdit {
# start row containing the textarea for the note
$wishlistHTMLedit .= &Apache::loncommon::continue_data_table_row('LC_hidden','note'.$index).
- '
'.
+ '
'.
'
';
@@ -999,19 +1370,17 @@ sub wishlistMove {
}
# entry is a link
else {
- if (!$isIn) {
- $wishlistHTMLmove .= '
'.
- '
';
- }
# higlight the title, if the link was selected to be moved
- else {
- $wishlistHTMLmove .= '
'.
- '
';
+ my $highlight = '';
+ if ($isIn) {
+ $highlight = 'style="color:red;"';
}
# link-image and title
- $wishlistHTMLmove .= ''.
- $n->value()->title().'
';
}
# note-icon, different icons for an entries with note and those without
@@ -1045,11 +1414,90 @@ sub wishlistMove {
}
}
+
+
+# HTML-Markup for table if in import-mode
+my $wishlistHTMLimport;
+my $indent = $indentConst;
+my $form = 1;
+sub wishlistImport {
+ 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
+ $wishlistHTMLimport .= ($n->parent()->value() eq 'root')?&Apache::loncommon::start_data_table_row('','row'.$index)
+ :&Apache::loncommon::continue_data_table_row('LC_hidden','row'.$index);
+
+
+ # checkboxes
+ $wishlistHTMLimport .= '
'.
+ ''.
+ ''.
+ ''.
+ ''.
+ '
';
+
+ # entry is a folder
+ if ($n->value()->path() eq '') {
+ $wishlistHTMLimport .= '
';
+ $form++;
+ }
+
+ # note-icon, different icons for an entries with note and those without
+ my $noteIMG = 'anot.png';
+
+ if ($n->value()->note() ne '') {
+ $noteIMG = 'anot2.png';
+ }
+
+ $wishlistHTMLimport .= '
';
+
+ $wishlistHTMLimport .= &Apache::loncommon::end_data_table_row();
+
+ # start row containing the textarea for the note, do not display note on default, readonly in import-mode
+ $wishlistHTMLimport .= &Apache::loncommon::continue_data_table_row('LC_hidden','note'.$index).
+ '
'.
+ '
';
+ $wishlistHTMLimport .= &Apache::loncommon::end_data_table_row();
+
+ # if the entry is a folder, it could have other entries as content. if it has, call wishlistImport for those entries
+ my @children = $n->children();
+ if ($#children >=0) {
+ $indent += 20;
+ &wishlistImport(\@children);
+ $indent -= 20;
+ }
+ }
+}
+
# Returns the HTML-Markup for wishlist
sub makePage {
+ my $rootgiven = shift;
my $mode = shift;
my $marked = shift;
+ $root = $rootgiven;
+ @childrenRt = $root->children();
+
# breadcrumbs and start_page
&Apache::lonhtmlcommon::clear_breadcrumbs();
&Apache::lonhtmlcommon::add_breadcrumb(
@@ -1060,10 +1508,7 @@ sub makePage {
'onload' => 'javascript:onLoadAction('."'".$mode."'".');',
'onunload' => 'javascript:window.name = '."'loncapaclient'"}});
- my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Wishlist '.
- ''.
- '');
+ my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs(&mt('Wishlist').&Apache::loncommon::help_open_topic('Wishlist'));
# get javascript-code for wishlist-interactions
my $js = &JSforWishlist();
@@ -1084,7 +1529,7 @@ sub makePage {
# icon for edit-mode, display when in view-mode
if ($mode eq 'view') {
$functions .= &Apache::lonhtmlcommon::add_item_funclist(''.
+ 'onclick="setFormAction('."'save','edit'".');" class="LC_menubuttons_link">'.
' '.
''.$lt{'ed'}.'');
@@ -1092,7 +1537,7 @@ sub makePage {
# icon for view-mode, display when in edit-mode
else {
$functions .= &Apache::lonhtmlcommon::add_item_funclist(''.
+ 'onclick="setFormAction('."'save','view'".');" class="LC_menubuttons_link">'.
' '.
''.$lt{'vw'}.'');
@@ -1128,7 +1573,7 @@ sub makePage {
# icon for saving changes
$functions .= &Apache::lonhtmlcommon::add_item_funclist(''.
+ 'onclick="setFormAction('."'saveOK','".$mode."'".'); " class="LC_menubuttons_link">'.
''.
''.$lt{'sv'}.'');
@@ -1142,7 +1587,7 @@ sub makePage {
'';
# only display subbox in view- or edit-mode
- if ($mode ne 'move') {
+ if ($mode eq 'view' || $mode eq 'edit') {
$inner .= $subbox;
}
@@ -1155,7 +1600,7 @@ sub makePage {
$inner .= &Apache::loncommon::end_data_table();
}
else {
- $inner .= ''.&mt("Your wihlist ist currently empty.").'';
+ $inner .= ''.&mt("Your wishlist ist currently empty.").'';
}
$wishlistHTMLedit = '';
}
@@ -1165,7 +1610,7 @@ sub makePage {
$inner .= '
'.$wishlistHTMLview.'
';
}
else {
- $inner .= ''.&mt("Your wihlist ist currently empty.").'';
+ $inner .= ''.&mt("Your wishlist ist currently empty.").'';
}
$wishlistHTMLview = '';
}
@@ -1177,18 +1622,18 @@ sub makePage {
if ($markStr) {
$markStr = substr($markStr, 0, length($markStr)-1);
$inner .= '';
- $inner .= ''.&mt('You have selected the red marked entries to be moved to another folder. '.
- 'Now choose the new destination folder.').'
';
+ $inner .= '
'.&mt('You have selected the red marked entries to be moved to another folder. '.
+ 'Now choose the new destination folder.').'
';
}
else {
- $inner .= ''.&mt("You haven't marked any entry to move.").' '.
+ $inner .= '
'.&mt("You haven't marked any entry to move.").'
'.
'';
}
}
@@ -1199,13 +1644,110 @@ sub makePage {
# end_page
my $endPage = &Apache::loncommon::end_page();
- # put all page-elements togther
+ # put all page-elements together
my $page = $startPage.$breadcrumbs.$js.$inner.$endPage;
return $page;
}
+# Returns the HTML-Markup for the PopUp, shown when a new link should set, when NOT
+# beeing in the wishlist-interface (method is called in lonmenu and lonsearchcat)
+sub makePopUpNewLink{
+
+ # Get all existing folders to offer posibility to set a new link
+ # into a folder
+ my %TreeHashLink = &Apache::lonwishlist::getWishlist();
+ my $rootLink = &Apache::Tree::HashToTree(\%TreeHashLink);
+ my @childrenRtLink = $rootLink->children();
+
+ $foldersOption = '';
+ @allFolders = ();
+ &getFoldersToArray(\@childrenRtLink);
+ &getFoldersForOption(\@childrenRtLink);
+
+ my $options = ''.$foldersOption;
+ $foldersOption = '';
+ @allFolders = ();
+
+ # HTML-Markup for 'Set a link for this resource to wishlist'
+ # this is written via JavaScript document.write (function set_wishlistlink)
+ # it is split into 3 parts and the inputfields for title and path are left out
+ # these fields are inserted later to set the values for title and path
+ # automatically via JavaScript (document.title and location.pathname)
+
+ my $start_page_wishlistlink =
+ &Apache::loncommon::start_page('Set link to wishlist',undef,
+ {'only_body' => 1,
+ 'js_ready' => 1,
+ 'bgcolor' => '#FFFFFF',});
+
+ my $warningLink = &mt('You must insert a title!');
+
+ my $in_page_wishlistlink1 = '
'.&mt('Set a link to wishlist').'
'.
+ '';
+ $options = '';
+
+ # remove all \n for inserting on javascript document.write
+ $in_page_wishlistlink1 =~ s/\n//g;
+ $in_page_wishlistlink2 =~ s/\n//g;
+ $in_page_wishlistlink3 =~ s/\n//g;
+
+ my $end_page_wishlistlink =
+ &Apache::loncommon::end_page({'js_ready' => 1});
+
+ # Add JavaScript-function to set link for a ressource to wishlist
+ my $js.=<